题 从Git中的分支删除提交


我想知道如何删除提交。

通过 delete,我的意思是,就好像我没有做出那样的提交,当我将来推动时,我的更改不会推送到远程分支。

我读了git help,我认为我应该使用的命令是 git reset --hard HEAD。它是否正确?


2582
2017-08-27 03:39


起源


我想是的 不 重复的 Git撤消上次提交 因为它询问如何删除 任何 从分支机构提交。我也认为没有答案实际上解决了这个问题。他们都回滚了最后的提交,而不是 cherry-pick 和 delete 可能在不久前发生的单个提交。 - Chris
@Chris,答案 git rebase -i HEAD~10 确实解决了这个问题,因为它确实让你随意挑选要删除的提交。 Git在您指定的范围内逐个应用提交,忽略您从日志中删除的提交。我今天使用这个命令来摆脱我的回购的第二次和第三次最新提交,同时保持最高的一次。我同意其他答案都不令人满意。 - MST
@MST是的,我应该说,在接受的答案中没有选项解决这个问题,但你是绝对正确的 - 这个命令似乎有效 - Chris


答案:


小心:  git reset --hard  将删除您的工作目录更改。务必 存储您想要保留的任何本地更改 在运行此命令之前。

假设你正坐在那个提交上,那么这个命令会搞砸它......

git reset --hard HEAD~1

HEAD~1 表示在头之前提交。

或者,你可以查看输出 git log,找到要备份的提交的提交ID,然后执行以下操作:

git reset --hard <sha1-commit-id>

如果你已经推了它,你需要做一个强制推动来摆脱它......

git push origin HEAD --force

然而如果其他人可能已经拉了它,那么你最好开始一个新的分支。因为当他们拉动时,它会将它合并到他们的工作中,并且你会再次将它推回去。

如果你已经推了,可能会更好用 git revert,创建一个将撤消更改的“镜像”提交。但是,两个提交都将在日志中。


仅供参考 - git reset --hard HEAD 如果你想摆脱WORK IN PROGRESS,那就太好了。它会将您重置为最近的提交,并清除工作树和索引中的所有更改。


最后,如果您需要查找“已删除”的提交,则通常会将其存在 git reflog 除非您有垃圾收集您的存储库。


3311
2017-08-27 03:44



HEAD~1 要不就 HEAD^。如果你推,你应该使用 git revert 代替。 - Jakub Narębski
在运行此命令之前,请务必隐藏您要保留的任何本地更改... - William Denniss
显然你也可以使用 HEAD~n 回去” n 从你头上承诺。也许从这一点你可以解释 ... --hard HEAD 也作为 HEAD~0 =>删除正在进行的工作。 - yoshi
@ beamrider9 imho git rebase几乎总是删除提交的更好方法(如Greg Hewgill的回答所述) - 尤其是因为rebase确实包含一个很大的警告,你将删除东西4realz。 - Noah Sussman
但这并不会从提交树中删除更改。 OP要求已经做出承诺。如果你 reset --hard,并检查 log --oneline --all,提交仍然留在树中。我们如何从树中删除这些提交?谢谢。 - iGbanam


如果您尚未将提交推送到任何地方,则可以使用 git rebase -i 删除该提交。首先,找出提交的回程(大约)。然后做:

git rebase -i HEAD~N

~N 意味着改变最后一个 N 提交(N 例如,必须是一个数字 HEAD~10)。然后,您可以编辑Git提供给您的文件以删除违规提交。在保存该文件时,Git将重写所有以下提交,就好像您删除的那个提交不存在一样。

Git Book有一个很好的 关于变基的部分 有图片和例子。

不过要小心,因为如果你改变了你的话  推到别处,除非你打算做推力,否则将需要另一种方法。


603
2017-08-27 03:51



注意:如果你碰巧在最后一批提交中有任何--no-ff合并,rebase将会屠杀它们:(这是在-p下提到的 这一页。问题是,如果你用-p替换-i,你就不会再弹出“编辑这个提交,sqush那一个”等选项。任何人都知道解决方案吗? - Bukov
如果你推了它怎么办? (只是我使用远程仓库) - Costa
@Costa你可以使用 push -f 强制推送并用本地分支替换远程分支。如果它只是你自己的远程回购,没问题。如果其他人在此期间取得了成功,麻烦就开始了。 - Greg Hewgill
我添加并提交了一个对GitHub来说太大的数据文件(是的,它可能不应该在源代码库中;哦,好吧)。当我试图推送时,GitHub因为文件太大而拒绝了。我想做的就是撤消这一次提交,同时保存一些其他无关的提交。该 git rebase -i HEAD~5命令是 究竟 我需要从我的本地仓库中完全删除此提交!谢谢! - aldo
@dumbledad:有 rebase -i,不保留与删除的提交相对应的更改。 - Greg Hewgill


另一种可能性是我最喜欢的命令之一:

git rebase -i <commit>~1

这将以交互模式启动rebase -i 在你要提交的提交之前的那一刻。编辑器将从那时开始列出所有提交。删除包含要删除的提交的行并保存文件。 Rebase将完成剩余的工作,仅删除该提交,并将所有其他提交重新放回日志中。


416
2017-08-27 03:49



thx,顺便说一句,如果遇到任何问题(如空提交),你可以使用 git rebase --continue - realgt
更容易: git rebase -i HEAD~1 - mmell
Wowzers。 git rebase -i HEAD~1 真的清理了很多回购!很难确切地知道它做了什么,但整个事情看起来更整洁。实际上有点惊人。 - Charles Wood
我认为值得注意的是,提交没有被删除,只是从列表中删除。如果你陷入困境,你可以使用 引用日志。 - Zaz
删除与d / drop相同的行吗? - Leo


我正在附上这个答案,因为我不明白为什么那些刚刚尝试提交工作的人会因为使用Git的一些错误而删除所有工作!

如果你想保留你的工作并且只是'撤消'那个提交命令(你在推送回购之前就抓住了):

git reset --soft HEAD~1

不要使用--hard 标志,除非您想要销毁自上次提交以来正在进行的工作。


281
2017-10-15 18:17



下面是一个原因示例:您在提交的开发服务器上执行一小部分工作。然后事实证明该服务器没有传出HTTPS访问权限,因此您无法将提交推送到任何地方。最容易假装它从未发生过,并从本地机器重做补丁。 - Steve Bennett
reset --soft 是不能失去当前工作的生命救星。 - RaphaelDDL
谢谢。此答案应排名更高或包含在接受的答案中。删除提交!=恢复提交。 - Alsciende
@RandolphCarter:你仍然会失去任何未提交的更改。 - naught101
@Rob,一个例子是当你不小心提交一个包含秘密(例如密码)的文件时,该文件永远不应该在源代码管理中。必须是本地提交 销毁,而不仅仅是撤消,所以它永远不会被推送到服务器。 - Bob Meyers


如果您没有发布更改,则可以执行删除最新提交

$ git reset --hard HEAD^

(请注意,这也会删除所有未提交的更改;请谨慎使用)。

如果您已经发布了要删除的提交,请使用 git revert

$ git revert HEAD

47
2017-08-27 10:47



那没用。当我git log时,一切都仍然存在,无论我为什么这样做只是添加更多提交。我想清理历史。 - Costa
@Costa:什么不起作用(即你使用的是哪个版本),你是如何git log的? - Jakub Narębski
我在这个Q&A上尝试了几乎所有的东西。 (我最近试过git revert HEAD)我的git日志: tree = log --all --graph --format=format:'%C(bold blue)%h%C(reset) %C(dim black)%s%C(reset)%C(bold red)%d%C(reset) %C(green)by %an, %ar%C(reset)' - Costa
我只想删除提交(就好像它们从未存在过)。我进行了一些奇怪的编码冒险,有几个新的提交,这一切都最终成了垃圾。我怎样才能从我的git日志中删除它们? - Costa
神圣的废话神奇地完成了我想要的东西......那些命令中的哪一个做到了?!!?! - Costa


删除整个提交

git rebase -p --onto SHA^ SHA

显然用您想要删除的引用替换“SHA”。该命令中的“^”是文字。

http://sethrobertson.github.io/GitFixUm/fixup.html


43
2017-08-31 19:36



我怎么能更多地回答这个问题?其他解决方案只是展示如何以交互方式执行或删除顶部提交。 - ribamar
谢谢你的链接!我想知道,在运行之后,为什么我仍然在我的git reflog中看到提交SHA? - bapors
为什么我们需要 -p 这里? - Serge Roussak
-p, --preserve-merges            重新创建合并提交,而不是通过重放合并提交引入的提交来展平历史记录。不保留合并冲突解决方案或手动修改合并提交。 - raittes


git reset --hard commitId

git push <origin> <branch> --force

PS:CommitId指的是您想要恢复的那个


33
2017-10-16 09:51



git push --force <origin> <branchName>。如果不提及分支名称,它可能会更改远程上的所有文件。 - sheelpriy