当前位置: 首页 > 科技观察

使用gitrebase-i修改你的Git提交历史

时间:2023-03-13 15:39:08 科技观察

给大家留下你曾经写过完美代码的印象,让你的补丁更容易审查和合并。软件开发很乱。有很多错误的转弯、错别字要修复、错误要修复、临时和粗略的代码要稍后修复,以及在开发后期会一遍又一遍地发现错误。有了版本控制,您就有了每一个bug的原始记录并修复了创建“完美”最终产品的方法(即准备好向上游提交的补丁)。就像电影中的花絮一样,它们可能有点尴尬,有时又很搞笑。如果您使用版本控制来定期跟踪您的工作,然后当您准备提交某些内容以供审查时,您可以隐藏所有这些私人草稿工作并只提交一个完美的补丁,这不是很好吗?gitrebase-i是重写历史并让每个人都认为您曾经写过完美代码的完美方式!gitrebase是做什么的?如果您不熟悉Git的复杂性,这里有一个简短的介绍。在幕后,Git将一个项目的不同版本与一个唯一标识符相关联,该标识符由父唯一标识符的散列和新版本与其父版本的差异组成。这形成了一个修订树,每个签出该项目的人都会得到自己的副本。不同的人可以把项目往不同的方向走,每个方向可能从不同的分支点开始。左边是origin仓库的master分支,右边是你个人副本的private分支。有两种方法可以将你的工作与原始仓库中的master分支集成:一种是使用合并:gitmerge,另一种是使用rebase:gitrebase。他们的工作方式非常不同。当您使用gitmerge时,会在主分支(master)上创建一个新的提交,其中包括来自源的所有更改和所有本地更改。如果有任何冲突(例如,如果其他人修改了您也在修改的文件),这些冲突会被标记出来,您有机会在将此“合并提交”提交到本地存储库之前解决它们。当您将更改推送回父存储库时,您所有的本地工作都会作为分支显示给Git存储库的其他用户。但是gitrebase的工作方式不同。它回滚你的提交并从master分支的顶端再次重播它们。这导致了两个重大变化。首先,由于您的提交现在是从不同的父级分支出来的,因此将重新计算它们的哈希值,并且任何克隆您的存储库的人最终都可能会得到一个损坏的存储库副本。其次,您没有“合并提交”,因此在将更改重放到master分支上时将识别任何合并冲突,因此您需要在进行变基之前修复它们。现在,当你推送你的更改时,你的工作不会出现在分支上,看起来你在master分支的最新提交上写了所有更改。合并提交(左)保留历史,而变基(右)重写历史。然而,这两种方法都有一个缺点:在您准备好共享代码之前,每个人都可以看到您在本地处理问题时所做的所有涂鸦和编辑。这就是gitrebase的--interactive(或简称-i)标志发挥作用的地方。gitrebase-i登场gitrebase最大的优点就是可以改写历史。但是,为什么要停止假装您是从以后的某个点开始分支的呢?还有另一种方法可以重写您如何就位此代码:gitrebase-i,一个交互式gitrebase。这个特性就是Git中的“神奇时间机器”特性。此标志允许您在进行变基时对修订历史记录进行复杂的更改。你可以隐藏你的错误!将许多小修复合并到一个闪亮的新功能补丁中!重新排列编辑历史中的显示顺序!gitrebase-i的输出当你运行gitrebase-i时,你会进入一个编辑器会话,其中列出了所有正在变基的提交,以及如何处理它们的几个选项。默认选择是拾取。Pick:将提交保留在您的历史记录中。Reword:允许您修改提交消息,可能会修复拼写错误或添加其他评论。编辑:允许您在重播分支时对提交进行更改。Squash:可以将多个提交合并为一个。您可以通过在文件中移动来重新排序提交。完成后,只需保存最终结果,变基操作就会执行。在您选择修改提交的每个阶段(无论是使用改写、编辑、压缩还是发生冲突时),变基都会停止并允许您在继续提交之前进行适当的更改。上述示例的结果是“One-linerbugfix”和“Integatenewheadereverywhere”被合并到一个提交中,而“Newheaderfordocswebsite”和“D'oh-typo.Fixed”被合并到另一个提交中提交中间。就像变魔术一样,其他提交的工作仍在您的分支中,但是相关的提交已经从您的历史记录中消失了!这使得使用gitsend-email或使用新策划的补丁集在父存储库中创建拉取请求变得容易,然后将干净的补丁提交到上游项目。这有很多好处,包括让您的代码更容易审查、更容易接受和更容易合并。