关于undo:我可以删除git commit但保留更改

Can I delete a git commit but keep the changes

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

现在我已经完成了演示并返回到我的开发分支,我想删除我所做的"临时提交",同时仍然保留我所做的更改。有可能吗?


就这么简单:

1
git reset HEAD^

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

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

1
git commit --amend [-m … etc]

它将编辑最近的提交,与上面的效果相同。

注意,如果你已经把坏承诺推到了一个可能有人把它从中拉出来的地方,那么这(和几乎所有Git答案一样)可能会导致问题。尽量避免那样


有两种处理方法。哪个更容易取决于你的情况

重置

如果你想摆脱的承诺是最后一个承诺,而你没有做任何额外的工作,你可以简单地使用git-reset

1
git reset HEAD^

在您当前的头之前将您的分支恢复到提交状态。但是,它实际上不会更改工作树中的文件。结果,提交中的更改显示为已修改-类似于"uncommit"命令。事实上,我有一个别名可以这样做。

1
git config --global alias.uncommit 'reset HEAD^'

然后,您可以在将来使用git uncommit来备份一个提交。

压扁

挤压提交意味着将两个或多个提交合并为一个提交。我经常这样做。在您的案例中,您已经提交了一个完成一半的特性,然后您将完成它,并使用适当的、永久的提交消息再次提交。

1
git rebase -i <ref>

我之所以这么说是因为我想澄清一下,这可能是任何数量的承诺。运行git log并找到您想要摆脱的承诺,复制它的sha1并用它代替。Git会把你带到交互式钢筋网模式。它将显示您当前状态和您取代所做的所有承诺。因此,如果在10之前提交,它将显示所有10个提交。

在每一次提交之前,它都会有一个单词pick。找到你想要摆脱的承诺,把它从pick改为fixupsquash。使用fixup只需放弃提交消息并将更改合并到列表中的直接前一个。squash关键字执行相同的操作,但允许您编辑新组合提交的提交消息。

请注意,当您退出编辑器时,提交将按照它们在列表中显示的顺序重新提交。因此,如果您进行了一次临时提交,然后在同一个分支上做了其他工作,并在以后的提交中完成了该特性,那么使用REBASE将允许您对提交进行重新排序并挤压它们。

警告:

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

藏匿

将来,为了避免这个问题,考虑使用git stash临时存储未提交的工作。

1
git stash save 'some message'

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

你可以浏览你的藏品清单…

1
git stash list

这将向您显示您的所有藏品、它们所使用的分支、消息和每行的开头,以及该藏品的标识符,它看起来像这样的stash@{#},其中是它在藏品阵列中的位置。

要恢复一个stash(可以在任何分支上执行,不管stash最初是在哪里创建的),只需运行…

1
git stash apply stash@{#}

再一次,藏匿点的排列中有一个位置。如果你想要恢复的藏匿处在0的位置,也就是说,如果是最近的藏匿处。然后你可以在不指定stash位置的情况下运行命令,git会假设你指的是最后一个:git stash apply

例如,如果我发现自己在处理错误的分支,我可以运行以下命令序列。

1
2
3
git stash
git checkout <correct_branch>
git stash apply

在您的例子中,您移动了更多的分支,但同样的想法仍然适用。

希望这有帮助。


我想你在找这个

埃多克斯1〔3〕

它将撤消最近的提交,同时将该提交中所做的更改保留到临时状态。


是的,您可以删除提交而不删除更改:Git重置@~


对于使用zsh的用户,必须使用以下内容:

江户十一〔四〕号

解释如下:https://github.com/robbyrussell/oh-my-zsh/issues/449

如果URL失效,重要的部分是:

Escape the ^ in your command

You can alternatively can use HEAD~ so that you don't have to escape it each time.


在我的情况下,我已经推进回购。哎哟!

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

1
git revert -n <sha>

这样我就能够保持我所需要的更改,并且取消了一个已经被推动的承诺。


使用Git2.9(精确地说是2.9.2.windows.1)git reset HEAD^提示输入更多信息;不确定这里需要什么输入。请参阅下面的屏幕截图

enter image description here

找到了其他解决方案git reset HEAD~#numberOfCommits,我们可以选择通过保持更改不变来选择要重置的本地提交数。因此,我们有机会放弃所有本地提交以及有限数量的本地提交。

请参阅下面显示git reset HEAD~1正在运行的屏幕截图:氧化镁

氧化镁


还有一种方法。

在临时提交的顶部添加提交,然后执行以下操作:

1
git rebase -i

要将两个提交合并为一个提交(命令将用显式指令打开文本文件,编辑它)。


你要找的不是git reset HEAD^ --soft就是git reset HEAD^ --mixed

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

埃多克斯1〔5〕

松开git commit。更改仍然存在于工作树(项目文件夹)+索引(--cached)中。

埃多克斯1〔6〕

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

埃多克斯1〔12〕

就像你从未对代码库做过这些更改一样。更改从工作树中消失。