Git Squash Commits

Azhar Bashir Khan 30 Januar 2023
  1. Verwendung des interaktiven Werkzeugs git rebase zum Zerdrücken von Git-Commits
  2. Verwenden von git merge -squash zum Squash von Git Commits
Git Squash Commits

In diesem Tutorial werden wir Git-Squashing lernen. Die Grundidee besteht darin, mehrere kontinuierliche Commits zu nehmen und sie zu einem zusammenzufassen.

Die Hauptabsicht besteht darin, viele Commits auf wenige relevante Commits zu verdichten. Dadurch sieht die Git-Historie prägnant und klar aus.

Eine andere Sichtweise ist, dass wir mehrere Commits im Zusammenhang mit einer bestimmten Aufgabe ausführen. Nach einer Weile, wenn wir einen zufriedenstellenden Zustand erreichen, überladen die vielen Commit-Nachrichten die Git-Historie.

An dieser Stelle möchten wir vielleicht die verschiedenen Commits zu einem kombinieren, damit die Git-Historie klar aussieht und die erledigte Aufgabe am besten widerspiegelt.

Ein weiterer Anwendungsfall ist das Squashing beim Zusammenführen von Zweigen. Normalerweise erstellen wir für einige Feature-Entwicklungen einen Feature-Branch aus dem Haupt-Branch.

Nach der Feature-Vervollständigung führen wir den Feature-Branch in den Haupt-Branch ein. Auch hier möchten wir vielleicht die verschiedenen Commit-Nachrichten, die im Feature-Zweig gemacht wurden, beim Zusammenführen in den Haupt-Zweig zu einer zusammenfassen.

Bitte beachten Sie, dass es keinen git squash-Befehl gibt.

Es gibt zwei Möglichkeiten, um Git-Squashing zu erreichen:

  • git rebase -i als interaktives Tool zum Squash von Commits
  • git merge -squash mit der Option -squash beim Zusammenführen

Verwendung des interaktiven Werkzeugs git rebase zum Zerdrücken von Git-Commits

Betrachten Sie den folgenden Git-Log-Auszug, der die letzten vier Commits von HEAD zeigt, an deren Squash wir interessiert sind.

25c38c4 remove .class files
da66e6a Delete version.ini
f4e3f09 Delete .log
b0e6655 Delete .lock
da66e6a github git notes

Wir können im Protokoll die ersten vier Commit-Meldungen sehen, die das Löschen verschiedener irrelevanter Dateien anzeigen. Jetzt werden wir diese vier Commits zu einem zusammenfassen.

Es folgt die Syntax des Befehls zum Squash der letzten X-Commits mit dem interaktiven Rebase-Tool.

git rebase -i HEAD~[X]

Um die vier Commits zu quetschen, würden wir also wie folgt vorgehen.

$ git rebase -i HEAD~4

Nach dem Ausführen dieses Befehls ruft Git den Standardeditor mit Details zu den Squash-Commits auf, wie unten gezeigt.

pick b0e6655 Delete .lock
pick f4e3f09 Delete .log 
pick da66e6a Delete version.ini
pick 25c38c4 remove .class files

# Rebase 652d2fe..25c38c4 onto 652d2fe (4 command(s))
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

Der Editor zeigt die verschiedenen Commits mit dem Befehl pick an. Es zeigt auch Informationen zu den verfügbaren Befehlen an. Wir werden den Befehl squash (oder s) verwenden.

Wie unten gezeigt, behalten wir den ersten Commit mit dem Befehl pick bei und wechseln von pick zum Befehl s (für Squash) für die verbleibenden drei Commits.

pick b0e6655 Delete .lock
s f4e3f09 Delete .log 
s da66e6a Delete version.ini
s 25c38c4 remove .class files

# Rebase 652d2fe..25c38c4 onto 652d2fe (4 command(s))
#
...

Die mit squash (oder s) markierten Commits werden mit der Haupt-Commit-Viz zusammengeführt. die mit pick markierte.

Jetzt werden wir die Änderungen im Editor speichern und beenden. Danach öffnet das rebase -i-Tool einen weiteren Editor, um die Commit-Nachricht wie folgt einzugeben:

# This is a combination of 4 commits. The first commit's message is:

Delete .lock

# This is the 2nd commit message:

Delete .log 

# This is the 3rd commit message:

Delete version.ini

# This is the 4th commit message:

remove .class files

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Sun Jan 3 16:39:23 2021 +0530
#
# interactive rebase in progress; onto 652d2fe
# Last commands done (4 commands done):
#    pick b0e6655 Delete .lock
#    s f4e3f09 Delete .log 
#    s da66e6a Delete version.ini
#    s 25c38c4 remove .class files
# No commands remaining.
# You are currently editing a commit while rebasing branch 'master' on '652d2fe'.
#
# Changes to be committed:
#       new file:   github-git-notes.txt
#

Jetzt fügen wir die neue Commit-Nachricht oben in die erste Commit-Nachricht ein.

Deleted irrelevant files

# This is a combination of 4 commits. The first commit's message is:

Delete .lock

# This is the 2nd commit message:

Delete .log
...

Nach dem Speichern und Verlassen des Editors druckt das Tool rebase -i die folgende Meldung.

HEAD~2
Rebasing (2/2)


[detached HEAD caab6e8] Deleted irrelevant files
 Date: Sun Jan 3 16:39:23 2021 +0530
 1 file changed, 54 insertions(+)
 create mode 100644 github-git-notes.txt
Successfully rebased and updated refs/heads/master.

Jetzt überprüfen wir das git log und sehen die squashed-Commit- (d. h.) einzelne Commit-Meldung anstelle der vier Commit-Meldungen.

$ git log --oneline
25c38c4 Deleted irrelevant files
da66e6a github git notes
...

Verwenden von git merge -squash zum Squash von Git Commits

Es folgt die Syntax des Befehls, um einen Branch mit dem aktuellen Branch (normalerweise main) zusammenzuführen und die Commits des Quell-Branchs zu quetschen.

git merge --squash <source_branch_name_to_squash>

Wir werden nun die Feature-Zweig-Viz zusammenführen. feature1 mit Squashing mit dem main-Zweig.

Zuerst werden wir in den main Zweig auschecken.

$ git checkout main
Switched to branch 'main'

Dann führen wir einen git merge mit der Option squash wie folgt durch.

$ git merge --squash feature1
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested

Wenn wir ein merge mit der Option --squash ausführen, erstellt Git keinen Merge-Commit im Ziel-Branch, wie es bei einem normalen Merge der Fall ist. Stattdessen übernimmt Git alle Änderungen in der Quellverzweigung, nämlich. feature1 und fügt es als lokale Änderungen in die Arbeitskopie des Ziel-Zweigs ein. “hauptsächlich”.

Siehe unten.

$ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   config.ini

Hier hat die Datei config.ini die Änderungen im Zweig feature1 vorgenommen.

Jetzt müssen Sie nur noch die Änderungen wie folgt in den Zweig main übertragen.

$ git commit -am 'Merged and squashed the feature1 branch changes'
[main 573b923] Squashed and merged the feature1 branch
 1 file changed, 4 insertions(+)

Somit haben wir nun die Änderungen im feature1-Zweig in den main-Zweig zusammengeführt und die Commit-Meldungen des feature1-Zweigs gequetscht. Wir haben jetzt nur noch eine einzige Commit-Nachricht im main-Zweig.

Verwandter Artikel - Git Rebase

Verwandter Artikel - Git Merge