在我的一个开发分支中,我对我的代码库进行了一些更改。在我能够完成我正在处理的功能之前,我不得不将当前分支切换到 master 来演示一些功能。但只是使用 “git checkout master” 保留了我在开发分支中所做的更改,从而破坏了 master 中的一些功能。所以我所做的是使用提交消息 “临时提交” 在我的开发分支上提交更改,然后为演示提供 checkout master。
现在我已完成演示并重新开始在我的开发分支上工作,我想删除我所做的 “临时提交”,同时仍然保留我所做的更改。那可能吗?
这很简单:
git reset HEAD^
git reset
没有--hard
或--soft
将你的HEAD
移动到指向指定的提交,而不更改任何文件。 HEAD^
指的是当前提交的(第一个)父提交,在您的情况下是临时提交之前的提交。
请注意,另一个选项是正常进行,然后在下一个提交点运行:
git commit --amend [-m … etc]
它将改为编辑最近的提交,具有与上述相同的效果。
请注意,如果您已将错误提交推送到其他人可能已将其撤消的位置,则此问题(与几乎所有 git 答案一样)可能会导致问题。尽量避免这种情况
有两种方法可以解决这个问题。哪个更容易取决于您的情况
重启
如果您想要删除的提交是最后一次提交,并且您还没有完成任何额外的工作,您只需使用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@{#}
其中#是它在 stashes 数组中的位置。
要恢复存储(可以在任何分支上完成,无论最初创建存储的位置),您只需运行...
git stash apply stash@{#}
同样,#是 stashes 数组中的位置。如果要恢复的存储位于0
位置 - 也就是说,如果它是最近的存储。然后你可以在不指定存储位置的情况下运行命令,git 将假设你的意思是最后一个: git stash apply
。
因此,例如,如果我发现自己在错误的分支上工作 - 我可能会运行以下命令序列。
git stash
git checkout <correct_branch>
git stash apply
在你的情况下,你移动分支更多,但同样的想法仍然适用。
希望这可以帮助。
我想你正在寻找这个
git reset --soft HEAD~1
它撤消最近的提交,同时保持该提交中的更改进行分段。