我正在进行一个包含多个冲突的大型"变基中"。
我想把这个过程搁置一下,尝试使用另一种方法解决这个问题。
是否有办法保存一个正在进行中的变基,以便稍后完成?
如果您在rebase的冲突合并中卡住了,那么您可能会感到困惑。下面是为什么,如何以及您可以做什么。
基本上,在Git中进行rebase操作只是一系列cherry-pick操作。我们从这样的东西开始:
...--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'
之后,以此类推。git cherry-pick
来执行每个“pick”操作。非交互式变基有几个选项,包括运行git cherry-pick
。README
、file
和otherfile
的文件组成,则会有三个索引条目。--ours
版本以及另一个或--theirs
或有时称为“远程”版本。您的任务是编辑该文件的工作树版本,解决冲突,然后git add
结果。这将把调整后的工作树版本复制到索引中的插槽零中,并清除插槽1-3条目。现在该文件已解决并准备好提交。1因此,要么插槽0被占用且1-3为空,要么插槽0为空且插槽1-3被占用。有一些奇怪的情况,其中插槽1、2和/或3也可以为空,例如如果您遇到修改/删除冲突或添加/添加冲突,但通常情况是“0为空表示1-3已满”,反之亦然。
短语“the” index暗示只有一个索引,这基本上是正确的。
因为未合并的状态在这个(“the”)索引中,而且只有一个索引,任何需要使用“the”索引的其他内容都无法进行,直到您完成解决冲突(然后提交更改)。
如果您愿意,可以只是git add
未修复/未解决的项目并git commit
结果,以摆脱冲突。但是这样做的缺点是Git不会保留哪些文件有冲突:您将删除插槽1-3条目,Git会认为您已经完成了所有工作。
您可以保存索引 - 它是一个普通的文件;您可以将其复制到.git/index
之外的其他地方。但是,由于它是一个具有各种特殊内部用途的二进制文件 - 索引也称为“缓存”,它会为了速度而缓存内部文件系统数据,因此这实际上并不安全。(如果Git有一种方法可以“导出”索引状态,然后稍后再“导入”它,以便您真正可以保存和恢复合并冲突状态,那将是很好的。但是Git没有这个功能。)
因此,出于安全考虑,建议完成解决此冲突的合并状态。或者,如果您尚未开始解决,请不要开始:那么就没有要保存的工作了。
假设您从上面的“分支B”的rebase中开始,并且当前卡在复制提交B2
的中间,还有一些未解决的冲突。下面是您当前实际拥有的内容:
...--A1--A2--A3--A4--A5 <-- branchA
\ \
\ B1' <-- HEAD
\
B1--B2--B3 <-- branchB
索引处于冲突状态。您还有一个“分离的HEAD”: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
。
git add
,将其写入槽0作为正常的未冲突版本。然后它就会进入下一个提交,因此每个提交中的内容也都是未冲突的。啊,我看到措辞问题了,我会修复的。 - torek我想到了一个可行的方法,但有点取巧:
将仓库重新克隆到另一个目录中,保留 正在进行中的变基。
git worktree add
,它可以创建一个具有自己独立索引的新工作树。然而,有一个限制:每个添加的工作树必须位于它自己的分支上。正在进行的变基操作没有分支(分离的HEAD),但一旦完成变基操作,它将尝试返回到其原始分支,因此在这里要小心。 - torekgit rebase --abort
。git reflog
命令查看过去git事件的历史记录。这将显示一个列表,其中你将看到中止事件和所有先前的cherry-pick
事件逐个列出。git reset --hard <hash-from-reflog-list>
跳转到中止前的最后一步。当然,你不会处于rebase模式,但现在你可以通过普通的cherry-pick继续rebase。