Połączyć dwa pierwsze commity repozytorium Git?

Załóżmy, że masz historię zawierającą trzy commity A, B iC :

A-B-C

Chciałbym połączyć dwa commity A i B w jeden commit AB :

AB-C

Próbowałem

git rebase -i A

Który otwiera mój edytor o następującej treści:

pick e97a17b B
pick asd314f C

Zmieniam to na

squash e97a17b B
pick asd314f C

Wtedy Git 1.6.0.4 mówi:

Cannot 'squash' without a previous commit
Jest jakiś sposób, czy jest to po prostu niemożliwe?
Author: Christian, 2009-01-12

7 answers

Użyj git rebase -i --root od wersji Git 1.7.12 .

W interaktywnym pliku rebase Zmień drugą linię commita B na squash i pozostaw pozostałe linie w Wybierz :

pick f4202da A
squash bea708e B
pick a8c6abc C

To połączy dwa commity A i B w jeden commit AB .

Znaleziono w tej odpowiedzi .

 139
Author: kostmo,
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-05-23 12:26:07

Próbowałeś:

git rebase -i A

Można zacząć w ten sposób, jeśli kontynuujesz edit zamiast squash:

edit e97a17b B
pick asd314f C

Następnie uruchom

git reset --soft HEAD^
git commit --amend
git rebase --continue
Zrobione.
 125
Author: David Lichteblau,
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
2009-02-12 14:29:00

A to był początkowy commit, ale teraz chcesz B być początkowym commitem. commity git są całymi drzewami, a nie diffami, nawet jeśli są normalnie opisane i przeglądane pod kątem różnic, które wprowadzają.

Ten przepis działa nawet jeśli istnieje wiele commitów między A i B oraz B i C.

# Go back to the last commit that we want
# to form the initial commit (detach HEAD)
git checkout <sha1_for_B>

# reset the branch pointer to the initial commit,
# but leaving the index and working tree intact.
git reset --soft <sha1_for_A>

# amend the initial tree using the tree from 'B'
git commit --amend

# temporarily tag this new initial commit
# (or you could remember the new commit sha1 manually)
git tag tmp

# go back to the original branch (assume master for this example)
git checkout master

# Replay all the commits after B onto the new initial commit
git rebase --onto tmp <sha1_for_B>

# remove the temporary tag
git tag -d tmp
 63
Author: CB Bailey,
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-25 06:00:58

W przypadku rebase interaktywnego, musisz to zrobić przed A, aby lista była:

pick A
pick B
pick C

Zostać:

pick A
squash B
pick C

Jeśli a jest początkowym commitem, musisz mieć inny commit, zanim A. Git pomyśli o różnicach, będzie działał na różnicy pomiędzy (a i B) i (B I C). Stąd squash nie działa w twoim przykładzie.

 10
Author: Loki,
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
2009-01-12 15:13:20

W przypadku, gdy masz setki lub tysiące commitów, użyj odpowiedzi kostmo z

git rebase -i --root

Może być niepraktyczne i powolne, tylko ze względu na dużą liczbę commitów, które skrypt rebase musi przetworzyć dwa razy , raz do wygenerowania interaktywnej listy edytorów rebase (gdzie można wybrać, jakie działania podjąć dla każdego commita), a raz do rzeczywistego wykonania re-zastosowania commitów.

Oto alternatywne rozwiązanie, które pozwoli uniknąć kosztów czasu generowania interaktywnej listy edytorów rebase przez nieużywanie interaktywnej rebase w pierwszej kolejności. W ten sposób jest to podobne do rozwiązania Charlesa Baileya . Po prostu tworzysz orphan branch z drugiego commita, a następnie zmieniasz wszystkie commity potomne na nim:

git checkout --orphan orphan <second-commit-sha>
git commit -m "Enter a commit message for the new root commit"
git rebase --onto orphan <second-commit-sha> master

Dokumentacja

 8
Author: Community,
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-05-23 10:31:10

W powiązanym pytaniu, udało mi się wymyślić inne podejście do potrzeby zmiażdżenia pierwszego commita, czyli, cóż, aby uczynić go drugim.

Jeśli jesteś zainteresowany: git: jak wstawić commit jako pierwszy, przesuwając wszystkie pozostałe?

 1
Author: kch,
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-05-23 10:31:10

Musisz wykonać trochę magii wiersza poleceń.

git checkout -b a A
git checkout B <files>
git commit --amend
git checkout master
git rebase a

To powinno pozostawić Ci gałąź, która ma AB i C jako commity.

 -1
Author: Bombe,
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-25 06:03:19