复杂合并的临时提交

temporary commit on complex merge

我有两个分支,master 是主分支,feature_branch_1 是很老的分支,很多提交落后于 master。我需要将 feature_branch_1 合并到 master 中,所以我做了:

git pull --rebase origin master

正如预期的那样,有很多冲突,不久之后需要在新 feature_branch_2 上开发另一个功能,这与 master 的 HEAD 背道而驰,绝对需要继续努力feature_branch_1 之前。或多或少处于复杂合并的中间,我如何在 feature_branch_1 上进行临时提交,以便稍后再回来处理。我知道我可以做一个:

git add <things-that-are-done>
git commit -m 'intermediary commit between merges'
... come back to it later
git checkout 'that-temp-commit-hash'
... after finishing
git add .
git commit -m 'done with feature_branch_1'
git rebase --interactive HEAD~1

进行临时提交然后变基以在之后压缩它。

这是处理此问题的最佳方法吗?

Git 不会让您使用包含未合并条目的索引进行提交。

使用 git add 将解决未合并的条目,以便您可以提交,但由于多种原因,这种方法可能不能令人满意。无需赘述:

  • 未解析的路径通过使用索引槽 1-3 而不是槽 0 来表示。它们包含文件的 merge-base 版本,"sides"(--ours--theirs,虽然在合并过程中角色有点交换)。
  • git add 从 work-tree 复制到 slot 0,破坏 slot 1-3,因此文件现在已解析(即使 work-tree 文件仍然充满冲突标记)。
  • 一个 "undo" (REUC) 条目也在此时记录在索引中,这样你就可以 git checkout -m 到 re-create 冲突的路径 (擦除插槽 0 条目并恢复 1-3 条目)。
  • 实际上提交合并结果永久失去撤消状态。

这意味着如果你提交部分合并,然后想返回并想完成它,一些信息——特别是未合并的状态,即使它被移动到一个撤消条目——丢失了。稍后,您最接近找出仍需要正确合并哪些文件的方法是搜索冲突标记。 (如果你觉得没问题的话,这个方法可能还是比较满意的。)

除此之外,rebase 会复制 多个提交 ,并且您没有提到在最后一次提交时是否发生了这种特定的合并冲突。在继续其他操作之前,您需要完成或中止变基。 (技术上可以在变基过程中做一些事情,但这很棘手。)

关于这部分:

... come back to it later
git checkout 'that-temp-commit-hash'
... after finishing
git add .
git commit -m 'done with feature_branch_1'
git rebase --interactive HEAD~1

因为这个特定的 unmerged-state(您故意快速解决 "wrong" 以便做其他事情并稍后回来)是变基而不是合并的结果,该序列可以工作。不过,将最后两个步骤替换为 git commit --amend 会更简单,也更普遍适用。 --amend 选项告诉 git commit 使用当前提交的 parent(s) 而不是当前提交本身来进行新提交。这适用于正常(single-parent、non-merge)提交和实际合并(两个或更多 parents)。

备选方案

你最好的选择可能是不理会这个 work-tree 并制作另一个你处理其他问题的地方。

最简单的方法,始终适用于 Git 的每个版本,就是制作另一个克隆。

您可以通过克隆 in-progress 变基来制作额外的克隆。在具有硬链接的合理系统上,如果您使用本地路径(例如 git clone work/repo work/new-clone-for-fast-fix,从您工作的地方向上一级)将您的存储库克隆到同一文件系统上的另一个存储库,Git 将使用底层包的硬链接和 objects,因此您只需要 work-tree space.

如果您的 Git 相对较新(我推荐至少 Git 2.6,尽管该功能在 2.5 中就有),您可以使用 git worktree add 创建一个新的 "linked work-tree".链接的 work-tree 会记住其原始存储库(反之亦然),但也有一个私有索引 / staging-area。你可以把它放在你想要的任何分支上,在那里做任何你喜欢的事情,包括创建其他分支或做其他变基,所有这些都不会影响你的 "main" work-tree 和 "main" 索引。