Saya perhatikan bahwa dua blok dari perintah git berikut memiliki perilaku yang berbeda dan saya tidak mengerti mengapa.
Saya memiliki A
dan B
cabang yang berbeda dengan satucommit
---COMMIT--- (A)
\
--- (B)
Saya ingin rebase B
cabang pada yang terbaru A
(dan memiliki komitmen pada B
cabang)
---COMMIT--- (A)
\
--- (B)
Tidak masalah jika saya lakukan:
checkout B
rebase A
Tetapi jika saya lakukan:
checkout B
rebase --onto B A
Tidak berfungsi sama sekali, tidak ada yang terjadi. Saya tidak mengerti mengapa kedua perilaku itu berbeda.
Phpstorm git client menggunakan sintaks kedua, dan sepertinya bagi saya benar-benar rusak, itu sebabnya saya meminta masalah sintaks ini.
git
git-rebase
Xmanoux
sumber
sumber
Jawaban:
tl; dr
Sintaks yang benar untuk rebase
B
di atasA
menggunakangit rebase --onto
dalam kasus Anda adalah:atau rebase
B
di atasA
mulai dari komit yang merupakan induk dariB
direferensikan denganB^
atauB~1
.Jika Anda tertarik pada perbedaan antara
git rebase <branch>
dangit rebase --onto <branch>
baca terus.Quick: git rebase
git rebase <branch>
akan rebase cabang saat ini Anda telah memeriksa, direferensikan olehHEAD
, di atas terbaru komit yang dicapai dari<branch>
namun tidak dariHEAD
.Ini adalah kasus rebasing yang paling umum dan bisa dibilang salah satu yang membutuhkan perencanaan kurang di muka.
Dalam contoh ini,
F
danG
adalah komitmen yang dapat dijangkaubranch
tetapi tidak dariHEAD
. Mengatakangit rebase branch
akan mengambilD
, itu adalah komit pertama setelah titik percabangan, dan rebase itu (yaitu mengubah induknya ) di atas komit terbaru yang dapat dicapai daribranch
tetapi tidak dariHEAD
, yaituG
.Precise: git rebase --onto dengan 2 argumen
git rebase --onto
memungkinkan Anda melakukan rebase mulai dari komit tertentu . Ini memberi Anda kontrol tepat atas apa yang sedang direstrukturisasi dan di mana. Ini untuk skenario di mana Anda harus tepat.Misalnya, mari kita bayangkan bahwa kita perlu rebase
HEAD
tepat di atasF
mulai dariE
. Kami hanya tertarik untuk membawaF
ke cabang kerja kami sementara, pada saat yang sama, kami tidak ingin menyimpannyaD
karena mengandung beberapa perubahan yang tidak kompatibel.Dalam hal ini, kami akan mengatakan
git rebase --onto F D
. Ini berarti:Dengan kata lain, ubah induk dari
E
dariD
menjadiF
. Sintaksnyagit rebase --onto
adalahgit rebase --onto <newparent> <oldparent>
.Skenario lain yang sangat berguna adalah ketika Anda ingin dengan cepat menghapus beberapa komit dari cabang saat ini tanpa harus melakukan rebase interaktif :
Dalam contoh ini, untuk menghapus
C
danE
dari urutan yang Anda katakangit rebase --onto B E
, atau rebaseHEAD
di atas diB
mana orang tua yang lama beradaE
.The Surgeon: git rebase --onto dengan 3 argumen
git rebase --onto
bisa melangkah lebih jauh dalam hal presisi. Bahkan, ini memungkinkan Anda untuk rebase kisaran komit sewenang - wenang di atas yang lain.Ini sebuah contoh:
Dalam hal ini, kami ingin mengubah rentang yang tepat
E---H
di atasF
, mengabaikan ke manaHEAD
saat ini menunjuk. Kita dapat melakukannya dengan mengatakangit rebase --onto F D H
, yang berarti:Sintaksnya
git rebase --onto
dengan rentang komit kemudian menjadigit rebase --onto <newparent> <oldparent> <until>
. Kuncinya di sini adalah mengingat bahwa komit direferensikan oleh<until>
yang termasuk dalam jangkauan dan akan menjadi baruHEAD
setelah rebase selesai.sumber
<oldparent>
Nama rusak jika dua bagian rentang berada di cabang yang berbeda. Secara umum: "Sertakan setiap komit yang dapat dijangkau<until>
tetapi kecualikan setiap komit yang dapat dijangkau<oldparent>
."git rebase --onto <newparent> <oldparent>
adalah penjelasan terbaik tentang --tingkah laku yang pernah kulihat!--onto
opsi ini, tetapi ini membuatnya sangat jelas! Saya bahkan tidak mengerti bagaimana saya tidak bisa memahaminya sebelumnya: D Terima kasih untuk "tutorial" yang sangat baik :-)Ini semua yang perlu Anda ketahui untuk mengerti
--onto
:Anda mengalihkan orang tua pada komit, tetapi Anda tidak menyediakan sha dari komit, hanya sha dari orang tua (lama) itu.
sumber
Masukan singkat, diberikan:
Yang sama dengan (karena
--onto
mengambil satu argumen):Berarti rebase komit dalam kisaran (D, H] di atas F. Perhatikan rentang tersebut adalah eksklusif sisi kiri. Ini eksklusif karena lebih mudah untuk menentukan komit pertama dengan mengetik misalnya
branch
untuk membiarkangit
menemukan komit 1 yang berbeda daribranch
mis.D
Yang mengarah keH
.Kasus OP
Dapat diubah menjadi perintah tunggal:
Apa yang tampak seperti kesalahan di sini adalah penempatan
B
yang berarti "pindahkan beberapa komit yang mengarah ke cabangB
di atasB
". Pertanyaannya adalah apa itu "beberapa komitmen". Jika Anda menambahkan-i
flag, Anda akan melihatnya komit tunggal yang ditunjuk olehHEAD
. Komit dilompati karena sudah diterapkan ke--onto
targetB
sehingga tidak ada yang terjadi.Perintah tidak masuk akal dalam hal apapun di mana nama cabang diulang seperti itu. Ini karena rentang komit akan menjadi beberapa komit yang sudah ada di cabang itu dan selama rebase semuanya akan dilewati.
Penjelasan lebih lanjut dan penggunaan yang berlaku dari
git rebase <upstream> <branch> --onto <newbase>
.git rebase
default.Perluas salah satu:
Checkout otomatis setelah rebase.
Saat digunakan dengan cara standar, seperti:
Anda tidak akan melihat bahwa setelah rebase
git
pindahbranch
ke komit yang baru saja dirubah dan lakukangit checkout branch
(lihatgit reflog
riwayat). Apa yang menarik ketika argumen ke-2 adalah hash bukan nama cabang rebase masih berfungsi tetapi tidak ada cabang untuk dipindahkan sehingga Anda berakhir di "HEAD terpisah" bukannya diperiksa keluar untuk pindah cabang.Abaikan komitmen berbeda utama.
The
master
di--onto
diambil dari 1git rebase
argumen.Begitu praktis, bisa berupa komit atau cabang lainnya. Dengan cara ini Anda dapat membatasi jumlah komit rebase dengan mengambil komit terbaru dan meninggalkan komit divergen utama.
Akan rebase tunggal komit ditunjuk oleh
HEAD
kemaster
dan berakhir di "KEPALA terpisah".Hindari checkout eksplisit.
Default
HEAD
ataucurrent_branch
argumen diambil secara kontekstual dari tempat Anda berada. Inilah sebabnya mengapa kebanyakan orang melakukan checkout ke cabang yang ingin mereka rebase. Tetapi ketika argumen rebase ke-2 diberikan secara eksplisit, Anda tidak perlu checkout sebelum rebase untuk memberikannya secara implisit.Ini artinya Anda dapat rebase komit dan cabang dari mana saja . Jadi bersama dengan checkout otomatis setelah rebase. Anda tidak harus secara terpisah checkout cabang yang direbahkan sebelum atau setelah rebase.
sumber
Sederhananya,
git rebase --onto
pilih serangkaian commit dan rebases mereka pada komit yang diberikan sebagai parameter.Baca halaman manual untuk
git rebase
, cari "ke". Contohnya sangat bagus:Dalam hal ini Anda memberi tahu git untuk mengubah komit dari
topicA
menjaditopicB
di atasmaster
.sumber
Untuk lebih memahami perbedaan antara
git rebase
dangit rebase --onto
itu baik untuk mengetahui apa perilaku yang mungkin untuk kedua perintah.git rebase
memungkinkan kita untuk memindahkan komit kita di atas cabang yang dipilih. Seperti di sini:dan hasilnya adalah:
git rebase --onto
lebih tepat. Hal ini memungkinkan kita untuk memilih komit tertentu di mana kita ingin memulai dan juga di mana kita ingin menyelesaikan. Seperti di sini:dan hasilnya adalah:
Untuk mendapatkan rincian lebih lanjut, saya sarankan Anda untuk membaca artikel saya sendiri tentang git rebase --tinjauan umum
sumber
git rebase --onto F D
sebagai set anak dari orangtua D sebagai F , bukan?Untuk
onto
Anda memerlukan dua cabang tambahan. Dengan perintah itu Anda dapat menerapkan komit daribranchB
yang didasarkan padabranchA
ke cabang lain misalnyamaster
. Dalam contoh di bawahbranchB
ini didasarkan padabranchA
dan Anda ingin menerapkan perubahanbranchB
padamaster
tanpa menerapkan perubahanbranchA
.dengan menggunakan perintah:
Anda akan mengikuti hierarki komit.
sumber
rebase --onto branchA branchB
akan menempatkan seluruh cabang master di kepala branchA?checkout branchB: rebase --onto master branchA
?Ada kasus lain di mana
git rebase --onto
sulit untuk dipahami: ketika Anda rebase ke komit yang dihasilkan dari pemilih perbedaan simetris (tiga titik '...
')Git 2.24 (Q4 2019) melakukan pekerjaan yang lebih baik dalam mengelola kasus itu:
Lihat komit 414d924 , komit 4effc5b , komit c0efb4c , komit 2b318aa (27 Agustus 2019), dan komit 793ac7e , komit 359eceb (25 Agustus 2019) oleh Denton Liu (
Denton-L
) .Dibantu-oleh: Eric Sunshine (
sunshineco
) , Junio ​​C Hamano (gitster
) , Ævar Arnfjörð Bjarmason (avar
) , dan Johannes Schindelin (dscho
) .Lihat komit 6330209 , komit c9efc21 (27 Agustus 2019), dan komit 4336d36 (25 Agustus 2019) oleh Ævar Arnfjörð Bjarmason ( Dibantu-oleh: Eric Sunshine ( ,
avar
).sunshineco
) Junio ​​C Hamano (gitster
) , Ævar Arnfjörð Bjarmason (avar
) , dan Johannes Schindelin (dscho
) .(Digabung oleh Junio ​​C Hamano -
gitster
- dalam komit 640f9cd , 30 Sep 2019)Pada titik ini, baca " Apa perbedaan antara titik ganda '
..
' dan titik tiga"...
"dalam rentang komit Git? "Di sini: "
master...
" mengacu padamaster...HEAD
, yaituB
: KEPALA adalah sisi KEPALA (saat ini sedang diperiksa): Anda sedang menujuB
.Apa yang kamu rebasing? Setiap komit yang tidak dikuasai, dan dapat dijangkau dari
side
cabang: hanya ada satu komit yang cocok dengan deskripsi tersebut:D
... yang sudah ada di atasB
!Sekali lagi, sebelum Git 2.24, hal seperti itu
rebase --onto
akan berakibatD
selalu diubah, apa pun yang terjadi.Itu mirip dengan
rebase --onto B A
OP, yang tidak melakukan apa pun.dan perintah yang gagal adalah
A
rebase --onto C F topic
berarti setiap komit setelahF
, dapat dijangkau olehtopic
KEPALA: ituG
hanya, bukanF
dirinya sendiri.Penerusan cepat dalam kasus ini akan termasuk
F
dalam cabang rebased, yang salah.sumber