【发布时间】:2010-10-02 05:24:01
【问题描述】:
我想修改历史更深的提交消息,并且我已经推送了许多新的提交。
如何更改提交消息?有可能吗?
【问题讨论】:
标签: git commit-message
我想修改历史更深的提交消息,并且我已经推送了许多新的提交。
如何更改提交消息?有可能吗?
【问题讨论】:
标签: git commit-message
来自 Linus Torvalds 的消息可能会回答您的问题:
Modify/edit old commit messages
简短回答:你不能(如果被推)。
提取(Linus 将 BitKeeper 称为 BK):
旁注,只是出于历史兴趣:在 BK 你可以。
如果你习惯了(就像我一样),它真的很实用。一世 会使用安德鲁的补丁炸弹,注意到有问题,然后 在推出之前对其进行编辑。
我可以用 git 做同样的事情。这本来很容易 只使提交消息不是名称的一部分,并且仍然保证 历史未被触及,并允许“稍后修复 cmets” 东西。
但我没有。
其中一部分纯粹是“内部一致性”。 Git 只是一个 cleaner 系统感谢所有东西都受到 SHA1 保护,并且所有对象都是 无论对象类型如何,都一样对待。是的,有四个 不同种类的物体,它们都非常不同,它们 不能以同样的方式使用,但同时,即使他们 磁盘上的编码可能不同,概念上它们都可以正常工作 一样的。
但内部一致性并不是不灵活的真正借口,而且 显然,如果我们可以在之后修复错误,那将是非常灵活的 他们发生了。所以这不是一个非常有力的论点。
git 不允许你更改提交消息的真正原因结束 起来非常简单:这样,您就可以信任这些消息。如果你允许 人们事后更改它们,消息本质上不是很 值得信赖。
为了完整起见,您可以重写您的本地提交历史记录以反映您想要的内容,如 suggested by sykora(带有一些变基和重置 --hard,喘气!)
但是,一旦您再次发布修改后的历史记录(带有git push origin +master:master,+ 符号会强制推送发生,即使它不会导致“快进"提交)...你might get into some trouble.
从另一个 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 再次完成!
【讨论】:
rebase 的-p 参数,preserves 合并。
假设你有一棵这样的树:
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 之前的提交从master 到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”命令的人没有帮助,但它确实为我们提供了一种方法来修复 cmets 中不正确的错误跟踪器引用,并且我所有的构建和发布工具都理解该约定。
这显然不是一个通用的答案,但它可能是人们可以在特定社区内采用的东西。我敢肯定,如果这在更大范围内使用,最终可能会出现某种瓷器支撑...
【讨论】:
(来自http://git.or.cz/gitwiki/GitTips#head-9f87cd21bcdf081a61c29985604ff4be35a5e6c0)
如何更改历史更深的提交
由于 Git 中的历史记录是不可变的,因此修复除最近提交(不是分支头的提交)之外的任何内容都需要从更改的提交中重写历史记录并转发。
您可以为此使用 StGIT,必要时初始化分支,取消提交到您要更改的提交,必要时弹出它,进行更改然后刷新补丁(如果要更正提交消息,请使用 -e 选项) ,然后推送所有内容并 stg 提交。
或者你可以使用 rebase 来做到这一点。创建新的临时分支,使用 git reset --hard 将其倒回到您要更改的提交,更改该提交(它将是当前头部的顶部),然后使用 git rebase --onto 在更改的提交之上重新设置分支。
或者您可以使用 git rebase --interactive,它允许进行各种修改,例如补丁重新排序、折叠、...
我认为这应该可以回答您的问题。但是,请注意,如果您将代码 推送 到远程存储库并且人们已经从中提取,那么这将会弄乱他们的代码历史以及他们所做的工作。所以要小心。
【讨论】: