Git Squash 提交

Azhar Bashir Khan 2023年1月30日
  1. 使用互動式 git rebase 工具壓縮 Git 提交
  2. 使用 git merge -squash 壓縮 Git 提交
Git Squash 提交

我們將在本教程中學習 Git 壓縮。基本思想是將多個連續提交合併為一個。

主要目的是將許多提交壓縮為幾個相關的提交。因此,這樣做會使 git 歷史看起來簡潔明瞭。

另一種看待它的方式是我們對某個任務進行多次提交。過了一會兒,當我們達到一個令人滿意的狀態時,許多提交訊息會打亂 git 歷史記錄。

此時,我們可能希望將不同的提交合併為一個,以便 git 歷史記錄看起來清晰並最好地反映已完成的任務。

另一個用例是在進行分支合併時進行壓縮。通常,我們從主分支建立一個功能分支,用於某些功能開發。

功能完成後,我們將功能分支合併到主分支中。在這裡,我們也可能希望在合併到主分支時將功能分支中完成的各種提交訊息壓縮為一個。

請注意,沒有 git squash 命令。

有兩種方法可以實現 Git 壓縮:

  • git rebase -i 作為用於壓縮提交的互動式工具
  • git merge -squash 在合併時使用 -squash 選項

使用互動式 git rebase 工具壓縮 Git 提交

考慮以下 git log 摘錄,它顯示了我們對壓縮感興趣的 HEAD 的最後四個提交。

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

我們可以在日誌中看到前四個提交訊息,表示刪除不同的不相關檔案的操作。現在,我們將把這四個提交合併為一個。

以下是使用互動式變基工具壓縮最後 X 次提交的命令的語法。

git rebase -i HEAD~[X]

因此,要壓縮四個提交,我們將執行以下操作。

$ git rebase -i HEAD~4

發出此命令後,Git 將呼叫預設編輯器,其中包含提交到壁球的詳細資訊,如下所示。

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

編輯器使用 pick 命令顯示各種提交。它還顯示有關可用命令的資訊。我們將使用 squash(或 s)命令。

如下所示,我們將使用 pick 命令保留第一個提交,並將其餘三個提交從 pick 更改為 s(用於壁球)命令。

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))
#
...

標有 squash(或 s)的提交將合併到主提交即。標有 pick 的那個。

現在,我們將在編輯器中儲存更改並退出。在此之後,rebase -i 工具將開啟另一個編輯器以輸入提交訊息,如下所示:

# 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
#

現在,我們將在第一條提交訊息的頂部新增新的提交訊息。

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
...

儲存並退出編輯器後,rebase -i 工具將列印以下訊息。

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.

現在,我們將檢查 git log 並檢視 squashed 提交(即)單個提交訊息而不是四個提交訊息。

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

使用 git merge -squash 壓縮 Git 提交

以下是將分支與當前分支(通常是 main)合併並壓縮源分支的提交的命令語法。

git merge --squash <source_branch_name_to_squash>

我們現在將合併功能分支即。feature1main 分支一起壓縮。

首先,我們將切換到 master 分支。

$ git checkout main
Switched to branch 'main'

然後,我們將使用 squash 選項執行 git merge,如下所示。

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

當我們使用 --squash 選項執行 merge 時,Git 不會像在正常合併中那樣在目標分支中建立合併提交。相反,Git 接受源分支中的所有更改。feature1 並將其作為本地更改放入目標分支即 master 的工作副本中。

請參閱下文。

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

在這裡,檔案 config.inifeature1 分支中進行了更改。

現在,剩下的就是將更改提交到 main 分支,如下所示。

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

因此,我們現在已將 feature1 分支中的更改合併到 main 分支,同時壓縮了 feature1 分支的提交訊息。我們現在在 main 分支中只有一條提交訊息。

相關文章 - Git Rebase

相關文章 - Git Merge