关于git-rebase:从git中的分支中删除提交

Delete commits from a branch in Git

我想知道如何删除提交。

delete中,我的意思是,好像我没有做出承诺,当我在将来进行推送时,我的更改不会推送到远程分支。

我读了Git帮助,我想我应该使用的命令是git reset --hard HEAD。这是正确的吗?

  • 我认为这不是git undo last commit的副本,因为它询问如何从分支中删除任何commit。我也认为没有答案能真正解决这个问题。他们都倒带上一个承诺,而不是刚才可能发生的单一承诺。
  • @Chris,git rebase -i HEAD~10的答案确实解决了这个问题,因为它让你随意选择承诺删除。Git在您指定的范围内逐个应用提交,忽略您从日志中删除的提交。我今天使用这个命令来摆脱最近第二次和第三次对回购的承诺,同时保持最高的承诺。我同意其他答案都不令人满意。
  • @是的,我应该说,不接受答案中的选项可以解决这个问题,但你是绝对正确的-这个命令似乎有效


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

假设您坐在提交上,那么这个命令会搞乱它…

1
git reset --hard HEAD~1

HEAD~1是指在head之前的承诺。

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

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


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

1
git push origin HEAD --force

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

如果已经推了,那么最好使用git revert创建一个"镜像"提交,它将撤消更改。但是,两个提交都将在日志中。


仅供参考——如果你想摆脱正在进行的工作,git reset --hard HEAD是很好的。它会将您重置回最新的提交,并清除工作树和索引中的所有更改。


最后,如果您需要找到一个"已删除"的提交,那么它通常会出现在git reflog中,除非您已经垃圾收集了您的存储库。

  • HEAD~1或只是HEAD^。如果你推了,你应该用git revert代替。
  • 显然,您也可以使用HEAD~n从您的头部"返回"n承诺。从这一点上,您可以将... --hard HEAD也解释为HEAD~0=>删除正在进行的工作。
  • @BeamRider9就是--hard的意思。
  • @BeamRider9 imho-Git-Rebase几乎总是删除提交的更好方法(如Greg Hewgill的回答中所述),尤其是因为Rebase实际上包含了一个巨大的警告,即您将删除4realz内容。
  • 也许这应该修改为提到——软?
  • 但这不会从提交树中删除更改。行动要求一个已经作出的承诺。如果你检查了reset --hard,并且检查了log --oneline --all,那么承诺仍然保留在树上。如何从树中删除这些提交?谢谢。
  • 感谢您提供完整的文档。我唯一要补充的是,REBASE通常用于处理多个分支,而不是删除单个分支中的单个提交。
  • 使用reset --soft删除本地提交,而不恢复正在进行的工作!
  • 很高兴我阅读了评论,了解到这个答案实际上并没有回答问题,回购协议中不应该有"好像我没有做出承诺"。
  • 你真的值得投赞成票,因为我去年至少查了5次
  • 确认在2015年9月,这对我起到了作用,使我做出最后一个承诺,"就像从来没有发生过一样"。
  • 我不明白为什么每个人都推荐git reset --hard ...,然后继续解释应该如何注意工作目录的更改等。那么,为什么不使用更合适、危险性更低的git reset [--soft](即软重置或混合重置)?
  • 通过REBASE放弃提交是实现相同目标的一个不太积极的解决方案。查看我的答案了解更多详细信息。
  • 如果我错了,请纠正我:我总是说HEAD~1的意思是"去做以前的承诺"。但是"转到"是命令的结果。HEAD~1的意思是"以前的承诺"。命令reset --hard HEAD~1表示转到〔上一次提交〕。`
  • HEAD是对当前签出的提交的引用。HEAD^引用它的父级。HEAD^^提到的是祖父母。HEAD~n引用了它的第n个父级。如果你看git log,你会发现HEAD~3是第四个入口。是的,这些可以用于任何需要提交作为参数的git操作。顺便说一下,分支只是对提交的另一个引用:)
  • 对我来说,这是一个技巧Git重置-硬头~1


如果您还没有在任何地方推送提交,那么可以使用git rebase -i删除该提交。首先,了解提交的时间(大约)有多远。然后这样做:

1
git rebase -i HEAD~N

~N表示重新平衡最后一次N承诺(N必须是数字,例如HEAD~10)。然后,您可以编辑Git提供给您的文件以删除违规提交。保存该文件后,Git将重写以下所有提交,就好像删除的提交不存在一样。

Git的书中有一个很好的部分,介绍了如何用图片和示例进行重新调整。

但是要小心,因为如果你改变了你在别处推过的东西,除非你打算进行强制推,否则就需要另一种方法。

  • 注意:如果您在最后一批提交中碰巧有任何--no ff合并,那么rebase将对它们进行杀戮:(这在本页的-p下提到)。问题是,如果用-p替换-i,就不会再弹出"编辑这个提交、sqush那个提交"等选项。有人知道解决方案吗?
  • 这是否比"重设硬"答案更好,因为它不会删除文件,只是错误的提交消息?因为它似乎删除了我的文件。如果要删除该文件,请将其添加为明确警告!
  • 如果你推了它怎么办?(只有我使用远程回购)
  • @Costa您可以使用push -f强制推送并用本地分支替换远程分支。如果只是你自己的远程回购,没问题。如果有人同时来了,麻烦就开始了。
  • 我添加并提交了一个对GitHub来说太大的数据文件(是的,它可能不应该出现在源repo中;哦,好吧)。当我试图推的时候,Github因为文件太大而拒绝了。我所要做的就是撤销这一个提交,同时保存接下来的一些其他不相关的提交。git rebase -i HEAD~5命令正是我从本地repo中完全删除该提交所需要的!谢谢!
  • @Bukov文档说,您可以同时使用-i-p,但是如果您这样做,"编辑提交和改写提交消息应该可以很好地工作,但是重新排序提交的尝试往往会产生违反直觉的结果。"我不确定删除提交的效果如何,但是您可以尝试它,然后在执行之前执行reset --hard。如果没有正常工作,重新调整钢筋(使用reflog)。
  • 或者,git rebase -i 592d26e9131e0a5a9b6ada78ab1574688cbbf9b7^,而592d26e9131e0a5a9b6ada78ab1574688cbbf9b7是要删除的最早提交的ID。
  • 当它删除commit时,它是否也删除更改(如原始post中的--hard),还是保留更改的完整性但未提交(c.f.--soft
  • @邓布利达:使用rebase -i时,删除的提交所对应的更改不会被保留。


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

1
git rebase -i <commit>~1

这将在您想要攻击的提交之前以交互模式-i启动rebase。编辑器将开始列出此后的所有提交。删除包含要删除的提交的行并保存文件。Rebase将完成剩下的工作,只删除该提交,并将所有其他提交重新放回到日志中。

  • thx,btw如果遇到任何问题(如空提交),可以使用git rebase --continue
  • 更简单:git rebase -i HEAD~1
  • WoZZER。git rebase -i HEAD~1确实清理了很多回购业务!很难说清楚它到底做了什么,但整个事情看起来要整洁得多。实际上有点吓人。
  • 当commit为空时,git rebase将显示注释掉的行(#)。如果不取消对该行的注释,那么在重新标记时,git将删除提交。删除空提交实际上正是我想要做的,但是如果你想保留你的提交,请先取消注释。
  • 我认为值得注意的是,这个承诺并没有被删除,只是从列表中删除了。如果你搞砸了,你可以使用reflog返回commit。
  • 删除行是否与删除相同?
  • 这是否适用于已推送的提交?
  • @Dragonmnl删除或修改推送提交是我理解的,不建议这样做


我附加这个答案是因为我不明白为什么任何刚尝试过提交工作的人都会因为使用git时出错而想要删除所有的工作!

如果您想保留您的工作,只需"撤消"提交命令(在推送到repo之前捕获):

1
git reset --soft HEAD~1

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

  • 下面是一个为什么的例子:在您提交的开发服务器上做一小部分工作。然后发现服务器没有传出的HTTPS访问权,所以您不能在任何地方强制提交。最简单的方法就是假装它从未发生过,然后从本地机器上重做补丁。
  • @克尔蒂克博斯总是会有反应。即使在git reset --hard HEAD~1之后,您以前的最新提交也可以通过reflog获得(直到您的提交到期);另请参见:gitready.com/intermediate/2009/02/09/&hellip;
  • 也许我使用的Git是错误的,但我希望--hard选项的一个情况是,当我有多个远程分支,并且我推错了分支时。假设我有一个master分支和一个staging分支,我在一个本地分支上工作,但是不小心合并并推进到master,然后意识到我做了错误的事情。然后,我想将master的头恢复到第二个最近的提交,并想从master中删除错误推送的所有痕迹,因为它不应该在master中。
  • 您也可以很容易地执行git commit——在这个场景中进行修改,这样就不那么令人困惑了。
  • 江户十一〔五〕是救命恩人,不失现在的工作。
  • 谢谢。此答案应排名更高或包含在接受的答案中。删除提交!=恢复提交。
  • @不过,您仍然会丢失任何未提交的更改。
  • @Rob,一个例子是当您意外地提交了一个包含永远不应该在源代码管理中的秘密(例如密码)的文件。本地提交必须被销毁,而不仅仅是撤消,所以它永远不会被推送到服务器上。
  • 这很管用!我不想撤消所有操作,在我最后两次提交的文件中只有几个文件夹。努力本可以奏效,但我必须把我想要保留的所有更改都保存下来,然后在后者中修补它们。软删除了本地提交。而"git reset head——"也是移除阶段性更改所必需的。然后我可以手动移除所有的坏东西,其他的一切——我的其他改变——都完好无损。
  • 非常重要!TnxM8


删除整个提交

1
git rebase -p --onto SHA^ SHA

显然,将"sha"替换为要删除的引用。该命令中的"^"是文字。

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

  • 我怎样才能更赞成这个答案????其他的解决方案只是演示如何交互地执行它,或者删除顶级提交。
  • 感谢您提供此链接!我在想,在运行完这个之后,为什么我仍然在我的Git reflog中看到commit sha?
  • 为什么我们需要在这里使用-p
  • -p, --preserve-merges重新创建合并提交,而不是通过重放提交来平缓历史,引入合并提交。合并冲突解决方案或对合并提交的手动修订不被保留。
  • 这是真正准确的答案


如果没有发布更改,要删除最新的提交,可以执行以下操作

1
$ git reset --hard HEAD^

(请注意,这还将删除所有未提交的更改;小心使用)。

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

1
$ git revert HEAD

  • 那不管用。当我Git日志时,所有东西都还在那里,不管我为什么这样做,只是增加了更多的提交。我要清理历史。
  • @科斯塔:什么不起作用(也就是说,你用的是哪个版本),你怎么Git日志?
  • 我在这个问答中尝试了几乎所有的方法(最近我尝试了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 reset --hard HEAD^时),您只"删除"当前分支的提交(实际上是移动分支指针),如果有其他分支,那么这个提交仍然存在。删除"commit with EDOCX1"〔12〕只需向后移动分支指针,使commit悬空并可用于修剪…如果没有被其他引用引用(其他分支、远程跟踪分支或标记)。还是你用了git revert HEAD
  • 我只想删除提交(就像它们从未存在过一样)。我开始了一些奇怪的编码冒险,有了几个新的承诺,结果都成了垃圾。我怎样才能从我的Git日志中删除这些内容呢?
  • 天哪,有什么神奇的事情完全按照我的意愿做了……是哪个命令做的?!!!?!


1
2
3
git reset --hard commitId

git push <origin> <branch> --force

ps:commitid指的是您想要恢复到的那个

  • git push--force。和不提到分支名称一样,它可能会更改远程上的所有文件。


强制改变历史

假设您不只是想删除最后一次提交,而是想删除最后n次提交的特定提交,请执行以下操作:

git rebase -i HEAD~,所以如果你想看到最后五个承诺,git rebase -i HEAD~5

然后在文本编辑器中,将要删除的每个提交旁边的单词pick更改为drop。保存并退出编辑器。哇!

附加更改历史记录

试试git revert 。Revert将创建一个撤消指定提交的新提交。

  • 未定义drop关键字。要删除提交,只需删除整行。
  • drop为我工作
  • 对于我来说,drop被定义为一个关键字,但是执行drop似乎并没有从历史记录中删除提交。但是,从交互钢筋中删除了该行。


如果要修复最近的提交,可以通过执行以下操作来撤消提交并取消其中的文件的保存:

1
git reset HEAD~1

这将使您的存储库恢复到git-add命令暂存文件之前的状态。您的更改将在您的工作目录中。head~1是指分支当前尖端以下的提交。

如果要取消提交n个提交,但要保留工作目录中的代码更改:

1
git reset HEAD~N

如果您想摆脱最近的提交,而不想保留代码更改,可以执行"硬"重置。

1
git reset --hard HEAD~1

同样,如果您希望放弃最后n次提交,而不希望保留代码更改:

1
git reset --hard HEAD~N


假设我们要从回购协议中删除承诺2和4。

1
2
3
4
5
commit 0 : b3d92c5
commit 1 : 2c6a45b
commit 2 :
commit 3 : 77b9b82
commit 4 :

注:由于您使用的是--hard-f,因此您需要对回购拥有管理权。

  • git checkout b3d92c5签出最后一次可用的提交。
  • git checkout -b repair创建了一个新的分支机构。
  • git cherry-pick 77b9b82贯通提交3。
  • git cherry-pick 2c6a45b贯通提交1。
  • git checkout master结账主。
  • git reset --hard b3d92c5将master重置为last usable commit。
  • git merge repair把我们的新分支合并到master上。
  • git push -f origin master将master推到远程repo。

  • 最后一步应该是git push -f origin master,没有选项--hard
  • 我猜commit 0commit 1老。你能告诉我为什么先经过commit 3(樱桃采摘),然后经过commit 1?在检查了b3d92cd(commit 0)之后,我希望樱桃选择commit 1,然后选择commit 3。谢谢。
  • @Jarekc我认为最高级的提交是这里最新的提交,除非我发现有什么问题…


1
git rebase -i HEAD~2

这里的"2"是您想要重新平衡的提交数。

1
'git rebase -i HEAD`

如果您想重新平衡所有提交。

然后您可以选择其中一个选项。

p, pick = use commit

r, reword = use commit, but edit the commit message

e, edit = use commit, but stop for amending

s, squash = use commit, but meld into previous commit

f, fixup = like"squash", but discard this commit's log message

x, exec = run command (the rest of the line) using shell

d, drop = remove commit

这些行可以重新排序;它们从上到下执行。如果在此处删除一行,则提交操作将丢失。但是,如果删除所有内容,则将中止重新平衡。注意,空提交被注释掉了

您可以使用选项"d"简单地删除该提交,或者删除具有该提交的行。

  • 在最新的git版本中,没有更多的选项d。只需从rebase中删除带有commits的行即可删除它们。


要在本地分支中删除,请使用

1
git reset --hard HEAD~1

要在远程分支中删除,请使用

1
git push origin HEAD --force

错误:

我用git rebase -i --root修改了我的分支,无知地认为我可以修改与主提交不同的第一个提交(用于Windows的Github默认视图是与主提交的比较,隐藏了它的完整性)。

我留着硅谷的胡须,900多个承诺让自己变得高尚。退出时没有任何变化,我充电,然后开始刮胡子,因为所有900+个人承诺,无意识地重新平衡-重置他们的承诺时间到现在。

为了打败Git并保留原来的时间,我删除了这个本地存储库并从远程重新克隆。

现在,它又增加了一个最新的不必要的承诺,我想删除主人,所以这样继续下去。

耗尽选项:

我不希望git revert--它将创建一个额外的提交,给git占上风。

在检查了reflog之后,git reset --hard HEAD什么也没做,最后也是唯一的HEAD是克隆人git的胜利。

为了获取最新的sha,我检查了github.com上的远程存储库-minor win。

在认为git reset --hard 已经工作之后,我更新了另一个分支,让master和1…2…噗!承诺又回来了-吉特赢了。

退房到master,该试试git rebase -i 了,然后把线路移开……没用,可悲的说。"如果在此处删除一行,则提交操作将丢失"。啊…掩盖了2.8.3发行说明中的n00b新特性。

解决方案:

git rebase -i ,然后是d, drop = remove commit

为了验证,我去了另一个分支,瞧,没有隐藏承诺从主服务器获取/拉。

祝你生日快乐。


另一种方法是:

签出要还原的分支,然后将本地工作副本重置回要成为远程服务器上最新的提交(之后的所有内容都将变为再见)。为此,在SourceTree中,我右键单击并选择"将BranchName重置为此提交"。我认为命令行是:

1
git reset --hard COMMIT_ID

因为您刚刚从远程签出了分支,所以不会有任何本地更改来担心丢失。但如果你这样做的话,就会失去他们。

然后导航到存储库的本地目录并运行以下命令:

1
2
git -c diff.mnemonicprefix=false -c core.quotepath=false \
push -v -f --tags REPOSITORY_NAME BRANCHNAME:BRANCHNAME

这将清除本地存储库中当前提交之后的所有提交,但仅限于该分支。


上面的所有命令都会像提交之前一样还原工作树和索引的状态,但不要还原存储库的状态。如果您查看它,"删除的"提交实际上并没有被删除,它只是不是当前分支尖端的提交。

我认为没有办法取消用瓷命令的承诺。唯一的方法是从日志和reflog中删除它,然后执行git prune --expire -now

  • 在stackoverflow上显示答案的顺序是不固定的。请不要参考"以上所有命令"。自己做一个独立的答案。
  • 这个答案并不完全正确。git prune实际上是"瓷器"命令之一。此外,很少有人希望完全清除您的reflog(一个用例是从您的repo中删除敏感信息,但如我所说,这是一个罕见的用例)。通常情况下,您会希望在reflog中保留旧的提交,以防需要恢复数据。请参见pro-git:9.7 git内部结构-维护和数据恢复。


如果您刚刚弄乱了上次提交的内容(错误的消息,忘记添加一些更改),并希望在将其推送到公共回购之前修复它,为什么不使用:

1
git commit --amend -m"New message here"

如果您有新的阶段性更改,它们将与上一次提交(您试图摆脱的)结合在一起,并将替换该提交。

当然,如果您在推后修改了一个提交,那么您将重写历史,因此如果您这样做,一定要理解它的含义。

如果希望使用上一个提交的消息,也可以传递"--no edit"选项而不是"-m"。

Docs:网址:http://git-scm.com/docs/git-commit.html

  • 这不是OP要求的。


如果要保留历史记录,显示提交和还原,则应使用:

1
git revert GIT_COMMIT_HASH

输入消息解释为什么要恢复,然后:

1
git push

当您发出git log时,您将看到"错误的"提交和恢复日志消息。

  • 是的,但是手术很明显,那不是他们想要的。


资料来源:https://gist.github.com/sagarjethi/c077223b2f4fa74ad8bdf229166cf79d8

删除最后一次提交

例如,上一次提交

git push-origin+aa61ab32^:master

现在您想删除这个提交,然后用一个简单的方法来完成下面的操作

步骤

  • 首先将分支重置为当前提交的父级

  • 用力推到遥控器上。

  • 1
    2
    3
    git reset HEAD^ --hard

    git push origin -f

    对于特定的提交,您要重置的内容如下

    1
    2
    3
    git reset bb676878^ --hard

    git push origin -f

    如果您已经推了,首先找到您想要的提交(这里是git-commit-hash),然后运行以下命令:

    1
    2
    git reset --hard $GIT_COMMIT_HASH_HERE
    git push origin HEAD --force

    然后复制repo的每个位置,运行:

    1
    git reset --hard origin/master


    当我承诺和推动的时候我通常做什么(如果有人推动他的承诺,这就解决了问题):

    1
    2
    3
    git reset --hard HEAD~1

    git push -f origin

    希望这有帮助


    在本地分支上重置

    1
    git reset --hard HEAD~<Number of commit> So git reset --hard HEAD~3

    强制推到原点

    1
    git push -f origin

    我已经pushed。这对一些commits remotly后返回。 有太多的变化tried, 但这只通过布什在NEA从贾斯廷我们工作精细的方法: </P >

    1
    2
    git reset --hard $GIT_COMMIT_HASH_HERE
    git push origin HEAD --force

    将代码备份到临时文件夹中。以下命令将重置服务器。

    1
    2
    3
    git reset --hard HEAD
    git clean -f
    git pull

    如果要保留更改并删除最近的提交

    1
    2
    git reset --soft HEAD^
    git pull

    delete local commit </P >

    你们可以在这是我想删除的图像恢复的"测试的变化2"Commit(SHA1 015b5220c50e3dfbb1063f23789d92ae1d3481a2(ID:你可以通过使用SHA1 id gitkget命令的bash的NEA))。 </P >

    那我可以用下面的命令下工作(使用的是本地的只。这些对你的推后删除): </P >

  • git reset --hard 515b5220c50e3dfbb1063f23789d92ae1d3481a2/ /它反向放大,你去那Commit(提交身份证的SHA1值的变化在515b5220c50e3dfbb1063f23789d92ae1d3481a2试验4)
  • git reset --hard HEAD~1/ / IT后台提交你的前一个。
  • git reset --hard HEAD^/ / to remove NEA从提交的孩子
  • 售后服务:删除 </P >

    after delete commit </P >


    Git重置--硬

    Git推原点--力

    如果标记了一个或多个提交,请先删除标记。否则不会删除标记的提交。


    假设您没有推送到远程存储库,您可以重新克隆存储库。这是我的选择方法。

    • 很明显,它是基于OP推送到存储库的。
    • @卢卡双不,不是:"当我在未来做一个推动,我的改变不会推动到遥远的分支。"


    使用git revert https://git-scm.com/docs/git-revert。它将还原所有代码,然后您可以进行下一次提交。然后head将指向最后一次提交。还原提交从不删除,但不会影响上一次提交。