如何撤消 Git 中的最新本地提交?

我不小心将错误的文件提交给Git ,但是我还没有将提交推送到服务器。

如何撤消本地存储库中的那些提交?

答案

撤消提交并重做

$ git commit -m "Something terribly misguided"             # (1)
$ git reset HEAD~                                          # (2)
<< edit files as necessary >>                              # (3)
$ git add ...                                              # (4)
$ git commit -c ORIG_HEAD                                  # (5)
  1. 这是您要撤消的操作。
  2. 这对您的工作树(磁盘上文件的状态)没有任何作用,但是会撤消提交,并使您提交的更改未进行暂存(因此,它们将在git status显示为 “未暂存为提交的更改”),因此您将需要在提交之前再次添加它们)。如果你只是想更多的变化添加到先前的承诺,或修改提交信息1,你可以使用git reset --soft HEAD~代替,这就好比是git reset HEAD~ 2但保留现有的变化上演。
  3. 对工作树文件进行更正。
  4. git add要包含在新提交中的任何内容。
  5. 提交更改,重新使用旧的提交消息。 reset将旧头复制到.git/ORIG_HEAD ; 使用-c ORIG_HEAD commit -c ORIG_HEAD将打开一个编辑器,该编辑器最初包含旧提交的日志消息,并允许您对其进行编辑。如果不需要编辑消息,则可以使用-C选项。

但是请注意,如果您向索引添加了任何新的更改,则使用commit --amend会将它们添加到以前的提交中。

如果代码已经推送到服务器,并且您有权覆盖历史记录(变基),则:

git push origin master --force

您还可以查看以下答案:

如何将 HEAD 移回先前的位置? (独立的头部)和撤消提交

上面的答案将向您显示git reflog ,用于查找您希望还原为的 SHA-1。找到要撤消的点后,即可使用上述命令序列。


1注意,但是,如果您在commit message了一个错误,则无需重置为较早的提交。较简单的选项是git reset (取消对您自此以来所做的任何更改),然后git commit --amend ,这将打开您的默认提交消息编辑器,该编辑器预填充了最后一条提交消息。

2 HEAD~HEAD~1相同。另请参阅git 中的 HEAD 是什么? 。如果您要取消提交多个提交,这将很有帮助。

如果您不知道提交的工作方式,则撤消提交会有些吓人。但是,如果您理解的话,实际上非常容易。

假设您有这个,其中 C 是您的 HEAD,(F)是您的文件状态。

(F)
A-B-C
    ↑
  master

您想核对 C,然后再也看不到它了 。你做这个:

git reset --hard HEAD~1

结果是:

(F)
A-B
  ↑
master

现在 B 是 HEAD。因为使用了--hard ,所以文件在提交 B 时将重置为其状态。

嗯,但是假设提交 C 并不是一场灾难,只是有点困难。您想要撤消提交,但是在进行更好的提交之前,请对更改进行一些编辑。从这里再次开始,以 C 作为您的 HEAD:

(F)
A-B-C
    ↑
  master

您可以执行此操作,而无需使用--hard

git reset HEAD~1

在这种情况下,结果为:

(F)
A-B-C
  ↑
master

在这两种情况下,HEAD 都只是指向最新提交的指针。当您执行git reset HEAD~1 ,您告诉 Git 将 HEAD 指针移回一次提交。但是(除非使用--hard否则)将文件保持原样。因此,现在git status显示您已签入 C 的更改。您还没有丢失任何东西!

对于最轻松的接触,您甚至可以撤消提交,但保留文件和索引

git reset --soft HEAD~1

这不仅让您的文件独自一人,甚至让索引也独自一人。当您执行git status ,您将看到与以前相同的文件在索引中。实际上,在执行此命令后,您可以执行git commit然后重做刚才的相同提交。

还有一件事: 假设您像第一个示例一样破坏了一个提交但是毕竟发现您需要它 ?运气不好吧?

不, 仍然有办法找回它。输入git reflog ,您将看到移入其中的(部分)提交SHA-1 哈希的列表。找到您破坏的提交,然后执行以下操作:

git checkout -b someNewBranchName shaYouDestroyed

您现在已经复活了该提交。在 Git 中,提交实际上并没有被销毁约 90 天,因此您通常可以回去拯救不是故意要摆脱的一个。

有两种方法可以 “撤消” 您的上一次提交,具体取决于您是否已将提交公开(推送到远程存储库):

如何撤消本地提交

假设我在本地提交了,但是现在我想删除该提交。

git log
    commit 101: bad commit    # Latest commit. This would be called 'HEAD'.
    commit 100: good commit   # Second to last commit. This is the one we want.

要将所有内容恢复到上一次提交之前的状态,我们需要resetHEAD之前的提交:

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 the changes you made

现在, git log将显示我们的上一次提交已被删除。

如何撤消公开提交

如果已经将提交公开,则需要创建一个新的提交,该提交将 “还原” 您在先前提交(当前 HEAD)中所做的更改。

git revert HEAD

您的更改现在将恢复并准备提交:

git commit -m 'restoring the file I removed by accident'
git log
    commit 102: restoring the file I removed by accident
    commit 101: removing a file we don't need
    commit 100: adding a file that we need

有关更多信息,请查看Git 基础知识 - 撤消事情

添加 / 删除文件以所需的方式获取内容:

git rm classdir
git add sourcedir

然后修改提交:

git commit --amend

先前的错误提交将被编辑以反映新的索引状态 - 换句话说,就好像您从未犯过错误。

请注意,只有在尚未推送的情况下,才应该这样做。如果已推送,则只需正常提交修复程序即可。

git rm yourfiles/*.class
git commit -a -m "deleted all class files in folder 'yourfiles'"

要么

git reset --hard HEAD~1

警告:以上命令将永久删除您要提交的对.java文件(和任何其他文件)的修改。

hard resetHEAD-1会将您的工作副本设置为错误提交之前的提交状态。

更改最后一次提交

替换索引中的文件:

git rm --cached *.class
git add *.java

然后,如果它是一个私有分支,则修改提交:

git commit --amend

或者,如果它是一个共享分支,请重新提交:

git commit -m 'Replace .class files with .java files'


要更改以前的提交 ,请使用令人敬畏的交互式 rebase 。)


ProTip™:将*.class添加到gitignore 中,以阻止这种情况再次发生。


还原提交

如果您需要更改最后的提交,则修改提交是理想的解决方案,但是reset了更通用的解决方案。

您可以使用以下命令将 Git 重置为任何提交:

git reset @~N

其中NHEAD之前的提交次数, @~重置为前一个提交。

因此,您可以使用:

git reset @~
git add *.java
git commit -m "Add .java files"

查看git help reset ,特别是--soft --mixed--hard上的部分,以更好地了解其功能。

刷新日志

如果您搞砸了,可以随时使用 reflog 查找丢弃的提交:

$ git reset @~
$ git reflog
c4f708b HEAD@{0}: reset: moving to @~
2c52489 HEAD@{1}: commit: added some .class files
$ git reset 2c52489
... and you're back where you started


使用git revert <commit-id>

要获取提交 ID,只需使用git log

如果您打算完全撤消本地提交,则对提交所做的任何更改,如果您对此不担心,只需执行以下命令即可。

git reset --hard HEAD^1

(此命令将忽略您的整个提交,并且您的更改将完全从本地工作树中丢失)。如果要撤消提交,但是要在登台区域中进行更改(在提交之前,就像在git add之后一样),请执行以下命令。

git reset --soft HEAD^1

现在,您提交的文件进入暂存区。假设如果您要升级文件,因为您需要编辑一些错误的内容,请执行以下命令

git reset HEAD

现在已提交的文件将从暂存区域进入未暂存区域。现在文件已准备好进行编辑,因此无论您进行什么更改,都希望对其进行编辑并将其添加并进行新的 / 新的提交。

更多

如果安装了Git Extras ,则可以运行git undo撤消最新的提交。 git undo 3将撤消最后三个提交。

我想撤消我们共享存储库中的最新五次提交。我查找了要回滚的修订版 ID。然后我输入以下内容。

prompt> git reset --hard 5a7404742c85
HEAD is now at 5a74047 Added one more page to catalogue
prompt> git push origin master --force
Total 0 (delta 0), reused 0 (delta 0)
remote: bb/acl: neoneye is allowed. accepted payload.
To git@bitbucket.org:thecompany/prometheus.git
 + 09a6480...5a74047 master -> master (forced update)
prompt>