我正处于大量“正在进行中的变革”中,其中存在大量冲突。
我想将此进展放在一边,并尝试使用其他方法解决此问题。
有没有办法可以保存正在进行的 rebase,以便我以后可以完成?
答案 0 :(得分:7)
如果你作为一个篮板的一部分而坐在冲突的合并中,你就会陷入困境。这就是为什么,如何以及能做什么。
从根本上说,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 提交的地方。通常,每个要提交的文件都有一个条目,因此如果您的下一个提交只包含三个名为README
,file
和otherfile
的文件,则会有三个索引条目
请注意,索引与工作树是分开的,工作树包含正常的非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~1
和saveme
;或者只提交saveme
,如果只有一个提交。
答案 1 :(得分:3)
我想出了一种有效的方法,但有点像黑客:
将repo重新克隆到另一个目录中,使 rebase-in-progress 保持原样。