如何在已经推送的git提交中编辑错误的提交信息?

159

我希望修改在历史记录深处的提交信息,而且我已经推送了许多新的提交。

如何更改提交信息?这是否可能?

7个回答

129

来自Linus Torvalds的消息可能会回答你的问题:

修改/编辑旧的提交信息

简短回答:如果已经推送,你不能这样做。


提取(Linus指的是BitKeeper作为BK):

顺便说一句,出于历史兴趣:在BK中,你可以。

如果你习惯了它(就像我一样),它真的非常实用。我会从Andrew那里应用一个补丁轰炸,注意到有些东西不对,然后在推出去之前进行编辑。

我也可以用git做同样的事情。很容易让提交消息不成为名称的一部分,并仍然保证历史记录不变,并允许“稍后修复注释”这件事。

但是我没有这样做。

其中一部分纯粹是“内部一致性”。由于所有内容都受到SHA1保护,并且所有对象都以相同的方式处理,因此Git只是一个更干净的系统。是的,有四种不同类型的对象,它们真的很不同,不能以相同的方式使用,但同时,即使它们的编码可能在磁盘上不同,从概念上讲它们都完全相同。

但是,内部一致性并不是不灵活的借口,显然,如果我们可以在发生错误后修正错误,它将非常灵活。所以这不是一个非常有力的论点。

Git不允许更改提交消息的真正原因非常简单:这样,您可以信任这些消息。如果允许人们在之后更改它们,则这些消息本质上是不可靠的。


为了完整起见,你可以重写本地提交历史以反映你想要的,就像sykora建议的那样(需要一些变基和重置--hard,喘口气!)
然而,一旦你再次发布你修订过的历史记录(使用git push origin +master:master+符号强制进行推送,即使它不会导致“快进”提交)...你可能会遇到一些麻烦
从另一个SO问题中提取出来:

我曾经使用--force推送到git.git存储库,并被Linus大声斥责。这将为其他人创建很多问题。简单的答案是“不要这样做”。


好的回答。您知道在新版本的Git中是否可以更改已推送的提交消息吗?自'09年发布以来有什么变化吗? - David West
@DavidWest 同样的原则适用:您可以重写您的历史并强制推送。 - VonC
2
为了更具体地说明,如果您修改/变基提交,它们的提交标识符(在git索引中的十六进制哈希)不可避免地会发生改变;这意味着编辑后的提交与它们在git版本控制历史中的旧提交是不同的。也就是说,如果您的开发团队成员已经拉取了旧的提交,则他们必须拉取已编辑的新提交,并在其本地工作副本中执行旧提交和新提交之间的合并。 - Shigerello
1
为了方便同事,最好重新推送编辑后的提交,从而有利地消除同事工作副本中合并的需要。 - Shigerello

29

目前使用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

完成。


12
@Jonah: 当我尝试推送到远程分支时,收到了“一切都是最新的”消息。 - Simon Kagwi
1
如另一个答案所提到的:使用带有reword选项的rebase -i命令。这将重写历史记录。 - Sylvain
谢谢你提供的解决方案,这正是我一直在寻找的。 你节省了我的时间! - Tomasz Kuter
1
@Jonah - 我有一个问题...你的解决方案在本地更新了我的提交日志,但是没有在远程更新。如何将它们推送到那里? - Tomasz Kuter
1
@TomaszKuter,我和你遇到了同样的问题。我的提交消息没有在远程更新。我通过使用GitHub提供的以下帮助解决了这个问题:https://help.github.com/articles/changing-a-commit-message。请按照“修改旧的或多个提交消息”的部分进行操作。这基本上就是由user987419下面给出的答案。如果您已经更改了提交消息,则可以在不必再次更改它的情况下执行pick和save。 - evaldeslacasa
显示剩余3条评论

21

你可以使用 git rebase -i(针对你从中分支出的分支), 'i' 代表交互模式。

将你想要更改的提交注释旁边的 pick 替换为 r(或 reword),保存并退出,这样你就能够进行编辑。

再次运行 git push 就完成了!


1
这不允许在合并提交时编辑消息。是否可以使用此命令的某个变体实现这一点? - Andrew Mao
1
尝试使用 rebase-p 参数,它可以保留合并。 - Cactus
4
我喜欢这个流程,但一开始并没有完全理解答案。如果有人需要帮助,GitHub帮助页面提供了关于此的良好信息:https://help.github.com/articles/changing-a-commit-message/ - evaldeslacasa

16

假设你有这样一棵树:

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]

然后,从master中挑选所有比946992新的提交,加入到temp分支并进行提交。如果需要修改它们的commit message,请使用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]

现在强制推送temp分支到远程:

git push --force origin temp:master

最后一步是删除本地的分支master,使用git fetch origin从服务器拉取分支master,然后切换到分支master并删除分支temp

现在,您的本地和远程都将拥有所有更新的消息。


7
在我们的商店中,我引入了一种约定,即在具有不正确消息的提交中添加可识别名称的注释标签,并使用注释作为替代。虽然这并不能帮助运行常规“git log”命令的人,但它确实为我们提供了一种修正评论中不正确的缺陷跟踪器引用的方法,而且我的所有构建和发布工具都能理解这种约定。显然,这不是通用的答案,但它可能是特定社区可以采纳的东西。我相信如果这被大规模使用,最终会出现某些支持它的瓷器。

3
"git notes" 可能具有类似的作用。 - Christian Goetze

2

(来源:http://git.or.cz/gitwiki/GitTips#head-9f87cd21bcdf081a61c29985604ff4be35a5e6c0)

如何更改历史记录中的提交

由于 Git 中的历史记录是不可变的,因此除了最近的提交(不是分支头)之外,修复任何东西都需要从更改的提交开始重写历史记录并向前。

您可以使用 StGIT 来完成这项工作,必要时初始化分支,撤消到您想要更改的提交,如果需要,请弹出到该提交,进行更改,然后刷新补丁(如果您想更正提交消息,则使用 -e 选项),然后推送所有内容并进行 stg 提交。

或者您可以使用 rebase 进行此操作。创建新的临时分支,使用 git reset --hard 将其回退到您想要更改的提交,更改该提交(它将成为当前 head 的顶部),然后将分支重新设置在更改的提交之上,使用 git rebase --onto 命令。

或者您可以使用 git rebase --interactive,它允许各种修改,例如补丁重新排序、折叠等。

我想这应该回答了您的问题。但是,请注意,如果您已经将代码 推送 到远程存储库并且其他人已经从中拉取了代码,则这将破坏他们的代码历史记录以及他们所做的工作。因此,请小心操作。


理论上是好答案,但在实践中非常危险:请参见https://dev59.com/gXVC5IYBdhLWcg3wjx_u。 - VonC

0
如果您正在使用Git扩展程序: 进入提交屏幕,底部应该有一个复选框,上面写着“修改提交”,如下图所示:

enter image description here


@KrunalPandya 是的,或者只需按提交并推送。 - batsheva

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接