在我的一个开发分支中,我对我的代码库进行了一些更改。在我能够完成我正在处理的功能之前,我不得不将当前分支切换到master来演示一些功能。但只是使用“git checkout master”保留了我在开发分支中所做的更改,从而破坏了master中的一些功能。所以我所做的是使用提交消息“临时提交”在我的开发分支上提交更改,然后为演示提供checkout master。
既然我已经完成了演示并重新开始在我的开发分支上工作,我想删除我所做的“临时提交”,同时仍然保留我所做的更改。这可能吗?
答案 0 :(得分:1209)
这很简单:
git reset HEAD^
没有git reset
或--hard
的{p> --soft
会使您的HEAD
指向指定的提交,而不会更改任何文件。 HEAD^
指的是当前提交的(第一个)父提交,在您的情况下是临时提交之前的提交。
请注意,另一个选项是正常继续,然后在下一个提交点运行:
git commit --amend [-m … etc]
将改为编辑最近的提交,具有与上述相同的效果。
请注意,如果您已将错误提交推送到其他人可能已将其撤消的位置,则此问题(与几乎所有git答案一样)可能会导致问题。尽量避免
答案 1 :(得分:154)
有两种方法可以解决这个问题。哪个更容易取决于您的情况
重置强>
如果要删除的提交是最后一次提交,并且您还没有完成任何其他工作,则只需使用git-reset
git reset HEAD^
将您的分支恢复到当前HEAD之前的提交。但是,它实际上并不会更改工作树中的文件。结果,该提交中的更改显示为已修改 - 它就像一个'uncommit'命令。事实上,我有一个别名就是这样做。
git config --global alias.uncommit 'reset HEAD^'
然后你可以在将来使用git uncommit
备份一个提交。
<强>挤压强>
压缩提交意味着将两个或多个提交合并为一个。我经常这样做。在你的情况下,你有一个半完成功能提交,然后你将完成它并再次使用正确的永久提交消息提交。
git rebase -i <ref>
我上面说的是因为我想说明这可能是任何数量的提交。运行git log
并找到要删除的提交,复制其SHA1并使用它代替<ref>
。 Git将带您进入交互式rebase模式。它将显示您当前状态与代替<ref>
之间的所有提交。因此,如果<ref>
在10次提交之前,它将向您显示所有10次提交。
在每次提交之前,它将包含单词pick
。找到您要删除的提交,并将其从pick
更改为fixup
或squash
。使用fixup
只会丢弃提交消息并将更改合并到列表中的前一个前任中。 squash
关键字执行相同的操作,但允许您编辑新组合提交的提交消息。
请注意,当您退出编辑器时,将按照它们在列表中显示的顺序重新提交提交。因此,如果您进行了临时提交,然后在同一分支上执行了其他工作,并在稍后的提交中完成了该功能,那么使用rebase将允许您重新对提交进行排序并压缩它们。
警告:强>
重新定位修改历史记录 - 不要对已经与其他开发人员共享的任何提交执行此操作。
<强>积攒强>
将来,为避免此问题,请考虑使用git stash
临时存储未提交的作品。
git stash save 'some message'
这会将您当前的更改存储到存储列表中。以上是stash命令的最明确版本,允许用注释来描述你的存储内容。您也可以简单地运行git stash
而不是其他任何内容,但不会存储任何消息。
您可以使用...
浏览您的存储列表git stash list
这将显示你所有的藏匿处,它们完成了什么分支,消息和每行的开头,以及该存储的标识符,看起来像这个stash@{#}
,其中#是它的位置一堆藏匿。
要恢复存储(可以在任何分支上完成,无论最初创建存储的位置),您只需运行...
git stash apply stash@{#}
同样,#是stashes数组中的位置。如果要恢复的存储位于0
位置 - 也就是说,如果它是最近的存储。然后你可以在不指定存储位置的情况下运行命令,git会假设你指的是最后一个:git stash apply
。
因此,例如,如果我发现自己在错误的分支上工作 - 我可能会运行以下命令序列。
git stash
git checkout <correct_branch>
git stash apply
在你的情况下,你移动分支更多,但同样的想法仍然适用。
希望这有帮助。
答案 2 :(得分:49)
我认为你正在寻找这个
git reset --soft HEAD~1
它撤消最近的提交,同时保持该提交中的更改进行暂存。
答案 3 :(得分:32)
是的,您可以删除提交而不删除更改: git reset @〜
答案 4 :(得分:8)
对于使用zsh的用户,您必须使用以下内容:
git reset --soft HEAD\^
此处解释:https://github.com/robbyrussell/oh-my-zsh/issues/449
如果URL失效,重要的部分是:
在命令中转义^
您也可以使用HEAD〜,这样就不必每次都转义它。
答案 5 :(得分:8)
2020简单方法:
git reset <commit_hash>
(您要保留的最后一次提交的提交哈希)。
如果提交已被推送,则可以执行以下操作:
git push -f
您将在本地保留未提交的更改
答案 6 :(得分:6)
在我的情况下,我已经推到了回购。哎哟!
您可以通过执行以下操作来还原特定提交,同时保留对本地文件的更改:
MultiViews
通过这种方式,我能够保留所需的更改并解除已经推送的提交。
答案 7 :(得分:3)
使用git 2.9(正好是2.9.2.windows.1)
git reset HEAD^
提示更多;不知道这里的预期输入是什么。请参考下面的截图
找到其他解决方案git reset HEAD~#numberOfCommits
,我们可以选择通过保持更改完整来选择要重置的本地提交数。因此,我们有机会丢弃所有本地提交以及有限数量的本地提交。
答案 8 :(得分:2)
另一种方法。
在临时提交的顶部添加提交,然后执行:
git rebase -i
将两个提交合并为一个(命令将打开带有显式指令的文本文件,编辑它)。
答案 9 :(得分:1)
在某些情况下,我只想撤消第一次提交时对特定文件的更改,以将它们添加到第二次提交中,并获得更干净的git日志。
在这种情况下,我的工作是:
git checkout HEAD~1 <path_to_file_to_put_in_different_commit>
git add -u
git commit --amend --no-edit
git checkout HEAD@{1} <path_to_file_to_put_in_different_commit>
git commit -m "This is the new commit"
当然,即使在rebase -i
的中间,如果要拆分的提交上具有编辑选项,此方法也能很好地工作。
答案 10 :(得分:0)
您正在寻找git reset HEAD^ --soft
或git reset HEAD^ --mixed
。
如docs所述,reset命令有3种模式:
git reset HEAD^ --soft
撤消git commit
。更改仍存在于工作树(项目文件夹)+索引(-缓存)中
git reset HEAD^ --mixed
撤消git commit
+ git add
。更改仍然存在于工作树中
git reset HEAD^ --hard
就像您从未对代码库进行过这些更改一样。更改从工作树中消失了。