Jak mogę scalić dwa commity w jeden, jeśli już uruchomiłem rebase?

Próbuję połączyć 2 commity w 1, więc wykonałem "squashing commits with rebase" z git ready .

I ran

git rebase --interactive HEAD~2

W edytorze wynikowym zmieniam pick na squash, a następnie save-quit, ale rebase się nie powiedzie z błędem

Nie można 'squasha' bez wcześniejszego commita

Teraz, gdy moje drzewo pracy osiągnęło ten stan, Mam problem z odzyskaniem zdrowia. Polecenie git rebase --interactive HEAD~2 kończy się niepowodzeniem z

Interaktywny rebase już rozpoczęte

And git rebase --continue fails with

Nie można 'squasha' bez wcześniejszego commita

 1017
Author: JGallardo, 2010-04-02

11 answers

Podsumowanie

Komunikat o błędzie

Nie można 'squasha' bez wcześniejszego commita

Oznacza, że prawdopodobnie próbowałeś " zgnieść się w dół."Git zawsze zgniata nowszy commit w starszy commit lub "w górę", jak pokazano na interaktywnej liście zadań rebase, czyli w commit w poprzedniej linii. Zmiana polecenia w pierwszej linii listy todo na squash zawsze spowoduje ten błąd, ponieważ nie ma nic dla pierwszego commitu do squasha do.

The Fix

Najpierw wróć do miejsca, w którym zacząłeś

$ git rebase --abort

Powiedz, że Twoja historia jest

$ git log --pretty=oneline
a931ac7c808e2471b22b5bd20f0cad046b1c5d0d c
b76d157d507e819d7511132bdb5a80dd421d854f b
df239176e1a2ffac927d8b496ea00d5488481db5 a

Oznacza to, że a był pierwszym commitem, potem b, a na końcu c. po popełnieniu c decydujemy się na zmiażdżenie b i c razem:

(Uwaga: uruchamianie git log przekierowuje swoje wyjście do pagera, less domyślnie na większości platform. Aby zamknąć pager i powrócić do wiersza polecenia, naciśnij klawisz q.)

Bieganie git rebase --interactive HEAD~2 daje Ci edytor z

pick b76d157 b
pick a931ac7 c

# Rebase df23917..a931ac7 onto df23917
#
# 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
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

(zauważ, że ta lista zadań jest w odwrotnej kolejności w porównaniu z wyjściem git log.)

Zmiana b pick na squash spowoduje błąd, który widziałeś, ale jeśli zamiast tego zmiażdżysz c na B (nowszy commit na starszy lub "zmiażdżysz w górę"), zmieniając listę todo na

pick   b76d157 b
squash a931ac7 c

I zapisz-rezygnując z edytora, dostaniesz innego redaktora, którego zawartość jest

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

b

# This is the 2nd commit message:

c

Kiedy zapisujesz i zamykasz, zawartość edytowanego pliku staje się komunikat commit nowego commita:

$ git log --pretty=oneline
18fd73d3ce748f2a58d1b566c03dd9dafe0b6b4f b and c
df239176e1a2ffac927d8b496ea00d5488481db5 a

Uwaga O Przepisywaniu Historii

Interaktywny rebase przepisuje historię. Próba pchnięcia do pilota, który zawiera starą historię, nie powiedzie się, ponieważ nie jest to przewijanie do przodu.

Jeśli branch, który rebasowałeś jest gałęzią tematyczną lub fabularną , w której pracujesz sam, nic wielkiego. Przejście do innego repozytorium będzie wymagało opcji --force, lub alternatywnie możesz być w stanie, w zależności od zdalnego uprawnienia repozytorium, aby najpierw usunąć starą gałąź, a następnie wypchnąć zrebasowaną wersję. Przykłady tych poleceń, które potencjalnie mogą zniszczyć pracę, są poza zakresem tej odpowiedzi.

Przepisywanie już opublikowanej historii na gałęzi, w której pracujesz z innymi ludźmi bez Bardzo {40]} dobry powód, taki jak wyciek hasła lub inne wrażliwe szczegóły, wymusza pracę na współpracownikach i jest antyspołeczny i denerwuje innych deweloperów. "Odzyskiwanie Z sekcji Upstream Rebase" w dokumentacji git rebase wyjaśnia, z dodanym naciskiem.

Rebasing (lub jakakolwiek inna forma przepisywania) gałęzi, na której inni oparli pracę, jest złym pomysłem: każdy, kto jest dalej, jest zmuszony ręcznie naprawić swoją historię. Ta sekcja wyjaśnia, jak zrobić poprawkę z punktu widzenia downstream. prawdziwą poprawką byłoby jednak uniknięcie rebasingu w upstream.

 1562
Author: Greg Bacon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-01 23:03:34

Jeśli istnieje wiele commitów, możesz użyć git rebase -i, aby rozdzielić dwa commity w jeden.

Jeśli są tylko dwa commity, które chcesz połączyć, i są to "ostatnie dwa", następujące polecenia mogą być użyte do połączenia dwóch commitów w jeden:

git reset --soft "HEAD^"
git commit --amend
 347
Author: user3828059,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-05 21:42:47

Rebase: You ain ' t Gonna Need It:

Prostszy sposób na najczęstszy scenariusz.

W większości przypadków:

Właściwie, jeśli chcesz tylko po prostu połączyć kilka ostatnich commitów w jeden, ale nie musisz drop, reword i inne prace rebase.

Możesz po prostu zrobić:

git reset --soft "HEAD~n"
  • zakładając, że ~n jest liczbą commitów do un-commit (tj. ~1, ~2,...)

Następnie użyj następującego polecenia, aby zmodyfikować commit wiadomość.

git commit --amend

Który jest dokładnie taki sam jak długi zakres squash i jeden pick.

I działa dla n commitów, ale nie tylko dla dwóch commitów jak powyżej.

 58
Author: pambda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-26 14:55:20

Najpierw powinieneś sprawdzić ile masz commitów:

git log

Istnieją dwa statusy:

Po pierwsze są tylko dwa commity:

Na przykład:

commit A
commit B

(w tym przypadku nie możesz użyć git rebase do zrobienia) musisz wykonać następujące czynności.

$ git reset --soft HEAD^1

$ git commit --amend

Innym jest to, że istnieje więcej niż dwa commity; chcesz połączyć commity C i D.

Na przykład:

commit A
commit B
commit C
commit D

(pod tym warunkiem możesz użyć git rebase)

git rebase -i B

I użycie "squash" do zrobienia. Reszta jest bardzo łatwa. Jeśli nadal nie wiesz, przeczytaj http://zerodie.github.io/blog/2012/01/19/git-rebase-i/

 51
Author: Haimei,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-27 19:01:46

Zakładając, że jesteś w swojej gałęzi tematycznej. Jeśli chcesz połączyć ostatnie 2 commity w jeden i wyglądać jak bohater, oddziel commit tuż przed dokonaniem ostatnich dwóch commitów.

git checkout -b temp_branch HEAD^2

Następnie squash zatwierdzi drugą gałąź w nowej gałęzi:

git merge branch_with_two_commits --squash

To wprowadzi zmiany, ale ich nie zatwierdzi. Więc po prostu je popełnij i jesteś skończony.

git commit -m "my message"

Teraz możesz scalić nową gałąź tematyczną z powrotem do swojej głównej gałęzi.

 26
Author: Homan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-26 20:08:20

Możesz anulować rebase za pomocą

git rebase --abort

I po ponownym uruchomieniu interaktywnego polecenia rebase ' squash; commit musi znajdować się poniżej wybierz commit na liście

 22
Author: Leom Burke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-01 20:59:48

Często używam git reset --mixed aby przywrócić wersję bazową przed wieloma commitami, które chcesz scalić, następnie robię nowy commit, w ten sposób mogę pozwolić, aby twój commit był najnowszy, upewnić się, że Twoja wersja jest głowa po wciśnięciu do serwera.

commit ac72a4308ba70cc42aace47509a5e
Author: <[email protected]>
Date:   Tue Jun 11 10:23:07 2013 +0500

    Added algorithms for Cosine-similarity

commit 77df2a40e53136c7a2d58fd847372
Author: <[email protected]>
Date:   Tue Jun 11 13:02:14 2013 -0700

    Set stage for similar objects

commit 249cf9392da197573a17c8426c282
Author: Ralph <[email protected]>
Date:   Thu Jun 13 16:44:12 2013 -0700

    Fixed a bug in space world automation

Jeśli chcę połączyć dwa commity w jeden, najpierw używam :

git reset --mixed 249cf9392da197573a17c8426c282

"249cf9392da197573a17c8426c282" była trzecią wersją, również jest twoją wersją bazową przed połączeniem, po tym robię nowy commit :

git add .
git commit -m 'some commit message'

To wszystko, nadzieja jest innym sposobem dla wszystkich.

Od git reset --help:

 --mixed
     Resets the index but not the working tree (i.e., the changed files are
     preserved but not marked for commit) and reports what has not been
     updated. This is the default action.
 13
Author: VinceStyling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-18 15:03:39

$ git rebase --abort

Uruchom ten kod w dowolnym momencie, jeśli chcesz cofnąć rebase git

$ git rebase -i HEAD~2

Aby ponownie zastosować ostatnie dwa commity. Powyższe polecenie otworzy Edytor kodu

  • [ najnowszy commit będzie na dole ]. Zmień ostatni / align = "left" / Ponieważ squash połączy się z poprzednim commitem.
  • następnie naciśnij klawisz esc i wpisz :wq, aby zapisać i zamknąć

Po :wq będziesz w aktywnej rebase mode

Uwaga: otrzymasz inny edytor, jeśli nie ma ostrzeżeń/komunikatów o błędach, jeśli jest błąd lub ostrzeżenie inny edytor nie pojawi się, możesz przerwać uruchamianie $ git rebase --abort jeśli widzisz błąd lub ostrzeżenie, po prostu kontynuuj uruchamiając $ git rebase --continue

Zobaczysz swoją wiadomość 2 commit. Wybierz jeden lub napisz własną wiadomość zatwierdzającą, Zapisz i zakończ [: wq]

Uwaga 2: Może być konieczne wymuszenie wypchnięcia zmian do zdalnego repo, jeśli uruchomisz polecenie rebase

$ git push -f

$ git push -f origin master

 11
Author: Gnanasekar S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-20 21:54:51

Jeśli twoja gałąź mastergit log wygląda następująco:

commit ac72a4308ba70cc42aace47509a5e
Author: <[email protected]>
Date:   Tue Jun 11 10:23:07 2013 +0500

    Added algorithms for Cosine-similarity

commit 77df2a40e53136c7a2d58fd847372
Author: <[email protected]>
Date:   Tue Jun 11 13:02:14 2013 -0700

    Set stage for similar objects

commit 249cf9392da197573a17c8426c282
Author: Ralph <[email protected]>
Date:   Thu Jun 13 16:44:12 2013 -0700

    Fixed a bug in space world automation

I chcesz połączyć dwa ostatnie commity, wykonaj następujące proste kroki:

  1. pierwszy, aby być po bezpiecznej stronie, drugi ostatni commit w oddzielnej gałęzi. Możesz nazwać oddział cokolwiek. git checkout 77df2a40e53136c7a2d58fd847372 -b merged-commits
  2. teraz po prostu wybierz zmiany z ostatniego commita do nowej gałęzi jako: git cherry-pick -n -x ac72a4308ba70cc42aace47509a5e. (Rozwiązuj konflikty, jeśli pojawią się jakiekolwiek)
  3. więc teraz Twoje zmiany w ostatnim commicie są w Twoim drugi ostatni commit. Ale nadal musisz zatwierdzić, więc najpierw dodaj zmiany, które właśnie wybrałeś, a następnie wykonaj git commit --amend.
To wszystko. Możesz wcisnąć tę scaloną wersję w gałęzi "merged-commits", jeśli chcesz.

Możesz teraz odrzucić dwa commity w gałęzi master. Po prostu zaktualizuj swoją gałąź master jako:

git checkout master
git reset --hard origin/master (CAUTION: This command will remove any local changes to your master branch)
git pull
 1
Author: Undefined,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-16 15:57:34

Ponieważ używam git cherry-pick do prawie wszystkiego, dla mnie naturalne jest, aby to robić nawet tutaj.

Biorąc pod uwagę, że mam branchX sprawdzone i są dwa commity na jego końcu, z których chcę utworzyć jeden commit łączący ich zawartość, robię to:

git checkout HEAD^ // Checkout the privious commit
git cherry-pick --no-commit branchX // Cherry pick the content of the second commit
git commit --amend // Create a new commit with their combined content

Jeśli chcę również zaktualizować branchX (i przypuszczam, że to jest dół tej metody) muszę również:

git checkout branchX
git reset --hard <the_new_commit>
 1
Author: Martin G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-26 10:52:43

Jeśli chcesz połączyć dwa najnowsze commity i po prostu użyć starszej wiadomości commita, możesz zautomatyzować proces za pomocą expect.

Zakładam:

  • używasz vi jako edytora
  • Twoje commity są Jednowierszowe

Testowałem z git version 2.14.3 (Apple Git-98).


#!/usr/bin/env expect
spawn git rebase -i HEAD~2

# down, delete word, insert 's' (for squash), Escape, save and quit
send "jdwis \033:wq\r"

expect "# This is a"

# down 4, delete 3 lines, save and quit
send "4j3d\r:wq\r"

interact
 0
Author: erwaman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-06 04:50:59