Bisakah saya squash komit di Mercurial?


109

Saya memiliki sepasang komitmen yang seharusnya hanya satu. Jika saya menggunakan git, saya akan menggunakan:

git rebase -i <some-commit-before>

dan kemudian remas.

Bisakah saya melakukannya dengan lincah? Jika ya, bagaimana caranya?

Jawaban:


88

Ya, Anda dapat melakukan ini menggunakan mercurial tanpa ekstensi apa pun dengan Concatenating Changesets .

Bergantian jika Anda ingin menggunakan ekstensi, Anda dapat menggunakan:


Ya, saya mendapatkan jawaban itu dari pertanyaan penipuan yang saya suka dalam komentar saya tentang pertanyaan umum. Saya pikir itu jawaban Anda untuk yang satu itu.
Ry4an Brase

4
Sedikit catatan tambahan: Ekstensi Histedit didistribusikan dengan Mercurial 2.3 dan yang lebih baru. Anda hanya perlu mengaktifkannya.
Paidhi

1
Dalam dokumen Concatenating Changesets menggunakan konsep abstrak "repo", bagaimana saya mereferensikannya? Misalnya: hg -R oldrepo export ... menghasilkan "abort: repository oldrepo tidak ditemukan!
Aleksandr Levchuk

13
Hanya mencoba meredam 2 komit. Apakah saya benar-benar membutuhkan halaman wiki dengan 10+ perintah atau ekstensi alternatif?
Aleksandr Levchuk

3
Lihat komentarnya. Histedit sekarang sudah ada di dalamnya, Anda hanya perlu mengaktifkannya (karena tidak ada perintah default yang akan mengubah riwayat)
Ry4an Brase

43

Favorit saya adalah hg strip --keepperintah. Dan kemudian saya melakukan semua perubahan dalam satu komit.

Ini adalah cara tercepat dan ternyaman bagi saya, karena saya suka melakukan banyak hal kecil selama pekerjaan saya sehari-hari;)


Catatan 1: stripmembutuhkan ekstensi bawaan mquntuk diaktifkan.
Catatan 2: Klien Git / Mercurial favorit saya (SmartGit / Hg) ditambahkan dengan --keepparameter default selama strip. Dan yang lebih nyaman: ini menyediakan opsi yang disebut join commits:]


4
Perintah lengkap untuk hg strip adalah: hg strip --keep --rev [rev] Di mana revnomor revisi dari komit pertama yang ingin Anda hilangkan dengan yang terakhir
Nicolas Forney

3
@NicolasForney Tidak persis, --revadalah opsional, perintah lengkap adalahhg strip --keep [rev]
G. Demecki

Revisi wajib bagi saya di 3.3.3: hg help stripmemberi hg strip [-k] [-f] [-n] [-B bookmark] [-r] REV..., dan menghilangkan revisi memberi saya abort: empty revision set.
Roman Starkov

3
Menggunakan hg stripbukanlah ide terbaik. Ini tidak sepenuhnya aman. Coba hg histedit, mungkin coba gunakan ekstensi berevolusi.
Martin Thomson

Tampaknya cara paling alami bagi orang-orang git;)
foo

32

The ekstensi Rebase bekerja seperti pesona. Untuk squash 2 komit:

$ hg rebase --dest .~2 --base . --collapse

Titik adalah jalan pintas untuk revisi saat ini.

Lebih mudah lagi bila Anda memiliki beberapa komit di cabang dan ingin menciutkan semuanya menjadi satu:

$ hg rebase --dest {destination branch (e.g. master)} --base . --collapse

Bagaimana ini bekerja:

masukkan deskripsi gambar di sini

(dari http://mercurial-scm.org/wiki/RebaseExtension#Collapsing )


1
Di mana Anda menemukan "~ 2" untuk dua komit?
Mi-La

1
Sudah dijelaskan di topik revsets, lihat hg help revsets.
mark dan

13

Jika Anda membaca jawaban ini, Anda dapat melupakan setiap opsi lain yang disebutkan dalam jawaban ini dan menggunakan foldperintah dari ekstensi evolve .

evolveadalah perpanjangan dari mercurial yang membantu kita dalam memiliki sejarah yang bisa berubah dengan aman, ini masih eksperimental. Anda dapat menggunakannya dengan kloning dari yang repo dan menambahkannya di .hgrc Anda seperti ini.

[extensions]
evolve = ~/evolve/hgext/evolve.py

Dengan asumsi Anda mengkloning repo evolve di direktori home Anda. Sekarang Anda siap untuk pergi. Anda juga dapat mencari bantuan dengan hg help fold.

Lipat Perintah

Anda memerintahkan folduntuk meremas / melipat rantai komitmen linier yang tidak putus. Apa yang dilakukan flip adalah, ia membuat kumpulan perubahan baru yang berisi perubahan dari semua kumpulan perubahan dan menandai semua komitmen tersebut sebagai usang. Anda dapat melihat lebih dalam tentang ini di dokumen .

Sekarang misalkan Anda memiliki sejarah berikut.

a -> b -> c -> d -> e -> f -> g

Anda ingin squash e, fdan g. Anda dapat melakukan

hg up g
hg fold -r e

Hasilnya akan seperti itu

a -> b -> c -> d -> h

di mana hperubahan yang berisi perubahan dari ketiga komit e, fdan g.

Anda juga dapat melipat rangkaian perubahan dari tengah histori, misalnya Anda tidak harus memilih rantai yang menyertakan ujungnya. Misalkan Anda ingin melipat b, cdan d. Anda dapat melakukan

hg up d
hg fold -r b
hg evolve --all

Ini akan menghasilkan

a -> i -> j

di mana iadalah changeset terlipat b, c, ddan jadalah changeset sama h. Panduan pengguna Evolve harus dibaca.


Sepertinya rebase mencakup sebagian besar (mungkin semua?) Kasus penggunaan ekstensi itu, dan tentu saja yang ditanyakan dalam pertanyaan ini. Fitur pembunuh dari ekstensi itu adalah menyembunyikan (daripada menghapus) revisi yang Anda ganti, tetapi --keepopsi rebase menutupi ini (diikuti dengan menandai revisi sebagai rahasia, atau menggunakan strip pada mereka setelah Anda memeriksa hasilnya). Bahkan memindahkan revisi di antara revisi lainnya dimungkinkan dengan urutan dua perintah rebase.
Arthur Tacca

... plus, jika Anda melakukan sesuatu yang sangat rumit, Anda selalu dapat mengkloning repo lokal terlebih dahulu untuk digunakan sebagai cadangan. Mempertimbangkan betapa langka (semoga!) Itu, ini lebih mudah daripada mempelajari cara menggunakan ekstensi yang benar-benar baru.
Arthur Tacca

"NameError: name 'execfile' tidak ditentukan" —yang berarti evolve ditulis dengan Python 2, yang pada dasarnya adalah zaman batu.
Neil G

1
@NeilG mercurial belum mendukung Python 3.
Pulkit Goyal

2
@NeilG ya, komunitas lincah bekerja keras untuk mendapatkan dukungan py3 secepatnya.
Pulkit Goyal

1

Dengan Mercurial 4.8 (November 2018, 9 tahun kemudian), Anda dapat mempertimbangkan perintah baru hg absorb(ini adalah fitur eksperimental sebelumnya ).

Lihat " Menyerap Perubahan Komit di Mercurial 4.8 "

Ekstensi absorb akan mengambil setiap perubahan dalam direktori kerja Anda, mencari tahu komit mana dalam rangkaian Anda yang memodifikasi baris itu, dan secara otomatis mengubah perubahan pada komit itu.
Jika ada ambiguitas (mis. Beberapa komit memodifikasi baris yang sama), maka absorb akan mengabaikan perubahan itu dan membiarkannya di direktori kerja Anda untuk diselesaikan secara manual.

Pada tingkat teknis, hg absorbtemukan semua perubahan yang tidak mengikat dan upaya untuk memetakan setiap baris yang diubah menjadi komit sebelumnya yang tidak ambigu.
Untuk setiap perubahan yang dapat dipetakan dengan rapi, perubahan yang tidak mengikat diserap ke dalam komit sebelumnya yang sesuai. Komitmen yang terpengaruh oleh operasi di-rebased secara otomatis.
Jika perubahan tidak bisa dipetakan ke komit sebelumnya yang tidak ambigu, itu dibiarkan tanpa komitmen dan pengguna bisa kembali ke alur kerja yang ada (misalnya menggunakan hg histedit).

Logika penulisan ulang otomatis hg absorbdiimplementasikan dengan mengikuti histori baris: Ini pada dasarnya berbeda dari pendekatan yang diambil oleh hg histeditatau git rebase, yang cenderung mengandalkan strategi penggabungan berdasarkan penggabungan 3 arah untuk mendapatkan versi baru dari file yang diberi beberapa masukan versi.

Pendekatan ini dikombinasikan dengan fakta bahwa hg absorb melompati perubahan dengan komit aplikasi yang ambigu berarti bahwa hg absorb tidak akan pernah mengalami konflik penggabungan!

Sekarang, Anda mungkin berpikir jika Anda mengabaikan baris dengan target aplikasi yang ambigu, tambalan akan selalu diterapkan dengan rapi menggunakan penggabungan 3 arah klasik. Pernyataan ini secara logis terdengar benar. Namun tidak: hg absorbdapat menghindari konflik penggabungan saat penggabungan dilakukan oleh hg histeditatau git rebase -iakan gagal.


0

Saya pikir chistedit(dibangun sejak Mercurial 2.3) adalah yang paling dekat dengan rebase -iMercurial murni ( chisteditadalah versi interaktif histedit). Setelah di histedit, foldpeta perintah ke rebase squashdan rollpeta perintah ke rebase fixup. Lihat dokumen histedit untuk info lebih lanjut.

Berikut ini contoh sederhananya. Asumsikan Anda memiliki yang berikut ini dan ingin memindahkan semua perubahan 1e21c4b1 ke revisi sebelumnya dan hanya menyimpan pesan revisi sebelumnya.

@  1e21c4b1 drees tip
|  A commit you want to squash
o  b4a738a4 drees
|  A commit
o  788aa028 drees
|  Older stuff

Anda dapat menjalankan hg chistedit -r b4a738a4untuk mengedit riwayat kembali ke b4a738a4. Di chistedit Anda kemudian mengarahkan kursor ke 1e21c4b1 dan tekan runtuk menunjukkan Anda ingin menggulung revisi itu. Perhatikan bahwa urutan dalam histedit (terlama ke terbaru) dibalik dari hg log(terbaru ke terlama).

#0  pick   160:b4a738a49916   A commit
#1  ^roll  161:1e21c4b1500c

Setelah memilih perubahan Anda, Anda kemudian memilih cuntuk mengikatnya. Hasilnya adalah sebagai berikut:

@ bfa4a3be drees tip | A commit o 788aa028 drees | Barang yang lebih tua

Jika Anda relatif baru mengenal mereka, maka histeditbisa menjadi pilihan yang lebih baik daripada chisteditkarena menyediakan deskripsi perintah dalam file histedit untuk referensi. Hanya perlu sedikit lebih banyak pengeditan untuk mengatur perintah menggunakan pengeditan teks biasa (seperti rebase normal).

Catatan, untuk menggunakan salah satu histeditatau chisteditAnda perlu menambahkan histeditekstensi di ~ / .hgrc Anda:

[extensions]
histedit =

Saya menyarankan chisteditkarena itu paling dekat rebase -idan bekerja di mana saja dalam sejarah. Jika Anda benar-benar hanya ingin memasukkan / mengubah revisi saat ini ke revisi sebelumnya, maka @G. Saran Demecki stripbisa bagus karena apa yang terjadi jelas. Itu dibangun sejak Mercuria 2.8. Untuk mendapatkan hasil yang setara seperti di atas, Anda dapat melakukan hal berikut:

hg strip .
hg add
hg commit --amend

Catatan strip, seperti histedit, perlu diaktifkan di ~ / .hgrc Anda:

[extensions]
strip =

0

Anggaplah Anda ingin memadatkan (menyatukan) 2 komit terbaru.

  1. Temukan nomor revisi

    hg log -G -l 3
    

    kemungkinan keluaran:

    @  changeset:   156:a922d923cf6f
    |  branch:      default
    |  tag:         tip
    |  user:        naXa!
    |  date:        Thu Dec 13 15:45:58 2018 +0300
    |  summary:     commit message 3
    |
    o  changeset:   155:5feb73422486
    |  branch:      default
    |  user:        naXa!
    |  date:        Thu Dec 13 15:22:15 2018 +0300
    |  summary:     commit message 2
    |
    o  changeset:   154:2e490482bd75
    |  branch:      default
    ~  user:        naXa!
       date:        Thu Dec 13 03:28:27 2018 +0300
       summary:     commit message 1
    
  2. Cabang reset lunak

    hg strip --keep -r 155
    
  3. Lakukan perubahan lagi

    hg commit -m "new commit message"
    

Catatan

stripmembutuhkan ekstensi bawaan untuk diaktifkan. Buat / edit ~/.hgrcfile konfigurasi dengan konten berikut:

[extensions]
strip = 

-1

Saya menggunakan:

hg phase --draft --force -r 267
...
hg rebase --dest 282 --source 267 --collapse
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.