我能删除一个 Git 提交但是保留改动吗?
我能删除一个 Git 提交但是保留改动吗?
在我的一个开发分支中,我对代码库进行了一些更改。在我完成正在进行的功能之前,我必须将当前分支切换到master来演示一些功能。但是,只是使用“git checkout master”会保留我在开发分支中所做的更改,从而破坏master中的某些功能。所以,我先使用了一个带有提交消息“临时提交”的开发分支进行更改,然后再进行演示,然后切换到master。
现在,我完成演示并回到我的开发分支工作,我想删除我所做的“临时提交”,同时保留我所做的更改。这可能吗?
有两种方法可以处理这个问题。哪种更容易取决于你的情况。
重置
如果要摆脱的提交是最后一次提交,并且您没有做任何其他工作,您可以简单地使用git-reset
。
git reset HEAD^
将您的分支带回到当前HEAD之前的提交。但是,它不会真正更改工作树中的文件。因此,该提交中的更改显示为已修改-就像一个“未提交”的命令。事实上,我有一个别名来做到这一点。
git config --global alias.uncommit 'reset HEAD^'
然后,您只需在将来使用git uncommit
即可将其备份。一个提交。
压缩
压缩提交意味着将两个或多个提交合并为一个。我经常这样做。在您的情况下,您已经提交了一个未完成的功能,然后您会完成它,然后再次提交具有正确的永久性提交消息。
git rebase -i
我之所以这样说是因为我想清楚这可能是任意数量的提交。运行git log
,找到要摆脱的提交,将其SHA1复制并在的位置使用。 Git将使您进入交互式重新基于模式。它将显示当前状态与您放置在
位置之间的所有提交。因此,如果
是10个提交之前,则会显示所有10个提交。
在每个提交的前面,它会有单词pick
。找到要摆脱的提交,并将其从pick
更改为fixup
或squash
。使用fixup
简单地丢弃那些提交消息并将更改合并到它在列表中的直接前任中。 squash
关键字执行相同的操作,但允许您编辑新组合提交的提交消息。
请注意,提交将按它们在列表中出现的顺序重新提交当您退出编辑器时。因此,如果您进行了临时提交,然后在同一分支上进行了其他工作,并在稍后的提交中完成了功能,则使用rebase将允许您重新排序提交并将它们压缩。
警告:
重新基础修改历史记录-不要对您已经与其他开发者共享的任何提交进行此操作。
存储
将来,为避免此问题,请考虑使用git stash
临时存储未提交的工作。
git stash save 'some message'
这将在您的存储列表中将当前更改存储到一侧。上面是存储命令的最明确版本,允许用于描述您正在存储的内容的注释。您也可以只运行git stash
,但不会存储任何消息。
您可以使用以下内容浏览您的存储列表...
git stash list
这将向您显示所有存储内容,它们在哪些分支上完成,以及每行开头的消息和标识符,该标识符看起来像stash@{#}
,其中#是它在存储数组中的位置。
要恢复一个存储 (无论原始存储在哪个分支上都可以完成), 你只需要运行...
git stash apply stash@{#}
再次提醒, # 是存储数组中的位置。如果要恢复的存储在位置 0
- 也就是最近的存储, 那么您可以只运行没有指定存储位置的命令, git 将认为您指的是最后一个存储: git stash apply
。
因此,例如,如果我发现自己正在错误的分支上工作 - 我可以运行以下一系列命令。
git stash git checkoutgit stash apply
在您的情况下,您在分支之间移动了更多,但是相同的思想仍然适用。
很简单:
git reset HEAD^
注意:某些 shell 将 ^
视为特殊字符(例如某些 Windows shell 或启用了通配符的 ZSH),因此在这些情况下,您可能需要引用 "HEAD^"
或使用 HEAD~1
。
git reset
不带 --hard
或 --soft
将您的 HEAD
指向指定的提交,而不更改任何文件。 HEAD^
是您当前提交的(第一个)父提交,这在您的情况下是临时提交之前的提交。
请注意,另一种选择是像往常一样继续进行,然后在下一次提交点运行:
git commit --amend [-m … etc]
这将编辑最新的提交,效果与上面相同。
请注意,这(与几乎所有 git 答案一样)可能会在您已经将错误提交推送到其他人可能已经从中提取的地方时造成问题。请尽量避免这种情况。