tl; dr :将我的整个本地存储库还原到特定时间点。我希望所有分支都恢复到那一点。我都想要 在那个时间点之后的提交完全消失了。我想一个描述它的好方法是切断所有分支的所有提示(正如你在SourceTree中看到的那样)比特定时间更新。
假设我有3个分支,每个分支实现“一种方式”。事实上,我希望将这三个分支完全分开。但是,当我发现一个错误时,我想在所有三个分支中修复它,例如。这就是我犯了错误的地方,我正试图以一种方式修复它。我将错误的分支合并到所有这三个分支中。 (git合并分支的方式与我预期的略有不同。)事实上,我希望将整个git存储库恢复到现实生活中的最后一个点哪里好。
我已经尝试了几个小时才能做到这一点。我尝试使用git reset --hard <commit>
,但这并没有恢复存储库本身。似乎只有工作目录。
答案 0 :(得分:2)
听起来你想要三个独立的git reset --hard
s。
让我绘制一张图表,我认为它代表了你以前所拥有的(并希望回到原点),以及你所拥有的:
--- x <-- badbranch
/
... - o - o - o <-- branch1
\
\-- o - o - o <-- branch2
\
- o - o <-- branch3
这是&#34;在你进行三次合并之前#34; branch1
至少有3次独立提交,branch2
至少有3次独立提交,而branch3
至少有3次至少2个(这些是o
个节点)。
与此同时,第四个分支(上面badbranch
)有一个&#34;坏&#34;提交x
。
然后你做了:
$ git checkout branch1; git merge badbranch
$ git checkout branch2; git merge badbranch
$ git checkout branch3; git merge badbranch
(加上可能的解决方案,但我假设所有合并都很容易合并和创建了合并提交,如下所示。)
正如提醒一下,merge
所做的是获得两个差异,一个用于当前分支提示(让我们说branch1
)与合并基础(在{ {1}}一系列提交),一个用于要合并的提示(...
)与同一个合并库。然后,在筛选出基本到尖端差异中已经存在的所有变化之后,它将从基础到x
的差异应用到当前分支的尖端;如果一切顺利,它会从结果中进行新的提交:
x
我们还不需要查看 --- x <-- badbranch
/ `---------\
... - o - o - o - M <-- branch1
和branch2
,但如果我们愿意,暂时忽略branch3
会有所帮助。我们这次只需branch1
,其中包括合并(我们会将branch3
称为M3
)以区别于M
:
--- x <-- badbranch
/ \
... \
\ \
\ \
\ \
- o - o - M3 <-- branch3
现在让我们看一下git reset
做什么,以图形方式。 (您已经知道,--hard
会重置您的工作树。)
让我们回过头来考虑branch1
:
$ git checkout branch1
上面有错误的合并M
。我会扩展绘图以使其更高一点,原因很明显,然后我同样会移动M
:
- x <-- badbranch
/ \
/ ------ M <-- branch1
/ /
... - o - o - o
(幸运的是,尽管现在看起来像卡通狗的脑袋,但它仍然很明显,它与之前的图形相同)。
当您使用commit-ID运行git reset
或使用指定commit-ID的名称时,它会查看当前分支(现在为branch1
)并将该标签移动到目标提交。在这种情况下,我们假设你使用HEAD^
或者提示最多o
的提交ID;任何一个都给出相同的结果,将branch1
向下移动到指向o
。现在图表是:
- x <-- badbranch
/ \
/ ------ M
/ /
... - o - o - o <-- branch1
&#34;坏&#34;合并提交M
不再直接可见,因为您获得的视图(使用git log
或图形查看器)从分支提示开始,分支提示不再显示合并提交M
。所以你看到的是:
- x <-- badbranch
/
/
/
... - o - o - o <-- branch1
这是你合并之前所拥有的。
当然,分支机构branch2
和branch3
仍然存在&#34;坏&#34;合并,但您可以通过检查这些分支并在每个分支上执行git reset --hard HEAD^
来轻松解决此问题。
每次重置都会将当前分支一次提交备份到您执行&#34; bad&#34;之前的位置。合并。你必须为每个提交重复一次,因为每个分支都是独立的,因为每个合并都是真正的合并,而不是&#34;快进&#34;。
如果某些分支 快速前进&#34;,您必须更加小心:HEAD^
可能不再适合每次重置。但一般情况下,将每个分支重置为所需的commit-ID,您可以在这些分支的reflog中找到它,这样做。
答案 1 :(得分:0)
实际上,git reset --hard <commit>
还会恢复存储库中有关当前分支和工作目录的信息(没有--hard
它只会恢复存储库中的信息并保持工作目录不变。)
如果您只有三个分支,最简单的方法就是每个分支只有git checkout
,然后git reset --hard <commit>
才能满足您的要求。
代替<commit>
,您还可以使用时间规范,例如HEAD@{yesterday}
,这可能会稍微简化一些事情。有关指定日期的详细信息(以及可以引用提交对象的无数其他方式),请参阅git-rev-parse man page的SPECIFYING REVISIONS
部分。
如果您有多个分支机构,您可能会稍微自动化一些事情,可能从git for-reach-ref refs/heads/
开始获取分支列表,但我还没有通过该特定解决方案。