Der Rebase-Befehl hat ein paar großartige Optionen in seinem --interactive
(oder -i
) Modus. Eine der wohl am weitesten verbreiteten Optionen ist das Zusammenführen/Vereinen oder “Squashen” von Commits. Es nimmt kleinere Commits und vereint sie zu größeren Commits. Das kann zum Beispiel nützlich sein, wenn du die Tagesarbeit zusammenfassen oder wenn du deine Änderungen anders paketieren möchtest. Im Folgenden wird beschrieben, wie das geht.
Vorsicht: Führe die Aktion nur für Commits durch, die du noch nicht zu einem externen Repository geschickt hast. Wenn andere Entwickler ihre Arbeit auf der Basis deiner Commits aufbauen, die du aber ändern oder löschen wirst, können eine ganze Reihe von Konflikten auftreten. Schreibe deine History einfach nicht neu, sobald du sie mit anderen geteilt hast!
Lass uns annehmen, du hast soeben ein paar kleine Commits vorgenommen und du möchtest daraus einen größeren Commit machen. Unsere Repository-History sieht derzeit ungefähr so aus:
Die letzten 4 Commits würden schöner aussehen, wenn sie zu einem zusammengefasst wären. Das machen wir jetzt, indem wir ein interaktives Rebase durchführen:
$ git rebase -i HEAD~4 pick 01d1124 Adding license pick 6340aaa Moving license into its own file pick ebfd367 Jekyll has become self-aware. pick 30e0ccb Changed the tagline in the binary, too. # Rebase 60709da..30e0ccb onto 60709da # # Commands: # p, pick = use commit # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted. #
Ein paar Dinge passieren hier. Als erstes habe ich Git gesagt, dass es einen Rebase mit den letzten vier Commits machen soll, ausgehend vom HEAD
, also HEAD~4
. Git hat mir einen Editor mit dem obigen Text geöffnet und eine kleine Erklärung eingefügt, was ich nun machen kann. Nun stehen ein paar Optionen zur Verfügung, aber wir möchten vorerst alles in einen Commit zusammenführen. Ändere die ersten vier Zeilen der Datei folgendermaßen und das gewünschte Ergebnis wird erreicht:
pick 01d1124 Adding license squash 6340aaa Moving license into its own file squash ebfd367 Jekyll has become self-aware. squash 30e0ccb Changed the tagline in the binary, too.
Im Grunde genommen wird Git gesagt, alle vier Commits sollen in den ersten Commit in der Liste zusammenführt werden. Sobald das erledigt und gespeichert ist, kommt wieder ein Editor mit dem folgenden Inhalt:
# This is a combination of 4 commits. # The first commit's message is: Adding license # This is the 2nd commit message: Moving license into its own file # This is the 3rd commit message: Jekyll has become self-aware. # This is the 4th commit message: Changed the tagline in the binary, too. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # Explicit paths specified without -i nor -o; assuming --only paths... # Not currently on any branch. # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: LICENSE # modified: README.textile # modified: Rakefile # modified: bin/jekyll #
Weil wir mehrere Commits zu einem zusammenführen, erlaubt uns Git die Commitnachricht auf der Grundlage der im Prozess involvierten Commits zu ändern. Bearbeite die Nachricht, wie es dir gefällt, speichere und schließe den Editor. Jetzt sind deine Commits erfolgreich zusammengeführt, sie sind “squashed”!
Created commit 0fc4eea: Creating license file, and making jekyll self-aware. 4 files changed, 27 insertions(+), 30 deletions(-) create mode 100644 LICENSE Successfully rebased and updated refs/heads/master.
Und wenn du wieder in die History schaust…
Das war soweit relativ schmerzfrei. Wenn du während des Rebase auf Konflikte triffst, sind sie in der Regel recht einfach aufzulösen und Git führt dich so gut es kann durch. Die Grundlage besteht in der Auflösung des fraglichen Konflikts. git add
auf die Datei und dann ein git rebase --continue
setzt den Prozess fort. Natürlich bringt dich ein git rebase --abort
zurück zu deinem vorherigen Zustand, wenn du möchtest. Solltest du aus irgendeinem Grund während des Rebase einen Commit verloren haben, kannst du reflog benutzen, um ihn wiederherzustellen.
Es gibt eine ganze Reihe von anderen Nutzungsmöglichkeiten für git rebase -i
, die noch nicht betrachtet wurden. Falls du eine kennst, die du mitteilen möchtest, reiche einen Tip ein! GitCasts hat ein schönes Video über den gesamten Prozess und behandelt ein paar komplexere Beispiele dieses Befehls.