如何取消提交git裸存储库中的最后一次提交?


91

考虑到有几个git命令在裸存储库中没有意义(因为裸存储库不使用索引并且没有工作目录),

git reset --hard HEAD^ 

不能取消提交此类存储库中的最后更改的解决方案。

通过互联网搜索,所有我能找到相关的话题就是这个,在我提出这样做的方式有三种:
1。“手动更新裁判(其中涉及水暖)”;
2.“ git push -f来自非裸仓库”;
3.“ git branch -f this $that”。

您认为哪种解决方案更合适,或者还有其他解决方案?不幸的是,我发现的有关git裸存储库的文档相当差。


8
@ Lavinia-Garbriela Dobrovol不要使用下面的复杂内容。您正在尝试将HEAD移至其他提交,这就是git reset的目的,即使在裸仓库中也是如此。根据我在下面的回答,使用:git reset --soft <commit>使用--soft,您不会尝试更改不存在的工作树和索引,因此git可以让您毫无问题地进行重置。
哈佐2011年

Answers:


130

您可以使用该git update-ref命令。要删除最后的提交,可以使用:

$ git update-ref HEAD HEAD^

或者,如果您不在无法删除上一次提交的分支中:

$ git update-ref refs/heads/branch-name branch-name^

如果需要,也可以通过sha1:

$ git update-ref refs/heads/branch-name a12d48e2

请参阅git-update-ref命令的文档。


@ Lavinia-Gabriela Dobrovolschi:是的,我不熟悉确切的语法。
VonC

@VonC您可以将<ref>指定为git update-ref <ref> <newvalue>右分支,例如“ refs / heads / master”而不是HEAD。希望我不要误会你的问题。
Lavinia-Gabriela Dobrovolschi

@Sylvain:+1好编辑。@ Lavinia-Gabriela Dobrovolschi感谢您的精确度。那要实际得多(我想,如果您可以直接访问远程服务器)。
VonC

3
这些例子在branch-name论点方面具有误导性。当update-ref与“分支”一起使用时,绝对必须指定分支的完整引用名称(即refs/heads/,以普通的短分支名称开头)。如果仅使用短名称,则最终将创建/更新$GIT_DIR/branch-name而不是$GIT_DIR/refs/heads/branch-name。两者的存在branch-name,并refs/heads/branch-name会导致“refname ......不明确”的警告。
克里斯·约翰森

答案比Zach提出的要复杂得多。他的解决方案效果很好。
Krystian

32

如果您在裸仓库中使用以下命令:

git reset --soft <commit>

那么您就不会遇到裸仓库中使用的问题--hard--mixed选项,因为您没有尝试更改裸仓库中不存在的内容(例如,工作树和索引)。具体来说,您要使用(从裸仓库中):

git reset --soft HEAD^

在远程仓库上切换分支,请执行以下操作:

git symbolic-ref HEAD refs/heads/<branch_name>

要查看当前选定的分支,请使用:

git symbolic-ref HEAD

https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-symbolic-ref.html


3
如何选择要移动的分支?您的示例在master上可以正常运行,但git checkout other_branch不能完全起作用。
Gauthier

1
嗯...我想知道是谁对此投了反对票。问题没有询问如何在远程仓库上切换分支,而是询问如何在裸仓库上重置分支。要更改远程仓库中的默认分支,请使用git symbolic-ref HEAD refs / heads / <branch_name>。
哈佐

7

git push -f应正常工作:
如果你克隆裸回购,除去最后提交的(git reset --hard HEAD^你提到,但在当地的一个非裸露回购)和推背(-f):

  • 您不会在删除的其他提交之前更改任何SHA1。
  • 您确定要回退裸仓库的确切内容减去多余的提交(因为您只是先克隆了它)。

@ VonC您好,Von,我已经看到您在Git上回答了很多,所以想问您...我很好奇,为什么git reset --soft <sha1>不如下面我的回答所示,是在裸仓库上移动HEAD的推荐做法?
哈佐

我想我要问的另一个原因是,对于裸存储库使用软重置不是容易获得的信息,并且由于打字量少,机会少而使软重置是最佳实践时,许多论坛似乎都具有不必要的复杂解决方法错误。
哈佐

2
@Zach:reset --soft直接在裸仓库上完成后应该可以工作。我怀疑这样做很少,因为裸仓库通常是上游仓库(即您要将数据推送到的仓库),并且在大多数情况下,您没有直接的本地访问权。但是,如果您这样做了,那么这肯定是“ reset --soft”用法的另一个很好的例子(例如在stackoverflow.com/questions/5203535/…中)。因此对您的答案+1。
VonC

2

您还可以使用git refspec表示法并执行以下操作:

git push -f origin +<commit you want to revert to>:<destination_head | branch_name>

这将目标分支(如ref所示)强制更新为该+<object ref>部分所表示的源提交。


2
除非分支上有一个ACL,否则通常会发生这种情况,如果您“需要在裸仓库中自己做” ...
David Schmitt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.