Git:恢复整个存储库

时间:2015-06-06 01:56:28

标签: git version-control

  

tl; dr :将我的整个本地存储库还原到特定时间点。我希望所有分支都恢复到那一点。我都想要   在那个时间点之后的提交完全消失了。我想一个描述它的好方法是切断所有分支的所有提示(正如你在SourceTree中看到的那样)比特定时间更新。

假设我有3个分支,每个分支实现“一种方式”。事实上,我希望将这三个分支完全分开。但是,当我发现一个错误时,我想在所有三个分支中修复它,例如。这就是我犯了错误的地方,我正试图以一种方式修复它。我将错误的分支合并到所有这三个分支中。 (git合并分支的方式与我预期的略有不同。)事实上,我希望将整个git存储库恢复到现实生活中的最后一个哪里好。

我已经尝试了几个小时才能做到这一点。我尝试使用git reset --hard <commit>,但这并没有恢复存储库本身。似乎只有工作目录。

2 个答案:

答案 0 :(得分:2)

短版

听起来你想要三个独立的git reset --hard s。

TL; DR Long版本

让我绘制一张图表,我认为它代表了你以前所拥有的(并希望回到原点),以及你所拥有的:

  --- 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

这是你合并之前所拥有的。

当然,分支机构branch2branch3仍然存在&#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 pageSPECIFYING REVISIONS部分。

如果您有多个分支机构,您可能会稍微自动化一些事情,可能从git for-reach-ref refs/heads/开始获取分支列表,但我还没有通过该特定解决方案。