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

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

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

934208 次浏览

就这么简单:

git reset HEAD^

注意:某些shell将^视为特殊字符(例如某些Windows shell或ZSH启用了全局输入),因此您可能必须引用"HEAD^"或在这些情况下使用HEAD~1

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

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

git commit --amend [-m … etc]

这将代替编辑最近的提交,具有与上述相同的效果。

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

还有一种方法可以做到。

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

git rebase -i

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

有两种处理方式哪一种更容易取决于你的情况

重置

如果你想要删除的提交是最后一次提交,并且你没有做任何额外的工作,你可以简单地使用git-reset

git reset HEAD^

将您的分支返回到当前HEAD之前的提交。但是,它实际上不会更改工作树中的文件。因此,该提交中的更改显示为已修改-就像“取消提交”命令一样。事实上,我有一个别名来做到这一点。

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

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

挤压

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

git rebase -i <ref>

我说以上是因为我想说清楚这可能是任何数量的提交。运行git log并找到你要删除的提交,复制它的SHA1并将其用于代替<ref>。Git将带你进入交互式重基模式。它将显示你当前状态和你取代<ref>的任何内容之间的所有提交。所以如果<ref>是10次提交前,它将显示所有10次提交。

在每个提交之前,它将有一个单词pick。找到你想要删除的提交,并将其从pick更改为fixupsquash。使用fixup只需丢弃该提交消息并将更改合并到列表中的直接前身。squash关键字做同样的事情,但允许您编辑新合并提交的提交消息。

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

警告:

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

藏匿

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

git stash save 'some message'

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

您可以浏览您的收藏列表与…

git stash list

这将显示您所有的藏匿点,它们在哪些分支上完成,以及消息和每行的开头,以及该藏匿点的标识符,看起来像这样stash@{#},其中#是它在藏匿数组中的位置。

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

git stash apply stash@{#}

同样,有#是存储数组中的位置。如果您要恢复的存储在0位置-也就是说,如果它是最近的存储。然后您可以运行命令而不指定存储位置,git会假设您指的是最后一个:git stash apply

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

git stashgit checkout <correct_branch>git stash apply

在你的例子中,你在分支周围移动了一点,但同样的想法仍然适用。

希望这有帮助。

是的,您可以在不删除更改的情况下删除您的提交:

git reset @~

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

您可以通过以下操作恢复特定的提交,同时保留本地文件中的更改:

git revert -n <sha>

通过这种方式,我能够保留我需要的更改并撤消已经推送的提交。

使用git 2.9(精确2.9.2.windows.1)git reset HEAD^提示更多;不确定此处的预期输入。请参考下面的截图

在此处输入图片描述

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

请参阅下面显示git reset HEAD~1的屏幕截图:输入图片描述

在此处输入图片描述

我觉得你在找这个

git reset --soft HEAD~1

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

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

git reset --soft HEAD\^

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

如果URL死了,重要的部分是:

逃离你命令中的^

你也可以使用HEAD~,这样你就不必每次都转义它。

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

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

git reset HEAD^ --soft

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

git reset HEAD^ --mixed

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

git reset HEAD^ --hard

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

2020简单方法:

git reset <commit_hash>

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

如果提交是推送的,你可以这样做:

git push -f

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

在某些情况下,我只想撤消第一次提交时对特定文件的更改,将它们添加到第二次提交中,并拥有更干净的git日志。

在这种情况下,我做的是:

git checkout HEAD~1 <path_to_file_to_put_in_different_commit>git add -ugit commit --amend --no-editgit checkout HEAD@{1} <path_to_file_to_put_in_different_commit>git commit -m "This is the new commit"

当然,即使在rebase -i中间,在提交到拆分上有编辑选项,这也能很好地工作。

首先,您可以使用以下命令查看日志-

git reflog

这显示所有提交,然后找出您要撤消的提交以及与之关联的头部编号,然后输入以下命令

git reset HEAD@{#NumberOfCommitYouWantToUndo}

例如git reset HEAD@{3}

git重置HEAD@{#}显示重置后所有未暂存的更改