Dengan Mercurial, bagaimana saya bisa "memampatkan" serangkaian perubahan menjadi satu sebelum mendorong?

96

Katakanlah saya memiliki repositori Mercurial lokal dan jarak jauh. Sekarang, saya mulai mengerjakan sebuah fitur. Saya mengerjakannya, dan ketika saya pikir itu sudah selesai, saya melakukan set perubahan. Mengujinya sedikit lagi, saya menemukan bahwa saya dapat lebih meningkatkan fitur ini dengan mengutak-atik sesuatu dalam kode. Saya membuat perubahan dan berkomitmen. 20 menit kemudian, saya menemukan ada bug di fitur baru ini, jadi saya memperbaikinya dan melakukannya juga.

Sekarang saya memiliki 3 kumpulan perubahan yang saya ingin dorong ke repositori jarak jauh sebagai satu kumpulan perubahan dengan pesan "Menerapkan fitur X", misalnya.

Bagaimana saya bisa melakukan ini tanpa banyak kerumitan? Saya yakin saya bisa melakukannya dengan tambalan, tetapi sepertinya banyak pekerjaan.

Lucas
sumber
40
Jelas bukan tempat saya untuk membujuk Anda agar tidak mencoba mengompresi set perubahan Anda, tetapi Anda mungkin ingin mempertimbangkan bahwa separuh nilai kontrol versi menjawab "mengapa" bukan hanya "apa" berbulan-bulan dan bertahun-tahun kemudian. Representasi akurat tentang bagaimana fitur muncul, dan dalam tahap apa, mungkin memiliki nilai di masa mendatang. Membuang sepertinya begitu ... tidak terkontrol.
Ry4an Brase
Hal ini menyebabkan pertanyaan lain ... Apa perbedaan antara 'histedit' dan 'collapse'
sylvanaar
1
collapse menyediakan subset dari fitur histedit, dan histedit memiliki UX yang jauh lebih intuitif.
Stefan Rusek
1
Ini juga menyediakan mekanisme untuk mengedit pesan perubahan yang digabungkan.
Stefan Rusek
1
@ Ry4an: Sebenarnya, squashing / collapsing menambahkan relevansi ke kontrol versi dalam beberapa kasus. Tanpa menekan, saya akan memiliki dua komit setiap hari yang tidak ada hubungannya dengan fitur atau perbaikan bug, tetapi untuk memindahkan kode dari laptop ke desktop dan sebaliknya. Mereka hanya menambahkan kebisingan ke riwayat versi.
John Reynolds

Jawaban:

39

Bagaimana dengan Ciutkan Ekstensi ?

Steve Losh
sumber
20
Salam dari masa depan! Saya baru saja mencari di Google untuk fungsi yang sama dan tampaknya saat ini hg mendukung ini di luar kotak dengan hg rebase --collapse. Lihat wiki hg pada perintah rebase. Karena pertanyaan ini adalah hasil pencarian keseluruhan ke-3 dan yang pertama di stackoverflow, saya pikir info itu mungkin berguna.
a.peganz
1
Salam dari masa depan !! Ekstensi rebase tampaknya hanya ditargetkan untuk memindahkan kumpulan perubahan dari satu cabang ke cabang lainnya. Ya, ada opsi --collapse, tetapi tampaknya masih hanya berlaku saat memindahkan kumpulan perubahan di seluruh cabang. Lihat < mercurial-scm.org/wiki/… >
Brad Oestreicher
3
Anda dapat menggunakan hg rebasedengan --collapsedalam satu cabang.
UuDdLrLrSs
52

The histedit ekstensi adalah apa yang Anda cari.

hg histedit -o

atau

hg histedit --outgoing

akan memunculkan daftar perubahan yang keluar. Dari daftar Anda bisa

  • Lipat 2 atau lebih kumpulan perubahan membuat satu kumpulan perubahan tunggal
  • Jatuhkan set perubahan untuk menghapusnya dari riwayat
  • Susun ulang set perubahan sesuka Anda.

histedit akan meminta Anda untuk pesan komit baru dari kumpulan perubahan terlipat yang defaultnya ke dua pesan dengan "\ n *** \ n" memisahkan mereka.

Anda juga bisa mendapatkan hasil yang serupa dengan menggunakan ekstensi mq, tetapi ini jauh lebih sulit.

Anda juga dapat menggunakan ekstensi penciutan untuk hanya melakukan pelipatan, tetapi tidak menyediakan UI sebaik dan tidak menyediakan cara untuk mengedit pesan komit yang dihasilkan. Mengedit pesan komit yang dihasilkan juga memungkinkan untuk membersihkan pesan terakhir, yang pada akhirnya selalu saya manfaatkan.

Stefan Rusek
sumber
terima kasih, itulah yang saya butuhkan. Akan menyenangkan jika Anda bisa melakukannya dari dalam TortoiseHg - tetapi baris perintahnya cukup sederhana.
sylvanaar
21

Ya, Anda dapat melakukannya dengan tambalan: Anggaplah pekerjaan Anda ada di set perubahan 100 hingga 110, inklusif

  1. Buat tambalan:

    % hg export -o mypatch 100:110 --git

  2. Perbarui ke 99:

    % hg update 99

  3. Terapkan tambalan dengan --no-commit (jika tidak, Anda akan mendapatkan semua perubahan Anda kembali):

    % hg import --no-commit mypatch

  4. Lakukan semua perubahan sekaligus:

    % hg commit

  5. Anda sekarang memiliki dua kepala (110 dan 111) yang seharusnya setara dalam hal file yang mereka hasilkan di direktori kerja Anda - mungkin membedakannya untuk kewarasan sebelum menghapus yang lama:

    % hg strip 100

Oke, sekarang setelah saya mengeja semuanya, memang tampak panjang, tetapi setelah melakukannya sendiri berkali-kali, saya tidak merasa itu terlalu banyak tugas ...

Arkady
sumber
1
Jawaban bagus, tetapi ada prasyarat: ekstensi MQ harus diaktifkan .
Chris Kelly
Untuk menyertakan perubahan dalam file biner juga, pastikan untuk menggunakan opsi --git: misalnya: "hg export -o mypatch 100: 110 --git" Untuk informasi selengkapnya, silakan lihat: stackoverflow.com/a/12537738/ 367663 Saya telah mengambil kebebasan untuk mengubah jawabannya.
Kharlos Dominguez
1
Tampaknya terlalu rumit, mengapa tidak hg strip --keepdan kemudian melakukan semuanya dalam satu komit?
G. Demecki
@ G.Demecki Karena ini adalah operasi yang berpotensi sangat merugikan ..? Meskipun MQ berlebihan (dan bahkan sering tidak disarankan), kecuali jika menginginkan alur kerja seperti itu.
pengguna2864740
@ user2864740 Anda mungkin benar, karena saya bukan ahli Mercurial. Tapi secara default, hg stripakan menempatkan backup di .hg/strip-backup/direktori. Saya kira itu tidak seaman git reflogtetapi masih menyediakan semacam penyelamatan.
G. Demecki
19

Jika Anda menggunakan TortoiseHg, gunakan hanya dapat memilih dua revisi (gunakan CTRL untuk memilih revisi non-berikutnya), klik kanan dan pilih "Kompres Riwayat" .

Setelah itu Anda akan mendapatkan daftar perubahan baru di kepala baru mulai dari perubahan pertama yang Anda pilih sebelumnya, itu akan berisi semua daftar perubahan turunan di antara yang Anda pilih.

Anda cukup menghapus daftar perubahan lama jika Anda tidak membutuhkannya lagi: gunakan ekstensi MQ untuk itu. Sekali lagi, di TortoiseHg: klik kanan pada daftar perubahan pertama yang perlu dihilangkan dengan semua turunannya, "Modify History -> Strip" .

George Marian
sumber
18

Metode yang saya sukai menggunakan mq untuk pelipatan ini adalah menggunakan TortoiseHg seperti yang dijelaskan di sini . Namun, ini dapat dengan mudah dilakukan dari baris perintah seperti:

hg qimport -r <first>:<last> 
    -- where <first> and <last> are the first and last changesets 
    -- in the range of revisions you want to collapse

hg qpop <first>.diff
    -- remove all except for the first patch from the queue
    -- note: mq names patches <#>.diff when it imports them, so we're using that here

hg qfold <next>.diff
    -- where <next> is <first>+1, then <first>+2, until you've reached <last>

hg qfinish -a
    -- apply the folded changeset back into the repository

(Mungkin ada cara yang lebih baik untuk melakukan langkah qfold, tapi saya tidak menyadarinya, karena saya biasanya menggunakan TortoiseHg untuk operasi itu.)

Tampaknya agak rumit pada awalnya, tetapi setelah Anda mulai menggunakan mq, itu sangat mudah dan alami - plus Anda bisa melakukan semua jenis hal lain dengan mq yang bisa sangat berguna!

Chris Phillips
sumber
4

hg collapsedan hg histeditcara terbaik. Atau, lebih tepatnya, akan menjadi cara terbaik, jika mereka bekerja dengan andal ... Saya harus histeditmenabrak tumpukan sampah dalam waktu tiga menit. Collapsetidak jauh lebih baik.

Pikir saya mungkin berbagi dua BKM lainnya:

  1. hg rebase --collapse

    Ekstensi ini didistribusikan dengan Mercurial. Saya belum punya masalah dengan itu. Anda mungkin harus memainkan beberapa game untuk mengatasi hg rebaseketerbatasan - pada dasarnya, ia tidak suka melakukan rebasing ke leluhur di cabang yang sama, bernama atau default, meskipun ia mengizinkannya jika melakukan rebasing di antara cabang (bernama).

  2. Pindahkan repositori ( foo/.hg) ke direktori kerja ( bar) dan file-nya. Bukan sebaliknya.

Beberapa orang telah berbicara tentang membuat dua pohon klon, dan menyalin file di antara keduanya. Atau menambal di antara mereka. Sebaliknya, lebih mudah untuk memindahkan .hgdirektori.

hg clone project work
... lots of edits
... hg pull, merge, resolve
hg clone project, clean
mv work/.hg .hg.work
mv clean/.hg work/.hg
cd work
... if necessary, pull, nerge, reconcile - but that would only happen because of a race
hg push

Ini bekerja selama repositori sebenarnya, .hgpohon, tidak bergantung pada direktori kerja dan file-nya.

Jika mereka tidak independen ...

Krazy Glew
sumber
Pada 2015, histeditadalah pilihan yang sangat bagus untuk tugas ini. Saya masih tidak mempercayainya karena saya melakukan git rebase -i, tetapi tidak macet .. setidaknya versi yang lebih baru akan meninggalkan Anda di cabang temp jika ada yang tidak beres jadi satu-satunya saat perubahan set akan dilucuti adalah setelah cabang baru dilakukan.
pengguna2864740
2

Saya belum pernah menggunakan Mercurial, tetapi ini sangat mirip dengan apa yang dibicarakan Martin Fowler di blognya belum lama ini:

http://martinfowler.com/bliki/MercurialSquashCommit.html

Joseph
sumber
Itu terlihat lebih dari sedikit rumit, tapi terima kasih untuk tautannya. Sejujurnya saya berharap untuk beberapa ekstensi ajaib yang akan melakukan apa yang saya inginkan, seperti mengambil dan transplantasi yang dilakukan dengan changset menarik dan pemetik ceri.
Lucas
0

Mengapa tidak hg strip --keepmemerintah saja ?

Kemudian Anda dapat melakukan semua perubahan sebagai satu komit.

G. Demecki
sumber
@Strawberry tidak memberikan jawaban ?? Ia pikir itu menjawab pertanyaan penulis dengan sempurna. Bisakah Anda menjelaskan maksud Anda?
G. Demecki
Ini sejarah kuno, jadi saya akan menarik kembali pernyataan itu - tetapi jawaban yang Disetujui sepertinya referensi yang lebih berwibawa.
Strawberry
1
@Strawberry Memang itu benang kuno. Tetapi jawaban yang diterima sudah usang, karena Mercurial tidak lagi membutuhkan ekstensi pihak ketiga yang terpisah untuk pekerjaan ini.
G. Demecki
0

HistEdit akan melakukan apa yang Anda inginkan, tetapi mungkin berlebihan. Jika satu-satunya hal yang Anda butuhkan adalah melipat beberapa kumpulan perubahan bersama, Ciutkan Ekstensi akan melakukan pekerjaan itu.

Steve Losh
sumber
1
meskipun itu memberikan lebih mudah untuk menggunakan dan memahami UI, yang lebih dari cukup alasan untuk menggunakannya, tetapi juga menyediakan mekanisme untuk mengedit pesan perubahan yang digabungkan, yang merupakan hal lain yang selalu ingin saya lakukan ketika saya gabungkan kumpulan perubahan.
Stefan Rusek
Dan masalah hanya memahami UI adalah orang yang benar-benar tidak mengerti .. Bagaimanapun, untuk masa lalu sementara histedit memungkinkan perubahan 'pesan', serta mengubah pesan saat 'melipat'. Histeditnya sempurna; jika ada, ekstensi penciutan kurang berguna.
pengguna2864740
0

Misalkan Anda memiliki dua tidak diterbitkan THISdan THATkomit di Mercurial dan ingin mereka bergabung menjadi komit tunggal di THIStitik ::

... --> THIS --> ... --> THAT --> ... --> LAST

Periksa apakah komit Anda tidak dipublikasikan ::

$ hg glog -r "draft() & ($THIS | $THAT)"

Perbarui untuk LASTmelakukan ::

$ hg up

dan impor komit hingga THISke MQ ::

$ hg qimport $THIS::.

Batalkan penerapan semua tambalan dan terapkan hanya terlebih dahulu THIS::

$ hg qpop -a
$ hg qpush
$ hg qapplied
... THIS ...

Bergabung dengan THAT::

$ hg qfold $THATNAME

CATATAN Untuk mencari nama THATNAMEgunakan ::

$ hg qseries

Terapkan semua tambalan dan pindahkan ke riwayat repositori ::

$ hg qpush -a
$ hg qfinish -a

Posting blog saya tentang subjek adalah Bergabung dengan dua komitmen di Mercurial .

gavenkoa.dll
sumber
0

Ya, strip --keepberfungsi untuk pertanyaan Penulis. Tapi itu sedikit berbeda dari yang lain, misalnya, jika Anda memiliki versi dari 1 hingga 30 tetapi hanya ingin menciutkan versi 12-15. Solusi lain berhasil tetapi tidak strip --keep.

Frank Tao
sumber