部分合并的Git工作流程?

3
我有两个分支deva。我需要将特性a合并到dev中,但我的队友在一个文件中制作了某些特性,这个文件还没有准备好合并。如果我只是合并并使用我的解决方案,git会将此文件中的更改标记为无效,而不是允许稍后合并这些更改,如果我尝试重新合并分支,则会快进。如果我不解决冲突,git会拒绝执行合并。
我的解决方法是创建一个分支并抑制损坏的特性,然后合并该分支。问题是这些git命令变得有些复杂,因此我需要专家的帮助。
如果可能的话,我希望将此类操作归纳为一个名为git-cherrymerge的git扩展程序。
步骤如下:
  1. 重播由用户指定的提交(也许可以通过一些策略自动化)到临时分支上
  2. 使用Git filter-branch删除损坏的文件
  3. 压缩临时分支,添加自动提交消息
  4. 将临时分支合并到目标分支(这里是dev)
我不是filter-branchrebase的专家,看起来我可能会严重损坏历史记录。
我的问题是:
  1. 这样做可以吗?还是有更好的规范方法来做到这一点?
  2. 我应该按什么顺序执行git命令以避免意外损坏我的存储库历史记录。

git将此文件中的更改标记为无效,你所说的“无效”是什么意思?你是指有冲突吗? - Schwern
@Schwern基本上,如果我再次尝试向上游合并,则在早期历史记录中存在的更改被认为是“不好的”,并且永远不会被自动合并策略“应用”。 - awiebe
你已经告诉 Git 你已经合并了这些文件,并通过告诉它如何应用更改来处理了合并,因此你忽略了它们。Git 不会在以后重试该合并,因为该提交已经被合并了。最好的方法是在执行合并之前处理这个问题,将工作分成两个不同的分支,一个可以合并,另一个不能合并。 - Lasse V. Karlsen
好的,但缺乏更好的措辞,我告诉git不要将它们保留在未来,因此基本上整个问题就是针对这种情况该怎么办,因为git范例没有部分合并概念,除了在合并之前弄清楚。 - awiebe
2个回答

5

您的想法基本上是正确的,您希望将一个分支分成两个:一个包含已准备好的内容的分支和一个在其之上的包含未完成更改的分支。例如,一个分支可能包含一堆重构和错误修复以及未完成的功能。

A - B - C - D [master]
         \
          R1 - B1 - F1 - R2 - B2 - F2 [feature]

R1和R2是重构更改。B1和B2是错误修复更改。F1和F2是未完成的功能。您需要的是这样:

A - B - C - D [master]
         \
          R1 - B1 - R2 - B2 [fixes]
                           \
                            F1 - F2 [feature]

这里有两个步骤,重新排列提交并声明新分支。使用git rebase -i来重新排列提交。这将呈现出如下内容:

pick f37beee Refactor 1
pick 7f238ea Bugfix 1
pick d100dd2 Feature 1
pick aa1124b Refactor 2
pick beadbee Bugfix 2
pick 0123abc Feature 2

然后您可以在编辑器中直接重新排序它们。
pick f37beee Refactor 1
pick 7f238ea Bugfix 1
pick aa1124b Refactor 2
pick beadbee Bugfix 2
pick d100dd2 Feature 1
pick 0123abc Feature 2

Git会通过按照新顺序应用这些补丁来重建分支。你可能需要解决冲突。更多信息请参见Pro Git中的Rewriting History

然后你需要声明一个新分支。只需使用git branch fixes beadbee来声明fixes分支,从你想要的最后一次提交开始。

通常情况下,提交并不是如此清晰地分开。如果你有一个包含多个更改的提交,而你只想要其中的一些,那么你可以将其拆分为多个提交。

像以前一样使用git rebase -i,但将你想要拆分的提交设置为edit而不是pick

pick f37beee Refactor 1
pick 7f238ea Bugfix 1
pick aa1124b Refactor 2
pick beadbee Bugfix 2
edit beacd4a Messy commit
pick d100dd2 Feature 1
pick 0123abc Feature 2

然后Git会停留在该提交,并允许您按照自己的喜好进行编辑。使用git add -p仅将更改的部分添加到暂存区(构建提交的地方)和git commit只提交部分更改。重复此操作,直到每个更改都有自己的提交。例如,它可能更改了方法的名称,修复了错误,但又更改了一个不相关的方法。您要将它们拆分为三个提交:一个更改名称,一个修复错误,一个更改不相关的方法。
您可以在交互式暂存中了解更多信息。
引用:
“我不太精通filter-branch或rebase,看起来如果我滥用它们,我可能会严重损坏历史记录。”
是的,但您可以撤消这些错误,并且除非您git push它,否则不会影响任何其他人。 Git不会重写历史记录,它会编写新的历史记录并假装一直以来都是这样的。旧的历史记录仍然存在一段时间,并且您可以使用诸如ORIG_HEADgit reflog之类的东西返回到它。
最坏的情况下,删除本地存储库并克隆一个新的存储库。

0

我已经将Schwern的答案标记为正确答案,因为它是最一般的情况 - 但值得注意的是,对于我的情况,有一个非常简单的策略如下。由于我打算压缩这些更改,这意味着该过程可以在单个提交中完成。仍然需要创建一个新分支,但可以使用软重置快速完成。如果只有少量易于管理的更改需要推迟,我建议使用此策略

  1. 检出A的HEAD
  2. 分支到临时分支
  3. Git软重置到A的“根”
  4. 提交更改,不包括您不想要的更改
  5. 合并到develop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接