如何修改已存在但未推送的提交信息?

7648

我在提交信息中写错了内容。

我该如何修改这个信息呢?该提交还未被推送到服务器上。


868
对于那些对 git 还比较新的人来说:Laurie 提到尚未推送的点是很重要的。和变基一样,这会改变历史记录。如果在原始历史记录和重写历史记录之间有人从你的仓库克隆/拉取,则他们无法在重写后再次拉取(该分支)。 - Pat Notz
27个回答

267

如果您需要在多个分支上更改旧的提交信息(即,带有错误信息的提交存在于多个分支中),您可以使用:

git filter-branch -f --msg-filter \
'sed "s/<old message>/<new message>/g"' -- --all

Git将创建一个临时目录进行重写,并在refs/original/中备份旧引用。

  • -f强制执行操作。如果临时目录已经存在或者已经存在存储在refs/original下的引用,则这是必要的。如果不是这种情况,则可以省略此标志。

  • --将filter-branch选项与修订选项分隔开。

  • --all将确保重写所有分支标记

由于备份了旧引用,您可以轻松地返回到执行该命令之前的状态。

假设您想恢复您的主分支并在分支old_master中进行访问:

git checkout -b old_master refs/original/refs/heads/master

4
这个回答与提问者的问题无关,因为他们只是想修复他们刚刚做的一次提交。我经常使用 git commit --amend 来修复注释或添加我忘记 git add 的文件,但只有在我没有 git push 之前才这样做。当我想完全混淆版本历史记录时,我也会使用 git filter-branch,但是提问者并不想这样做,所以这个答案需要一个大警告 - 不要在家里尝试这个操作! - kbro

258

如果这是你的最后一次提交,只需 修改 提交:

git commit --amend -o -m "New commit message"

(使用-o--only)标志确保仅更改提交消息)


如果是一个隐藏的提交,请使用强大的交互式变基

git rebase -i @~9   # Show the last 9 commits in a text editor
找到你想要的提交,将pick改为rreword),然后保存并关闭文件。完成!



小型 Vim 教程(或者说只需 8 个按键就可以变基 3jcwrEscZZ):
  • 如果有时间,运行vimtutor
  • hjkl 对应移动键
  • 所有命令都可以带上“范围”,例如 3j 向下移动三行
  • i 进入插入模式 —— 输入的文本将出现在文件中
  • EscCtrlc 退出插入模式并返回到“正常”模式
  • u 撤销
  • Ctrlr 重做
  • dddwdl 删除一行、一个单词或一个字母
  • cccwcl 更改一行、一个单词或一个字母(与 ddi 相同)
  • yyywyl 复制(“yank”)一行、一个单词或一个字母
  • pP 粘贴到当前位置的后面或前面,分别
  • :wEnter 保存文件
  • :q!Enter 不保存退出
  • :wqEnterZZ 保存并退出

如果你经常编辑文本,请切换到Dvorak键盘布局,学习触摸打字并学习Vim。值得付出这个努力吗?是的。



ProTip™️:不要害怕尝试“危险”的重写历史命令 - Git 默认情况下会保留你的提交90天;你可以在reflog中找到它们:

$ git reset @~3   # Go back three commits
$ git reflog
c4f708b HEAD@{0}: reset: moving to @~3
2c52489 HEAD@{1}: commit: more changes
4a5246d HEAD@{2}: commit: make important changes
e8571e4 HEAD@{3}: commit: make some changes
... earlier commits ...
$ git reset 2c52489
... and you're back where you started

* 不过要注意像 --hard--force 这样的选项——它们可能会丢弃数据。 * 另外,在任何你正在协作的分支上不要重写历史记录。


5
Vim部分完全与主题无关,与其鼓励用户花时间学习一个神秘的编辑器,为什么不教他们一些更相关的东西,比如如何将默认的git编辑器设置为用户友好的“nano”?我们正在谈论需要对文本文件进行的琐碎修改,而不是会引发有关“最佳”文本编辑器的激烈争论的硬核编码。 - Dan Dascalescu
4
因为使用以上的指令学习 Vim 比使用 nano 进行多次 rebase 更快。Git 之所以打开文本编辑器而不是使用自己的界面进行 rebase,是因为 Vim 存在:它轻量级,大多数系统默认安装,并且非常容易学习,足以轻松执行 rebase,例如 ddjjpZZ 可以将一个提交向下移动 2 个位置。基本的 Vim 知识并没有什么神秘的地方;花费 10 分钟时间学习 Vim 就可以比使用 nano 更加熟练。 - Zaz
3
“-o” 标志正是我一直在寻找的:可以在不添加暂存文件的情况下更改提交消息。谢谢! - Liran H

229

使用

git commit --amend

为了详细了解,可以参考这篇优秀的文章:4. 重写Git历史记录。它还讨论了不适合使用 git commit --amend 的情况。

2
有没有好的方法可以修复已经推送到公共仓库的提交信息?到目前为止,我得出结论,一旦推送,我的提交信息中的错别字和思维错误就必须永久存在。 - stackunderflow
2
总之,不行!撤回已经推送的内容没有好的方法。所有的撤回都会带来不同程度的问题。你需要养成在自己的私有仓库中使用分支进行工作的习惯,每次添加一点、测试一点、调整一点就进行多次提交。然后将整个分支合并为一个提交,编写新的提交消息描述整体变更,校对后再推送。 - kbro
1
只是明显的一点,当从一个特性分支回退时,并不需要进行单个提交。许多人所做的是在目标分支上进行变基(使事情看起来干净),然后合并并选择抑制快进选项。同意在推送之前要小心的主要观点。 - ShawnFumo
1
在你写下回答之前,git commit --amend的答案已经被多次给出了。为什么你还要再次发布它呢?如果你想添加一个指向“重写Git历史”的链接,你可以编辑现有答案之一,或者留下评论。 - Dan Dascalescu

201

修改

这里有几个选项。你可以:

git commit --amend

只要是你的最后一次提交,就不需要进行交互式变基。

交互式变基

否则,如果不是你的最后一次提交,你可以进行交互式变基。

git rebase -i [branched_from] [hash before commit]

然后在交互式 rebase 中,您只需将 “edit” 添加到该提交中。当它出现时,执行 git commit --amend 并修改提交消息。如果您想回滚到该提交点之前,您也可以使用 git reflog 并删除该提交。然后您只需再次执行 git commit


186

如果您使用的是 Git GUI,您可以使用以下命令修改尚未推送的最后一次提交:

Commit/Amend Last Commit

169

我尽可能地使用Git GUI,它提供了修改最后一次提交的选项:

勾选这个框

此外,git rebase -i origin/master 是一个很好的口令,它将始终向您呈现在 master 分支之上的提交,并提供修改、删除、重新排序或压缩的选项。无需首先获取那个哈希值。


2
这是Windows Git Gui的右下角。只需选择“修改上次提交”切换,它将填充最近的提交信息。 - wbdarby

149

如果有人正在寻找一个Windows/Mac GUI来帮助编辑较旧的消息(不仅仅是最新的消息),我推荐使用Sourcetree。下面是跟随的步骤图片。

Sourcetree交互式变基

对于还没有推送到远程的提交:

  1. 确保您已经提交或者存储所有当前更改(即“文件状态”选项卡中没有任何文件)-否则它将无法工作。
  2. 在“日志/历史记录”选项卡中,右键单击与您想要编辑的提交下面一行有相邻线条的条目,然后选择“交互地变基子级 <commit ref>...”
  3. 选择要更改的提交消息的整行 (点击“Message”列)
  4. 单击“Edit Message”按钮。
  5. 在弹出的对话框中按需要编辑消息,然后单击OK
  6. 如果有其他提交消息需要更改,请重复步骤3-4。
  7. 单击OK: 变基将开始。如果一切顺利,则输出将以“成功完成”结尾。注意:当尝试同时修改多个提交消息时,有时会出现“无法创建 'project_path/.git/index.lock': File exists.”的失败。不确定问题具体是什么,或者Sourcetree的未来版本是否会修复它,但如果出现这种情况,建议一个接一个地变基(速度较慢但似乎更可靠)。

... 或者 ... 对于已经被推送的提交:

按照此答案中的步骤进行操作,其与上述步骤类似,但需要使用命令行运行进一步的命令(git push origin <branch> -f)来强制推送分支。我建议您仔细阅读并采取必要的谨慎措施!


2
在所有答案中,这是最适合所有 Git 新手的(使用免费程序 SourceTree,并在要编辑的提交之前应用“Rebase children of”)。 - revelt

141

哇,有很多种方法可以做到这一点。

另一种方法是删除最后一次提交,但保留其更改,以便您不会丢失工作。然后,您可以使用更正后的消息进行另一次提交。操作方式如下:

git reset --soft HEAD~1
git commit -m 'New and corrected commit message'

如果我忘记添加文件或进行更改,我总是这样做。

记住使用--soft而不是--hard,否则您将完全丢失该提交记录。


5
这个命令与 git commit --amend 的功能完全相同,只是它需要分成两步完成。 - Joseph K. Strauss
4
我认为修改提交还可以保留原来的提交作者和日期信息,同时将新的提交者和日期信息分开。我不确定这种方法是否能做到这一点。 - everton
4
@EvertonAgner 您是正确的。 --amend 将保留作者信息,但问题只要求更改消息。 - Joseph K. Strauss
这里有一个小修正,如果所有文件都被删除了,那么你需要将它们重新添加回来,可以使用 git add . 命令,然后使用 git commit -m "New message" 和 git push origin BRANCH_NAME 命令提交更改。 - sid7747

132

如果您只想编辑最新的提交记录,请使用:

git commit --amend
或者
git commit --amend -m 'one line message'

但是如果你想要编辑一系列提交记录,你应该使用变基(rebase):

git rebase -i <hash of one commit before the wrong commit>

Git rebase editing

在像上面的文件中,输入edit/e或其他选项,然后保存并退出。

现在你将会在第一个错误的提交处。更改文件内容,它们将自动为你暂存。键入

git commit --amend

保存并退出,然后输入

git rebase --continue

要移动到下一个选择,直到完成所有选择。

请注意,在特定提交之后,这些操作将更改您的所有SHA哈希值。


2
git rebase -i <错误提交之前的一个提交哈希值> 对我很有用。谢谢。 - Viraths
所有的重置文件中的消息都是一行的,但是我原本有多行。我担心如果以这种方式保存,它会变得一团糟。我试图按照原始形式排列编辑,但是消息被截断为第一行,所以我不得不重置更改。我该如何保留原始文本形式? - undefined

130

如果你只想修改你最后一条消息,你应该使用--only标志或其快捷方式-ocommit --amend一起使用:

如果您只想更改上一条提交的信息,请使用--only标志或其缩写-ocommit --amend一起使用:

git commit --amend -o -m "New commit message"

这样可以确保您不会意外地将暂存的内容与提交混合。当然,最好有一个适当的$EDITOR配置。然后您可以省略-m选项,Git会使用旧的提交信息填充提交信息。以此方式可以轻松编辑。


1
“顶级”答案并没有回答问题。它只是对git commit --amend进行了一般性的介绍。问题非常具体,因此长并不等于好。关键的 -o 标志可能会被淹没在其他信息中。我也不太舒服编辑已经有很多赞的答案。 - David Ongaro
2
话虽如此,你可以自由编辑置顶回答,因为有真正的危险,人们正在将其作为“正确”答案使用。你很容易会发生在提交中添加已暂存内容的情况——我也曾经遇到过,当你提交了这种情况时,真的很烦人。但是,数量并不保证正确性。无论是回答数量还是投票数量都是如此。 - David Ongaro
1
我不会说最佳答案是“错误的”,也不会说它“没有回答问题”。它肯定是有效的并且回答了问题,只需要确保在尝试修改时没有暂存更改。但我理解你的观点,需要提醒人们注意这一点。如果有时间,我稍后会进行编辑。 - user456814
2
公平地说:尽管自Git 1.3.0以来,--amend选项的--only选项可用,但直到在1.7.11.3中修复后才能正常工作(ea2d4ed35902ce15959965ab86d80527731a177c)。因此,回到2008年的正确答案可能是:git stash; git commit --amend; git stash pop - David Ongaro

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