使用 Git rebase 来整理 Git 提交历史
这篇文章的目标读者是那些想学习如何使用诸如 rebase 之类的命令并学习一些技巧以获得更好的 Git 体验的人。
好了,让我们先从我在 Github 上的第一个项目的 Git 历史开始观看:

这样不好

这样也不好

我的天,我到底做了什么
自嘲过后, 现在我们来看看我的大多数项目是什么样的 😄

哎呀,好多了
如果您不知道这一切意味着什么,请让我简要说明一下:
这代表了您在 Github 上的 Git 历史,意思就是随着时间的推移您在项目分支上所做的提交。
您可以通过导航到您的一个 GitHub 项目的
Insights选项卡,然后点击左侧的Network选项卡来查看自己的内容。
黑色栏代表主分支 master,蓝色和绿色交替交替代表独立的分支。
如您所见,在最近的更好的历史记录中,它们交替地合并到 master 中,从而创建了编写和合并代码的良好流程(始终建议这样做,而不是累积 pull 请求)。
那么,如何才能拥有更简洁的历史记录呢? 让我们来看一下实际的用例。
git rebase 的魔力
Git rebase 使您可以根据自己的意愿重塑 Git 历史。 将其视为一种处理给定分支上的提交列表的方法。
例如,您可以完全删除提交(基本上是对 Git 历史深渊说再见),对其进行重命名(重写您的提交消息),将它们合并为另外的提交(这对于隐藏小改变的提交很有用,例如添加一个分号,您真的不想在历史记录中看到它们)以及更多其他内容。
通过实践学习
转到以下我特地准备的 项目,从这个项目开始创建分支。
我们可以轻松地使用分支来为您自己的项目进行备份!为此,请点击右上角的fork按钮:

然后,克隆代码仓库到您的分支。
示例1:使用rebase修复提交
场景1:您提交的了您不想要的文件或者在拉取代码之前想要减少分支上提交的数量。
-
在
master分支中,创建一个新分支。 -
创建一个新文件,其内容并不重要。
-
将该文件提交到您的分支上。
git add index.js
git commit -m "add index.js"
-
再次修改该文件的内容
-
重新提交文件,可提交备注“update index.js”
-
执行
git log,如您所见,我们现在有2次提交
现在我们想将update提交合并到add提交中,因为这细微的修改不值得当作一次代码的提交。
为此,我们将使用git rebase的interactive模式,该模式使我们可以通过一个不错的界面来应用rebasing。
- 像这样运行rebase命令:
git rebase -i HEAD~2
HEAD~2是指从分支的最后一次提交开始(head),然后返回之前2次提交。如果我们想返回更多之前的提交,可以将最右边的值2修改为其他你想返回的值。
现在,您应该可以查看到类似于以下内容的界面:

不要惊慌,这只会在顶部显示您正在更改的两个提交,并且可用的命令会在下面显示。
默认情况下,rebase界面使用Vim来编辑,只需按i健即可。您现在处于“INSERT”模式。因为我们想在第一个提交中修复第二个提交,所以我们要做的就是在其前面写fixup或者f而不是pick。我们的update index.js提交内容将被压缩到add index.js中,只留下add index.js提交信息。
- 像这样更新第二行:
pick c0091ec add index.js
f a19336e update index.js
现在,我们要应用rebase,按escape退出INSERT模式,按:(冒号)并输入wq进行“写入”和“退出”并按下“ENTER”使应用修改更新。冒号仅允许您编写命令以供Vim执行。
现在,以下信息应出现在您的控制台中:
Successfully rebased and updated refs/heads/{YOUR BRANCH NAME}.
查看git log,现在您的提交变得漂亮且干净!
- 最后,强行推送该分支以将rebase推送到远程服务器
git push origin {BRANCH-NAME} -f
-f是必不可少的,因为rebase会修改您的git历史记录所以需要强制执行。
示例2:删除提交
接下来的两个步骤将与第一个步骤类似,因为您现在拥有工具可以进行任一rebasing。
场景:你想完全删除提交
我们将删除先前所做的add FILENAME提交:
- 运行rebase命令
git rebase -i HEAD~1
- 在您要删除的提交之前添加
d或者drop

-
在您的Vim编辑器上输入
:wq(并用git log检查提交是否被删除) -
别忘了将其强制推送到您的远程服务器
示例3:重新撰写提交
非常相似,只有一处不同的地方
场景: 您要修正拼写错误或重写提交的标题或描述
- 随意创建一次提交

- 运行rebase命令
git rebase -i HEAD~1
-
在您要重新撰写的提交之前添加
r或者reword(现在无需编辑标题) -
在Vim编辑器中输入
:wq。这将打开一个类似的编辑器使您可以重新编辑提交。

- 根据您的意愿更新提交的标题和描述,然后输入
:wq就可以了!使用git log检查是否修改提交

- 别忘了将其强制推送到您的远程服务器
示例4:以master为基础
此示例未在GitHub项目中复制,但可以对其进行测试。
场景: 您同时创建多个分支拉取请求

您第一个分支合并了master主分支,但是第二个分支并没有更新到master主分支上,这真是糟糕!

这种情况是非常常见的,我们将第二个分支以master为基础重新建立一个分支,以便第二个分支可以合并第一个分支的内容。
- 从要重新设置为基准的分支(在本例中是第二个分支)中,运行以下命令:
git fetch
这将下载远程主分支更新的内容到自己的分支上。
- 然后,重新执行设置,如下所示:
git rebase origin/master
- 最后,运行
git push origin {MY-BRANCH} -f将分支推送到远程服务器上。

欢呼 !
干净的git log
您是否觉得您的git log太多了?

您是否觉得将git log输出变得整洁干净是有必要的?

现在就来教你!下面是如何实现它的方法,在控制台中,粘贴以下内容:
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
您现在已经为git log创建了一个干净输出的命令,名为git lg,它将输出更加干净简洁的git历史记录。让我们输入git lg来尝试以下(或git lg -p来查看已更改的行)。
关于强制推送的危害及其他注意事项
如Nick Huanca所述:当与团队合作开发项目时,强制推送是非常危险的。
因此,可以选择另外一种替代方法--force-with-lease,它允许团队某人强制推送而不会无意间覆盖其他人的提交。只有在本地分支与远程跟踪分支具有相同的内容的情况下,它才会更新到本地。参考.非常感谢Nick! 😄
你可能会注意到,他还提到了git rebase --abort,它使我们可以在发生任何错误的情况下停止重新设置基准。因此,如果由于任何原因可能发送错误,请使用--abort修正并重新开始。
结语
学习如何使用Git是我们作为开发人员所需要的一项重要技能。希望你们中的一些人不会像我前一阵子那样害怕使用rebase
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

关于 LearnKu
推荐文章: