有没有办法 'soft revert' 旧提交?

Is there a way to 'soft revert' an old commit?

有没有办法在不更改工作目录中的文件的情况下恢复旧的提交? 我不久前提交了一次,但我提交的代码还没有准备好,我希望这些更改作为未提交的更改保留在我的工作目录中,以便我现在可以继续处理它们。 我查看了 revert 命令,但这改变了工作目录。 我正在考虑检查旧版本,重置 head 1 并存储更改,但我已经有了更改。我只是希望它就好像我当时从未进行过一次提交,但我希望保留对文件的更改。

简短的回答是 "no"。

较长的答案:git revert——像所有 merge-oriented 操作一样,包括 git cherry-pickgit rebase,当然还有 git merge 本身——修改一个可修改的work-tree,使用索引。您可以提交或隐藏您当前的工作,或者获得第二个 work-tree(使用另一个克隆,或者如果您有 Git 2.5 或更高版本,则使用 git worktree)。

您可以使用 git revert -n,它允许 work-tree 变脏,但我在这里不建议这样做。

我处理这个问题的方法是现在提交:

$ git add ...
$ git commit -m 'temporary commit, do not push'

然后,作为常规提交执行所需的恢复:

$ git revert <hash>

然后使用git rebase -i交换新的还原提交和临时提交的顺序:

$ git rebase -i HEAD~2  # and edit the two "pick" lines

然后使用 git reset --soft HEAD^(或 HEAD~1,同样的事情)或 git reset --mixed HEAD^ 到 un-commit 临时提交。此时您处于(大部分)与进行临时提交之前相同的状态。

(主要)与索引状态有关:如果您使用 git reset --soft,所有这些 git add 现在都有效。如果您使用 git reset --mixed,其中 git add 中的 none 现在生效。

仅限专家

如果在你开始任何这些之前,你已经有一些精心准备的状态——例如,来自 git add -p——你想保留,这需要做 two 提交,并且 git stash 在还原之前,之后 git stash apply --index 更简单。这是因为 git stash 实际上 进行了 两次提交,并且 git stash apply --index 提取并将这两次提交分别应用于索引和 work-tree。 (如果一切顺利,那么 git stash drop 藏起来。)

根据您对 git stash 的适应程度,您甚至可以将上面的整个序列替换为 git stash && git revert <hash> && git stash pop,从而将其作为 one-liner。添加 --index 以恢复单独的索引状态。 (请注意,如果您输入 --index 并且您的 Git 版本不够现代,无法检测到错误,这会将两个单独的提交混在一起并删除存储。这就是为什么我喜欢使用 git stash apply 而不是这里的 git stash pop。)

如果在此过程中出现任何错误,您将需要确切地知道发生了什么,以及如何处理,因此 "for experts only" header 在这部分上面。

你可以这样做

git revert hash_of_your_commit
git reset HEAD^

之后,您对还原的提交进行了未暂存的更改。

另一种方法是设置错误的 $EDITOR,例如:

EDITOR=nope git revert <hash>

尝试编辑提交消息时它会退出但已经暂存更改

git revert <commit-hash>

git cherry-pick -n <commit-hash>

这个命令通常对我有用: git revert --no-commit <commit>