我想修改历史更深的提交消息,并且我已经推送了许多新的提交。
如何更改提交消息?可能吗?
来自 Linus Torvalds 的消息可能会回答您的问题:
简短的回答:你不能(如果被推)。
提取(Linus 将 BitKeeper 称为 BK):
旁注,只是出于历史兴趣:在 BK 你可以。
如果你习惯了(就像我一样),它真的很实用。我会使用 Andrew 的补丁炸弹,发现有问题,然后在推出之前对其进行编辑。
我可以用 git 做同样的事情。让提交消息不成为名称的一部分已经很容易了,并且仍然保证历史未被触及,并允许“稍后修复评论”的事情。
但我没有。
其中一部分纯粹是“内部一致性”。Git 只是一个更干净的 系统,这要归功于所有内容都受 SHA1 保护,并且无论对象类型如何,所有对象都被同等对待。是的,有四种不同的对象,它们都非常不同,它们不能以相同的方式使用,但同时,即使它们在磁盘上的编码可能不同,从概念上讲它们都可以正常工作相同。
但内部一致性并不是不灵活的真正借口,如果我们能在错误发生后纠正错误,显然会非常灵活。所以这不是一个非常有力的论据。
git 不允许您更改提交消息的真正原因最终非常简单:这样,您就可以信任这些消息。如果您允许人们事后更改它们,则这些消息本质上不是很值得信赖。
为了完整起见,您可以按照sykora的建议重写本地提交历史记录以反映您想要的内容(使用一些 rebase 和 reset --hard,喘气!)
但是,一旦您再次发布修改后的历史记录(带有git push origin +master:master
,+
强制推送发生的标志,即使它不会导致“快进”提交)......您可能会遇到一些麻烦。
从另一个 SO 问题中提取:
实际上,我曾经用 --force 推送到 git.git 存储库并被 Linus BIG TIME 责骂。它会给其他人带来很多问题。一个简单的答案是“不要这样做”。
目前git replace可能会解决问题。
详细:创建临时工作分支
git checkout -b temp
重置为要替换的提交
git reset --hard <sha1>
用正确的信息修改提交
git commit --amend -m "<right message>"
用新的提交替换旧的提交
git replace <old commit sha1> <new commit sha1>
回到你所在的分支
git checkout <branch>
删除临时分支
git branch -D temp
推
guess
完毕。
您可以使用git rebase -i
(针对您分支的分支)“i”进行交互。
pick
将您希望更改的提交注释旁边的替换为r
(或reword
),保存并退出,然后您将能够进行编辑。
git push
再一次,你就完成了!
假设你有一棵这样的树:
dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master]
首先,checkout
一个临时分支:
git checkout -b temp
在temp
分支上,reset --hard
要更改其消息的提交(例如,该提交是946992
):
git reset --hard 946992
用于amend
更改消息:
git commit --amend -m "<new_message>"
之后,树将如下所示:
dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master]
\
b886a0 [temp]
然后,cherry-pick
所有在946992
from master
to之前的temp
提交并提交它们,amend
如果您也想更改它们的消息,请使用:
git cherry-pick 9143a9
git commit --amend -m "<new_message>
...
git cherry-pick 5a6057
git commit --amend -m "<new_message>
树现在看起来像这样:
dd2e86 - 946992 - 9143a9 - a6fd86 - 5a6057 [master]
\
b886a0 - 41ab2c - 6c2a3s - 7c88c9 [temp]
现在强制将临时分支推送到远程:
git push --force origin temp:master
最后一步,master
在本地删除分支,从服务器git fetch origin
拉取分支master
,然后切换到分支master
并删除分支temp
。
现在您的本地和远程都将更新所有消息。
在我们的商店中,我介绍了将可识别命名的带注释标签添加到具有错误消息的提交的约定,并使用注释作为替换。
尽管这对运行随意的“git log”命令的人没有帮助,但它确实为我们提供了一种方法来修复评论中不正确的错误跟踪器引用,并且我所有的构建和发布工具都理解这个约定。
这显然不是一个通用的答案,但它可能是人们可以在特定社区内采用的东西。我敢肯定,如果这被大规模使用,最终可能会出现某种瓷器支撑物……
(来自http://git.or.cz/gitwiki/GitTips#head-9f87cd21bcdf081a61c29985604ff4be35a5e6c0)
如何更改历史更深的提交
由于 Git 中的历史是不可变的,因此修复除最近提交(不是分支头的提交)之外的任何内容都需要从更改的提交中重写历史并转发。
您可以为此使用 StGIT,必要时初始化分支,取消提交到您要更改的提交,必要时弹出它,进行更改然后刷新补丁(如果要更正提交消息,请使用 -e 选项),然后推送一切和 stg 提交。
或者你可以使用 rebase 来做到这一点。创建新的临时分支,使用 git reset --hard 将其倒回到您要更改的提交,更改该提交(它将是当前头部的顶部),然后使用 git rebase --onto 在更改的提交之上重新设置分支。
或者您可以使用 git rebase --interactive,它允许进行各种修改,例如补丁重新排序、折叠、...
我认为这应该回答你的问题。但是,请注意,如果您已将代码推送到远程存储库并且人们已从中提取代码,那么这将弄乱他们的代码历史以及他们所做的工作。所以要小心。