如何在 git 中编辑不正确的提交消息(我已经推送了) ?

我想修改一个提交消息更深入的历史,我已经推出了许多新的提交。

如何更改提交消息? 可能吗?

140548 次浏览

莱纳斯 · 托沃兹的信息可以回答你的问题:

修改/编辑旧的提交消息

简短的回答: 你不能(如果被逼的话)。


提取(Linus 称 BitKeeper 为 BK) :

边注,只是出于历史兴趣: 在 BK 你可以。

如果你已经习惯了(像我一样) ,那么它真的很实用 会从安德鲁身上贴一个贴片炸弹,注意到有些不对劲,然后 在推出之前先编辑一下。

我也可以对 Git 做同样的事情,这很容易 使提交消息不成为名称的一部分,并且仍然保证 历史没有改变,允许“稍后修复评论” 东西。

但我没有。

它的一部分纯粹是“内部一致性”,Git 只是一个“ em”清理器 系统,因为所有东西都是 SHA1保护的,所有对象都是 无论对象类型如何都是一样的。是的,有四个 不同种类的物体,它们都是不同的 不能以同样的方式使用,但在同一时间,即使他们 编码可能在磁盘上不同,概念上他们都正确地工作 一样。

但是内部的一致性并不能成为不灵活的借口 很明显,如果我们能在事后纠正错误,这将是非常灵活的 它们发生了,所以这不是一个很有说服力的论点。

真的原因 git 不允许您更改提交消息结束 非常简单: 这样,你就可以相信信息。如果你允许 人们改变他们之后,信息本质上是不太 值得信赖。


为了完整起见,您可以将本地提交历史记录重写为 由 Sykora 建议(使用一些重新基准和重新设置——硬,喘气!)

然而,一旦你发布了修改后的历史 再来一次(使用 git push origin +master:master,即使没有导致“快进”提交,+标志也会强制推送发生) ... ... 你就是 可能会惹上麻烦

从另一个 SO 问题中摘录出来:

实际上,我曾经使用—— force 来推送 git.git 存储库,结果被 Linus BIG TIME 骂了一顿。这会给其他人带来很多问题。一个简单的答案是“不要这样做”。

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

如何改变历史更深层次的承诺

由于 Git 中的历史是不可变的,除了最近的提交(不是分支头的提交)之外,修复任何内容都需要从更改后的提交和前进中重写历史。

你可以使用 StGIT,如果需要的话可以初始化分支,取消提交到你想要更改的提交,如果需要的话可以弹出到它,做一个更改然后刷新补丁(如果你想更正提交消息,可以使用 -e 选项) ,然后推送所有内容和 stg 提交。

或者您可以使用 rebase 来实现这一点。创建新的临时分支,使用 git rebase 将其重新回退到您想要更改的提交(硬盘) ,更改提交(它将位于当前头部的顶部) ,然后在更改后的提交上重新设置分支的基础,使用 git rebase-into。

或者您可以使用 git rebase ——交互式的,它允许各种修改,比如补丁重新排序、崩溃、 ... ..。

我想这应该能回答你的问题了。但是,请注意,如果您有 被推下去的代码到远程存储库,并且人们已经从中提取了代码,那么这将会搞乱他们的代码历史,以及他们已经完成的工作。所以要小心。

目前,废物替代品可能会起作用。

详细情况: 创建一个临时工作分支

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”代表互动。

r(或 reword)替换提交注释旁边的 pick,保存并退出,这样就可以进行编辑。

再来一次 git push你就完了!

在我们的工作室中,我引入了这样的约定: 添加可识别的命名注释标记来提交不正确的消息,并使用注释作为替代。

尽管这并不能帮助那些随意运行“ git log”命令的人,但它确实为我们提供了一种修复评论中错误的 bug 跟踪器引用的方法,而且我所有的构建和发布工具都理解这个约定。

这显然不是一个通用的答案,但它可能是人们可以在特定的社区采用的东西。我敢肯定,如果这个被大规模使用,某种瓷器支持它可能会突然出现,最终..。

假设你有一棵这样的树:

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之前的提交从 mastertemp并提交它们,如果你想改变它们的消息,也可以使用 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

最后一步,在本地删除分支 mastergit fetch origin从服务器上拉取分支 master,然后切换到分支 master并删除分支 temp

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

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

enter image description here