Ardışık olmayan iki taahhüdü nasıl ezebilirim?


183

Git içindeki tüm yeniden basma özelliği için biraz yeniyim. Diyelim ki aşağıdaki taahhütleri yerine getirdim:

A -> B -> C -> D

Daha sonra, Deklenen yeni koda bağlı bir düzeltme içerdiğini Ave bu taahhütlerin bir arada olduğunu fark ediyorum . Nasıl ezmeye do A& Daraya ve izni Bve Cyalnız?

Yanıtlar:


258

git rebase --interactiveD'yi B'den önce çalıştırabilir ve yeniden sıralayabilir ve D'yi A'ya sıkıştırabilirsiniz.

Git bir düzenleyici açar ve bunun gibi bir dosya görürsünüz, ör: git rebase --interactive HEAD~4

pick aaaaaaa Commit A
pick bbbbbbb Commit B
pick ccccccc Commit C
pick ddddddd Commit D

# Rebase aaaaaaa..ddddddd onto 1234567 (4 command(s))
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

Şimdi şuna benzeyen dosyayı değiştirirsiniz:

pick aaaaaaa Commit A
squash ddddddd Commit D
pick bbbbbbb Commit B
pick ccccccc Commit C

Ve git şimdi A ve D değişikliklerini tek bir taahhütte birleştirecek ve daha sonra B ve C'yi koyacaktır. D yerine kaydetme mesajını saklamak istemediğinizde squash, fixupanahtar kelimeyi kullanırsınız . Daha fazla fixupbilgi için git rebasedokümanlara başvurabilir veya iyi yanıtları olan bu soruya göz atabilirsiniz .


5
Başlangıçta "A'ya rebase D, D'yi A'ya squash et, sonra B'yi DA'ya rebase" olarak okudum. Cevaptan, bunun bir metin düzenleyicide satırların yeniden sıralanmasıyla yapılabileceği açık değildir.
Victor Sergienko

3
There is no tracking information for the current branchŞubeniz yerelse, yeniden basarken hata alırsınız . Bu durumda böyle, çalışmak istediğiniz kaydedilmesini sayısını belirtmek gerekir: git rebase -i HEAD~4. Bu cevaba bakınız .
johndodo

1
Etkileşimli modu (git rebase -i) yıllarca kullanıyorum, sadece yeniden sıralanabileceğini fark ettim . Teşekkürler 🤟🏻
CalvinChe

43

Not: Sonuçları bilmediğiniz sürece başka bir repoya itilmiş olan taahhütleri hiçbir şekilde değiştirmemelisiniz .

git log --oneline -4

D commit_message_for_D
C commit_message_for_C
B commit_message_for_B
A commit_message_for_A

git rebase --interactive

pick D commit_message_for_D
pick C commit_message_for_C
pick B commit_message_for_B
pick A commit_message_for_A

Tip i(VIM'i ekleme moduna getirin)

Listeyi şu şekilde görünecek şekilde değiştirin (İşleme iletisini kaldırmanız veya eklemeniz gerekmez). Yanlış yazmayın squash! :

pick C commit_message_for_C
pick B commit_message_for_B
pick A commit_message_for_A
squash D

Tür Escsonra ZZ(Kaydet ve çıkış VIM)

# This is a combination of 2 commits.
# The first commit's message is:

commit_message_for_D

# This is the 2nd commit message:

commit_message_for_A

tip i

Metni, yeni yürütme iletisinin görünmesini istediğiniz şekilde değiştirin. Bunu taahhüt değişikliklerin bir açıklamadan ibaret tavsiye Ave D:

new_commit_message_for_A_and_D

Tür EscsonraZZ

git log --oneline -4

E new_commit_message_for_A_and_D
C commit_message_for_C
B commit_message_for_B

git show E

(You should see a diff showing a combination of changes from A and D)

Şimdi yeni bir taahhüt oluşturdunuz E. Taahhüt eder Ave Dartık geçmişinizde değildir ancak gitmez. Bu noktada ve bir süre için onları kurtarabilirsiniz git rebase --hard D( git rebase --hardyerel değişiklikleri yok edeceksiniz! ).


3

SourceTree kullananlar için :

Taahhütleri henüz itmediğinizden emin olun.

  1. Depo> Etkileşimli Rebase ...
  2. D'yi (yeni işlem) doğrudan A'nın (daha eski işlem) üzerinde olacak şekilde sürükleyin
  3. D taahhüdünün vurgulandığından emin olun
  4. Tıklayın Squash with previous

1

Etkileşimli rebase, ana dalınızda 20-30 taahhüt ve / veya birkaç birleşimden oluşan büyük bir özellik dalı olana ve dalınızda işlem yaparken çakışmaları giderene kadar iyi çalışır. Hatta tarih boyunca benim kaydedilmesini bulma ve değiştirme ile pickbirlikte squashburada çalıştı etmez. Bu yüzden başka bir yol arıyordum ve bu makaleyi buldum . Bunu ayrı dalda çalışmak için değişikliklerimi yaptım:

git checkout master
git fetch
git pull
git merge branch-name
git reset origin/master
git branch -D branch-name
git checkout -b branch-name
git add --all
#Do some commit
git push -f --set-upstream origin branch-name

Bundan önce, master + sabitleme çatışmalarından 2-3 birleştirme ile yaklaşık ~ 30 taahhüt ile çekme isteğimi aldım. Ve bundan sonra bir taahhüt ile net PR aldım.

PS burada otomobilde bu adımları yapmak için bash betiği .


Bu makaledeki ilk çözüm gerçekten güzel, bağlantı için teşekkürler
Hoody

-1

$ git ödeme yöneticisi

$ git log --oneline

D
C
B
A

$ git rebase --onto KAFA ^ ^ ^ KAFA ^

$ git log --oneline

D
A

Sanırım demek istiyorsun --oneline? Ve görünüşe göre düşmüşsünC ve BOP niyeti ne değildir, hangi.
bstpierre

Benim için çalışmadı. Hem HEAD'ımı hem de efendimi A'ya indirdi, ancak D'yi A ( git show A) ile birleştirmedi ve D-C ve B ref-logumda kayboldu. Zorunda kaldı git rebase Dgeri almak için.
Nate
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.