2010-10-13 13 views
93

Jestem trochę nowy w całej funkcji ponownego umieszczania w git. Załóżmy, że zrobiłem następujące zobowiązuje:Jak zgnieść dwie nieudane zatwierdzenia?

A -> B -> C -> D 

Następnie, zdaję sobie sprawę, że D zawiera poprawkę, która zależy od jakiegoś nowego kodu dodanego w A, i że te rewizje należą razem. Jak zgrupować razem i pozostawić oddzielnie i pozostawić tylko?

Odpowiedz

120

można uruchomić git rebase --interactive i uporządkować D przed B i D do squasha A.

Git otworzy edytor, a zobaczysz plik tak:

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 

Teraz zmienić plik wygląda to tak:

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

i git będzie teraz łączą zmiany a i D razem do jednej popełnić, i umieścić B i C potem. Jeśli nie chcesz zachować komunikatu zatwierdzenia D, możesz również użyć słowa kluczowego "napraw".

+3

Początkowo czytałem to jako "rebase D na A, squash D na A, a następnie na B na DA". Z odpowiedzi nie wynika jasno, że można to zrobić poprzez zmianę kolejności linii w edytorze tekstów. –

-1

$ git checkout mistrz

$ git log --oneline

D 
C 
B 
A 

$ git rebase --onto HEAD HEAD ^^^^

$ git log --oneline

D 
A 
+0

Myślę, że masz na myśli '--oneline'? Wygląda na to, że upuściłeś 'C' i' B', co nie jest zamierzeniem OP. – bstpierre

+0

Nie działa dla mnie. Przesunął on zarówno HEAD, jak i master do A, ale nie scałował D w A ('git show A'), a D, C i B zaginęły w moim dzienniku ref. Musiałam 'git rebase D' wrócić. – Nate

38

Uwaga: Powinieneś nie zmieniać zobowiązań, które zostały pchnięte do innego repo w dowolny sposób , chyba że znasz consequences.

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 

Rodzaj i (Put Vima w trybie wstawiania)

zmienić listę wyglądać tak (Nie trzeba usunąć lub obejmować komunikat zatwierdzenia). Nie wprowadzaj błędów w pisowni squash!:

pick C commit_message_for_C 
pick B commit_message_for_B 
pick A commit_message_for_A 
squash D 

Rodzaj Esc następnie ZZ (Save and exit 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 

Rodzaj i

zmienić tekst, co chcesz popełnić nowa wiadomość wyglądać.Polecam to być opis zmian w popełnić A i D:

new_commit_message_for_A_and_D 

Rodzaj Esc następnie ZZ

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) 

Utworzono nowy commit E. Zobowiązania A i D nie są już w Twojej historii, ale ich nie ma. Nadal możesz je odzyskać w tym momencie i przez jakiś czas przez git rebase --hard D (git rebase --hard zniszczą wszelkie zmiany lokalne!).

3

Dla osób korzystających SourceTree:

Upewnij się, że nie mają już pchnął zobowiązuje.

  1. Repository> Interaktywny rebase ...
  2. Drag D (nowsze popełnić), aby być bezpośrednio powyżej A (starszy popełnić)
  3. Producent pewien popełnić D jest podświetlona
  4. Kliknij Squash with previous
Powiązane problemy