【问题标题】:Git workflow for partial merges?部分合并的 Git 工作流程?
【发布时间】:2017-09-04 21:01:58
【问题描述】:

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

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

如果可能的话,我希望将这种类型的操作概括为一个 git 扩展,我会调用 git-cherrymerge 的效果。

步骤如下:

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

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

我想我的问题是

  1. 这会起作用还是有更好的规范方法来做到这一点?
  2. 我应该按什么顺序执行哪些 git 命令以避免意外损坏我的存储库历史记录。

【问题讨论】:

  • "git 将此文件中的更改标记为无效" 你是什么意思“无效”?你的意思是有冲突吗?
  • @Schwern 基本上,如果我尝试再次向上游合并,那么早期历史中存在的那些更改被认为是“坏的”,并且永远不会被自动合并策略“应用” .
  • 不是“坏”或“无效”。你已经告诉 git 你已经合并了这些文件并通过告诉它如何应用更改来处理合并,你忽略了它们。 Git 稍后不会重试该合并,因为该提交已被合并。最好的办法是在执行合并之前处理这个问题,将工作分成两个不同的分支,一个可以合并,一个不能合并。
  • 嗯,是的,但是由于没有更好的词,我告诉 git 不要在将来保留它们,所以基本上整个问题是如何处理这种情况,因为 git 范式没有t 有一个部分合并的概念,除了是的,在合并之前弄清楚它。

标签: git version-control merge git-filter-branch cherry-pick


【解决方案1】:

您的想法基本上是正确的,您想将一个分支变成两个:一个包含准备就绪的分支,以及一个位于不完整更改之上的分支。例如,一个分支可能包含一堆重构和错误修复,其中包含不完整的功能。

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 之上 rebase 功能。


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

像以前一样使用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 中阅读更多相关信息。


我不是过滤器分支或变基方面的专家,而且看起来我滥用它们会严重破坏历史。

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-17
      • 1970-01-01
      相关资源
      最近更新 更多