2011-08-04 12 views
288

Mam kilka zatwierdzeń w moim lokalnym repozytorium, które są tematycznie podobne. Chciałbym połączyć je w jedno zatwierdzenie przed przejściem do zdalnego. Jak mam to zrobić? Myślę, że robi to rebase, ale nie mogę zrozumieć dokumentów.Łączenie wielu zatwierdzeń przed wciśnięciem w Git

+1

Aby zmienić/sparować dowolnie dużą liczbę zatwierdzeń, zobacz [moja odpowiedź do "Squash/Combine/rebase arbitrally large number commits"] (http://stackoverflow.com/a/22161885/456814). –

+1

Powiązane [Jak mogę zgnieść moje ostatnie X commits razem używając git?] (Http://stackoverflow.com/q/5189560/456814). –

Odpowiedz

449

To, co chcesz zrobić, jest określane jako "zgniatanie" w git. Istnieje wiele opcji kiedy to robi (zbyt wiele?), Ale jeśli chcesz po prostu połączyć wszystkie swoje unpushed zatwierdzeń w jeden commit, to zrobić:

git rebase -i origin/master 

To przyniesie swój edytor tekstu (-i jest "interaktywny") z pliku, który wygląda tak:

pick 16b5fcc Code in, tests not passing 
pick c964dea Getting closer 
pick 06cf8ee Something changed 
pick 396b4a3 Tests pass 
pick 9be7fdb Better comments 
pick 7dba9cb All done 

zmienić wszystkie pick do squash (lub s) z wyjątkiem pierwszego:

pick 16b5fcc Code in, tests not passing 
squash c964dea Getting closer 
squash 06cf8ee Something changed 
squash 396b4a3 Tests pass 
squash 9be7fdb Better comments 
squash 7dba9cb All done 

Zapisz plik i zamknij edytor. Następnie otworzy się inny edytor tekstu, aby umożliwić łączenie komunikatów o zatwierdzeniu ze wszystkich zatwierdzeń w jedną dużą wiadomość zatwierdzenia.

Voila! Googling "git squashing" da ci wyjaśnienia wszystkich innych dostępnych opcji.

+14

Przez "origin/master', masz na myśli' '? Jeśli gałąź źródłowa jest skonfigurowana, czy jest ona niejawna, czy nadal muszę ją określić? –

+0

To świetny sposób na zmniejszenie liczby zatwierdzeń, ale co jeśli chcę po prostu usunąć jedno podwykonawstwo, na przykład: usunąć "c964dea Podejście bliżej" to podpasowanie w zatwierdzeniu, czy to możliwe? – Jusleong

+7

Użyj 'fixup' zamiast' squash', aby pominąć krok tworzenia nowej wiadomości zatwierdzenia. Ostatni komunikat zatwierdzenia ("Wszystko zrobione") zostanie użyty automatycznie dla końcowego zatwierdzenia utworzonego przez 'rebase'. – faizal

1

Prawdopodobnie chcesz użyć Interactive Rebasing, który jest szczegółowo opisany w tym łączu.

Możesz znaleźć inne dobre zasoby, jeśli szukasz "git rebase interactive".

24

Można to zrobić z git rebase -i, przechodzącą w przeglądzie, który chcesz użyć jako „root”:

git rebase -i origin/master 

otworzy okna edytora pokazujący wszystkie zobowiązuje zostały wykonane po ostatnim popełnić w origin/master. Możesz odrzucić zatwierdzenia, zmiażdżyć zatwierdzenia w jednym zatwierdzeniu lub edytować poprzednie zatwierdzenia.

Istnieje kilka zasobów, które prawdopodobnie można to wyjaśnić w lepszy sposób i pokazać kilka innych przykładów:

http://book.git-scm.com/4_interactive_rebasing.html

i

http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html

są pierwsze dwa dobre strony Mógłbym znaleźć.

50

Jeśli masz wiele z zatwierdzeń i chcesz tylko zgnieść ostatni X zobowiązuje, znaleźć identyfikator commit popełnić od którego chcesz rozpocząć zgniecenia i zrobić

git rebase -i <that_commit_id> 

Następnie postępować zgodnie z opisem w odpowiedzi leopda, zmieniając wszystkie s1, z wyjątkiem pierwszego.

+2

Zajęło mi trochę czasu, aby dowiedzieć się, ale wydaje się, że sam NIE zostanie zgnieciony. – lznt

+2

Powinno powiedzieć "znajdź identyfikator zatwierdzenia zatwierdzenia tuż przed zbiorem zatwierdzeń, które chcesz zgnieść w jeden". – BenjaminBallard

10

wymyśliłem

#!/bin/sh 

message=`git log --format=%B origin..HEAD | sort | uniq | grep -v '^$'` 
git reset --soft origin 
git commit -m "$message" 

łączy, sortuje, ujednolicenia i usunąć puste wiersze z komunikatem zatwierdzenia. Używam tego do lokalnych zmian w wiki github (używając gollum)

+0

To naprawdę sprytny pomysł! – zatziky

+0

Z jakiegoś powodu (może to moja konfiguracja lub sposób korzystania z GIT), origin..HEAD dał mi niejednoznaczny błąd argumentu. Aby upewnić się, że zawsze przynosi ona różnicę z bieżącą gałęzią, musiałem dostosować pierwszą linię z "logiem git" do tego 'git fetch && git log --format =% B FETCH_HEAD..HEAD' [... ] Pobieranie najpierw upewnia się, że GIT ma najnowszą wiedzę potrzebną i tworzy referencję FETCH_HEAD, której możemy użyć. –

3

Możesz zgniatać (łączyć) zatwierdzenia z Interactive Rebase. Jest to całkiem ładny wideo YouTube, który pokazuje, jak to zrobić w linii poleceń lub z SmartGit:

Jeśli jesteś już użytkownikiem SmartGit następnie można wybrać wszystkie wychodzące zobowiązuje (przytrzymując klawisz Ctrl) i otwórz menu kontekstowe (prawy przycisk myszy), aby zgnieść twoje zatwierdzenia.

Jest to bardzo wygodne:

enter image description here

Jest też bardzo ładny poradnik z Atlassian który pokazuje, jak to działa:

5

A mój sposób squashing wielokrotny push jest (być może ty popchnąłeś do swojej własnej sieci wiele commitów, a teraz chcesz wykonać żądanie ściągnięcia i nie chcesz zaśmiecać ich wieloma zatwierdzeniami, które już wcześniej wysłałeś). Sposób, w jaki to robię (nie ma innej prostszej opcji, o ile mogę to stwierdzić).

  1. Utwórz nowy oddział ze względu na squash (gałąź z oryginalnej gałęzi, do której chcesz wysłać żądanie).
  2. Naciśnij nowo utworzoną gałąź.
  3. Połącz oddział z zatwierdzeniami (już wciśnięto) do nowego oddziału.
  4. Rozwiń nową gałąź i squash.
  5. Naciśnij nowy oddział.
  6. Utwórz nowe żądanie pobrania dla nowego oddziału, które ma teraz jedno zatwierdzenie.

Przykład:

git checkout from_branch_you_wish_to_pull_request_to 
git checkout -b new_branch_will_have_single_squashed_commit 
git push -u new_branch_will_have_single_squashed_commit 
git merge older_branch_with_all_those_multiple_commits 
git rebase -i (here you squash) 
git push origin new_branch_will_have_single_squashed_commit 

Teraz można wyciągnąć wniosek do from_branch_you_wish_to_pull_request_to

20

Istnieje sporo odpowiedzi tu pracować, ale znalazłem ten najprostszy. To polecenie otworzy się edytor, w którym można po prostu zastąpić pick z squash w celu usunięcia/połączyć je w jeden

git rebase -i HEAD~4 

gdzie 4 jest liczba zobowiązuje chcesz zgnieść w jednym. Zostało to również wyjaśnione jako here.

Powiązane problemy