Wie verwende ich git merge --squash?

1209

Ich habe einen Remote-Git-Server. Hier ist das Szenario, das ich ausführen möchte:

  • Für jeden Fehler / jede Funktion erstelle ich einen anderen Git-Zweig

  • Ich schreibe meinen Code in diesem Git-Zweig weiterhin mit nicht offiziellen Git-Nachrichten fest

  • Im Top-Repository müssen wir ein Commit für einen Fehler mit der offiziellen Git-Nachricht durchführen

Wie kann ich meinen Zweig mit dem Remote-Zweig zusammenführen, sodass er nur ein Commit für alle meine Check-Ins erhält (ich möchte sogar eine Commit-Nachricht dafür bereitstellen)?

SunnyShah
quelle
1
Ich bin mir nicht sicher, ob ich Sie vollständig verstanden habe, aber Sie möchten vielleicht eine "Octopus Merge".
MatrixFrog
27
Normalerweise verwende ich git rebase -i, um alle meine Commits zu einem Commit zusammenzufassen und die Commit-Nachricht neu zu schreiben. Dann schicke ich es stromaufwärts.
Edward Falk
17
git merge --squashmacht alles auf einmal in der Kommandozeile und Sie hoffen nur, dass es funktioniert. git rebase -iRuft einen Editor auf und lässt Sie die Rebase optimieren. Es ist langsamer, aber Sie können sehen, was Sie tun. Es gibt auch Unterschiede zwischen Rebase und Merge, die etwas zu aufwendig sind, um in einem Kommentar behandelt zu werden.
Edward Falk
4
Das Problem bei all diesen Antworten ist, dass Sie sich lokal im Hauptzweig befinden und den Befehl merge --squash ausführen müssen ... Ich möchte den Befehl merge --squash vom Feature-Zweig aus ausführen, nicht vom Hauptzweig Wenn ich fertig bin, kann ich den Feature-Zweig an die Fernbedienung senden und eine PR einreichen. Ist das möglich?
Alexander Mills
2
@AlexanderMills, ich denke, Sie brauchen nur einen zweiten Feature-Zweig (geklont vom Master-Zweig). Machen Sie das merge --squashvom alten zum neuen und führen Sie dann den neuen Zweig zum Master zusammen. Der alte Zweig ist veraltet.
Gyromite

Antworten:

2000

Angenommen, Ihr Bugfix-Zweig wird aufgerufen bugfixund Sie möchten ihn zusammenführen in master:

git checkout master
git merge --squash bugfix
git commit

Dadurch werden alle Commits aus dem bugfixZweig übernommen, zu einem Commit zusammengefasst und mit Ihrem masterZweig zusammengeführt.


Erklärung :

git checkout master

Wechselt zu Ihrer masterNiederlassung.

git merge --squash bugfix

Nimmt alle Commits aus der bugfixFiliale und führt sie mit Ihrer aktuellen Filiale zusammen.

git commit

Erstellt ein einzelnes Commit aus den zusammengeführten Änderungen.

Durch Weglassen des -mParameters können Sie einen Entwurf einer Festschreibungsnachricht ändern, der jede Nachricht aus Ihren gequetschten Festschreibungen enthält, bevor Sie die Festschreibung abschließen .

Abyx
quelle
222
Wenn Sie Verweise auf die alten Festschreibungsnachrichten beibehalten möchten, die Sie schreiben können git commit(ohne -mParameter), können Sie eine entworfene Festschreibungsnachricht ändern, die alle Festschreibungsnachrichten enthält, die Sie gequetscht haben.
Alex
12
Sie können dasselbe erreichen, indem Sie es git commit --amend -m '...'später tun .
Janusz Lenar
19
Wenn Zusammenführungskonflikte auftreten und Sie diese Konflikte lösen, git commitwird die nützliche Festschreibungsnachricht mit allen von Ihnen gequetschten Festschreibungsnachrichten nicht mehr angezeigt. Versuchen Sie es in diesem Fall git commit --file .git/SQUASH_MSG(über stackoverflow.com/a/11230783/923560 ).
Abdull
23
Beachten Sie, dass beim Squashing die Commits standardmäßig dem Squasher zugeordnet werden . Um den ursprünglichen Autor git commit -a --author="Author" --message="Issue title #id"
beizubehalten
5
git merge --squashMit dieser Option können Sie ein einzelnes Commit über dem aktuellen Zweig erstellen, dessen Wirkung dem Zusammenführen eines anderen Zweigs entspricht. Der Zusammenführungsdatensatz wird jedoch nicht erstellt, was bedeutet, dass Ihre Pull-Anfrage als Ergebnis keine Änderungen aufweist, jedoch nicht als zusammengeführt markiert wird! Sie müssen also nur diesen Zweig löschen, um dies zu tun.
am0wa
129

Was mir das schließlich klar machte, war ein Kommentar , der Folgendes zeigte:

git checkout main
git merge --squash feature

ist das Äquivalent zu tun:

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

Wenn ich einen Feature-Zweig mit 105 (!!) Commits zusammenführen und sie alle zu einem zusammenfassen möchte, möchte ich dies nicht, git rebase -i origin/masterda ich Zusammenführungskonflikte für jeden der Zwischen-Commits (oder zumindest für diejenigen, die dies tun) separat lösen muss git kann sich nicht selbst herausfinden). Durch die Verwendung git merge --squasherhält ich das gewünschte Ergebnis eines einzelnen Commits zum Zusammenführen eines gesamten Feature-Zweigs. Und ich muss höchstens eine manuelle Konfliktlösung durchführen.

Dan Kohn
quelle
75
Ich empfehle dringend, die Zusammenführung zuerst im Feature-Zweig git merge masterund erst dann git merge --squash featureim Master-Zweig durchzuführen .
Dotancohen
8
@dotancohen Tut mir leid, dass ich einen alten Kommentar ausgegraben habe :) Was bringt das Zusammenführen im Feature-Zweig, bevor ich git merge --squash featurevom Master-Zweig aus spiele ?
Bitsmack
57
Sie möchten den Master zuerst in den Feature-Zweig einbinden und alle manuellen Korrekturen in Ihrem Feature-Zweig vornehmen. Auf diese Weise können Sie auch Tests ausführen und sicherstellen, dass Ihr Feature-Zweig ordnungsgemäß funktioniert. Dann ist Ihnen garantiert, dass Sie eine automatische Zusammenführung Ihres Feature-Zweigs mit dem Master durchführen können.
Dan Kohn
4
@dankohn Ich schlage vor, Sie fügen die Erklärung in Ihrem obigen Kommentar in Ihre Antwort ein.
Guntbert
3
@bitsmack: Sie würden Master zuerst in Feature zusammenführen. Dies gibt Ihnen die Möglichkeit, Konflikte auf dem Feature zu lösen, bevor Sie das Feature in Master zusammenführen
Mike
97

Sie möchten mit der Squash-Option zusammenführen. Das ist, wenn Sie es einen Zweig nach dem anderen tun möchten.

git merge --squash feature1

Wenn Sie alle Zweige gleichzeitig mit einzelnen Commits zusammenführen möchten, müssen Sie zuerst interaktiv neu starten und jedes Feature quetschen, bevor Octopus zusammengeführt wird:

git checkout feature1
git rebase -i master

Squash in ein Commit und dann wiederholen für die anderen Funktionen.

git checkout master
git merge feature1 feature2 feature3 ...

Diese letzte Zusammenführung ist eine "Octopus-Zusammenführung", da viele Zweige gleichzeitig zusammengeführt werden.

Hoffe das hilft

Adam Dymitruk
quelle
3
Warum gründen Sie neu?
Umair A.
12
@UmairAshraf ist eine interaktive Rebase, mit der Sie einen Squash in Ihrer Filiale durchführen können.
Andho
1
Rebasing ist eine schlechte Idee. Rebase nicht bereits veröffentlichte Commits
Sebi2020
1
@ Sebi2020 git merge --squash wird Ihre bereits veröffentlichten Commits auf eine Weise neu basieren, die schlimmer ist als eine interaktive Basis. Eine interaktive Rebase (auf einem Feature-Zweig) hat nur geringe bis keine nachteiligen Auswirkungen.
xiix
1
@xiix Dies gilt nur, wenn Sie der einzige sind, der mit dem Feature-Zweig arbeitet. Dies ist keine Annahme, die Sie machen können. Ich empfehle, die Seiten zu lesen, die sich auf das Rebasieren auf Git-SCM beziehen . Darin heißt es: " Setzen Sie Commits, die außerhalb Ihres Repositorys vorhanden sind, nicht neu, und die Mitarbeiter haben möglicherweise eine darauf basierende Arbeit. " Und wenn Sie nicht sicher sind, ob Personen, die bereits auf veröffentlichten Commits basieren, arbeiten (was Sie aufgrund der Dezentralisierung nicht wissen können Natur von git) das solltest du nicht tun.
Sebi2020
23

Wenn Sie bereits git merge bugfixaktiviert sind main, können Sie Ihr Merge-Commit zu einem zusammenfassen mit:

git reset --soft HEAD^1
git commit
qwertzguy
quelle
git reset --soft HEAD^1scheint das letzte vor dem Zusammenführen durchgeführte Commit rückgängig zu machen , zumindest im Falle eines schnellen Vorlaufs.
Jesper Matthiesen
@JesperMatthiesen Im Falle eines schnellen Vorlaufs erhalten Sie kein Merge-Commit, also würden Sie es tun git reset --soft HEAD^<number-of-commits-to-squash>.
qwertzguy
Dies hat mir geholfen, nach einer nachgelagerten Zusammenführung alles zu einem einzigen Commit zusammenzufassen.
Killjoy
18

Merge newFeatureZweig in mastermit einem benutzerdefinierten begehen:

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

Wenn Sie es stattdessen tun

git merge --squash newFeature && git commit

Sie erhalten eine Commit-Nachricht, die alle newFeatureBranch-Commits enthält, die Sie anpassen können.

Ich erkläre es hier ausführlich: https://youtu.be/FQNAIacelT4

Vagelis Prokopiou
quelle
10

Ich weiß, dass es bei dieser Frage nicht speziell um Github geht, aber da Github so weit verbreitet ist und dies die Antwort ist, nach der ich gesucht habe, werde ich sie hier teilen.

Github kann Squash-Zusammenführungen durchführen, abhängig von den für das Repository aktivierten Zusammenführungsoptionen.

Wenn Squash-Zusammenführungen aktiviert sind, sollte die Option "Squash and Merge" in der Dropdown-Liste unter der Schaltfläche "Merge" angezeigt werden.

Screenshot der Github-Funktion "Squash and Merge"

Aaron
quelle
GitHub verwendet die Standard-E-Mail, die Ihrem Konto zugeordnet ist. Wenn Sie mehrere E-Mail-Adressen haben und eine sekundäre verwenden müssen, können Sie die GH-Benutzeroberfläche nicht verwenden.
Luca Guidi
4

Angenommen, Sie haben in feature / task1 mit mehreren Commits gearbeitet.

  1. Gehen Sie zu Ihrem Projektzweig (project / my_project)

    git checkout project/my_project
    
  2. Erstellen Sie einen neuen Zweig (feature / task1_bugfix)

    git checkout -b feature/task1_bugfix
    
  3. Marge mit der --squashOption

    git merge --squash feature/task1
    
  4. Erstellen Sie ein einzelnes Commit

    git commit -am "add single comments"
    
  5. Schieben Sie Ihren Zweig

    git push --set-upstream origin feature/task1_bugfix
    
Farid Haq
quelle
1

Für Git

Erstellen Sie eine neue Funktion

über Terminal / Shell:

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

Dadurch wird es nicht festgeschrieben, Sie können es zuerst überprüfen.

Dann schreiben Sie die Funktion aus diesem neuen Zweig fest und beenden sie. Löschen / ignorieren Sie die alte (die, die Sie entwickelt haben).

Demian Berisford-Maynard
quelle
@Melebius Der einzige Verweis auf "SourceTree" befindet sich in Ihrem Satz, wenn es sich um ein Tag oder eine vorherige Frage handelte: Es existiert nicht mehr.
Jordan Stefanelli
1
@JordanStefanelli SourceTree wurde in der Originalversion dieser Antwort verwendet . Vielen Dank für die Benachrichtigung, dass es behoben ist!
Melebius
1

Wenn Sie eine Fehlermeldung erhalten: Das Festschreiben ist nicht möglich, da Sie nicht zusammengeführte Dateien haben.

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

Alle Konfliktdateien wurden behoben

git add . 

Sie könnten auch verwenden

git add [filename]
ResUta
quelle
0

So zerquetschen Sie Ihren lokalen Zweig, bevor Sie ihn drücken:

  1. Überprüfen Sie den betreffenden Zweig, um ihn zu bearbeiten, falls er noch nicht ausgecheckt ist.

  2. Finden Sie den sha des ältesten Commits, das Sie behalten möchten.

  3. Erstellen / Auschecken eines neuen Zweigs (tmp1) aus diesem Commit.

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

  4. Füge den ursprünglichen Zweig in den neuen zusammen, der zerquetscht wird.

    git merge --squash <original branch>

  5. Übernehmen Sie die durch die Zusammenführung erstellten Änderungen mit einer zusammenfassenden Festschreibungsnachricht.

    git commit -m <msg>

  6. Kasse des ursprünglichen Zweigs, den Sie quetschen möchten.

    git checkout <branch>

  7. Setzen Sie das ursprüngliche Commit zurück, das Sie behalten möchten.

    git reset --soft <sha1>

  8. Starten Sie diesen Zweig basierend auf dem neuen Zweig tmp1 neu.

    git rebase tmp1

  9. Das war's - löschen Sie jetzt den temporären tmp1-Zweig, sobald Sie sicher sind, dass alles in Ordnung ist.

Jool
quelle
0

Sie können das von mir erstellte Tool verwenden, um diesen Prozess zu vereinfachen: Git-Squash . Um beispielsweise alle Commits für den Feature-Zweig zu quetschen, der vom Master-Zweig verzweigt wurde, schreiben Sie:

git squash master
git push --force
Sheerun
quelle