Jak korzystać z Git Merge - Quash?


1208

Mam zdalny serwer Git, oto scenariusz, który chcę wykonać:

  • Dla każdego błędu / funkcji tworzę inną gałąź Git

  • Nadal zatwierdzam swój kod w tym oddziale Git z nieoficjalnymi wiadomościami Git

  • W górnym repozytorium musimy wykonać jedno zatwierdzenie dla jednego błędu z oficjalną wiadomością Git

Jak więc połączyć moją gałąź z gałęzią zdalną, aby otrzymali tylko jedno zatwierdzenie dla wszystkich moich meldowań (nawet chcę podać w tym celu komunikat zatwierdzenia)?


1
Nie jestem pewien, czy całkowicie cię zrozumiałem, ale możesz chcieć „scalenia ośmiornicy”.
MatrixFrog,

26
Zwykle używam git rebase -i, aby zwinąć wszystkie moje zatwierdzenia w jeden zatwierdzenie i ponownie napisać komunikat zatwierdzenia. Następnie wysyłam to w górę.
Edward Falk

17
git merge --squashrobi to wszystko w wierszu poleceń za jednym strzałem i masz tylko nadzieję, że to zadziała. git rebase -iwywołuje edytor i pozwala dostroić rebase. Jest wolniejszy, ale możesz zobaczyć, co robisz. Istnieją również różnice między rebase a scalaniem, które są zbyt zaangażowane, aby uwzględnić je w komentarzu.
Edward Falk,

4
problem z tymi wszystkimi odpowiedziami polega na tym, że musisz być lokalnie w gałęzi master i uruchomić polecenie merge --squash ... Chcę uruchomić scalanie - quash z gałęzi funkcji, a nie gałęzi master .. więc to kiedy skończę, mogę przesunąć gałąź funkcji do pilota i przesłać PR, czy to możliwe?
Alexander Mills,

2
@AlexanderMills, myślę, że potrzebujesz tylko drugiej gałęzi funkcji (sklonowanej z gałęzi master). Wykonaj czynności merge --squashze starego do nowego, a następnie połącz nową gałąź do opanowania. Stara gałąź staje się przestarzała.
Gyromite

Odpowiedzi:


1998

Powiedzmy, że twoja gałąź naprawiania błędów jest wywoływana bugfixi chcesz połączyć ją w master:

git checkout master
git merge --squash bugfix
git commit

Spowoduje to pobranie wszystkich zatwierdzeń z bugfixgałęzi, zgniecenie ich w 1 zatwierdzenie i scalenie go z mastergałęzią.


Objaśnienie :

git checkout master

Przełączniki do masteroddziału.

git merge --squash bugfix

Pobiera wszystkie zatwierdzenia z bugfixoddziału i łączy je z bieżącym oddziałem.

git commit

Tworzy pojedyncze zatwierdzenie na podstawie scalonych zmian.

Pominięcie -mparametru pozwala zmodyfikować wersję roboczą wiadomości zatwierdzenia zawierającą każdą wiadomość z twoich zgniecionych zatwierdzeń przed sfinalizowaniem twojego zatwierdzenia.


222
Jeśli chcesz zachować odniesienia do starych komunikatów zatwierdzenia, możesz napisać git commit(bez -mparametrów), a będziesz mógł zmodyfikować szkicowaną wiadomość zatwierdzenia zawierającą wszystkie zgniecione wiadomości zatwierdzenia.
Alex

12
Możesz osiągnąć to samo, robiąc git commit --amend -m '...'później.
Janusz Lenar

19
W przypadku wystąpienia konfliktów scalania i rozwiązania tych konfliktów, git commitnie będzie już wyświetlać użytecznego komunikatu zatwierdzenia zawierającego wszystkie zgniecione wiadomości zatwierdzenia. W takim przypadku spróbuj git commit --file .git/SQUASH_MSG(przez stackoverflow.com/a/11230783/923560 ).
Abdull

23
Należy pamiętać, że squash domyślnie przypisuje zatwierdzenia do squashera . Aby zachować oryginalnego autora, musisz wyraźnie to określić w następujący sposób:git commit -a --author="Author" --message="Issue title #id"
gaborous

5
git merge --squashumożliwia utworzenie jednego zatwierdzenia na bieżącej gałęzi, którego efekt jest taki sam jak scalenie innej gałęzi. Ale nie wygeneruje rekordu scalania, co oznacza, że ​​Twoje żądanie ściągnięcia nie spowoduje żadnych zmian, ale nie zostanie oznaczone jako scalone! Aby to zrobić, wystarczy usunąć tę gałąź.
am0wa,

129

To, co ostatecznie mnie wyjaśniło, to komentarz pokazujący, że:

git checkout main
git merge --squash feature

jest odpowiednikiem robienia:

git checkout feature
git diff main > feature.patch
git checkout main
patch -p1 < feature.patch
git add .

Kiedy chcę scalić gałąź funkcji ze 105 zatwierdzeniami (!!) i zmiażdżyć je wszystkie w jednym, nie chcę, git rebase -i origin/masterponieważ muszę osobno rozwiązywać konflikty scalania dla każdego z pośrednich zatwierdzeń (lub przynajmniej tych, które git nie może się zorientować). Użycie git merge --squashdaje mi wynik, jaki chcę, z jednego zatwierdzenia do scalenia całej gałęzi funkcji. Potrzebuję tylko jednego ręcznego rozwiązania konfliktu.


75
Zdecydowanie sugeruję wykonanie scalenia najpierw w gałęzi funkcji git merge master, a dopiero potem git merge --squash featurew gałęzi głównej.
dotancohen,

8
@dotancohen Przepraszam za pogłębienie starego komentarza :) Co zyskujesz dzięki scaleniu w gałęzi funkcji przed wykonaniem git merge --squash featurez gałęzi master?
bitsmack

57
Chcesz najpierw scalić wzorzec z gałęzią funkcji i zająć się wszelkimi ręcznymi poprawkami w gałęzi funkcji. Pozwala to również na uruchomienie testów i upewnienie się, że gałąź funkcji działa poprawnie. Następnie masz gwarancję, że możesz wykonać automatyczne scalenie gałęzi funkcji w master.
Dan Kohn

4
@dankohn Proponuję dodać wyjaśnienie w powyższym komentarzu do swojej odpowiedzi.
guntbert,

3
@bitsmack: najpierw scalisz wzorzec z funkcją. Daje to możliwość rozwiązania konfliktów dotyczących obiektu przed połączeniem obiektu w master
Mike

97

Chcesz połączyć z opcją squash. Dzieje się tak, jeśli chcesz to zrobić pojedynczo.

git merge --squash feature1

Jeśli chcesz scalić wszystkie gałęzie w tym samym czasie, co pojedyncze zatwierdzenia, najpierw najpierw wykonaj interaktywny podział i wyciśnij każdą funkcję, a następnie scal ośmiornicę:

git checkout feature1
git rebase -i master

Squash w jednym zatwierdzeniu, a następnie powtórz dla pozostałych funkcji.

git checkout master
git merge feature1 feature2 feature3 ...

To ostatnie scalenie jest „scaleniem ośmiornicy”, ponieważ łączy wiele gałęzi jednocześnie.

Mam nadzieję że to pomoże


3
Dlaczego bazujesz?
Umair A.,

12
@UmairAshraf to interaktywna baza, która daje możliwość zrobienia squasha w twoim oddziale.
andho

1
Rebasing to zły pomysł. Nie rebase już opublikowane zobowiązania
Sebi2020

1
@ Sebi2020 git merge - quash spowoduje zmianę już opublikowanych zatwierdzeń w sposób gorszy niż interaktywny rebase. Interaktywny rebase (w gałęzi funkcji) niesie niewiele lub nie ma żadnych negatywnych skutków.
xiix

1
@xiix Dotyczy to tylko sytuacji, w której pracujesz tylko z gałęzią funkcji. Nie możesz tego założyć. Polecam przeczytać strony związane z bazowaniem na Git-SCM . Stwierdza: „ Nie zmieniaj baz danych, które istnieją poza twoim repozytorium, a ludzie mogą na nich opierać pracę. A jeśli nie wiesz na pewno, czy ludzie już bazują na opublikowanych zobowiązaniach (których nie możesz poznać z powodu decentralizacji natura git) nie powinieneś tego robić.
Sebi2020

23

Jeśli masz już git merge bugfixwłączony main, możesz zmiksować zatwierdzenie scalania w jeden z:

git reset --soft HEAD^1
git commit

git reset --soft HEAD^1wydaje się cofać ostatnie zatwierdzenie wykonane przed scaleniem, przynajmniej w przypadku, gdy scalenie jest przewijaniem do przodu.
Jesper Matthiesen

@JesperMatthiesen w przypadku przewijania do przodu nie otrzymujesz zatwierdzenia scalania, więc zrobiłbyś to git reset --soft HEAD^<number-of-commits-to-squash>.
qwertzguy

Pomogło mi to zmiażdżyć wszystko w jednym zatwierdzeniu po scaleniu.
killjoy

18

Scal newFeaturegałąź masterz niestandardowym zatwierdzeniem:

git merge --squash newFeature && git commit -m 'Your custom commit message';

Jeśli zamiast tego zrobisz

git merge --squash newFeature && git commit

otrzymasz komunikat zatwierdzenia, który będzie zawierał wszystkie zatwierdzenia newFeatureoddziału, które możesz dostosować.

Dokładnie to wyjaśniam tutaj: https://youtu.be/FQNAIacelT4


10

Wiem, że to pytanie nie dotyczy konkretnie Github, ale ponieważ Github jest tak szeroko stosowane i to jest odpowiedź, której szukałem, podzielę się nią tutaj.

Github ma możliwość wykonywania połączeń squash, w zależności od opcji scalania włączonych dla repozytorium.

Jeśli scalenia squasha są włączone, opcja „Squash and merge” powinna pojawić się w menu pod przyciskiem „Scal”.

Zrzut ekranu z funkcją Github „Squash and merge”


GitHub używa domyślnego adresu e-mail powiązanego z Twoim kontem. Jeśli masz wiele adresów e-mail i musisz użyć drugiego, nie możesz użyć interfejsu GH.
Luca Guidi,

4

Załóżmy, że pracowałeś w funkcji / zadaniu 1 z wieloma zatwierdzeniami.

  1. Przejdź do gałęzi projektu (project / my_project)

    git checkout project/my_project
    
  2. Utwórz nowy oddział (feature / task1_bugfix)

    git checkout -b feature/task1_bugfix
    
  3. Połącz z --squashopcją

    git merge --squash feature/task1
    
  4. Utwórz pojedynczy zatwierdzenie

    git commit -am "add single comments"
    
  5. Pchnij swój oddział

    git push --set-upstream origin feature/task1_bugfix
    

1

Dla Gita

Utwórz nową funkcję

przez Terminal / Shell:

git checkout origin/feature/<featurename>
git merge --squash origin/feature/<featurename>

Nie zatwierdza go, pozwala najpierw go przejrzeć.

Następnie zatwierdź i zakończ funkcję z tej nowej gałęzi, a następnie usuń / zignoruj ​​starą (tę, którą stworzyłeś).


@ Melebius Jedyne odniesienie do „SourceTree” znajduje się w twoim zdaniu, jeśli był to tag lub poprzednie pytanie: To już nie istnieje.
Jordan Stefanelli

1
@JordanStefanelli SourceTree został użyty w oryginalnej wersji tej odpowiedzi . Dziękujemy za powiadomienie, że zostało to naprawione!
Melebius

1

jeśli pojawi się błąd: zatwierdzenie nie jest możliwe, ponieważ masz nie scalone pliki.

git checkout master
git merge --squash bugfix
git add .
git commit -m "Message"

naprawiono wszystkie pliki konfliktu

git add . 

możesz również użyć

git add [filename]

0

Aby zgnieść lokalny oddział przed wypchnięciem go:

  1. sprawdź gałąź, o której mowa, aby pracować, jeśli nie jest jeszcze wyewidencjonowana.

  2. Znajdź sha najstarszego zatwierdzenia, które chcesz zachować.

  3. Utwórz / sprawdź nową gałąź (tmp1) z tego zatwierdzenia.

    git checkout -b tmp1 <sha1-of-commit>

  4. Scal oryginalną gałąź w nową zgniatanie.

    git merge --squash <original branch>

  5. Zatwierdź zmiany, które zostały utworzone przez scalenie, z komunikatem o zatwierdzeniu podsumowania.

    git commit -m <msg>

  6. Do kasy oryginalnej gałęzi, którą chcesz zgnieść.

    git checkout <branch>

  7. Zresetuj do pierwotnego zatwierdzenia, które chcesz zachować.

    git reset --soft <sha1>

  8. Ponownie uruchom tę gałąź w oparciu o nową gałąź tmp1.

    git rebase tmp1

  9. To wszystko - teraz usuń tymczasową gałąź tmp1, gdy masz pewność, że wszystko jest w porządku.


0

Możesz użyć narzędzia, które stworzyłem, aby ułatwić ten proces: git-squash . Na przykład, aby zgnieść wszystkie zatwierdzenia w gałęzi funkcji, która została rozgałęziona z gałęzi głównej, napisz:

git squash master
git push --force
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.