如何撤销初始的Git提交?

576

我第一次向 Git 存储库提交了更改,但后来我后悔了这个提交并想要撤消它。我尝试使用

# git reset --hard HEAD~1

我收到了这个消息:

fatal: ambiguous argument 'HEAD~1': unknown revision or path not in the working tree.

这个提交是该存储库的第一次提交。有什么办法可以撤销Git的初始提交吗?

11个回答

904

您只需要删除您当前所在的分支即可。不能使用git branch -D,因为它具有防止此操作的安全检查。可以使用update-ref来完成此操作。

git update-ref -d HEAD

不要使用 rm -rf .git 或类似的命令,因为这会完全清除您的整个存储库,包括所有其他分支以及您尝试重置的分支。


1
在 rebase 过程中尝试将第一个 commit 拆分,然后运行了 git status 命令,但出乎意料的是,git 报错说 fatal: Not a git repository (or any parent up to mount point ...) ! - Matt Fenwick
1
这对我没用。创建文件,包括一些应该被忽略但没有 .gitignore 的文件。运行 git add .git commit -m "initial commit"git update-ref -D HEAD 命令后,创建一个 .gitignore 文件,注意到 Git 仍然看到之前已添加但应该被忽略的文件。换句话说,git update-ref -d HEAD 没有将我带回到初始提交之前的状态。 - gman
2
但这正是原始问题的重点。回到最初提交之前的状态。 - gman
2
git reset --hard HEAD~1 会删除所有其他提交中添加的文件。显然问题是如何达到与该命令在所有其他情况下的作用相同的状态。请参阅此 gist 以证明您的解决方案无效。https://gist.github.com/greggman/522fa69a21d6cfb3ff0b - gman
32
如果有人对gman的评论感到困惑:git update-ref -d HEAD实际上会还原初始提交,但会保留添加到索引中的所有先前提交的更改。如果您想删除这些更改,只需执行以下git reset --hard即可。即使不完整,此答案确实是最好的答案,因此请避免使用rm -fr .git(除非您知道自己在做什么)。 - rsenna
显示剩余10条评论

114

您可以删除 HEAD 并将存储库恢复到新状态,从而可以创建一个新的初始提交:

git update-ref -d HEAD

如果你已经将新的 commit 推送到远程,那么你需要强制推送以覆盖先前的初始 commit:

git push --force origin

3
值得注意的是,这是正确的命令,但它并不删除 HEAD,而是删除了 .git\HEAD 文件引用的 ref(位于 .git\refs\heads 下)。运行此命令后,您仍然可以找到 HEAD 文件指向您已删除的 refs/heads/<name> 文件,但如果您按照该路径查看,您会发现 heads 引用已不再存在。 - user2858650
它删除了我的本地分支并分离了HEAD。运行后开始出现(HEAD detached at origin/master)的错误。这浪费了几个小时,最后不得不获取新的代码。 - Pankaj Prakash

33

这个问题是从这篇博客文章中链接过来的,针对较新版本的Git提出了另一种解决方案:

git branch -m master old_master
git checkout --orphan master
git branch -D old_master

这个解决方案假设:

  1. 你的master分支只有一个提交
  2. 没有名为old_master的分支,所以我可以自由使用那个名称

它将现有分支重命名为old_master并创建一个新的孤立分支master (就像为新存储库创建的那样),之后您可以自由地删除old_master ...或不删除。由你决定。

注意:移动或复制Git分支会保留其reflog (参见此代码),而删除然后创建新分支则会破坏它。由于您希望回到没有历史记录的原始状态,因此您可能需要删除该分支,但其他人可能要考虑这个小注释。


与目前所述的相反,这个解决方案实际上并不假设原始分支上只有一个提交:它将简单地用一个新的空分支替换现有的“master”分支,而不考虑现有分支的状态。 - Tom

22

根据问题中所规定的条件:

  • 该提交是存储库中的第一个提交。
  • 这意味着只执行了非常少的命令:
    • git init
    • 大概有一些 git add 操作,
    • 和一个 git commit
    • 就是这样!

如果满足这些前提条件,则撤消初始提交的最简单方法是:

rm -fr .git

从您执行git init的目录开始。然后,您可以重新执行git init来重新创建Git存储库,并使用任何有意义的更改来重新添加以及重新进行初始提交。

危险! 这将删除Git存储库目录。

这将永久且不可恢复地删除Git存储库目录,除非您在其他地方备份了该目录。在特定前提下,如果您在存储库中没有需要保留的内容,则不会丢失任何内容。 假设您尚未修改文件并且尚未删除它们等情况下,您添加的所有文件仍然可用于工作目录。但是,只有当您的存储库中没有其他内容时,才能安全地执行此操作。在描述“第一次提交存储库,然后后悔”的情况下,此操作是安全的。但很多时候并不安全。

如果要删除不需要的克隆存储库,则这样做也是安全的;它不会对被克隆的存储库造成任何损害。它会放弃您在副本中所做的任何事情,但不会影响原始存储库。

请小心使用,并确保满足前提条件时才安全有效执行此操作。

如果您的存储库中还有其他需要保留的内容,则不应使用此技术-您的存储库不再符合使用此技术的前提条件。


10
这是个糟糕的建议。如果存储库中还有其他你不想丢失的东西怎么办? - Matt Fenwick
8
那它就不会是最初的提交了,因为只有一个最初的提交。 - Jonathan Leffler
10
“那么它就不会是最初的提交了”——实际上,它仍然是。你忽略了多个分支的非常普遍的情况。请参考Charles的答案。 - Matt Fenwick
2
有帮助,但应该附上警告。 - Simon Bengtsson
5
这确实有效。被接受的答案则不然。请看评论。 - gman
显示剩余2条评论

20
要撤销初始提交,请使用以下命令。
git update-ref -d HEAD

完成后,未提交的文件现在位于暂存区。您可以通过 git status 命令确认此暂存状态,并且您将获得类似于下面链接中的截图的结果。

我的暂存区中未提交的文件为黄色

Git建议使用以下命令语法取消暂存相关文件(请参见上面的图片)。简而言之,请使用以下命令:

git rm --cached . -r

命令中的点( . )表示当前位置 / 目录,而标志 -r 会递归地取消暂存文件,无需每个文件都提示确认。
现在可以执行快速的 git status 以确认暂存区现在为空。
如果您已经将文件推送到远程仓库,则下一步是将这些更改推送到远程仓库,以恢复本地和远程之间的平衡。
但是,在推送之前,请创建一个 .gitignore 文件,并将其填写为不必要的文件。阅读如何创建 .gitignore 文件 这里
此时,下一个最好的逻辑解决方案是使用 git push git push -f 推送更改(但请始终记住强制推送很危险 - 阅读 这里)。
然而,这两个推送命令都可能返回错误,可能需要拉取并解决合并冲突。因此,为了避免这种麻烦,您可能需要删除整个远程存储库(在 GitHub 上使用这些说明),然后使用相同的名称重新创建它。
另外:
- 使用rm -rf .git删除本地 git 存储库, - 使用git init重新初始化它, - 使用git add -A将所有当前文件添加到暂存区, - 使用git commit -m "<commit message>"提交它们, - 使用git remote add origin <repo url>添加远程源 URL, - 最后,再次使用git push -u origin main推送本地文件。
附注:
有很多理由可以撤销第一次提交。然而,我认为最常见的原因之一是忘记添加一个.gitignore文件来排除不必要的文件。在我的情况下,这个错误意味着我无意中将node_modules目录推送到远程存储库。
经过进一步研究,我发现了一篇技术文章,解释了一个更简单的方法忽略先前提交的文件,省去了撤销和删除远程存储库的繁琐过程。

7

一种选择是删除仓库并创建一个新的:

rm -rf .git
git init

1
他试图说“git reset --hard”,那么为什么他会使用“git add -A”呢? - Aristotle Pagaltzis
可以的。请参考其他答案。 - Steve Smith
@AristotlePagaltzis 很好的观点。我更新了我的答案。 - ma11hew28
@SteveSmith 我刚刚看了其他答案,我没有找到撤销初始提交的方法。请参见 我的注释 - ma11hew28

7
我最终做了以下工作,解决了问题。需要删除代码库上的初始提交,因为隔离数据被误放,该提交已经被推送。
请确保您当前在正确的分支上。
git checkout master git update-ref -d HEAD
git commit -m "Initial commit"
git push -u origin master 这能够解决问题。
重要提示:
这是针对一个内部代码库的操作,它不会公开出去。如果你的代码库是公开的,请假设任何需要撤回的内容已经被其他人拉取下来。

为此,我得到了错误:无法推送一些引用...提示:更新被拒绝,因为您当前分支的顶端落后于其远程对应物。在再次推送之前,请集成远程更改(例如'git pull...')。 我该如何解决这个问题? - Manpreet

4

对我而言:

git update-ref -d HEAD
git rm --cached . -r

第一行是CB Bailey建议的(不确定为什么需要第二行,但只有当我这样做后git才会取消提交文件 - 我可以通过在上述第二行之前和之后运行 git status 来确认)


1
谢谢,立刻就起作用了。干杯! - saulius2

4

我想知道为什么@damkrat把"修正"(amend)的建议划掉了,因为在我看来,修正似乎是最有效地解决修复错误提交的根本问题的正确方法,因为没有初始提交是没有目的的。正如一些人所强调的,只有在没有人克隆你的存储库时,才应该修改"公共"分支,如主分支...

git add <your different stuff>
git commit --amend --author="author name <author.name@email.com>"-m "new message"

1
--author 只有在需要更正提交的作者时才需要。 - Richard

1

从技术上讲,要恢复最初的提交,您需要执行以下操作:

git revert HEAD

但是,既然记录了一个撤销上一个提交的新提交,您可能会自己创建一个新的提交,以修复初始提交引入的问题。这样,您将保留初始提交(即,您将保持历史记录不变),这可能是您想要做的(特别是如果,例如,您已经推送到共享存储库)。否则,您可能更喜欢重新开始。也就是说,删除存储库并创建一个新的存储库


@ReinstateMonica3167040 是的,没错。 - ma11hew28
3
git revert HEAD 这个命令把我所有的文件都删掉了 :( - Tapa Dipti Sitaula
无法相信这是唯一回答问题标题的答案。 - Guildenstern

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