Dokumentasirebase
Git untuk perintah ini cukup singkat:
--preserve-merges
Instead of ignoring merges, try to recreate them.
This uses the --interactive machinery internally, but combining it
with the --interactive option explicitly is generally not a good idea
unless you know what you are doing (see BUGS below).
Jadi apa yang sebenarnya terjadi ketika Anda menggunakannya --preserve-merges
? Apa bedanya dengan perilaku default (tanpa tanda itu)? Apa artinya "menciptakan kembali" gabungan, dll.
git
git-rebase
Chris
sumber
sumber
git --rebase-merges
pada akhirnya akan menggantikan yang lamagit --preserve-merges
. Lihat jawaban saya di bawah iniJawaban:
Seperti halnya git rebase normal, git dengan
--preserve-merges
pertama mengidentifikasi daftar commit yang dibuat dalam satu bagian dari grafik commit, dan kemudian mengulang komit-komit tersebut di atas bagian lain. Perbedaan--preserve-merges
terkait dengan komit yang dipilih untuk diputar ulang dan bagaimana putar ulang bekerja untuk gabungan bergabung.Untuk lebih eksplisit tentang perbedaan utama antara rebase normal dan penggabungan-mempertahankan:
git checkout <desired first parent>
), sedangkan rebase normal tidak perlu khawatir tentang itu.Pertama saya akan mencoba untuk menggambarkan "cukup tepat" apa yang
--preserve-merges
dilakukan rebase , dan kemudian akan ada beberapa contoh. Seseorang tentu saja bisa mulai dengan contoh-contoh, jika itu tampaknya lebih bermanfaat.Algoritma dalam "Brief"
Jika Anda ingin benar-benar memasuki gulma, unduh sumber git dan jelajahi file tersebut
git-rebase--interactive.sh
. (Rebase bukan bagian dari inti C Git, melainkan ditulis dalam bash. Dan, di belakang layar, ia berbagi kode dengan "rebase interaktif".)Tapi di sini saya akan membuat sketsa apa yang saya pikir adalah esensi dari itu. Untuk mengurangi jumlah hal yang perlu dipikirkan, saya telah mengambil beberapa kebebasan. (mis. Saya tidak mencoba menangkap dengan akurasi 100% urutan yang tepat di mana perhitungan dilakukan, dan mengabaikan beberapa topik yang tampak kurang sentral, misalnya apa yang harus dilakukan tentang komit yang telah dipilih dengan ceri di antara cabang).
Pertama, perhatikan bahwa rebase non-penggabungan agak sederhana. Lebih atau kurang:
Rebase
--preserve-merges
relatif rumit. Ini sesederhana yang saya bisa membuatnya tanpa kehilangan hal-hal yang tampaknya cukup penting:Rebase dengan
--onto C
argumen harus sangat mirip. Hanya alih-alih mulai melakukan komit di HEAD of B, Anda mulai melakukan komit di HEAD of C. (Dan gunakan C_new bukan B_new.)Contoh 1
Misalnya, ambil grafik komit
m adalah gabungan komitmen dengan orang tua E dan G.
Misalkan kita topik rebased (H) di atas master (C) menggunakan rebase normal, non-penggabungan melestarikan. (Sebagai contoh, checkout topic; rebase master .) Dalam hal ini, git akan memilih commit berikut untuk replay:
dan kemudian perbarui grafik komit seperti:
(D 'adalah ekuivalen replayed dari D, dll.)
Perhatikan bahwa komit gabungan m tidak dipilih untuk diputar ulang.
Jika kita malah melakukan
--preserve-merges
rebase H di atas C. (Sebagai contoh, topik checkout; rebase --preserve-merge master .) Dalam kasus baru ini, git akan memilih komit berikut untuk diputar ulang:Sekarang m itu dipilih untuk replay. Juga perhatikan bahwa menggabungkan orang tua E dan G dipilih untuk dimasukkan sebelum menggabungkan komit m.
Berikut adalah grafik komit yang dihasilkan:
Sekali lagi, D 'adalah versi D. (sama diciptakan kembali) dari D. Sama untuk E', dll. Setiap komit tidak pada master telah diputar ulang. Baik E dan G (gabungan orang tua m) telah diciptakan kembali sebagai E 'dan G' untuk berfungsi sebagai orang tua m '(setelah rebase, sejarah pohon masih tetap sama).
Contoh 2
Tidak seperti rebase normal, rebase pelestarian gabungan dapat membuat banyak anak-anak dari kepala hulu.
Sebagai contoh, pertimbangkan:
Jika kita rebase H (topik) di atas C (master), maka komit yang dipilih untuk rebase adalah:
Dan hasilnya seperti ini:
Contoh 3
Dalam contoh di atas, komit gabungan dan kedua orang tuanya adalah komit yang diputar ulang, alih-alih dari orangtua asli yang dimiliki komit gabungan. Namun, dalam rebases lain, komit gabungan yang diputar dapat berakhir dengan orang tua yang sudah ada di grafik komit sebelum penggabungan.
Sebagai contoh, pertimbangkan:
Jika kita mengubah topik menjadi master (mempertahankan penggabungan), maka komitmen untuk memutar ulang akan menjadi
Grafik komit yang ditulis ulang akan terlihat seperti ini:
Di sini, replayed merge commit m 'membuat orang tua yang sudah ada sebelumnya dalam grafik commit, yaitu D (HEAD of master) dan E (salah satu orang tua dari gabungan mate commit m).
Contoh 4
Rebase pengawetan gabungan dapat membingungkan dalam kasus "komit kosong" tertentu. Setidaknya ini benar hanya beberapa versi git yang lebih lama (mis. 1.7.8.)
Ambil grafik komit ini:
Perhatikan bahwa komit m1 dan m2 harus menggabungkan semua perubahan dari B dan F.
Jika kita mencoba melakukan
git rebase --preserve-merges
H (topik) ke D (master), maka komit berikut dipilih untuk diputar ulang:Perhatikan bahwa perubahan (B, F) yang disatukan dalam m1 harus sudah dimasukkan ke dalam D. (Perubahan itu harus dimasukkan ke dalam m2, karena m2 menggabungkan anak-anak B dan F.) Oleh karena itu, secara konseptual, memutar ulang m1 di atas D mungkin harus berupa no-op atau membuat komit kosong (yaitu komis di mana perbedaan antara revisi berturut-turut kosong).
Sebaliknya, git dapat menolak upaya untuk memutar ulang m1 di atas D. Anda bisa mendapatkan kesalahan seperti:
Sepertinya orang lupa memberikan flag ke git, tetapi masalah mendasarnya adalah bahwa git tidak suka membuat commit kosong.
sumber
git rebase --preserve-merges
ini jauh lebih lambat daripadarebase
tanpanya--preserve-merges
. Apakah itu efek samping dari menemukan komitmen yang tepat? Adakah yang bisa dilakukan seseorang untuk mempercepatnya? (Ngomong-ngomong ... terima kasih untuk jawaban yang sangat terperinci!)Git 2.18 (Q2 2018) akan sangat meningkatkan
--preserve-merge
opsi dengan menambahkan opsi baru."
git rebase
" belajar "--rebase-merges
" untuk mentransplantasikan seluruh topologi grafik commit di tempat lain .(Catatan: Git 2.22, Q2 2019, sebenarnya sudah usang
--preserve-merge
, dan Git 2.25, Q1 2020, berhenti mengiklankannya digit rebase --help
keluaran " " )Lihat komit 25cff9f , komit 7543f6f , komit 1131ec9 , komit 7ccdf65 , komit 537e7d6 , komit a9be29c , komit 8f6aed7 , komit 1644c73 , komit d1e8b01 , komit 4c68e7d , komit 9055e40 , komit cb5206e , komit a01c2a5 , komit 2f6b1d1 , komit bf5c057 (25 Apr 2018) oleh Johannes Schindelin (
dscho
) .Lihat commit f431d73 (25 Apr 2018) oleh Stefan Beller (
stefanbeller
) .Lihat komit 2429335 (25 Apr 2018) oleh Phillip Wood (
phillipwood
) .(Digabung oleh Junio C Hamano -
gitster
- di komit 2c18e6a , 23 Mei 2018)git rebase
halaman buku panduan sekarang memiliki bagian lengkap yang didedikasikan untuk memunculkan kembali sejarah dengan penggabungan .Ekstrak:
Lihat komit 1644c73 untuk contoh kecil:
Apa bedanya dengan
--preserve-merge
?Commit 8f6aed7 menjelaskan:
Dan oleh "Anda benar-benar", penulis menyebut dirinya: Johannes Schindelin (
dscho
) , yang merupakan alasan utama (dengan beberapa pahlawan lainnya - Hannes, Steffen, Sebastian, ...) bahwa kami memiliki Git Untuk Windows (meskipun kembali pada hari - 2009 - itu tidak mudah ).Dia bekerja di Microsoft sejak September 2015 , yang masuk akal mengingat Microsoft sekarang banyak menggunakan Git dan membutuhkan layanannya.
Itu tren dimulai pada 2013 sebenarnya, dengan TFS . Sejak itu, Microsoft mengelola repositori Git terbesar di planet ini ! Dan, sejak Oktober 2018, Microsoft mengakuisisi GitHub .
Anda dapat melihat Johannes berbicara dalam video ini untuk Git Merge 2018 pada April 2018.
Di sini Jonathan berbicara tentang Andreas Schwab dari Suse.
Anda dapat melihat beberapa diskusi mereka pada tahun 2012 .
(Skrip gunting taman Git direferensikan dalam tambalan ini di commit 9055e40 )
Git 2.19 (Q3 2018) meningkatkan
--rebase-merges
opsi baru dengan membuatnya berfungsi--exec
.Opsi "
--exec
" untuk "git rebase --rebase-merges
" menempatkan perintah exec di tempat yang salah, yang telah diperbaiki.Lihat komit 1ace63b (09 Agustus 2018), dan komit f0880f7 (06 Agt 2018) oleh Johannes Schindelin (
dscho
) .(Digabung oleh Junio C Hamano -
gitster
- dalam commit 750eb11 , 20 Agu 2018)Git 2.22 (Q2 2019) memperbaiki penggunaan referensi / ditulis ulang / hierarki untuk menyimpan status perantara rebase, yang secara inheren membuat hierarki per worktree.
Lihat komit b9317d5 , komit 90d31ff , komit 09e6564 (07 Mar 2019) oleh Nguyễn Thái Ngọc Duy (
pclouds
) .(Digabung oleh Junio C Hamano -
gitster
- dalam komit 917f2cd , 09 Apr 2019)a9be29c (sequencer: make ref yang dihasilkan oleh
label
perintah worktree-local, 2018-04-25, Git 2.19) ditambahkanrefs/rewritten/
sebagai ruang referensi per-worktree.Sayangnya (salah saya) ada beberapa tempat yang perlu diperbarui untuk memastikan itu benar-benar per-worktree.
Dengan Git 2.24 (Q4 2019), "
git rebase --rebase-merges
" belajar untuk mendorong berbagai strategi penggabungan dan memberikan opsi khusus strategi kepada mereka.Lihat commit 476998d (04 Sep 2019) oleh Elijah Newren (
newren
) .Lihat komit e1fac53 , komit a63f990 , komit 5dcdd74 , komit e145d99 , komit 4e6023b , komit f67336d , komit a9c7107 , komit b8c6f24 , komit d51b771 , komit c248d32 , komit 8c1e240 , komit 5efed0e , komit 68b54f6 , komit 2e7bbac , komit 6180b20 , berkomitmen d5b581f (31 Jul 2019) olehJohannes Schindelin (
dscho
) .(Digabung oleh Junio C Hamano -
gitster
- dalam komit 917a319 , 18 Sep 2019)Dengan Git 2.25 (Q1 2020), logika yang digunakan untuk memberi tahu worktree local dan repositori global terpisah adalah tetap, untuk memfasilitasi penggabungan-penggabungan.
Lihat komit f45f88b , komit c72fc40 , komit 8a64881 , komit 7cb8c92 , komit e536b1f (21 Okt 2019) oleh SZEDER Gábor (
szeder
) .(Digabung oleh Junio C Hamano -
gitster
- di commit db806d7 , 10 Nov 2019)sumber
--preserve-merges
tidak benar-benar "mempertahankan" gabungan seperti yang Anda inginkan, itu sangat naif. Ini memungkinkan Anda untuk melestarikan gabungan komit & orang tua mereka melakukan hubungan sambil memberi Anda fleksibilitas rebase interaktif. Fitur baru ini luar biasa & jika bukan karena jawaban SO yang ditulis dengan baik ini, saya tidak akan tahu!