2010-05-01

Subversion 用户眼中的 Git (9): 单亲 VS 多亲

SVN 和 GIT 对比的系列博文尚有几篇一直放在草稿中,处于构思阶段,今天从故纸堆里检出来(checkout?) 我们在《Subversion 用户眼中的 Git (7): 完全不同的分支和里程碑的实现》中介绍过,Git 和 Svn 的分支实现机制完全的不同,这也直接导致了 SVN 在分支合并中困难重重。尽管在 SVN 1.5 之后,通过 svn:mergeinfo 属性引入了合并追踪机制,但是在特定情况下,合并仍会出现很多困难。 在《SVN 树冲突和目录丢失问题(1)》系列博文中,介绍了帮助我的一个朋友解决SVN树冲突的过程。这实际上在 GIT 中是 “a piece of cake”。你可以用 Git 模拟一下不同分支中文件目录改名引发合并冲突,在Git 中解决的是那么自然和漂亮! 这是为什么呢?因为 SVN 是单亲家庭,而 GIT 是双亲/多亲家庭啊。

SVN 的单亲家庭

在博文《Subversion 用户眼中的 Git (4): 全局版本号和全球版本号》中我们提到过,SVN 的版本号是连续的版本号。每一次新的提交都会版本号+1 ,而无论这个提交是在哪个分支中进行的。我们在《Subversion 用户眼中的 Git (7): 完全不同的分支和里程碑的实现》也提到过,SVN一个提交可以同时修改不同分支的不同文件,因为提交命令可以在 /trunk, /branches, /tags 的上一级目录执行。
  • SVN 的提交是单线索的,每一个提交(最原始的提交0除外)都只有一个单亲节点(版本号小一个的提交节点)
  • SVN 的提交链只有一条,仅从版本号和提交说明,我们无法获得分支图
  • SVN 的分支图在某些工具(如乌龟SVN)可以提供,那是需要对提交内容进行检查,对目录拷贝动作视为分支,对 svn:mergeinfo 的改动视为合并,但这会由于目录管理的灵活性,导致千奇百怪的分支图表
  • SVN 的单亲节点的设计,是SVN分支合并输在起跑线上的唯一原因。也是 SVN 永远无法在 GIT 面前抬头的最重要原因

Git 的双亲/多亲家庭

Git 的提交实际上是按照多亲进行设计的,即一个提交可以包含两个以上的多亲节点,不过一般合并是双分支合并,因此合并节点以双亲居多。
  • 大部分提交实际上只用到了多亲节点中的一个,即大部分提交是对前一个提交的修改
  • 合并操作一般用到两个双亲节点(或者更多),这很自然 合并操作是将两个提交合二为一,因此在新的合并结果的提交后产生的节点会有两个双亲节点。
Git 的提交也没有顺序的要求
  • 不必非要基于最新节点提交,因为作为分布式版本控制系统,你根本不知道是不是有人在你之前进行和提交
  • 你甚至可以先切换(检出)到之前老的提交节点,修改代码再进行提交,提交就形成分支
  • 和其他人的版本库合并,也会形成分支
基于以上的特点,提交之间会形成复杂的提交家族谱系。从一个原始节点开始(甚至多个原始节点),派生出任意多的谱系。
  • 可以用下面的命令查看提交关系图
    • 最简单的命令是:
      $ git log --graph
    • 还可以通过工具 gitk,qgit 等提供图形化的分支显示界面
  • 下面是一个分支关系图示例。其中 A 为顶级节点(最新提交);B 节点是三个多亲节点的合并;后面类似公式一样的东西是 Git 节点的快捷操作符示例。
    G   H   I   J
     \ /     \ /
      D   E   F
       \  |  / \
        \ | /   |
         \|/    |
          B     C
           \   /
            \ /
             A
    
    A =      = A^0
    B = A^   = A^1     = A~1
    C = A^2  = A^2
    D = A^^  = A^1^1   = A~2
    E = B^2  = A^^2
    F = B^3  = A^^3
    G = A^^^ = A^1^1^1 = A~3
    H = D^2  = B^^2    = A^^^2  = A~2^2
    I = F^   = B^3^    = A^^3^
    J = F^2  = B^3^2   = A^^3^2
附:相比 GIT的多亲节点,Hg/Mercurial 是按照双亲设计的,即在 Hg 中一次只能进行两个分支的合并。并且 Hg 提供 hg parents 命令查看节点的双亲。 预告一下,下一个对比的题目是:《Subversion 用户眼中的 Git —— 命令行的人性化设计》。 需要补充一句:抱歉关于版本控制的单亲和双亲的说法,可能会伤害到很多人,因为人类社会家庭分类中的相似概念。特别需要指出的是,这里的单亲双亲的概念和比较并不适合人类社会,因为对于人类社会的不适合的双亲关系,还不如单亲来得简单和直接。
blog comments powered by Disqus