Git: Wie man alle Commits auf dem Zweig quetscht

315

Ich mache einen neuen Zweig aus master:

git checkout -b testbranch

Ich mache 20 Commits.

Jetzt möchte ich diese 20 Commits zerquetschen. Ich mache das mit:

git rebase -i HEAD~20

Was ist, wenn ich nicht weiß, wie viele Commits? Gibt es eine Möglichkeit, etwas zu tun wie:

git rebase -i all on this branch
user3803850
quelle
6
Sie können git rebase -i 58333012713fc168bd70ad00d191b3bdc601fa2deine interaktive Rebase durchführen, bei der die Commit-Nummer die letzte Commit ist, die unverändert
denns
@denns Mit dieser Methode mit dem letzten Commit in der Branche Dir Rebasing von fantastisch gearbeitet. Vielen Dank!
Joshua Pinter

Antworten:

395

Eine andere Möglichkeit, alle Ihre Commits zu quetschen, besteht darin, den Index auf master zurückzusetzen:

 git checkout yourBranch
 git reset $(git merge-base master yourBranch)
 git add -A
 git commit -m "one commit on yourBranch"

Dies ist nicht perfekt, da Sie wissen, aus welcher Branche "yourBranch" stammt.
Hinweis: Das Finden dieses Ursprungszweigs ist mit Git nicht einfach / möglich (der visuelle Weg ist oft der einfachste , wie hier gezeigt ).


BEARBEITEN: Sie müssen verwenden git push --force


Karlotcha Hoa fügt in den Kommentaren hinzu :

Für den Reset können Sie tun

git reset $(git merge-base master $(git rev-parse --abbrev-ref HEAD)) 

[Das] verwendet automatisch den Zweig, in dem Sie sich gerade befinden.
Und wenn Sie das verwenden, können Sie auch einen Alias ​​verwenden, da der Befehl nicht vom Zweignamen abhängt .

VonC
quelle
2
Besser zur Kasse gehen, um festzuhalten, wo YourBranchgerade ist. Dies wird YourBranchintakt bleiben, wenn Sie dies tunreset
Eugen Konkov
1
@Abdurrahim Oder öffne eine Git-Bash und du kannst diese Befehle kopieren und einfügen!
VonC
3
Für das Zurücksetzen können Sie git reset $(git merge-base master $(git rev-parse --abbrev-ref HEAD))den Zweig, in dem Sie sich gerade befinden, automatisch verwenden. Und wenn Sie das verwenden, können Sie auch einen Alias ​​verwenden, da der Befehl nicht vom Zweignamen abhängt.
Karlotcha Hoa
1
@ Druska Für einfache Verzweigungsfälle, nein, es sollte gut funktionieren.
VonC
1
@Shimmy ja, vorausgesetzt, Sie erzwingen nach dem Zurücksetzen einen Push: git push --force(und warnen Ihre Kollegen, wenn Sie mehrere Personen sind, die an diesem Zweig arbeiten)
VonC
112

Überprüfen Sie den Zweig, für den Sie alle Commits in einem Commit zusammenfassen möchten. Sagen wir, es heißt , feature_branch.

git checkout feature_branch

Schritt 1:

Führen Sie einen Soft-Reset origin/feature_branchmit Ihrer lokalen masterNiederlassung durch (je nach Bedarf können Sie auch mit origin / master zurücksetzen). Dadurch werden alle zusätzlichen Commits in Ihrem System zurückgesetzt feature_branch, ohne dass Änderungen an Ihren Dateien lokal vorgenommen werden müssen.

git reset --soft master

Schritt 2:

Fügen Sie alle Änderungen in Ihrem Git-Repo-Verzeichnis zu dem neuen Commit hinzu, das erstellt werden soll. Und begehen Sie dasselbe mit einer Nachricht.

git add -A && git commit -m "commit message goes here"

shanky
quelle
6
Dies war für mich die zuverlässigste Lösung - weder Rebase-Fehler noch Zusammenführungskonflikte.
ANTARA
1
Warnung: Der Git Add -A fügt ALLES hinzu, was Sie im lokalen Ordner haben - zum Zweig.
David H
liebe diese Lösung! genau das wollte ich!
Jacoballenwood
1
Die beste Lösung für einen Noob - zerstörungsfreien und nur oops Moment kann darin bestehen, zu viel wie App-Geheimnisse usw. einzuchecken, was keine Rolle spielen sollte, wenn Sie eine richtige Gitignore-Datei haben
kkarakk
@NSduToit Kurze Antwort: Nein, das musst du nicht. Nachdem Sie die oben genannten Schritte in meiner Antwort ausgeführt haben, erhalten Sie ein Commit mit einigen Codeänderungen. Sie können es sich wie jedes andere Commit mit einigen Codeänderungen vorstellen. Sie können dies ohne das -fFlag an Ihren Remote-Zweig senden.
Shanky
110

Was Sie tun, ist ziemlich fehleranfällig. Mach einfach:

git rebase -i master

Dadurch werden automatisch nur die Commits Ihrer Zweigstelle auf den aktuell neuesten Master zurückgesetzt.

Eevee
quelle
5
danke, ich habe das, aber warum ist mein System fehleranfällig
user3803850
10
Wahrscheinlich, weil es leicht ist, die Nummer falsch zu verstehen?
Daniel Scott
13
Einverstanden ist dies Ihre beste Lösung. Folgen Sie diesem Link , um besser zu erklären, was Sie tun müssen.
Christo
3
Anstatt Commits zu quetschen, können Sie den Zweig zum Master zusammenführen und einen Git-Reset auf origin / master durchführen, um alle Commits aufzuheben. Damit können Sie Ihren vorhandenen nicht bereitgestellten Code mitcommit -am "the whole thing!"
nurettin
2
@nurettin Ich denke, die reset origin/masterMethode ist wirklich schlecht, da sie genauso ist wie das Festschreiben direkt auf dem Master - es gibt keinen "Merge Branch" -Historie, keine Pull-Request-Option. Die Antwort von @WaZaA entspricht meiner Meinung nach viel mehr dem normalen Git-Workflow
Drenai,
79

Eine andere einfache Möglichkeit, dies zu tun: Gehen Sie zum Ursprungszweig und führen Sie a aus merge --squash. Dieser Befehl führt das "gequetschte" Commit nicht aus. Wenn Sie dies tun, werden alle Festschreibungsnachrichten Ihrer Branche gesammelt.

$ git checkout master
$ git merge --squash yourBranch
$ git commit # all commit messages of yourBranch in one, really useful
 > [status 5007e77] Squashed commit of the following: ...
WaZaA
quelle
1
Wahr. Ich erwähnte den Unterschied zwischen Merge --squash und Rebase -i in stackoverflow.com/a/2427520/6309
VonC
1
Dies funktioniert, wenn Sie nicht in den übergeordneten Zweig quetschen möchten. Erstellen Sie einfach einen neuen Zweig, der auf dem übergeordneten Zweig basiert, und wechseln Sie zu diesem, und führen Sie den Squash in diesen Zweig ein.
Charlotte
Prost Kumpel, toller Tipp!
Nestor Milyaev
nett! Ich erstelle einen "temporären" Zweig von "master", um zuerst "yourBranch" zu quetschen, und füge dann "temp" zu "master" zusammen.
Lazieburd
34

Angenommen, Sie haben vom Master verzweigt, müssen Sie nicht immer yourBranchin den Reset-Schritt eintreten :

git checkout yourBranch
git reset --soft HEAD~$(git rev-list --count HEAD ^master)
git add -A
git commit -m "one commit on yourBranch"

Erklärung :

  • git rev-list --count HEAD ^masterzählt die Commits, seit Sie Ihren Feature-Zweig vom Master aus erstellt haben, z. 20.
  • git reset --soft HEAD~20führt einen Soft-Reset der letzten 20 Commits durch. Dadurch bleiben Ihre Änderungen in den Dateien, die Commits werden jedoch entfernt.

Verwendung :

In meinem .bash_profile habe ich einen Alias ​​hinzugefügt gisquash, um dies mit einem Befehl zu tun:

# squash all commits into one
alias gisquash='git reset --soft HEAD~$(git rev-list --count HEAD ^master)'

Nach dem Zurücksetzen und Festschreiben müssen Sie eine git push --force.

Hinweis :

Wenn Sie Gitlab> = 11.0 verwenden, müssen Sie dies nicht mehr tun, da es beim Zusammenführen von Zweigen eine Squashing-Option bietet . Gitlab Squashing Option

mles
quelle
15

Basierend auf dem Lesen mehrerer Stackoverflow-Fragen und Antworten zum Squashing denke ich, dass dies ein guter Einzeiler ist, um alle Commits in einem Zweig zu quetschen:

git reset --soft $(git merge-base master YOUR_BRANCH) && git commit -am "YOUR COMMIT MESSAGE" && git rebase -i master

Dies setzt voraus, dass der Master der Basiszweig ist.

Travis Reeder
quelle
1
Vielen Dank, das Unternehmen hat viele Einschränkungen und konnte die übliche Vorgehensweise mit einem Editor nicht neu festlegen, da das Speichern nicht laut war. Außerdem konnte die Squash- und Merge-Funktion in Git nicht verwendet werden, da dieser Zweig zum Zusammenführen an Lead Dev geht und er ihn nicht mag. Dieser 1 Liner funktionierte und ersparte Kopfschmerzen. Beeindruckende Arbeit.
L1ghtk3ira
10

Lösung für Leute, die lieber klicken:

  1. Sourcetree installieren (kostenlos)

  2. Überprüfen Sie, wie Ihre Commits aussehen. Höchstwahrscheinlich haben Sie etwas Ähnliches Geben Sie hier die Bildbeschreibung ein

  3. Klicken Sie mit der rechten Maustaste auf das übergeordnete Commit. In unserem Fall handelt es sich um eine Hauptniederlassung.

Geben Sie hier die Bildbeschreibung ein

  1. Sie können das Commit mit dem vorherigen quetschen, indem Sie auf eine Schaltfläche klicken. In unserem Fall müssen wir 2 mal klicken. Sie können auch die Festschreibungsnachricht ändern Geben Sie hier die Bildbeschreibung ein

  2. Die Ergebnisse sind fantastisch und wir sind bereit zu pushen! Geben Sie hier die Bildbeschreibung ein

Randnotiz: Wenn Sie Ihre Teil-Commits auf die Fernbedienung übertragen haben, müssen Sie nach dem Squash Force Push anwenden

Marcin Szymczak
quelle
Danke dafür!
Crystal
0

Eine andere Lösung wäre, alle Festschreibungsprotokolle in einer Datei zu speichern

git log> branch.log

Jetzt hat branch.log alle Commit-IDs von Anfang an. Scrollen Sie nach unten und nehmen Sie das erste Commit (dies wird im Terminal schwierig sein) mit dem ersten Commit

git reset --soft

Alle Commits werden gequetscht

Pranav
quelle
0

Git-Reset ist, wie in vielen Antworten bereits erwähnt, bei weitem der beste und einfachste Weg, um das zu erreichen, was Sie wollen. Ich benutze es im folgenden Workflow:

(auf Entwicklungszweig)

git fetch
git merge origin/master  #so development branch has all current changes from master
git reset origin/master  #will show all changes from development branch to master as unstaged
git gui # do a final review, stage all changes you really want
git commit # all changes in a single commit
git branch -f master #update local master branch
git push origin master #push it
Marcus
quelle
0

All dieses Git-Reset, hart, weich und alles andere, was hier erwähnt wird, funktioniert wahrscheinlich (es hat bei mir nicht funktioniert), wenn Sie die Schritte richtig machen und eine Art Geist.
Wenn Sie der durchschnittliche Joe Smo sind, versuchen Sie Folgendes :
Wie verwende ich Git Merge --squash?


Ich habe mein Leben gerettet und werde mein Squash sein. Ich habe es 4 Mal benutzt, seit ich davon erfahren habe. Einfach, sauber und im Grunde 1 comamnd. Kurz gesagt:


Wenn Sie sich in einem Zweig befinden, nennen Sie ihn "my_new_feature" off "Entwickeln" und Ihre Pull-Anfrage hat 35 Commits (oder wie viele auch immer) und Sie möchten, dass es 1 ist.

A. Stellen Sie sicher, dass Ihr Zweig auf dem neuesten Stand ist. Fahren Sie fort Entwickeln Sie, erhalten Sie die neuesten Informationen und führen Sie Konflikte mit "my_new_feature" zusammen und lösen Sie sie
(diesen Schritt sollten Sie wirklich so schnell wie möglich

ausführen ). B. Holen Sie sich die neuesten Entwicklungen und verzweigen Sie in einen neuen Zweig, nennen Sie ihn "my_new_feature_squashed".

C. Magie ist hier.
Sie möchten Ihre Arbeit von "my_new_feature" zu "my_new_feature_squashed" bringen. Gehen Sie
also einfach vor (während Sie in Ihrem neuen Zweig die Entwicklung erstellt haben):
git merge --squash my_new_feature

Alle Ihre Änderungen befinden sich jetzt in Ihrer neuen Niederlassung. Testen Sie sie einfach. Führen Sie dann einfach 1 Commit, Push und neue PR für diese Niederlassung durch - und warten Sie auf die Wiederholung am nächsten Tag.
Liebst du nicht das Codieren? :) :)

ItaiRoded
quelle