题 如何修改现有的,未删除的提交?


我在提交消息中写了错误的东西。或者,我忘了包含一些文件。

如何更改提交消息/文件?提交尚未被推送。


7680
2017-10-07 15:44


起源


对于那些对git来说有些新意的人来说:Laurie关于尚未推出的观点很重要。像改变一样,这正在改变历史。如果有人在原始目录和重写历史记录之间克隆/撤回了回购,那么在重写之后他们将无法撤回(对于该分支)。 - Pat Notz


答案:


修改最新的提交消息

git commit --amend

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

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

...但是,这可能使多行提交消息或小修正更加麻烦。

确保您没有任何工作副本更改 上演 在这之前,他们也会得到承诺。 (未分级 更改不会被提交。)

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

如果你已经将提交推送到远程分支,那么你就可以了 需要强制推送提交 有:

git push <remote> <branch> --force
# Or
git push <remote> <branch> -f

警告:强制推送将使用本地状态覆盖远程分支。如果您在本地分支中没有远程分支上的提交,则为您  失去那些承诺。

警告:谨慎修改已与其他人共享的提交。 主要修改提交 重写 他们有不同 SHA ID,如果其他人拥有您已重写的旧提交的副本,则会出现问题。拥有旧提交副本的任何人都需要将他们的工作与新重写的提交同步,这有时会很困难,因此请确保在尝试重写共享提交历史记录时与其他人协调,或者只是避免重写共享提交共。


使用交互式rebase

另一种选择是使用交互式rebase。
这允许您编辑要更新的任何消息,即使它不是最新消息。

为了做一个git squash,请按照下列步骤操作:

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

一旦你压缩你的提交 - 选择 e/r 用于编辑消息

enter image description here

关于Interactive rebase的重要说明

当你使用 git rebase -i HEAD~X 可以有 更多 比 X 提交。 Git将“收集”最后提交的所有提交 X 提交并且如果在该范围之间存在合并,您将看到所有提交,因此结果将是X +。

好提示:

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


文档


14802
2018-02-08 04:26



然而 git commit --amend 并不像 git rebase -i。 - Jeffrey Jose
@jeffjose,绝对不需要。也, git commit --amend 可以修复(a?)主提交。 - strager
如果你已经推了,只需再次强制推动: git push -f origin branchname - hughes
@hughes不是 git push -f 如果其他人使用相同的存储库有点危险吗? - Armand
如果您不想重写整个提交消息,请转到 git commit --amend -c HEAD。这将打开预先填充旧提交消息的编辑器,以便您可以更改它。 - Sam


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

2415
2017-10-07 19:52



我做了git commit --amend -m“新消息”,但推送到Github生成了“在再次推送之前合并远程更改”。在pull,commit --amend和再次推送之后,新消息不会出现。相反,我有“github.com的合并分支'大师':[myrepo]” - Dave Everitt
@DaveEveritt你最有可能在尝试修复它之前推送你的提交。 - Thorbjørn Ravn Andersen
@Kyralessa不是真的。在bash中,您可以轻松地编写多行提交消息,只需在完成之前不关闭报价(在报价中的每一行末尾点击返回)。 - hobs
我不知道答案看起来很像两年前写的答案的主要想法,而且接受的答案得到了如此多的选票。奇怪。 (虽然答案没有错) - happy coder
@AmalMurali,好吧。我的观点不在于问题的普及程度,也不在于答案的实用性。但是这个特定的答案并不是最古老的答案,也没有提供对已接受答案的进一步了解。它似乎是已接受答案的一部分的副本。这是我的观点。干杯! - happy coder


如果要修复的提交不是最新的提交:

  1. git rebase --interactive $parent_of_flawed_commit

    如果要修复多个有缺陷的提交,请传递最旧的提交的父级。

  2. 将出现一个编辑器,其中列出了自您提交的所有提交以来的所有提交。

    1. 更改 pick 至 reword (或旧版本的Git,to edit)在你想修复的任何提交之前。
    2. 保存后,Git将重播列出的提交。
       

  3. 对于您想要的每个提交 改写,Git会把你带回你的编辑器。对于您想要的每个提交 编辑,Git将你带入shell。如果你在shell中:

    1. 以您喜欢的任何方式更改提交。
    2. git commit --amend
    3. git rebase --continue

大多数此序列将通过各种命令的输出向您解释。这很容易,你不需要记住它 - 只记得那个 git rebase --interactive 无论多久以前,都可以让你正确提交。


请注意,您不希望更改已推送的提交。或者也许你这样做,但在这种情况下,你必须非常谨慎地与每个可能已经完成提交并完成工作的人沟通。 在有人推送rebase或重置到已发布的分支后,如何恢复/重新同步?


2297
2017-08-15 21:20



可以更改第一次提交的消息(没有父级)吗? - 13ren
在其他一个答案中提到了这一点,但我将在此处记下它。由于git 1.6.6你可以使用 reword 代替 pick 编辑日志消息。 - MitMaro
顺便, $parent_of_flawed_commit 相当于 $flawed_commit^。 - Peeja
如果你已经向上游推进,那么永远不要这样做(或者一般来说是反叛的)! - Daniel Rinser
使用 -p (--preserve-merges如果在有缺陷的提交之后存在合并。 - ahven


要修改先前的提交,请进行所需的更改并暂存这些更改,然后运行

git commit --amend

这将在文本编辑器中打开一个表示新提交消息的文件。它首先填充旧提交消息中的文本。根据需要更改提交消息,然后保存文件并退出编辑器以完成。

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

git commit --amend -C HEAD

要通过完全删除它来修复先前的提交,请运行

git reset --hard HEAD^

如果要编辑多个提交消息,请运行

git rebase -i HEAD~commit_count

(更换 commit_count 您要编辑的提交数。)此命令启动您的编辑器。将第一个提交(您要更改的提交)标记为“编辑”而不是“选择”,然后保存并退出编辑器。进行您要提交的更改然后运行

git commit --amend
git rebase --continue

注意:您也可以从打开的编辑器中“进行所需的更改” git commit --amend


750
2018-06-06 21:16



git rebase -i HEAD~commit_count 还允许您更改您选择的多次提交的提交消息。只需将所选提交标记为“reword”而不是“pick”。 - Joe
如果你不想改变怎么办?你只想更改旧邮件? - SuperUberDuper
git reset --hard 歼灭未提交的更改。请更换 --hard 同 --soft。 - eel ghEEz


如前所述, git commit --amend 是覆盖最后一次提交的方法。一个注意事项:如果你也想 覆盖文件,命令就是

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

381
2017-09-01 20:35



如果你不想添加所有内容,你可以先做 git add file.ext 然后就是 git commit --amend - MalcolmOcean


你也可以使用git filter-branch 为了那个原因。

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

它并不像琐碎那么容易 git commit --amend,但如果您在错误的提交消息后已经有一些合并,那么它特别有用。

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


346
2018-01-10 14:23



如果正则表达式没有找到任何内容,是否有一个版本不会更改提交? - sjakubowski
AFAIK filter-branch --msg-filter在任何情况下都会生成新的提交。但是,您可以在msg-filter中检查,如果sed成功并在filter-branch操作结束时使用此信息将树重置为refs / original。 - Mark
@DavidHogue只有在使用filter-branch方法时才会这样。如果使用交互式rebase,则修改后的提交后的提交ID不会更改。 - Mark
@Mark是的他们这样做,他们是必须的。提交ID取决于先前的提交。如果他们没有改变,git将毫无用处。 - Miles Rout
你需要 $flawed_commit^..HEAD不是 $flawed_commit..HEAD。正如手册页所述:«该命令只会重写命令行中提到的正引用(例如,如果传递a..b,则只会重写b)。» - Ángel


我更喜欢这种方式。

git commit --amend -c <commit ID>

否则,将有一个带有新提交ID的新提交


306
2017-11-08 03:51



对我来说,使用上面的命令实际上创建了一个新的提交,其中包含一个新的提交ID以及另一个提交,称“合并分支”作为默认提交消息。 - Jan
修订 总是 使用新的提交ID创建新的提交。提交ID是提交内容的SHA哈希,包括提交消息和创作/提交的时间戳。这是Git的一个特性,除非发生哈希冲突,否则确保具有相同ID的两个提交完全相同,具有完全相同的内容,历史记录等。 - Emil Lundberg
同意埃米尔。另外,阅读文档 - 似乎所有“-c”都告诉git哪个提交的消息用作新提交的默认/模板。实际上它已经默认执行“-c <commit ID>” ,所以不需要指定它。 - Gal
该 -c 做了一些事情。它默认使用旧消息,但它也复制作者信息(人和时间)。 -C 做同样的事情,除了它不要求你编辑消息。 - Joseph K. Strauss
就像@SantanuDey一样,它对我不起作用。我有 fatal: Option -m cannot be combined with -c/-C/-F/--fixup. - Andrew Grimm


如果您使用的是Git GUI工具,则会有一个名为modify last commit的按钮。单击该按钮,然后它将显示您上次提交的文件和消息。只需编辑该消息,您就可以使用新的提交消息提交它。

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

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

304
2018-01-22 17:23





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

$ git rebase bbc643cd^ --interactive

在默认编辑器中,将“pick”修改为要修改其提交的行中的“edit”。进行更改,然后进行演示

$ git add <filepattern>

现在你可以使用了

$ git commit --amend

修改提交,然后修改

$ git rebase --continue

返回上一个头部提交。


279
2017-10-22 11:22



如果你想确保改变 git commit --amend 你可以使用影响 git show 它会显示新消息。 - Steve Tauber


  1. 如果您只想修改上次提交消息,请执行以下操作:

    git commit --amend
    

    这将使您进入文本存储器并让您更改上次提交消息。

  2. 如果要更改最后3个提交消息或任何提交消息,请提供 HEAD~3 到了 git rebase -i 命令:

    git rebase -i HEAD~3
    

270
2017-11-15 09:29



这个早先的答案 已经说过你可以用了 git commit --amend,它还说你可以使用 git rebase -i HEAD~commit_count你所做的就是插上电源 3 对于 commit_count。


如果您必须在多个分支上更改旧的提交消息(即,多个分支中存在错误消息的提交),您可能希望使用:

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

Git将创建一个临时目录,用于重写和另外备份旧引用 refs/original/

  • -f 将强制执行该操作。如果临时目录已经存在或者存在已存在的引用,则这是必需的 refs/original。如果不是这种情况,您可以删除此标志。

  • -- 将过滤器分支选项与修订选项分开。

  • --all 将确保,所有 分支机构 和 标签 被重写。

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

比如说,您想要恢复您的主人并在分支中访问它 old_master

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

251
2018-03-27 20:43



这个答案没有解决OP的问题,因为他们纯粹对修复他们刚刚完成的提交感兴趣。我经常使用 git commit --amend 修复评论或添加我忘记的文件 git add, 但只有 曾经 在我之前 git push编辑。我也用 git filter-branch 当我想完全搞乱版本历史,但OP不想要这个,所以这个答案需要一个很大的健康警告 - 不要在家里尝试这个,偷看!! - kbro