Git 压缩提交快速指南 方法 1:一次提交即可统治主分支 方法 2:没那么多! 方法 3:挑剔

2025-05-28

压缩 Git 提交的快速指南

方法一:一次提交统治主分支

方法#2:没那么多!

方法三:挑剔

首先,让我们先搞清楚一件事:为了拥有一棵漂亮的树而重写 Git 历史记录,尤其是在公共仓库中,通常是不可取的。这有点像回到过去,你对自己项目版本所做的更改,会导致它看起来与别人从你现在已经删除的某个历史点 fork 出来的版本完全不同——我的意思是,你没看过《回到未来 第二部》吗?(如果你想坚持认为《回到未来》只拍过一部,这样你就不用再看续集了,我理解。)

重点来了。如果你把一些杂乱的提交推送到公共仓库,我建议你直接去处理,别再纠结了。(我们都会从尴尬中吸取教训,尤其是公开的尴尬——我说的就是你,过去的维多利亚。)如果你的杂乱提交目前只存在于你的本地版本,那就太好了!我们可以把它们整理成一个干净、描述清晰的提交,我们会很自豪地推送它,而且不会有人觉得你有什么问题。

有几种不同的方法可以压缩提交,选择合适的方法取决于我们需要实现的目标。

以下示例使用 进行演示git log --graph,并附带一些简洁的选项。我们可以设置一个方便的别名,以便在终端中查看此日志格式:

git config --global alias.plog "log --graph --pretty=format:'%h -%d %s %n' --abbrev-commit --date=relative --branches"
Enter fullscreen mode Exit fullscreen mode

然后我们只需git plog查看漂亮的日志即可。

方法一:一次提交统治主分支

这适用于以下情况:

  • 我们直接提交到 master
  • 我们不打算打开合并功能请求
  • 我们不想保留尚未推送的分支或变更的历史记录

此方法采用如下所示的 Git 树:

*   3e8fd79 - (HEAD -> master) Fix a thing
|
*   4f0d387 - Tweak something
|
*   0a6b8b3 - Merge branch 'new-article'
|\
| * 33b5509 - (new-article) Update article again again
| |
| * 1782e63 - Update article again
| |
| * 3c5b6a8 - Update article
| |
* | f790737 - (master) Tweak unrelated article
|/
|
* 65af7e7 Add social media link
|
* 0e3fa32 (origin/master, origin/HEAD) Update theme
Enter fullscreen mode Exit fullscreen mode

并使其看起来像这样:

* 7f9a127 - (HEAD -> master) Add new article
|
* 0e3fa32 - (origin/master, origin/HEAD) Update theme
Enter fullscreen mode Exit fullscreen mode

方法如下——抓住你的悬浮滑板,这非常复杂:

git reset --soft origin/master
git commit
Enter fullscreen mode Exit fullscreen mode

好的,就这些。我们可以用 删除不需要的分支git branch -D new-article

方法#2:没那么多!

这适用于以下情况:

  • 我们希望压缩最后x 个提交,但不是所有提交,因为origin/master
  • 我们想打开一个拉取请求来合并一个分支

此方法采用如下所示的 Git 树:

* 13a070f - (HEAD -> new-article) Finish new article
|
* 78e728a - Edit article draft
|
* d62603c - Add example
|
* 1aeb20e - Update draft
|
* 5a8442a - Add new article draft
|
| * 65af7e7 - (master) Add social media link
|/
|
* 0e3fa32 - (origin/master, origin/HEAD) Update theme
Enter fullscreen mode Exit fullscreen mode

并使其看起来像这样:

* 90da69a - (HEAD -> new-article) Add new article
|
| * 65af7e7 - (master) Add social media link
|/
|
* 0e3fa32 - (origin/master, origin/HEAD) Update theme
Enter fullscreen mode Exit fullscreen mode

为了将分支上的最后五次提交压缩new-article为一次,我们使用:

git reset --soft HEAD~5
git commit -m "New message for the combined commit"
Enter fullscreen mode Exit fullscreen mode

其中--soft,我们的文件保持不变并处于暂存状态,5可以被认为是“我想要合并的先前提交的数量”。

然后我们就可以git merge master创建我们的拉取请求。

方法三:挑剔

假设我们度过了一个非常混乱的下午,我们的 Git 树如下所示:

* dc89918 - (HEAD -> master) Add link
|
* 9b6780f - Update image asset
|
* 6379956 - Fix CSS bug
|
*   16ee1f3 - Merge master into branch
|\
| |
| * ccec365 - Update list page
| |
* | 033dee7 - Fix typo
| |
* | 90da69a - Add new article
|/
|
* 0e3fa32 - (origin/master, origin/HEAD) Update theme
Enter fullscreen mode Exit fullscreen mode

我们希望保留部分历史记录,但清理提交。我们还想更改部分提交的消息。为此,我们将使用git rebase

这适用于以下情况:

  • 我们只想压缩一些提交
  • 我们想要编辑之前的提交信息
  • 我们想要删除或重新排序特定的提交

Gitrebase是一款功能强大的工具,一旦掌握了它,就会非常方便。要更改自 以来的所有提交origin/master,我们执行以下操作:

git rebase -i origin/master
Enter fullscreen mode Exit fullscreen mode

或者,我们可以这样做:

git rebase -i 0e3fa32
Enter fullscreen mode Exit fullscreen mode

其中提交哈希是我们希望保留的最后一次提交。

-i选项允许我们运行交互式 rebase 工具,它会启动我们的编辑器,本质上是一个供我们修改的脚本。我们将看到与 git log 中相反顺序的提交列表,最早的提交位于顶部:

pick 90da69a Add new article
pick 033dee7 Fix typo
pick ccec365 Update list page
pick 6379956 Fix CSS bug
pick 9b6780f Update image asset
pick dc89918 Add link

# Rebase 0e3fa32..dc89918 onto 0e3fa32 (6 commands)
#
# 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
#
~
Enter fullscreen mode Exit fullscreen mode

这些注释为我们提供了便捷的指南,告诉我们可以做什么。现在,让我们将小改动的提交压缩成更重要的提交。在编辑器中,我们将脚本修改如下:

pick 90da69a Add new article
squash 033dee7 Fix typo
pick ccec365 Update list page
squash 6379956 Fix CSS bug
squash 9b6780f Update image asset
squash dc89918 Add link
Enter fullscreen mode Exit fullscreen mode

保存更改后,交互式工具将继续运行。它将按顺序执行我们的指令。在这种情况下,我们再次看到编辑器,其中包含以下内容:

# This is a combination of 2 commits.
# This is the 1st commit message:

Add new article

# This is the commit message #2:

Fix typo

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# interactive rebase in progress; onto 0e3fa32
# Last commands done (2 commands done):
#    pick 90da69a Add new article
#    squash 033dee7 Fix typo
# Next commands to do (4 remaining commands):
#    pick ccec365 Update list page
#    squash 6379956 Fix CSS bug
# You are currently rebasing branch 'master' on '0e3fa32'.
#
# Changes to be committed:
#       modified:   ...
#
~
Enter fullscreen mode Exit fullscreen mode

如果我们愿意的话,现在是时候为这第一个 squash 创建新的提交消息了​​。保存后,交互式工具将进入下一个指令。除非……

[detached HEAD 3cbad01] Add new article
 1 file changed, 129 insertions(+), 19 deletions(-)
Auto-merging content/dir/file.md
CONFLICT (content): Merge conflict in content/dir/file.md
error: could not apply ccec365... Update list page

Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".

Could not apply ccec365... Update list page
Enter fullscreen mode Exit fullscreen mode

再次强调,该工具提供了一些非常有用的说明。一旦我们解决了合并冲突,就可以使用 继续该过程git rebase --continue。我们的交互式 rebase 会从中断的地方继续执行。

一旦所有压缩完成,我们的 Git 树看起来如下所示:

* 3564b8c - (HEAD -> master) Update list page
|
* 3cbad01 - Add new article
|
* 0e3fa32 - (origin/master, origin/HEAD) Update theme
Enter fullscreen mode Exit fullscreen mode

呼,好多了。

这篇文章是从我的博客上关于 Git 提交实践的一篇较长的文章中精心摘录的。

文章来源:https://dev.to/victoria/a-quick-guide-to-squashing-git-commits-7io
PREV
一个自动交互的预提交清单,类似信息广告风格。什么是预提交钩子?如何获取预提交清单?拿我的钱去吧!
NEXT
咖啡时间介绍算法的时间复杂度 什么是“时间复杂度”?确定时间复杂度 P vs NP、NP-complete 和 NP-hard 在编写代码之前估算算法的效率 改进现有代码的时间复杂度 资料来源