Git 管理多个分支的公共部分 How to manage the common part of multiple branches

我们在使用 git 进行版本控制时,可能遇到这样的需求:同时维护多个永久性的 branch(分支),每个 branch 可能对应于针对不同客户的不同实现;在分支间切换,可以方便地为各个客户生成特定的版本。这些所谓“永久性”的分支,与通常使用分支的情形不同,因为它们会长期存在并随着整个软件的演进不断变化,而不是实现某些 feature 后就并入主分支(master)。各个永久分支的差异并不大,如何管理各个分支的公共部分(common part)成为一个重要问题。

 

我们首先给出满足这一需求的方案,然后指明对于遗留的、已经“污染”的分支结构如何重组为新方案。


最合理的分支结构应该是这样的,选取 master 或某个分支作为共同部分的代表,也就是说所有对共同部分的更改都切换到这个分支下进行;然后各个永久分支只改动自己特殊的部分,并不断 rebase 到这个共同分支的顶端(head),以各自更新共同部分。如下图。

           H--I customB
          /
          | E---F---G customA
          |/
  A---B---C---D  master

经过 rebase 后,变为:

               H'--I' customB
              /
              | E'---F'---G' customA
              |/
  A---B---C---D  master

这样,共同部分的更改就并入了各个永久分支,而原分支的更改不会受到影响。


那么,对于已存在的混乱的分支,如何调整为上述结构呢?所谓“混乱”是指某些对公共部分的更改掺杂在了各个分支的更改中。此种情况可按如下步骤处理。

(1) 选取最能囊括当前公共部分的某次提交(commit),如分支前的最后一次提交;或者,如果某分支包括了对公共部分的大部分更改,它有关公共部分的最后一次提交也可作为选择。按如下命令检出(checkout)该次提交,并从此处建立新的分支“common”(或其他名称)。

  $ git checkout <HashID>

  $ git branch common

(2) 查看各个分支记录,将对公共部分的更改抽取出来并入 common 分支。下面命令使用 cherry-pick 将 master 分支倒数第2次和最新的提交(倒数第0次)并入了 common 分支。

  $ git checkout common

  $ git cherry-pick -x master~2

  $ git cherry-pick -x master

较糟糕的情况是,对公共部分的更改并没有隔离在某几次提交中,而是与其他本地更改相互混杂(这也建议我们提交时尽量把相关更改放在一起),那么额外引入的更改在 rebase 操作时就可能与其他分支的更改冲突,可参照第5步处理。

(3) 与此同时,除了按提交(commit)并入更改,还可以文件为单位。下述命令从 master 分支的最新状态中并入了若干文件(注意当前处于 common 分支),然后进行提交覆盖掉原有 common 分支的相应文件。

  $ git checkout master <FileName1, FileName2, ...>
  $ git commit -am "MessageContent"

这种方法很实用,因为所谓公共部分就是若干特定文件,我们需要做的就是保持它们的最新状态。上述两种并入更改的方法需根据具体状况和提交历史配合使用,才能使 rebase 时的冲突最少。

(4) 至此,可按照新结构进行 rebase 操作:

  $ git checkout <BranchName>

  $ git rebase common

  $ git push --force

(5) 当 rebase 出现冲突(conflict)时,按照提示,以正常方式编辑冲突文件解决冲突(通常遵从 HEAD 时居多),然后继续即可:

  $ git add .

  $ git rebase --continue

(注意继续时不必指明 rebase 的对象,此时 git 已经有记录)

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页