如何在Git中撤销最近的本地提交?

26051
我不小心提交了错误的文件到Git,但还没有将提交推送到服务器。
我该如何从本地仓库撤销这些提交?

684
你知道git需要什么?就是"git undo",这样一来,git对于我们这些凡人所犯下的错误的处理名声就消失了。实现的方法是在执行任何"git"命令之前将当前状态推送到git堆栈上。这会影响性能,所以最好增加一个配置标志来决定是否启用它。 - Yimin Rong
57
可以使用Git的“alias”功能来完成这个操作:https://git-scm.com/book/zh/v2/Git-基础-Git-别名 - Edric
134
针对VsCode用户,只需按下ctrl+shift+G,然后单击三个点,即“更多选项”,接着再点击“撤销上一次提交”。请注意,翻译过程中不会添加解释或其他任何额外信息。 - ashad
29
您要撤销的是什么?有很多不同的功能用例,其中“撤销”意味着完全不同的事情。我敢打赌,添加一个新的花哨的“魔法棒”只会更加混淆事情。 - Romain Valeri
50
不太相信,人们仍然会弄乱并撤销不应该撤销的事情。但更重要的是,git reflog 已经接近你所描述的内容,但它给用户更多的控制权来确定需要(撤销)做的事情。但是请注意,“撤销”在各个地方的工作方式不同,人们会期望这个功能实现许多不同的事情。撤销上一个提交?撤销上一个操作?如果最后一个操作是推送,如何撤销,(重置并推送)还是(撤销并推送)? - Romain Valeri
显示剩余10条评论
107个回答

540

我更喜欢使用git rebase -i来完成这个任务,因为它会弹出一个漂亮的列表,我可以在其中选择要摆脱的提交。它可能不像其他答案那样直接,但只是感觉正确

选择您想要列出的提交数量,然后像这样调用(以列出最后三个)

git rebase -i HEAD~3

示例清单

pick aa28ba7 Sanity check for RtmpSrv port
pick c26c541 RtmpSrv version option
pick 58d6909 Better URL decoding support

然后Git会删除你删除的任何行的提交记录。


506

如何修复之前的本地提交

使用git-gui(或类似工具)执行 git commit --amend 。从GUI中,您可以添加或删除单个文件到提交中。您还可以修改提交信息。

如何撤销之前的本地提交

只需将分支重置到上一个位置即可(例如,使用 gitk git rebase )。然后从保存的副本重新应用更改。在本地存储库的垃圾回收之后,它将像不需要的提交从未发生过一样。要在单个命令中执行所有操作,请使用 git reset HEAD~1

警告: 粗心使用 git reset 是让您的工作副本进入混乱状态的好方法。如果可能的话,我建议Git新手避免使用此功能。

如何撤消公共提交

执行反向cherry pickgit-revert)以撤消更改。

如果您还没有将其他更改拉到分支上,只需...

git revert --no-edit HEAD

然后将您更新的分支推送到共享存储库。

提交历史将单独显示这两个提交


高级: 在公共存储库中更正私有分支

这可能很危险--确保您有要重新推送的本地分支副本。

还要注意:如果可能有其他人正在处理该分支,则不要执行此操作。

git push --delete (branch_name) ## remove public version of branch

清理您本地的分支,然后重新提交...

git push origin (branch_name)

通常情况下,您可能不需要担心私有分支提交历史记录是否完整无缺。只需推送一个后续提交(请参见上文的“如何撤消公共提交”),然后稍后执行压缩合并以隐藏历史记录即可。


13
如果您想撤销一个 '--amend' 提交,gitk --all $(git reflog | cut -c1-7)& 可能会有所帮助。 - Brent Bradburn
8
请注意,如果您试图在推送到共享仓库之前删除秘密信息,执行还原操作是无济于事的,因为该信息仍然会存在于之前提交的历史记录中。如果您想确保更改不对他人可见,您需要使用 git reset - Jherico
在远程仓库中更正私有分支也可以通过简单的 git push origin (branch_name) --force 命令完成。 - Brent Bradburn

418

如果您想永久撤消操作,并且您已经克隆了某个代码库。

可以通过以下方式查看提交ID:

git log 

然后你可以这样做:

git reset --hard <commit_id>

git push origin <branch_name> -f

如果您不使用“<commit_id>”,而只是使用“git reset --hard”会怎样呢?我通常只想摆脱我尚未提交的最新更新,并回到我所做的最新提交,我总是使用“git reset --hard”。 - Jaime Montoya
7
您可以使用 git reset --hard 撤销最近的更改,但如果您需要永久删除最后的 "n" 个提交记录,则需要指定一个 SHA。 - poorva
运行得非常顺利。被重置的分支('master')没有被任何人签出,因此不存在任何冲突的可能性。 - Gsv

411

如果您已经提交了代码更改但是还没有推送。

git reset --soft HEAD~1

HEAD~1是指当前提交之前的快捷方式。如果需要重置,您也可以引用哈希值的SHA-1。使用--soft选项将删除提交但会保留所有已更改的文件作为“要提交的更改”,就像git状态所描述的那样。

如果要消除自上一次提交以来工作目录中任何跟踪文件的更改,请使用"--hard"。

或者

如果您已经推送并有人拉取了代码(通常是我),则无法使用git reset。不过,您可以使用git revert

git revert HEAD

这将创建一个新的提交,它会撤销意外提交引入的所有更改。


我处于第二种情况,但当我执行“git revert HEAD”时,它会显示“错误:提交[ID]是一个合并,但没有给出-m选项。致命错误:还原失败”。有什么建议吗? - metaforge
8
可能值得一提的是,您可以使用由git log --statgit reflog显示的实际哈希值,而不是HEAD~1 - 当您需要“撤消”多个提交时非常有用。 - ccpizza

352
SourceTree(GitHub的GUI),您可以右键单击提交并执行“Reverse Commit”操作。这将撤消您的更改。
在终端上:
您也可以使用:
git revert

或者:

git reset --soft HEAD^ # Use --soft if you want to keep your changes.
git reset --hard HEAD^ # Use --hard if you don't care about keeping your changes.

323
一个命令:
git reset --soft 'HEAD^' 

撤消最后一次本地提交的效果非常好!


17
因为我是从 Windows 命令提示符中编写的,所以我需要用双引号把 git reset --soft "HEAD^" 括起来。 - Ena

302

使用以下git命令来重置它:

git reset --soft HEAD~1
解释: git reset是将代码回滚到你想要返回的任何提交,如果与--soft关键字一起使用,则会回滚并保留文件中的更改,使得你回到文件刚被添加的状态,HEAD是该分支的最新提交,如果与~1组合使用(在这种情况下,还可以使用HEAD^),则仅回滚一个提交,这正是你想要的...
我在下面的图片中详细展示了所有可能发生的步骤和提交代码的情况: 如何撤销 Git 中的最后一次提交?

295

“将工作树重置为上一个提交”

git reset --hard HEAD^ 

"清理工作树中的未知文件"

git clean    

参见-Git快速参考

注意:这个命令会删除你之前的提交记录,因此请谨慎使用!git reset --hard更安全。


git reset --hard 有什么不同之处? - Hashim Aziz

275

如何撤销最后一次 Git 提交?

要将所有内容恢复到最后一次提交之前的状态,我们需要重置为 HEAD 前面的提交。

  1. 如果您不想保留所做的更改:

    git reset --hard HEAD^
    
  2. 如果您想保留您所做的更改:

  3. git reset --soft HEAD^
    
    现在检查一下你的 git 日志。它会显示我们最后一次提交被删除了。


225

使用reflog查找正确的状态

git reflog

reflog before 重置前的Reflog

选择正确的Reflog(在我的情况下是f3cb6e2),并键入

git reset --hard f3cb6e2

此后,仓库 HEAD 将被重置为该 HEADid。 reset effect 重置后的日志

最后,引用日志将会像下面的图片一样。

reflog after 引用日志最终结果


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