大家好,今天我们来聊聊git中一个很重要的功能——修改历史记录。有时候我们会突然发现某个地方需要修改,最常见的就是提交了一个不该提交的文件。我们希望它不仅不会再出现在后续版本中,而且会完全从git存储库中删除。这时候我们需要修改git之前的历史。这个时候怎么办?不用担心,git中有很多方法可以修改之前的历史提交记录。修改上次提交这一点我们在上一篇文章中已经提到,如果我们只是想修改上次提交记录,这个比较简单。我们只需要直接修改我们要修改的部分,在提交的时候加上一个参数--amend即可。gitcommit--amendamend是patch的意思,可以把我们这次的修改合并到之前的历史记录中,而不产生新的commit记录。运行后会打开一个vim编辑器,我们也可以修改上次commit时输入的提示信息。如果我们用gitlog查看,会发现历史记录的修改时间还是最后一次。就好像什么都没发生过一样,悄无声息地变了。修改多条信息--amend好用,但是只能修改最后一次提交的信息。如果我们要修改的提交记录是在那之前怎么办?Git并没有提供直接的工具来实现这个,但是我们可以使用rebase来实现。我们可以添加-i以交互方式变基,我们可以在任何需要的修改后停止,添加文件,或做任何我们想做的事情。但是我们rebase的目标不是某个分支,而是当前分支的某个历史节点,所以需要提供具体的commitid或者指针位置。gitrebase-i非常强大,我们几乎可以用它来做任何我们想做的事情。比如我们要修改倒数第二个提交,可以执行gitrebase-iHEAD~3。即以倒数第二个节点为参考节点进行rebase。这时候git会进入一个vim窗口,在这个窗口中我们可以看到最近的三个提交记录。首先我们可以看到上面三行是我们可以修改的三个commit,分别显示了要执行的操作,commitid和commitmessage。这里的操作默认是pick,也就是使用commit。关于我们可以进行的操作,git在下面也给出了充分的提示,其中比较常用的有pick、edit和squash。这次我们要做的是修改commit记录,所以要执行edit,把我们要修改的commit之前的pick改成edit。比如退出后,git会自动带我们回到我们选择编辑的分支之后的版本。我们做我们想要的改变,这里我在第15篇文章中加了一行:tryrebase。然后使用gitadd和gitcommit--amend修改提交结果。然后我们执行gitrebase--continue来应用剩下的要应用的更改。一切都结束后,我们可以使用gitshow命令查看我们修改bee9ce3的commit记录。可以看到已经有这一行了,说明我们修改成功了。Sequencechange,merging,splittingSequencechange我们不仅可以修改某个commit的内容,还可以修改这些commit的相对顺序,并允许它们进行合并和拆分。修改顺序其实很简单,我们只需要人为修改rebase-i后弹出的vim文件即可。比如原来的记录是:pickAchangeApickBchangeBpickCchangeC如果我们要改变顺序,只需要修改这个文件即可。比如变成:pickBchangeBpickAchangeApickCchangeC那么当我们退出vim时,git会先应用commitB的更改,然后应用A,最后应用C。除了合??并,我们还可以将多个commit记录合并为一个。操作方法也很简单,就是我们只需要将pick改成squash即可。Git会自动将所有压缩提交记录合并在一起。pickAchangeAsquashBchangeBsquashCchangesplit有时一个commit很大,我们可能也想拆分它,其实操作很简单。例如,我们想将提交B分成两部分。首先,我们将提交B前面的pick更改为在rebase期间进行编辑。pickAchangeAeditBchangeBpickCchangeC退出时,会进入Bcommit刚刚提交的状态。由于我们要做的是拆分B的commit,所以需要执行gitresetHEAD^来重置上次的commit。然后分别添加我们要拆分提交的文件。整个操作如下:gitresetHEAD^gitaddtest/*gitci-m'addtest'gitaddcode/*gitci-m'updatecode'gitrebase--continue这样我们就把commitB拆分成了两个commit插入到history中。最后需要大家注意的是,虽然这些方法在修改记录的时候非常有用。但是如果这些commit已经提交到远程了,我们就不能直接gitpush来同步了。因为git会对我们提交的hash值进行校验,如果发现有误,就会禁止我们提交。所以如果要提交到远程,只能用gitpush-f强制覆盖。但这是一个非常非常危险的操作。如果你gitpush-f,没有人会知道你修改了什么。只建议在你自己独特的分支上这样做,并且你必须谨慎使用它。本文转载自微信公众号「TechFlow」,可通过以下二维码关注。转载请联系TechFlow公众号。
