Git 部分合并的工作流程?

Git workflow for partial merges?

我有两个分支 deva。我需要将功能 a 合并到 dev 中,但我的队友在一个尚未准备好合并的文件中创建了某些功能。如果我只是使用我的合并和解析,git 会将此文件中的更改标记为无效,而不是允许这些更改在以后合并,如果我尝试重新合并分支则只是快进。如果我不解决冲突,git 拒绝执行合并。

我解决这个问题的策略是在旁边创建一个分支并抑制损坏的功能,然后合并到这个分支中。问题是 git 命令有点复杂,所以我需要专家的帮助。

如果可能的话,我想将这种类型的动作概括为 git 扩展,我会调用一些东西来达到 git-cherrymerge.

的效果

步骤如下:

  1. 重播用户指定的提交(也许这可以通过某种策略自动执行)到临时分支
  2. Git filter-branch 删除损坏的文件
  3. 压缩临时分支,添加自动提交消息
  4. 将临时分支合并到目标分支(这里是dev)

我不是 filter-branchrebase 方面的专家,看起来我可以非常认真地 滥用它们来破坏历史

我想我的问题是

  1. 这行得通吗?有更好的规范方法吗?
  2. 我应该按什么顺序执行什么 git 命令,以避免意外损坏我的存储库历史记录。

您的想法基本上是正确的,您想要将一个分支变成两个:一个分支包含已准备就绪的内容,另一个分支在其之上是未完成的更改。例如,一个分支可能包含一堆重构和错误修复,与不完整的功能交织在一起。

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 将通过按新顺序应用这些补丁来重建分支。您可能必须解决冲突。有关详细信息,请参阅 Rewriting History in Pro Git

然后你需要声明一个新的分支。这只是 git branch fixes beadbee 声明从您想要的最后一次提交开始的修复分支。

将修复程序正常合并到 master 中,并在 master 之上重新设置功能。


但是通常提交并不是那么整齐地分开的。如果您有一个包含多个更改的提交并且您只想要其中的一些更改,则可以将其变成多个提交。

像以前一样使用 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 仅添加部分更改。这样做直到每个更改都有自己的提交。例如,它可能更改了一个方法的名称,修复了一个错误,但也更改了一个不相关的方法。您可以将它们分成三个提交:一个更改名称,一个修复错误,一个更改不相关的方法。

您可以在 Interactive Staging 中阅读更多相关信息。


I'm not quite an expert in filter-branch or rebase and it looks like I can quite seriously damage the history be misusing them.

是的,但是您可以扭转这些错误,除非您 git push 否则不会影响任何其他人。 Git 不会重写历史,它会编写新的历史并假装一直都是这样。旧的历史仍然存在一段时间,您可以使用 ORIG_HEADgit reflog.

之类的东西返回它。

最坏的情况,delete your local repository and clone a new one

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

  1. 检查 A
  2. 的 HEAD
  3. 分支到临时分支
  4. Git软重置为A
  5. 的"root"
  6. 提交更改,不包括您不想要的更改
  7. 合并到develop