如何在不删除最新提交的情况下恢复到之前的提交?

How do I revert to the previous commit without deleting the latest commit?

假设我有 2 个提交,我已经将它们推送到我的远程分支。

如何在不删除提交 A 的情况下恢复到提交 B?我只想比较这两个提交之间的结果。

注意:不需要进行代码比较。我只想比较 Commit A 与 Commit B

的输出

还原 提交 B 不会删除 提交 A。它只会创建 提交 C这将撤消您在 提交 B

中所做的一切
git revert commit-b-hash
git revert <Commit B>

Given one or more existing commits, revert the changes that the related patches introduce, and record some new commits that record them. This requires your working tree to be clean (no modifications from the HEAD commit). git docs


但是,如果您只是想看看两者之间的区别:

git diff <Commit B>..<Commit A>

Show changes between the working tree and the index or a tree, changes between the index and a tree, changes between two trees, changes resulting from a merge, changes between two blob objects, or changes between two files on disk. git docs

我强烈反对建议您使用 git revert 的其他答案。这实际上会真正恢复由 提交 A 引入的更改并自行生成提交。

由于您想查看过去某个时间点的状态,您可以直接签出 提交 B,以便检查内容。之后签出原始分支以返回最新提交。

git checkout $HASH_OF_COMMIT_B   # now you are in a detached head state at commit B
git checkout $BRANCH             # now you are back at the tip of the branch (commit A)

很多工具可以让您直接看到两个参考文献之间的区别,而无需检查。在命令行上,可以使用 git diff:

git diff $HASH_OF_COMMIT_A..$HASH_OF_COMMIT_B

How do I revert to Commit B without deleting Commit A?

您可以轻松使用git rebase -i <commit_hash>

  • Select 在提交 B 之前提交一次,即提交 C

HEAD <- Commit A <- Commit B <- Commit C

  • git rebase -i <commit_hash_commitC>
  • 以上命令将在您的文本编辑器中列出提交,看起来像这样:
pick f7f3f6d Commit B
pick a5f4a0d Commit A

# Rebase 710f0f8..a5f4a0d onto 710f0f8
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
  • 删除表示提交 B 的行,然后保存并退出文本编辑器。
  • Git 将重播交互式编辑器中提到的所有提交并停止,这将完全删除提交 B。

您可以进行交互式变基,删除不需要的提交,然后在删除分支上进行硬推送。

git rebase -i     //opens interactive rebasing window

pick #commitID2 My commit 2
pick #commitID1 My commit 1    <- To unpick/remove this commit, using editor remove 
                                  line->

save the window.
git push origin branchname -f