回退到特定的提交版本但不丢失历史记录

25

我知道这种问题已经有很多重复了,但我想开一个新的问题,因为在所有其他问题中,我没有找到最好的方法来按照我的意愿进行操作的解释。

我知道可以通过以下方式还原并保留历史记录:

git reset --soft c14809fa

我希望将 development 分支还原,并将历史记录保留在另一个分支中。

如果在还原提交之前将 development 检出到新的分支中 - 例如

git checkout -b beforeRevert

然后我将回到开发分支并进行还原操作(因为我想继续使用我已经还原的提交数据进行工作)。
另一个分支"beforeRevert"将保留所有"还原前"的历史和数据,以备将来再次使用,但不包括在当前的开发分支中。还是说,在开发分支上的还原会以某种方式影响到"beforeRevert"分支?
5个回答

28

如果您确信软重置或创建多个分支对您的用例都不起作用,那么您可以执行

git diff HEAD commit_hash_to_go_to | git apply
这将创建一个最新提交与所需状态提交之间更改的差异,并自动应用它。这只会更改文件,所以您需要将它们添加到暂存区并提交结果。如果您想尝试不同的解决方案并在同一分支中保留更改历史记录或避免创建多个本地分支,则可能会很有用。 如果遇到“无法应用二进制补丁到没有完整索引行的文件”的错误,请添加--binary标志:
git diff HEAD commit_hash_to_go_to --binary | git apply

在执行此操作之前,请确保您没有未提交的更改——否则补丁将无法应用(它是原子性的,因此要么所有更改都会通过,要么没有一个更改,因此您不会处于不一致的状态)

注意:这只是更改文件并将其标记为已修改。它不会更改提交历史记录或创建新的提交。

提示:如果您只想撤消最后一次提交,可以执行以下操作:

git diff HEAD HEAD~1 | git apply

“~1”表示您希望回退的提交次数。在这种情况下,仅后退1个提交。


我做了这个...但是在此期间,我对我的分支进行了一些反向合并,因此我无法将那些更改拉回来,因为这会创建一个前向提交。 - cegprakash
@cegprakash 这很奇怪,因为git diff只在本地文件上操作,根本不会触及提交。可能是你对文件应用了差异,并提交了结果。如果是这样的话,而且提交还没有推送到上游,你可以尝试使用git revert来撤销更改。 - wondersz1

13

像你所说的那样,最简单的方法是在HEAD处创建一个新分支,然后将development还原到你想要恢复工作的提交:

git checkout development   # Make HEAD point to the 'development' branch
git branch beforeRevert    # Create a new branch reference pointing to HEAD
git reset --hard c14809fa  # Move HEAD, the index and your working copy to c14809fa

这里是一个图形化的表示,展示了接下来会发生什么:
    Step 1               Step 2                  Step 3

            develop    develop, beforeRevert   develop   beforeRevert
           /                    /             /         /
A-B-C-D-E-F          A-B-C-D-E-F             A-B-C-D-E-F
          ^                    ^             ^
         HEAD                 HEAD          HEAD

重要的是,这里的 HEAD 总是指向 development 分支,因此当您运行 git reset --hard c14809fa 时,该分支将被移动。新的 beforeRevert 分支仍将指向还原之前的 HEAD

听起来像是我想做的。让我检查一下,然后我会批准你的答案。谢谢! - Aviv Paz
答案已批准? - Hang

1
不要撤销你的更改,只需返回到先前的提交并从那里检出一个新分支。
git checkout development
git checkout c14809fa
git checkout -b newBranch

这样,您可以访问“development”分支查看旧更改和历史记录,并且您可以在“newBranch”中进行进一步更改。
如果您想要相反的操作,可以使用-来重命名分支。
git branch -m <oldname> <newname>

1
你可以一次性完成它:`git checkout -b newBranch c14809fa' - Miroslav Franc
1
这会把分支搞反。OP想让新分支指向他当前所在的位置,而开发分支指向旧提交。 - Holloway
如我所提到的,简单的方法是稍后使用“git branch -m <oldname> <newname>”重命名分支。只需交换两个分支的名称即可。 - Harish Ved
1
Enrico Campidoglio的回答更正确,我认为。 - Harish Ved

0
找到答案了这里
git reset --hard oldestCommitHash
git reset --soft mostRecentCommitHash #
git commit
  • 这将保留您的历史记录,但将您移回到与oldestCommitHash相同的状态
  • 请注意,在mostRecentCommitHash后的#是有意的,并且需要存在

-1

git merge <old commit>

这将创建一个新的提交(带有您选择的消息),将您的工作空间恢复到旧的提交状态。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接