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.