我可以删除git提交但保留更改

tan*_*ben 915 git undo git-reset

在我的一个开发分支中,我对我的代码库进行了一些更改.在我能够完成我正在处理的功能之前,我不得不将当前分支切换到master来演示一些功能.但只是使用"git checkout master"保留了我在开发分支中所做的更改,从而破坏了master中的一些功能.所以我所做的是使用提交消息"临时提交"在我的开发分支上提交更改,然后为演示提供checkout master.

现在我已完成演示并重新开始在我的开发分支上工作,我想删除我所做的"临时提交",同时仍然保留我所做的更改.那可能吗?

Gar*_*eth 1407

这很简单:

git reset HEAD^
Run Code Online (Sandbox Code Playgroud)

git reset没有--hard--soft移动HEAD指向指定的提交,而不更改任何文件.HEAD^指的是当前提交的(第一个)父提交,在您的情况下是临时提交之前的提交.

请注意,另一个选项是正常进行,然后在下一个提交点运行:

git commit --amend [-m … etc]
Run Code Online (Sandbox Code Playgroud)

它将改为编辑最近的提交,具有与上述相同的效果.

请注意,如果您已将错误提交推送到其他人可能已将其撤消的位置,则此问题(与几乎所有git答案一样)可能会导致问题.尽量避免这种情况

  • 这是迄今为止最简单的,但是如果你已经把你的提交推到了遥控器而其他人就把它拉了下来,除了道歉之外,我会非常犹豫做什么. (44认同)
  • @DaAwesomeP听起来像是在使用一个将`^`视为特殊字符的shell.您可以引用引用"HEAD ^",或者使用替代语法`HEAD~1`取消引用 (44认同)
  • 这样做后,我得到了"更多?".无论我在那个提示符下输入什么,都会给我一个致命的:含糊不清的论点'HEADwhateverItypedIn':未知的修订或路径不在工作树中. (30认同)
  • @sicophrenic,在这个场合不要错过阅读["重置揭秘"](http://git-scm.com/2011/07/11/reset.html)的机会. (11认同)
  • 为我工作,不得不逃避字符虽然`git reset HEAD\^` (7认同)
  • @kostix FWIW该链接已更改为https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified (6认同)
  • 在Windows上我不得不使用`git reset"HEAD ^"` (3认同)
  • 该死的!我没有阅读评论,并且在读取"HEAD ^指向当前提交的(第一个)父提交后,执行了`git reset parent commit`,在您的情况下,它是临时提交之前的提交."并且丢失了我所有的改变.幸运的是他们不是很多. (3认同)
  • 现在使用git已经8年了,我仍然需要查找一下 (2认同)

edd*_*oya 170

有两种方法可以解决这个问题.哪个更容易取决于您的情况

重启

如果您要删除的提交是最后一次提交,并且您还没有完成任何其他工作,则可以使用 git-reset

git reset HEAD^
Run Code Online (Sandbox Code Playgroud)

将您的分支恢复到当前HEAD之前的提交.但是,它实际上并不会更改工作树中的文件.结果,该提交中的更改显示为已修改 - 它就像一个'uncommit'命令.事实上,我有一个别名来做到这一点.

git config --global alias.uncommit 'reset HEAD^'
Run Code Online (Sandbox Code Playgroud)

然后你可以git uncommit在将来用来备份一个提交.

挤压

压缩提交意味着将两个或多个提交合并为一个.我经常这样做.在你的情况下,你有一个半完成功能提交,然后你将完成它并再次使用正确的永久提交消息提交.

git rebase -i <ref>
Run Code Online (Sandbox Code Playgroud)

我上面说的是因为我想说明这可能是任何数量的提交.运行git log并找到要删除的提交,复制其SHA1并使用它代替<ref>.Git将带您进入交互式rebase模式.它将显示当前状态与您放置的任何内容之间的所有提交<ref>.因此,如果<ref>是10次提交之前,它将向您显示所有10次提交.

在每次提交之前,它都会有这个词pick.找到要删除的提交并将其更改pickfixupsquash.使用fixup简单的丢弃提交消息并将更改合并到列表中的前一个前导中.该squash关键字做同样的事情,但允许你编辑的新联合提交的提交信息.

请注意,当您退出编辑器时,将按照它们在列表中显示的顺序重新提交提交.因此,如果您进行了临时提交,然后在同一分支上执行了其他工作,并在稍后的提交中完成了该功能,那么使用rebase将允许您重新对提交进行排序并压缩它们.

警告:

重新修改修改历史记录 - 不要对已经与其他开发人员共享的任何提交执行此操作.

积攒

将来,为避免此问题,请考虑使用git stash临时存储未提交的工作.

git stash save 'some message'
Run Code Online (Sandbox Code Playgroud)

这会将您当前的更改存储在存储列表中.以上是stash命令的最明确版本,允许用注释来描述你的存储内容.您也可以简单地运行git stash其他任何内容,但不会存储任何消息.

您可以使用...浏览您的存储列表

git stash list
Run Code Online (Sandbox Code Playgroud)

这将显示你所有的藏匿处,它们完成的分支,消息和每行的开头,以及该存储的标识符,stash@{#}其中#是它在stashes数组中的位置.

要恢复存储(可以在任何分支上完成,无论最初创建存储的位置),您只需运行...

git stash apply stash@{#}
Run Code Online (Sandbox Code Playgroud)

同样,#是stashes数组中的位置.如果要恢复的存储位于该0位置 - 也就是说,如果它是最近的存储.然后你可以在不指定存储位置的情况下运行命令,git会假设你的意思是最后一个:git stash apply.

因此,例如,如果我发现自己在错误的分支上工作 - 我可能会运行以下命令序列.

git stash
git checkout <correct_branch>
git stash apply
Run Code Online (Sandbox Code Playgroud)

在你的情况下,你移动分支更多,但同样的想法仍然适用.

希望这可以帮助.

  • `git config --global alias.uncommit reset HEAD ^`只是别名uncommit才能重置.相反,做`git config --global alias.uncommit'reset HEAD ^'` (6认同)
  • 请注意,如果在Windows命令提示符下使用,则必须使用^^而不是^。 (3认同)

小智 80

我想你正在寻找这个

git reset --soft HEAD~1

它撤消最近的提交,同时保持该提交中的更改进行分段.

  • @Tyron`^`是DOS中的转义字符。与新行配对时,它用作前面命令的继续提示。在Windows上输入`git reset HEAD ^^`应该可以。 (7认同)
  • 谢谢.这对我有用.在Windows上调用`git reset HEAD ^`会提示"更多?" - 不管它是什么意思 (6认同)

Bar*_*ing 49

您正在寻找git reset HEAD^ --softgit reset HEAD^ --mixed

文档中所述,重置命令有 3 种模式:

git reset HEAD^ --soft

撤消git commit. 工作树(项目文件夹)+索引(--cached)中仍然存在更改

git reset HEAD^ --mixed

撤消git commit+ git add。工作树中仍然存在更改

git reset HEAD^ --hard

就像您从未对代码库进行过这些更改一样。更改从工作树中消失了。


DUR*_*iya 37

是的,你可以删除你的提交而不删除更改:git reset @~

  • 这真的是我想要的,在我看来它应该是公认的答案,非常感谢! (7认同)
  • 有趣的紧凑语法,我以前从未见过或使用过。和git reset --soft或git reset --keep有什么不同? (2认同)

Xys*_*Xys 19

2020 简单方法:

git reset <commit_hash>
Run Code Online (Sandbox Code Playgroud)

(您要保留的最后一次提交的提交哈希)。

如果提交被推送,您可以执行以下操作:

git push -f
Run Code Online (Sandbox Code Playgroud)

您将在本地保留现在未提交的更改

  • 当您说这是“2020 年简单方法”时,是否暗示此方法在以前的版本中是不可能的?如果是的话,需要哪个版本的 Git 才能使用此方法? (3认同)

Gre*_*ton 8

对于那些使用zsh的人,你必须使用以下内容:

git reset --soft HEAD\^

在此解释:https://github.com/robbyrussell/oh-my-zsh/issues/449

如果URL变为死亡,重要的部分是:

在命令中转义^

您也可以使用HEAD~,这样您每次都不必逃避它.

  • 我永远不会记住这个命令,并且必须谷歌这个并找到我自己的答案hahahaha (11认同)
  • `git reset HEAD^` 正在 zsh 中为我工作,可能已修复。 (3认同)

Wim*_*jen 6

在我的情况下,我已经推到了回购.哎哟!

您可以通过执行以下操作来还原特定提交,同时保留对本地文件的更改:

git revert -n <sha>
Run Code Online (Sandbox Code Playgroud)

通过这种方式,我能够保留所需的更改并解除已经推送的提交.

  • 就我而言,我需要恢复已经推送到远程存储库的内容。更哎哟!最好的方法是`git revert bad-commit-sha`,然后是`git revert -n revert-commit-just-created-sha`,然后从那里修复。你让我半途而废。谢谢! (2认同)