Skip to content

GitLab - 合并提交

合并提交(Squashing commits)是将多个 Git 提交合并成一个单一、有条理的提交的过程。这通常在将特性分支(feature branch)合并到主分支(例如 main 或 master)之前完成,以创建更清晰、更容易理解的项目历史。一个合并后的提交总结了一系列更小、增量式的变更,形成一个更有意义的更新。

合并提交的好处包括:

  • 更清晰的 Git 历史,更容易阅读和导航。
  • 简化回滚操作,只需回滚一个提交即可撤销整个特性功能。
  • 代码审查更聚焦,审阅者可以一次性看到某个特性的最终总变化(当然,合并前仍可以对单个提交进行审阅)。

方法 1:通过 GitLab 合并请求合并提交(推荐)

Section titled “方法 1:通过 GitLab 合并请求合并提交(推荐)”

GitLab 在合并合并请求 (Merge Request) 时提供了方便的合并提交选项。对于大多数用户来说,这通常是最简单和首选的方法。

步骤:

  1. 将你的特性分支及其多个提交推送到 GitLab。
  2. 从你的特性分支向目标分支(例如 main)创建一个合并请求(MR)。
  3. 在合并之前,在合并请求小部件中查找通常标记为“Squash commits”(合并提交)或类似名称的复选框。此选项可能位于“Merge options”(合并选项)等部分下。
  4. 确保此选项已被选中。你可能还可以编辑合并后的提交消息。默认情况下,GitLab 通常使用 MR 标题并连接提交消息。
  5. 点击“Merge”(合并)按钮。GitLab 随后将把你的特性分支上的所有提交合并成目标分支上的一个单一提交。

此方法会保留你特性分支上的独立提交(如果你不删除该分支),但在目标分支上创建一个单一、干净的提交。

方法 2:使用 git rebase -i 在本地合并提交(进阶)

Section titled “方法 2:使用 git rebase -i 在本地合并提交(进阶)”

你也可以在推送之前或在收到反馈后,使用交互式 Rebase (git rebase -i) 在本地特性分支上合并提交。这提供了更多控制,但需要谨慎处理。

注意:切勿 Rebase 那些已经推送到其他团队成员可能正在使用的共享分支上的提交,因为这会改写历史,可能导致严重的冲突。通常,在特性分支合并之前,Rebase 你自己的特性分支是安全的。

步骤 1:创建一个新分支并进行一些提交

首先,确保你当前在你的特性分支上。如果这是你第一次创建该分支以进行示例:

$ git checkout -b my-feature-branch main
# Switched to a new branch 'my-feature-branch'

现在,创建一些文件并进行几次提交。例如:

$ echo "Initial content" > feature_file.txt
$ git add feature_file.txt
$ git commit -m "feat: Add initial feature file"
$ echo "More content" >> feature_file.txt
$ git commit -am "feat: Add more details to feature"
$ echo "Final touch" >> feature_file.txt
$ git commit -am "fix: Correct typo in feature file"

现在你的 my-feature-branch 分支上有三个你想要合并的提交。

要合并最后 3 个提交,请使用 git rebase -i HEAD~3 命令:

$ git rebase -i HEAD~3

HEAD~3 告诉 Git 对当前 HEAD 起的最后 3 个提交进行 Rebase。如果你想合并 5 个提交,则使用 HEAD~5。请注意,执行涉及多个提交的合并操作至少需要两个提交。

步骤 3:在编辑器中选择要合并的提交

Section titled “步骤 3:在编辑器中选择要合并的提交”

此命令将打开你的默认文本编辑器,其中列出了你即将进行 Rebase 的提交,看起来类似这样:

pick a1b2c3d feat: Add initial feature file
pick e4f5g6h feat: Add more details to feature
pick i7j8k9l fix: Correct typo in feature file
# Rebase ... onto ...
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# d, drop <commit> = remove commit
# ...

要合并提交,你需要将要合并到前一个提交中的那些提交的 pick 改为 squash(或 s)。第一个提交通常保持为 pick。

将第二个和第三个 pick 改为 squash(或 s):

pick a1b2c3d feat: Add initial feature file
squash e4f5g6h feat: Add more details to feature
squash i7j8k9l fix: Correct typo in feature file

保存并关闭编辑器(例如,在 Vim 中按 Esc,然后输入 :wq 并回车)。

步骤 4:编辑新的合并提交的提交消息

Section titled “步骤 4:编辑新的合并提交的提交消息”

关闭第一个编辑器后,会打开另一个编辑器窗口。此窗口允许你为合并操作产生的新单一提交撰写提交消息。它将包含所有被合并提交的消息。

# This is a combination of 3 commits.
# This is the 1st commit message:
feat: Add initial feature file
# This is the commit message #2:
feat: Add more details to feature
# This is the commit message #3:
fix: Correct typo in feature file
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# ...

删除现有的消息,并撰写一条新的、清晰的提交消息,概括所有变更。例如:

feat: Implement complete feature X with corrections
This commit adds the initial files for feature X,
includes further details, and corrects a typo.

保存并关闭此编辑器。Git 现在将应用变更,你最后的三个提交将被一个单一的新提交所取代。

如果你之前已经推送过这个分支,你将需要强制推送(force push),因为你已经改写了它的历史记录:

$ git push origin my-feature-branch --force-with-lease

--force-with-lease 比 --force 更安全,因为它在强制推送之前会检查远程分支是否已被其他人更新过。

如果这是第一次推送该分支,则只需进行普通推送:

$ git push -u origin my-feature-branch

通常,在你创建合并请求之前,或者在合并之前,对你的特性分支上的提交进行合并,以确保主分支的历史记录保持干净和易于理解。有些团队偏好在合并过程中进行合并(GitLab UI 方法),而另一些团队则希望开发者在提出合并请求之前清理自己的分支。

与你的团队讨论,以建立一个一致的合并提交策略。