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

7648

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

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


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

18413

修改最近的提交信息

git commit --amend

将打开您的编辑器,允许您更改最近一次提交的提交消息。此外,您可以使用以下命令在命令行中直接设置提交消息:

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

然而,这会使得多行提交信息或小改动更加繁琐。

确保在进行此操作之前没有任何工作副本更改被暂存,否则它们也将被提交。(未暂存的更改不会被提交。)

更改已经推送到远程分支的提交信息

如果您已经将提交推送到远程分支,则在本地修改提交(如上所述)后,您还需要强制推送提交

git push <remote> <branch> --force
# Or
git push <remote> <branch> -f
警告:强制推送将使用本地分支的状态覆盖远程分支。 如果远程分支上有您本地分支中没有的提交,那么您将会丢失这些提交。
警告:小心修改已经与他人共享的提交。 修改提交实质上是将其重写为具有不同SHA ID的提交,如果其他人拥有旧提交的副本,则会出现问题。 拥有旧提交副本的任何人都需要将他们的工作与您新重写的提交同步,这可能有时很困难,因此请确保在尝试重写共享提交历史时与他人协调,或者完全避免重写共享提交。

执行交互式变基

另一个选项是使用交互式变基。 这使您可以编辑任何您想要更新的消息,即使它不是最新的消息。

为了进行Git压缩,请按照以下步骤进行:

// n is the number of commits up to the last commit you want to be able to edit
git rebase -i HEAD~n

一旦您压缩了提交记录 - 选择e/r以编辑消息:

Screenshot of terminal while editing commit

关于交互式变基的重要提示

当您使用git rebase -i HEAD~n时,可能会有多于n个提交。 Git将“收集”最后n个提交中的所有提交,并且如果该范围内的某个位置存在合并,则还将显示所有提交,因此结果将为n +。

好的提示:

如果您需要对多个分支执行此操作,并且在修改内容时可能会遇到冲突,请设置git rerere并让Git自动为您解决这些冲突。


文档


274
然而,git commit --amend并不像git rebase -i那样强大。 - Jeffrey Jose
82
@jeffjose,这绝对不是必须的。此外,git commit --amend 可以修补主提交。 - strager
125
如果您已经推送过了,只需强制再次推送:git push -f origin branchname - hughes
192
如果其他人也在使用同一个仓库,那么git push -f命令是不是有些危险? - Armand
105
如果您不想重写整个提交信息,请使用“git commit --amend -c HEAD”。这将打开编辑器,并自动填充旧的提交信息,以便您可以更改它。 - Sam
显示剩余30条评论

2658
git commit --amend -m "your new message"

9
我执行了 git commit --amend -m "New message" 命令,但是推送到 Github 后生成了 "在再次推送之前合并远程更改" 的提示。在拉取后,执行 commit --amend 和再次推送后,新消息并没有出现。相反,我看到了 "Merge branch 'master' of github.com:[myrepo]"。 - Dave Everitt
8
您很可能在尝试修复之前就将提交推送到了上游。 - Thorbjørn Ravn Andersen
12
@Kyralessa 错了。在Bash中,你可以通过不关闭引号直到完成(在引号内每行结尾处按回车键)来轻松地组合多行提交消息。 - hobs
42
我不明白为什么一个答案看起来很像两年前写的答案和已被接受的答案,却得到了如此多的投票。奇怪。(不过答案本身没问题) - happy coder
11
@AmalMurali,好的。我的观点并不是关于问题的流行度或答案的实用性。而是这个特定的答案不是最老的答案,也没有提供任何有关被接受答案的进一步见解。它似乎是被复制粘贴自被接受答案的一个部分。那就是我的观点。干杯! - happy coder
显示剩余11条评论

2491
如果您想要修复的提交不是最近的一个:
  1. git rebase --interactive $有瑕疵提交的父提交

    如果您想要修复多个有瑕疵的提交,请传递其中最旧的提交的父提交。

  2. 一个编辑器将出现,并显示从您提供的那个提交以来的所有提交的列表。

    1. 在您想要修复的任何提交前面,将 pick 改为 reword(或在旧版本的 Git 中改为 edit)。
    2. 保存后,Git 将重放列出的提交。

  3. 对于每个您想要重写的提交,Git 将使您返回到您的编辑器。对于每个您想要编辑的提交,Git 会将您带到 shell 中。如果您在 shell 中:

    1. 随意更改提交。
    2. git commit --amend
    3. git rebase --continue

大部分的操作流程将通过各个命令的输出向您解释。这很容易;您不需要记住它 - 只需记住 git rebase --interactive 让您可以纠正任何时候的提交。


请注意,您不会想要更改已经推送的提交。或者也许您想这样做,但在这种情况下,您将需要非常小心地与可能拉取了您的提交并在其上完成工作的所有人进行沟通。当有人将重置或重新设置发布的分支后,我该如何恢复/同步?

45
第一次提交(没有父提交记录)的信息可以更改吗? - 13ren
28
这在其他答案中已经提到,但我会在这里做一个记录。自从 Git 1.6.6 版本以后,你可以使用 reword 替代 pick 来编辑提交日志信息。 - MitMaro
92
顺便提一下,"$parent_of_flawed_commit" 相当于 "$flawed_commit^"。 - Peeja
70
如果您已经向上游推送了代码,请永远不要这样做(或者一般情况下进行变基操作)! - Daniel Rinser
23
如果在错误的提交后进行了合并,请使用“-p”(“--preserve-merges”)选项。 - ahven
显示剩余7条评论

823

要修改之前的提交,请进行您想要的更改并将这些更改暂存,然后运行:

git commit --amend

这将在文本编辑器中打开一个文件,该文件表示您的新提交消息。它最初使用旧的提交消息中的文本填充。按照您的需求更改提交消息,然后保存文件并退出编辑器以完成操作。

要修改先前的提交并保留相同的日志消息,请运行

git commit --amend -C HEAD

要通过完全删除之前的提交来修复问题,请运行

git reset --hard HEAD^

如果你想编辑多个提交信息,运行以下命令:

git rebase -i HEAD~commit_count

(用要编辑的提交次数替换commmit_count。)此命令会打开您的编辑器。 将第一个提交(您想要更改的那个)标记为“edit”而不是“pick”,然后保存并退出编辑器。 执行所做的更改,然后运行

git commit --amend
git rebase --continue

注意:你也可以通过由git commit --amend打开的编辑器来“进行所需的更改”。


22
git rebase -i HEAD~commit_count 还可以让您更改所选提交的提交信息。只需将所选提交标记为“reword”而不是“pick”。 - Joe
3
如果你不想进行变基操作,而只是想更改一个旧的提交记录,该怎么办? - SuperUberDuper
3
git reset --soft 可以撤销提交前的更改,而保留这些更改的内容在工作目录中。请将 --hard 替换为 --soft - eel ghEEz
3
赞同,git reset --hard 是一个完全合法的命令,但在这个问题中使用它是具有误导性的。如果你想要丢弃提交的更改,则使用 --hard,而不是在提交信息中犯了一个拼写错误时使用它! - Soren Bjornstad
git commit --amend -C HEAD 是黄金操作!谢谢。 - Rafael Nobre

411

如前所述,git commit --amend 是覆盖上一个提交的方式。请注意:如果你也想覆盖文件,那么命令会是

git commit -a --amend -m "My new commit message"

5
如果你不想添加所有内容,你可以先运行 git add file.ext 然后执行 git commit --amend - MalcolmOcean

368

你也可以使用git filter-branch来实现。

git filter-branch -f --msg-filter "sed 's/errror/error/'" $flawed_commit..HEAD

这并不像一个简单的 git commit --amend 那样容易,但如果在你的错误提交信息之后已经有一些合并的话,它就会特别有用。

请注意,这将尝试重写从 HEAD 到有缺陷的提交之间的每个提交,所以你应该非常明智地选择你的 msg-filter 命令;-)


4
如果正则表达式没有找到任何匹配项,是否有不更改提交的版本? - sjakubowski
3
据我所知,filter-branch --msg-filter无论如何都会生成新的提交记录。然而,在msg-filter中,您可以检查sed命令是否成功,并在filter-branch操作结束时使用此信息将树重置为refs/original。 - Mark
4
仅当使用 filter-branch 方法时才成立。如果使用交互式 rebase,则修改后的提交后面的提交 ID 不会更改。 - Mark
7
是的,他们需要这样做,这是必须的。提交ID依赖于先前的提交。如果它们不改变,Git将毫无用处。 - Miles Rout
2
你需要使用 $flawed_commit^..HEAD,而不是 $flawed_commit..HEAD。正如 man page 所述:«_该命令只会重写命令行中提到的正向引用(例如,如果你传递 a..b,则只有 b 会被重写)_»。 - Ángel

340

我更喜欢这种方式:

git commit --amend -c <commit ID>
否则,将会有一个新的提交和一个新的提交 ID。

10
对我而言,使用你上面的命令实际上会创建一个新的提交记录,并生成一个额外的提交记录,其中包含“合并分支”的默认提交信息。 - Jan
49
修改操作总是会创建一个包含新的提交ID的新提交。提交ID是提交内容的SHA哈希值,包括提交信息和作者/提交时间戳。这是Git的一个特性,除非出现哈希碰撞,否则保证具有相同ID的两个提交完全相同,具有完全相同的内容、历史等。 - Emil Lundberg
8
同意 Emil 的观点。此外,阅读文档后发现,“-c”选项只是告诉 Git 使用哪个提交的信息作为新提交的默认/模板。实际上,默认情况下它已经会执行“-c <提交ID>”,因此不需要指定该选项。 - Gal
2
“-c” 做了几件事情。它默认使用旧消息,但也复制作者信息(人和时间)。 “-C” 做同样的事情,只是它不会要求您编辑消息。 - Joseph K. Strauss
1
像 @SantanuDey 一样,这对我也没用。我得到了 fatal: Option -m cannot be combined with -c/-C/-F/--fixup. - Andrew Grimm
显示剩余3条评论

318

如果你正在使用Git GUI工具,那么有一个名为Amend last commit的按钮。单击该按钮,它会显示您最后一次提交的文件和消息。只需编辑该消息,然后使用新的提交消息将其提交。

或者在控制台/终端中使用此命令:

git commit -a --amend -m "My new commit message"

7
这个回答与这个旧回答 字面上 完全相同。在提供另一个回答之前,您是否已经检查过现有的回答? - Dan Dascalescu
2
这个答案并非“字面上”完全相同。它的意思甚至都不一样,因为这个答案添加了信息,即这也可以在 GUI 中完成。不确定他指的是哪个 GUI。我知道 GitHub Desktop 有这个功能,而且大多数其他 GUI 客户端可能也有,或者它们可以做更多的事情。 - Nils Lindemann

291

您可以使用Git 变基。例如,如果要修改回到提交 bbc643cd,运行:

$ git rebase bbc643cd^ --interactive

在默认编辑器中,将要修改的提交行中的 'pick' 改为 'edit'。做出你的更改,然后使用 "stage" 将它们添加到暂存区。
$ git add <filepattern>

现在您可以使用

$ git commit --amend

修改提交后,然后...

$ git rebase --continue

返回到之前的主头提交。


2
如果您想确保从 git commit --amend 所做的更改生效,您可以使用 git show 命令,它将显示新的消息。 - Steve Tauber

282
  1. 如果您只想修改最后一次提交的消息,则执行以下操作:

    git commit --amend
    

这将使你进入文本编辑器,让你更改最后一次提交的消息。

  1. 如果你想要更改最近三次提交或者在那之前的任何提交消息,请向 git rebase -i 命令提供 HEAD~3

git rebase -i HEAD~3

7
早期的回答已经提到可以使用 git commit --amend 命令,还提到了可以使用 git rebase -i HEAD~commit_count 命令,你所做的只是将 3 替换了 commit_count。请注意,此处不提供解释。 - user456814
1
同样被踩了。人们只是不费心去阅读已有的答案 - Dan Dascalescu
1
这不是完整的答案,缺少“找到您想要的提交,将pick更改为r(重写)...”如此处所述 https://dev59.com/ynVC5IYBdhLWcg3wz0h9#28421811 - Pawel Cioch

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