Wie kann ich meine letzten X-Commits mit Git zu einem Commit zusammenfassen?
Wie kann ich meine letzten X-Commits mit Git zu einem Commit zusammenfassen?
Antworten:
Verwenden git rebase -i <after-this-commit>
und ersetzen Sie "pick" beim zweiten und nachfolgenden Commit durch "squash" oder "fixup", wie im Handbuch beschrieben .
In diesem Beispiel <after-this-commit>
ist dies entweder der SHA1-Hash oder die relative Position vom HEAD des aktuellen Zweigs, von dem aus Commits für den Rebase-Befehl analysiert werden. Wenn der Benutzer beispielsweise 5 Commits vom aktuellen HEAD in der Vergangenheit anzeigen möchte, lautet der Befehl git rebase -i HEAD~5
.
<after-this-commit>
?
<after-this-commit>
ist Commit X + 1, dh übergeordnetes Element des ältesten Commits, das Sie quetschen möchten.
rebase -i
Ansatz und reset --soft
besteht darin, rebase -i
dass ich den Commit-Autor behalten reset --soft
und erneut festlegen kann. Manchmal muss ich Commits von Pull-Anfragen quetschen und dabei die Autoreninformationen beibehalten. Manchmal muss ich Soft auf meine eigenen Commits zurücksetzen. Upvotes zu beiden tollen Antworten sowieso.
Sie können dies ziemlich einfach ohne git rebase
oder tun git merge --squash
. In diesem Beispiel werden die letzten 3 Commits gequetscht.
Wenn Sie die neue Festschreibungsnachricht von Grund auf neu schreiben möchten, reicht dies aus:
git reset --soft HEAD~3 &&
git commit
Wenn Sie mit dem Bearbeiten der neuen Festschreibungsnachricht mit einer Verkettung der vorhandenen Festschreibungsnachrichten beginnen möchten (dh ähnlich wie mit einer Befehlsliste pick / squash / squash /… / squash git rebase -i
), müssen Sie diese Nachrichten extrahieren und übergeben sie zu git commit
:
git reset --soft HEAD~3 &&
git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"
Beide Methoden zerlegen die letzten drei Commits auf dieselbe Weise zu einem einzigen neuen Commit. Der Soft-Reset zeigt HEAD nur auf das letzte Commit, das Sie nicht quetschen möchten. Weder der Index noch der Arbeitsbaum werden vom Soft-Reset berührt, sodass der Index für Ihr neues Commit im gewünschten Zustand bleibt (dh er enthält bereits alle Änderungen gegenüber den Commits, die Sie "wegwerfen" möchten).
git rebase --squash-recent
oder sogar git commit --amend-many
.
branch@{upstream}
(oder nur @{upstream}
für den aktuellen Zweig; in beiden Fällen kann der letzte Teil mit abgekürzt werden @{u}
; siehe Gitrevisions ). Dies kann von Ihrem „letzten Push-Commit“ abweichen (z. B. wenn jemand anderes etwas gepusht hat, das auf Ihrem letzten Push aufgebaut wurde, und Sie das dann abgerufen haben), aber es scheint, als ob es nahe an dem liegt, was Sie wollen.
push -f
aber sonst war es schön, danke.
git push --force
danach verwenden, damit es das Commit dauert
Sie können dafür verwenden git merge --squash
, was etwas eleganter ist als git rebase -i
. Angenommen, Sie sind auf dem Master und möchten die letzten 12 Commits zu einem zusammenfassen.
WARNUNG: Stellen Sie zunächst sicher, dass Sie Ihre Arbeit festschreiben - überprüfen Sie, ob diese git status
sauber ist (da git reset --hard
inszenierte und nicht inszenierte Änderungen weggeworfen werden).
Dann:
# Reset the current branch to the commit just before the last 12:
git reset --hard HEAD~12
# HEAD@{1} is where the branch was just before the previous command.
# This command sets the state of the index to be as it would just
# after a merge from that commit:
git merge --squash HEAD@{1}
# Commit those squashed changes. The commit message will be helpfully
# prepopulated with the commit messages of all the squashed commits:
git commit
In der Dokumentation zugit merge
wird die --squash
Option ausführlicher beschrieben.
Update: Der einzige wirkliche Vorteil dieser Methode gegenüber dem git reset --soft HEAD~12 && git commit
von Chris Johnsen in seiner Antwort vorgeschlagenen einfacheren ist, dass Sie die Festschreibungsnachricht mit jeder Festschreibungsnachricht, die Sie quetschen, vorab ausgefüllt erhalten.
git rebase -i
, aber Sie geben keinen Grund dafür an. Dies vorläufig, weil es mir so scheint, als ob tatsächlich das Gegenteil der Fall ist und dies ein Hack ist; Führen Sie nicht mehr Befehle als nötig aus, nur um git merge
eines der Dinge zu erzwingen , für die git rebase
es speziell entwickelt wurde?
git merge --squash
ist auch in einem Skript einfacher zu verwenden. Im Wesentlichen war die Begründung, dass Sie dafür überhaupt nicht die "Interaktivität" benötigen git rebase -i
.
git merge --squash
es angesichts von Verschiebungen / Löschungen / Umbenennungen weniger wahrscheinlich zu Zusammenführungskonflikten kommt als bei einer erneuten Basierung, insbesondere wenn Sie aus einem lokalen Zweig zusammenführen. (Haftungsausschluss: basierend auf nur einer Erfahrung, korrigieren Sie mich, wenn dies im allgemeinen Fall nicht wahr ist!)
HEAD@{1}
nur auf der sicheren Seite zu sein, z. B. wenn Ihr Workflow für eine Stunde durch einen Stromausfall usw. unterbrochen wird.
Ich empfehle, git reset
wenn möglich zu vermeiden - besonders für Git-Neulinge. Wenn Sie einen Prozess, der auf einer Reihe von Commits basiert, nicht wirklich automatisieren müssen , gibt es einen weniger exotischen Weg ...
git merge --squash (working branch name)
git commit
Die Festschreibungsnachricht wird basierend auf dem Squash vorab ausgefüllt.
gitk
, um die Codezeile zu kennzeichnen, die Sie quetschen, und auch die Basis, auf der gequetscht werden soll. Im Normalfall sind diese beiden Beschriftungen bereits vorhanden, sodass Schritt (1) übersprungen werden kann.
git branch your-feature && git reset --hard HEAD~N
den bequemsten Weg gefunden. Es wird jedoch erneut ein Git-Reset durchgeführt, was durch diese Antwort vermieden werden sollte.
Basierend auf der Antwort von Chris Johnsen ,
Fügen Sie einen globalen "Squash" -Alias von bash hinzu: (oder Git Bash unter Windows)
git config --global alias.squash '!f(){ git reset --soft HEAD~${1} && git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"; };f'
... oder über die Windows-Eingabeaufforderung:
git config --global alias.squash "!f(){ git reset --soft HEAD~${1} && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; };f"
Sie ~/.gitconfig
sollten jetzt diesen Alias enthalten:
[alias]
squash = "!f(){ git reset --soft HEAD~${1} && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; };f"
Verwendungszweck:
git squash N
... die automatisch die letzten N
Commits zusammenquetscht, einschließlich.
Hinweis: Die resultierende Festschreibungsnachricht ist eine Kombination aller gequetschten Festschreibungen in der angegebenen Reihenfolge. Wenn Sie damit nicht zufrieden sind, können Sie es jederzeit git commit --amend
manuell ändern. (Oder bearbeiten Sie den Alias nach Ihrem Geschmack.)
git squash -m "New summary."
und N
automatisch bestimmen.
git commit --amend
die Nachricht weiter ändern. Mit diesem Alias können Sie jedoch gut beginnen, was in der Festschreibungsnachricht enthalten sein soll.
Dank dieses praktischen Blogposts habe ich festgestellt, dass Sie diesen Befehl verwenden können, um die letzten 3 Commits zu quetschen:
git rebase -i HEAD~3
Dies ist praktisch, da es auch dann funktioniert, wenn Sie sich in einer lokalen Filiale ohne Tracking-Informationen / Remote-Repo befinden.
Der Befehl öffnet den interaktiven Rebase-Editor, mit dem Sie wie gewohnt neu ordnen, quetschen, umformulieren usw. können.
Verwenden des interaktiven Rebase-Editors:
Der interaktive Rebase-Editor zeigt die letzten drei Commits an. Diese Einschränkung wurde durch HEAD~3
Ausführen des Befehls bestimmt git rebase -i HEAD~3
.
Das letzte Commit HEAD
wird zuerst in Zeile 1 angezeigt. Die mit a beginnenden Zeilen #
sind Kommentare / Dokumentationen.
Die angezeigte Dokumentation ist ziemlich klar. In jeder Zeile können Sie den Befehl von pick
in einen Befehl Ihrer Wahl ändern .
Ich bevorzuge die Verwendung des Befehls, fixup
da dies die Änderungen des Commits in das Commit in der obigen Zeile "quetscht" und die Nachricht des Commits verwirft.
Da das Commit in Zeile 1 lautet HEAD
, würden Sie dies in den meisten Fällen als belassen pick
. Sie können nicht verwenden squash
oder fixup
da es kein anderes Commit gibt, in das Sie das Commit drücken können.
Sie können auch die Reihenfolge der Commits ändern. Auf diese Weise können Sie Commits quetschen oder korrigieren, die chronologisch nicht benachbart sind.
Ein praktisches Alltagsbeispiel
Ich habe kürzlich eine neue Funktion festgelegt. Seitdem habe ich zwei Bugfixes begangen. Aber jetzt habe ich einen Fehler (oder vielleicht nur einen Rechtschreibfehler) in der neuen Funktion entdeckt, die ich begangen habe. Wie nervig! Ich möchte kein neues Commit, das meine Commit-Historie verschmutzt!
Als erstes behebe ich den Fehler und mache ein neues Commit mit dem Kommentar squash this into my new feature!
.
Ich starte dann git log
oder gitk
und erhalte die Commit-SHA der neuen Funktion (in diesem Fall 1ff9460
).
Als nächstes rufe ich den interaktiven Rebase-Editor mit auf git rebase -i 1ff9460~
. Die ~
SHA nach dem Festschreiben weist den Editor an, dieses Festschreiben in den Editor aufzunehmen.
Als Nächstes verschiebe ich das Commit mit dem fix ( fe7f1e0
) unter das Feature-Commit und wechsle pick
zu fixup
.
Wenn Sie den Editor schließen, wird das Update in das Feature-Commit gequetscht und mein Commit-Verlauf sieht gut und sauber aus!
Dies funktioniert gut, wenn alle Commits lokal sind. Wenn Sie jedoch versuchen, bereits auf die Fernbedienung übertragene Commits zu ändern, können Sie anderen Entwicklern, die denselben Zweig ausgecheckt haben, wirklich Probleme bereiten!
pick
in Zeile 1. Wenn Sie squash
oder fixup
für das Commit in Zeile 1 wählen , zeigt git die Meldung "Fehler: Ohne vorheriges Commit kann nicht 'repariert' werden". Dann haben Sie die Möglichkeit, das Problem zu beheben: "Sie können dies mit 'git rebase --edit-todo' beheben und dann 'git rebase --continue' ausführen." oder Sie können einfach abbrechen und von vorne beginnen: "Oder Sie können die Rebase mit 'git rebase --abort' abbrechen."
Wenn Sie TortoiseGit verwenden, können Sie die Funktion Combine to one commit
:
Show Log
Combine to one commit
aus dem KontextmenüDiese Funktion führt automatisch alle erforderlichen Single-Git-Schritte aus. Leider nur für Windows verfügbar.
Dazu können Sie den folgenden git-Befehl verwenden.
git rebase -i HEAD~n
n (= 4 hier) ist die Anzahl der letzten Festschreibungen. Dann haben Sie folgende Optionen:
pick 01d1124 Message....
pick 6340aaa Message....
pick ebfd367 Message....
pick 30e0ccb Message....
Aktualisieren Sie wie unten beschrieben pick
ein Commit und squash
die anderen in das neueste,
p 01d1124 Message....
s 6340aaa Message....
s ebfd367 Message....
s 30e0ccb Message....
Für Details klicken Sie auf den Link
Basierend auf diesem Artikel fand ich diese Methode für meinen Anwendungsfall einfacher.
Mein 'dev'-Zweig lag um 96 Commits vor' origin / dev '(daher wurden diese Commits noch nicht auf die Fernbedienung übertragen).
Ich wollte diese Commits zu einem zusammenfassen, bevor ich die Änderung vorantreibe. Ich ziehe es vor, den Zweig auf den Status 'origin / dev' zurückzusetzen (dies lässt alle Änderungen von den 96 Commits nicht inszeniert) und dann die Änderungen sofort festzuschreiben:
git reset origin/dev
git add --all
git commit -m 'my commit message'
Führen Sie in der Verzweigung, in der Sie die Commits kombinieren möchten, Folgendes aus:
git rebase -i HEAD~(n number of commits back to review)
Beispiel:
git rebase -i HEAD~1
Dadurch wird der Texteditor geöffnet und Sie müssen die Auswahl vor jedem Commit durch "Squash" ersetzen, wenn diese Commits zusammengeführt werden sollen. Aus der Dokumentation:
Wenn Sie beispielsweise alle Commits zu einem zusammenführen möchten, ist die Auswahl das erste Commit, das Sie vorgenommen haben, und alle zukünftigen Commits (unter dem ersten) sollten auf "Squash" gesetzt werden. Wenn Sie vim verwenden, verwenden Sie : x im Einfügemodus, um den Editor zu speichern und zu beenden.
Dann, um die Rebase fortzusetzen:
git rebase --continue
Weitere Informationen zu diesem und anderen Möglichkeiten zum Umschreiben Ihres Commit-Verlaufs finden Sie in diesem hilfreichen Beitrag
--continue
und vim :x
macht.
git add
die richtige Konfiguration in Ihren Dateien vorgenommen haben git rebase --continue
, wechseln Sie zum nächsten Commit und beginnen mit dem Zusammenführen. :x
ist ein Befehl, der die Änderungen der Datei bei Verwendung von vim speichert, siehe dies
Die Antwort von Anomies ist gut, aber ich fühlte mich unsicher, deshalb habe ich beschlossen, ein paar Screenshots hinzuzufügen.
Sehen Sie, wo Sie sind git log
. Am wichtigsten ist, dass Sie den Commit-Hash des ersten Commits finden, den Sie nicht quetschen möchten. Also nur die:
Führen Sie git rebase -i [your hash]
in meinem Fall aus:
$ git rebase -i 2d23ea524936e612fae1ac63c95b705db44d937d
In meinem Fall möchte ich alles auf dem Commit zerquetschen, was zum ersten Mal war. Die Bestellung erfolgt vom ersten bis zum letzten, also genau umgekehrt wie in git log
. In meinem Fall möchte ich:
Wenn Sie nur ein Commit ausgewählt und den Rest gequetscht haben, können Sie eine Commit-Nachricht anpassen:
Das ist es. Sobald Sie dies ( :wq
) gespeichert haben, sind Sie fertig. Schau es dir an mit git log
.
git log
1) Identifizieren Sie den Commit Short Hash
# git log --pretty=oneline --abbrev-commit
abcd1234 Update to Fix for issue B
cdababcd Fix issue B
deab3412 Fix issue A
....
Hier kann sogar git log --oneline
auch verwendet werden, um kurzen Hash zu bekommen.
2) Wenn Sie die letzten beiden Commits quetschen (zusammenführen) möchten
# git rebase -i deab3412
3) Dies öffnet einen nano
Editor zum Zusammenführen. Und es sieht aus wie unten
....
pick cdababcd Fix issue B
pick abcd1234 Update to Fix for issue B
....
4) Benennen Sie das vorher vorhandene Wort pick
um . Nach dem Umbenennen sollte es wie folgt sein.squash
abcd1234
....
pick cdababcd Fix issue B
squash abcd1234 Update to Fix for issue B
....
5) Speichern und schließen Sie nun den nano
Editor. Drücken Sie ctrl + o
und drücken Sie Enter
zu speichern. Drücken Sie dann ctrl + x
, um den Editor zu verlassen.
6) Anschließend wird der nano
Editor erneut geöffnet, um Kommentare zu aktualisieren und gegebenenfalls zu aktualisieren.
7) Jetzt ist es erfolgreich gequetscht. Sie können es überprüfen, indem Sie die Protokolle überprüfen.
# git log --pretty=oneline --abbrev-commit
1122abcd Fix issue B
deab3412 Fix issue A
....
8) Drücken Sie nun auf Repo. Hinweis zum Hinzufügen eines +
Zeichens vor dem Filialnamen. Dies bedeutet erzwungenen Druck.
# git push origin +master
Hinweis: Dies basiert auf der Verwendung von git on ubuntu
shell. Wenn Sie ein anderes Betriebssystem ( Windows
oder Mac
) verwenden, sind die obigen Befehle mit Ausnahme des Editors identisch. Möglicherweise erhalten Sie einen anderen Editor.
git add <files>
--fixup
Option und das OLDCOMMIT
sollte sein, auf dem wir dieses Commit zusammenführen (Squash) müssen.git commit --fixup=OLDCOMMIT
Dies schafft nun ein neues Commit über HEAD mit fixup1 <OLDCOMMIT_MSG>
.
OLDCOMMIT
.git rebase --interactive --autosquash OLDCOMMIT^
Hier ^
bedeutet das vorherige Commit zu OLDCOMMIT
. Dieser rebase
Befehl öffnet ein interaktives Fenster in einem Editor (vim oder nano), in dem Sie nichts weiter tun müssen, nur das Speichern und Beenden ist ausreichend. Da die an diese Option übergebene Option das letzte Commit automatisch neben das alte Commit verschiebt und den Vorgang in fixup
(entspricht Squash) ändert . Dann wird die Rebase fortgesetzt und beendet.
--amend
können Mittel mit verwendet werden git-commit
. # git log --pretty=oneline --abbrev-commit
cdababcd Fix issue B
deab3412 Fix issue A
....
# git add <files> # New changes
# git commit --amend
# git log --pretty=oneline --abbrev-commit
1d4ab2e1 Fix issue B
deab3412 Fix issue A
....
Hier werden --amend
die neuen Änderungen zum letzten Commit zusammengeführt cdababcd
und eine neue Commit-ID generiert1d4ab2e1
So zerquetschen Sie die letzten 10 Commits zu einem einzigen Commit:
git reset --soft HEAD~10 && git commit -m "squashed commit"
Wenn Sie auch den Remote-Zweig mit dem Squashed Commit aktualisieren möchten:
git push -f
Wenn Sie sich in einem Remote-Zweig (aufgerufen feature-branch
) befinden, der aus einem Golden Repository () geklont wurde golden_repo_name
, können Sie Ihre Commits wie folgt in einen Zweig zerlegen :
Kasse das goldene Repo
git checkout golden_repo_name
Erstellen Sie daraus einen neuen Zweig (goldenes Repo) wie folgt
git checkout -b dev-branch
Squash wird mit Ihrer lokalen Niederlassung zusammengeführt, die Sie bereits haben
git merge --squash feature-branch
Übernehmen Sie Ihre Änderungen (dies ist das einzige Commit, das in dev-branch ausgeführt wird).
git commit -m "My feature complete"
Schieben Sie den Zweig in Ihr lokales Repository
git push origin dev-branch
Was wirklich praktisch sein kann:
Finden Sie beispielsweise den Commit-Hash, auf den Sie Squash ausführen möchtend43e15
.
Jetzt benutzen
git reset d43e15
git commit -am 'new commit name'
Das ist super-duper kludgy, aber irgendwie cool, also werfe ich es einfach in den Ring:
GIT_EDITOR='f() { if [ "$(basename $1)" = "git-rebase-todo" ]; then sed -i "2,\$s/pick/squash/" $1; else vim $1; fi }; f' git rebase -i foo~5 foo
Übersetzung: Stellen Sie einen neuen "Editor" für git bereit, der, wenn der zu bearbeitende Dateiname lautet git-rebase-todo
(die interaktive Rebase-Eingabeaufforderung), alle bis auf die erste "Auswahl" in "Squash" ändert und ansonsten vim erzeugt - so dass, wenn Sie dazu aufgefordert werden Um die Squashed Commit-Nachricht zu bearbeiten, erhalten Sie vim. (Und natürlich habe ich die letzten fünf Commits auf Branch Foo gequetscht, aber Sie können das ändern, wie Sie möchten.)
Ich würde wahrscheinlich tun, was Mark Longair vorgeschlagen hat.
Wenn Sie jedes Commit in ein einzelnes Commit zerlegen möchten (z. B. wenn Sie ein Projekt zum ersten Mal öffentlich veröffentlichen), versuchen Sie Folgendes:
git checkout --orphan <new-branch>
git commit
Ich denke, der einfachste Weg, dies zu tun, besteht darin, einen neuen Zweig aus dem Master zu machen und einen Merge-Quash des Feature-Zweigs durchzuführen.
git checkout master
git checkout -b feature_branch_squashed
git merge --squash feature_branch
Dann haben Sie alle Änderungen bereit, um festzuschreiben.
Einfacher Einzeiler, der immer funktioniert, vorausgesetzt, Sie befinden sich derzeit in dem Zweig, den Sie quetschen möchten, Master ist der Zweig, aus dem er stammt, und das letzte Commit enthält die Commit-Nachricht und den Autor, den Sie verwenden möchten:
git reset --soft $(git merge-base HEAD master) && git commit --reuse-message=HEAD@{1}
Wenn Sie beispielsweise die letzten 3 Commits für ein einzelnes Commit in einem Zweig (Remote-Repository) quetschen möchten, zum Beispiel: Bedingungen https://bitbucket.org
Was ich getan habe ist
(MASTER)
Fleetwood Mac Fritz
║ ║
Add Danny Lindsey Stevie
Kirwan Buckingham Nicks
║ ╚═══╦══════╝
Add Christine ║
Perfect Buckingham
║ Nicks
LA1974══════════╝
║
║
Bill <══════ YOU ARE EDITING HERE
Clinton (CHECKED OUT, CURRENT WORKING DIRECTORY)
In dieser sehr verkürzten Historie des Repositorys https://github.com/fleetwood-mac/band-history haben Sie eine Pull-Anfrage geöffnet, um das Bill Clinton-Commit mit dem Original zusammenzuführen (MASTER
) Fleetwood Mac-Commit zusammenzuführen.
Sie haben eine Pull-Anfrage geöffnet und auf GitHub sehen Sie Folgendes:
Vier Commits:
Ich denke, dass es niemanden interessieren würde, den vollständigen Repository-Verlauf zu lesen. (Es gibt tatsächlich ein Repository, klicken Sie auf den Link oben!) Sie beschließen, diese Commits zu quetschen. Also gehst du und rennst git reset --soft HEAD~4 && git commit
. Dann Siegit push --force
es auf GitHub, um deine PR aufzuräumen.
Und was passiert? Sie haben gerade eine einzige Verpflichtung eingegangen, die von Fritz zu Bill Clinton führt. Weil Sie vergessen haben, dass Sie gestern an der Buckingham Nicks-Version dieses Projekts gearbeitet haben. Und git log
stimmt nicht mit dem überein, was Sie auf GitHub sehen.
git checkout
siegit reset --soft
dasgit commit
, die sich direkt von von nach nach oben verziehtgit rebase -i HEAD^^
wobei die Anzahl der ^ 's X ist
(In diesem Fall quetschen Sie die beiden letzten Commits.)
Zusätzlich zu anderen hervorragenden Antworten möchte ich hinzufügen, wie git rebase -i
mich immer mit der Festschreibungsreihenfolge verwechselt wird - älter als neuere oder umgekehrt? Das ist also mein Workflow:
git rebase -i HEAD~[N]
, wobei N die Anzahl der Commits ist, an denen ich teilnehmen möchte, beginnend mit dem letzten . Damitgit rebase -i HEAD~5
würde bedeuten , „quetscht die letzten 5 Commits in einen neuen“;Was ist mit einer Antwort auf die Frage zu einem solchen Workflow?
merge --squash
nach der PR zu arbeiten, aber das Team dachte, dies würde den Prozess verlangsamen.)Ich habe auf dieser Seite keinen solchen Workflow gesehen. (Das können meine Augen sein.) Wenn ich rebase
richtig verstehe , würden mehrere Zusammenführungen mehrere Konfliktlösungen erfordern . Ich möchte nicht einmal darüber nachdenken!
Das scheint also für uns zu funktionieren.
git pull master
git checkout -b new-branch
git checkout -b new-branch-temp
git checkout new-branch
git merge --squash new-branch-temp
// setzt alle Änderungen in die Bühnegit commit 'one message to rule them all'
git push
Ich finde, eine allgemeinere Lösung besteht nicht darin, 'N'-Commits anzugeben, sondern die Verzweigungs- / Commit-ID, auf die Sie quetschen möchten. Dies ist weniger fehleranfällig als das Zählen der Festschreibungen bis zu einem bestimmten Festschreiben. Geben Sie das Tag einfach direkt an, oder wenn Sie wirklich zählen möchten, können Sie HEAD ~ N angeben.
In meinem Workflow starte ich einen Zweig, und mein erstes Commit für diesen Zweig fasst das Ziel zusammen (dh es ist normalerweise das, was ich als "endgültige" Nachricht für das Feature an das öffentliche Repository senden werde.) Wenn ich also fertig bin, alles Ich möchte tun ist git squash master
zurück zur ersten Nachricht und dann bin ich bereit zu pushen.
Ich benutze den Alias:
squash = !EDITOR="\"_() { sed -n 's/^pick //p' \"\\$1\"; sed -i .tmp '2,\\$s/^pick/f/' \"\\$1\"; }; _\"" git rebase -i
Dadurch wird der gequetschte Verlauf zuvor gelöscht. Dies gibt Ihnen die Möglichkeit, ihn wiederherzustellen, indem Sie eine alte Festschreibungs-ID von der Konsole abrufen, wenn Sie zurücksetzen möchten. (Solaris-Benutzer beachten, dass die GNU sed- -i
Option verwendet wird. Mac- und Linux-Benutzer sollten damit einverstanden sein.)
git squash master
wenn wir auf dem Slave ausgecheckt sind. was wird es passieren Werden wir den Konflikt verbergen?
In Frage könnte es mehrdeutig sein, was mit "zuletzt" gemeint ist.
git log --graph
gibt beispielsweise Folgendes aus (vereinfacht):
* commit H0
|
* merge
|\
| * commit B0
| |
| * commit B1
| |
* | commit H1
| |
* | commit H2
|/
|
Dann sind die letzten Commits nach Zeit H0, Merge, B0. Um sie zu quetschen, müssen Sie Ihren zusammengeführten Zweig auf Commit H1 neu gründen.
Das Problem ist, dass H0 H1 und H2 enthält (und im Allgemeinen mehr Commits vor dem Zusammenführen und nach dem Verzweigen), während B0 dies nicht tut. Sie müssen also mindestens Änderungen von H0, Merge, H1, H2, B0 verwalten.
Es ist möglich, Rebase zu verwenden, jedoch auf andere Weise als in anderen genannten Antworten:
rebase -i HEAD~2
Dies zeigt Ihnen Auswahlmöglichkeiten (wie in anderen Antworten erwähnt):
pick B1
pick B0
pick H0
Setzen Sie Squash statt Pick auf H0:
pick B1
pick B0
s H0
Nach dem Speichern und Beenden werden bei Rebase nach H1 nacheinander Commits angewendet. Das bedeutet, dass Sie aufgefordert werden, Konflikte erneut zu lösen (wobei HEAD zuerst H1 ist und dann Commits ansammelt, wenn sie angewendet werden).
Nach Abschluss der Rebase können Sie eine Nachricht für die gequetschten H0 und B0 auswählen:
* commit squashed H0 and B0
|
* commit B1
|
* commit H1
|
* commit H2
|
PS Wenn Sie nur einen Reset auf BO durchführen: (Dies wird beispielsweise reset --mixed
hier unter https://stackoverflow.com/a/18690845/2405850 näher erläutert. )
git reset --mixed hash_of_commit_B0
git add .
git commit -m 'some commit message'
Dann quetschen Sie sich in B0-Änderungen von H0, H1, H2 (der Verlust geht vollständig für Änderungen nach der Verzweigung und vor dem Zusammenführen über.