如何保存git“rebase in progress”?

时间:2017-01-16 22:07:43

标签: git rebase

我正处于大量“正在进行中的变革”中,其中存在大量冲突

我想将此进展放在一边,并尝试使用其他方法解决此问题。

有没有办法可以保存正在进行的 rebase,以便我以后可以完成?

2 个答案:

答案 0 :(得分:7)

如果你作为一个篮板的一部分而坐在冲突的合并中,你就会陷入困境。这就是为什么,如何以及做什么。

Rebase =重复樱桃选择

从根本上说,Git中的rebase操作只是一系列挑选操作。我们从这样的事情开始:

...--A1--A2--A3--A4--A5   <-- branchA
          \
           B1--B2--B3   <-- branchB

我们希望最终得到:

...--A1--A2--A3--A4--A5   <-- branchA
          \           \
           \           B1'-B2'-B3'  <-- branchB
            \
             B1--B2--B3   [abandoned]

我们(或Git)实现此目的的方法是使用git cherry-pick或类似的东西来复制现有提交B1(将其转换为补丁并应用它)在A5之后到来,并在B2之后复制B1',依此类推。

交互式rebase为每个&#34; pick&#34;字面上运行git cherry-pick。您在说明书中留下的操作。非交互式rebase有几个选项,包括运行git cherry-pick

在挑选提交时,如果在应用时存在冲突,Git可以使用三向合并。这仍然可能因冲突而失败。这会阻止rebase。或者,当使用交互式rebase时,您可以选择&#34;编辑&#34;提交,在这种情况下Git cherry-picks提交然后停止rebase。在任何一种情况下,Git都会留下足够的信息让你让Git稍后恢复变基。

冲突在索引

作为快速提醒,请注意Git的索引是您构建 next 提交的地方。通常,每个要提交的文件都有一个条目,因此如果您的下一个提交只包含三个名为READMEfileotherfile的文件,则会有三个索引条目

请注意,索引与工作树是分开的,工作树包含正常的非Gitty格式的文件。与索引和存储库文件的内部Git格式不同,您可以编辑这些文件,编译它们,使用它们来提供网页等等。 (工作树也可以保存未跟踪的文件,而不是在rebase期间这很重要。)

在冲突合并期间,每个索引条目都会公开其各个广告位。每个条目最多有四个插槽,并且它们已编号。 Slot zero保存正常的,未受冲突的文件(如果存在),否则为空。插槽1-3,如果正在使用,则保留必须解决的三个冲突部分。 1 这些是 base 版本(来自合并基础),&#34; local&#34;或--ours版本,另一个或--theirs或有时&#34;远程&#34;版本分别。您的工作是编辑文件的工作树版本,解决冲突,然后git add结果。这会将调整后的工作树版本复制到索引中的插槽零中,从而消除插槽1-3条目。现在文件已解析并准备提交。

1 因此, 插槽0被占用,1-3为空,或者插槽0为空,插槽1-3被占用。有一些奇怪的情况,插槽1,2和/或3也可能是空的,例如,如果你得到修改/删除冲突或添加/添加冲突,但通常它是&#34; 0为空意味着1-3是满的&#34;反之亦然。

但是只有一个索引

短语 索引意味着只有一个。这基本上是正确的。

因为未合并状态在此(&#34;&#34;)索引中,并且只有一个索引,所以其他任何需要使用 的索引在完成解决冲突(然后进行提交)之前,index无法继续。

如果您愿意,只需git add未修复/未解决的项目和git commit结果,您就可以将冲突排除在外。这里的缺点是Git不会保留哪些文件存在冲突:你将删除插槽1-3条目,Git会认为你已经完成了。

你可以保存索引 - 它是一个普通的文件;您可以将其从.git/index复制到其他地方。但是因为它是一个具有各种特殊内部使用的二进制文件 - 索引也称为&#34;缓存&#34;并且它缓存内部文件系统数据以提高速度 - 这实际上并不十分安全。 (如果Git有办法导出#34;导出&#34;索引状态,然后&#34;导入&#34;稍后再进行,那么你真的可以保存并恢复合并冲突状态。但是Git没有。)

因此,为了安全,如果没有别的,建议完成解决这个冲突的合并状态。或者,如果你还没有开始解决,那就不要开始:那么就没有工作可以保存。

你现在在哪里

让我们说你开始了#34;分支B&#34;我在上面画了一个rebase,目前卡在复制提交B2的中间,有些冲突尚未解决。这就是你现在所拥有的:

...--A1--A2--A3--A4--A5   <-- branchA
          \           \
           \           B1'  <-- HEAD
            \
             B1--B2--B3   <-- branchB

索引处于冲突状态。你还有一个&#34;分离的HEAD&#34;:Git正在以这种方式构建新的提交链。名称HEAD指向所有已完成的提交。

如果你做了一些解决工作,你应该完成它(因为它太难以保存未解决的状态)或至少记下未解决的问题(因为你可以添加文件到你的下一次提交)然后运行git commit来创建提交B2'

...--A1--A2--A3--A4--A5   <-- branchA
          \           \
           \           B1'-B2'  <-- HEAD
            \
             B1--B2--B3   <-- branchB

如果您尚未进行任何解决工作,则无法保存实际工作,因此请勿运行git commit。但是无论哪种方式现在它是时候创建一个分支或标记名称,指向HEAD现在指向的同一个提交:

$ git branch saveme    # or git tag saveme

现在你有了这个:

...--A1--A2--A3--A4--A5   <-- branchA
          \           \
           \           B1'-B2'  <-- HEAD, saveme
            \
             B1--B2--B3   <-- branchB

现在你可以:

$ git rebase --abort

这使得Git停止了rebase尝试并返回branchB

...--A1--A2--A3--A4--A5   <-- branchA
          \           \
           \           B1'-B2'  <-- saveme
            \
             B1--B2--B3   <-- HEAD->branchB

现在你已经保存了迄今为止所做的所有工作,并且可以返回并稍后重试rebase。您拥有({Git})为B1'所做的解决方案,如果您提交了B2',那么您也可以获得解决方案。这些分别是提交saveme~1saveme;或者只提交saveme,如果只有一个提交。

答案 1 :(得分:3)

我想出了一种有效的方法,但有点像黑客:

将repo重新克隆到另一个目录中,使 rebase-in-progress 保持原样。