如何在不删除最新提交的情况下恢复到上一个​​提交?

Posted

技术标签:

【中文标题】如何在不删除最新提交的情况下恢复到上一个​​提交?【英文标题】:How do I revert to the previous commit without deleting the latest commit? 【发布时间】:2021-08-18 19:05:52 【问题描述】:

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

提交 A(2021 年 5 月 31 日) 提交 B(2021 年 5 月 30 日)

如何在不删除提交 A 的情况下恢复到提交 B?我只是想比较这 2 次提交的结果。

注意:不需要代码比较。我只是想比较 Commit A 和 Commit B 的输出

【问题讨论】:

在 git 中删除提交实际上是不可能的。所以你不应该害怕。 是的有点担心,因为它是生产代码。无论如何,将在我的个人演示项目中尝试“风险更高”的选项 我的意思是,在 git 中没有冒险的方法,因为你的提交永远不会被删除。 git 中没有删除提交的选项,你可以随时取回它。 只签出提交 B? @JawadElFou:可能会丢失提交,但这需要一些工作——如果你将 Git 存储库连接到另一个 Git 存储库,提交将会返回它。 :-) 【参考方案1】:

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

由于您想查看某个时间点的状态,您可以直接签出Commit 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

【讨论】:

是的,问题标题中的 revert 会让人误入歧途。旁注:Git 人员正试图让人们远离使用 git diff 中的两点符号。任何git diff A..B 总是可以写成git diff A B,这实际上使命令更短。唯一需要这两个点的地方是,如果您省略 AB 之一以暗示 HEADgit diff A.. 必须替换为 git diff A @,这不会使其更短。跨度> 强烈同意。如果您只想比较两个提交的行为,这实际上很简单。只需检查第一个,测试,检查另一个,测试。【参考方案2】:

如何在不删除提交 A 的情况下恢复到提交 B?

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

在提交 B 之前选择一个提交,即提交 C

HEAD

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。

【讨论】:

【参考方案3】:

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

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 

【讨论】:

【参考方案4】:

还原 Commit B 不会删除 Commit A。它只会创建 commit C,这将撤消您在 中所做的一切提交 B

git revert commit-b-hash

【讨论】:

【参考方案5】:
git revert <Commit B>

给定一个或多个现有提交,还原相关补丁引入的更改,并记录一些记录它们的新提交。这要求您的工作树是干净的(不修改 HEAD 提交)。 git docs


不过,如果你只是想看看两者的区别:

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

显示工作树和索引或树之间的更改、索引和树之间的更改、两棵树之间的更改、合并导致的更改、两个 blob 对象之间的更改或磁盘上两个文件之间的更改。 git docs

【讨论】:

以上是关于如何在不删除最新提交的情况下恢复到上一个​​提交?的主要内容,如果未能解决你的问题,请参考以下文章

您是不是可以在不产生冲突的情况下恢复除最后一次以外的提交?

如何在不影响之后的提交的情况下编辑旧提交

如何在不刷新的情况下提交表单?

如何用 Git 将代码恢复到一个历史的版本

git rm 删除了文件 怎么恢复到上一个版本

git rm 删除了文件 怎么恢复到上一个版本