第24章 子树合并

    使用子树合并,同样可以实现在一个项目中引用其他项目的数据。但是和子模组方式不同的是,使用子树合并模式,外部的版本库会作为一个目录被整个复制到本版本库中,并且复制到本版本库中的子目录下的数据可以和原版本库数据建立跟踪关联。使用子树合并模式,对源自外部版本库的数据的访问和对本版本库数据的访问没有区别,也可以对其进行本地修改,并且能够以子树合并的方式将外部版本库的新的改动和本地的修改相合并。

    24.1 引入外部版本库

    为演示子树合并至少需要准备两个版本库,一个是将要被作为子目录引入的版本库util.git,另外一个是主版本库main.git。


    $git—git-dir=/path/to/repos/util.git init—bare $git—git-dir=/path/to/repos/main.git init—bare

    在本地检出这两个版本库:


    $cd/path/to/my/workspace $git clone/path/to/repos/util.git $git clone/path/to/repos/main.git

    需要为这两个空版本库添加些数据。非常简单,每个版本库下只创建两个文件:Makefile和version。当执行make命令时显示version文件的内容。对version文件多次提交以建立多个提交历史。别忘了在最后使用git push origin master将版本库推送到远程版本库中。

    Makefile文件示例如下。注意第二行前面的空白是<TAB>字符,而非空格。


    all: @cat version

    在之前尝试的git fetch命令都是获取同一项目的版本库的内容。其实命令git fetch从哪个项目获取数据并没有什么限制,因为Git的版本库不像Subversion那样用一个唯一的UUID标识让Subversion的版本库之间势同水火。当然也可以用git pull来获取其他版本库中的提交,但是那样将把两个项目的文件彻底混杂在一起。对于这个示例来说,因为两个项目具有同样的文件Makefile和version,使用git pull将导致冲突。所以为了将不同项目的版本库引入,并在稍后以子树合并的方式添加到一个子目录中,需要用git fetch命令从其他版本库获取数据,具体操作过程如下。

    (1)为了便于以后对外部版本库的跟踪,在使用git fetch前,先在main版本库中注册远程版本库util.git。


    $cd/path/to/my/workspace/main $git remote add util/path/to/repos/util.git

    (2)查看注册的远程版本库。


    $git remote-v origin/path/to/repos/main.git/(fetch) origin/path/to/repos/main.git/(push) util/path/to/repos/util.git(fetch) util/path/to/repos/util.git(push)

    (3)执行git fetch命令获取util.git版本库的提交。


    $git fetch util

    (4)查看分支,包括远程分支。


    $git branch-a *master remotes/origin/master remotes/util/master

    在不同的分支:master分支和remotes/util/master分支中,文件version的内容并不相同,因为来自不同的上游版本库。

    在master分支中执行make命令,显示的是main.git版本库中version文件的内容。


    $make main v2010.1

    从util/master远程分支创建一个本地分支util-branch,并切换分支。


    $git checkout-b util-branch util/master Branch util-branch set up to track remote branch master from util. Switched to a new branch 'util-branch'

    执行make命令,显示的是util.git版本库中version文件的内容。


    $make util v3.0

    像这样在main.git中引入util.git显然不能满足需要,因为在main.git的本地克隆版本库中,master分支访问不到只有在util-branch分支中才出现的util版本库数据。这就需要做进一步的工作,将两个版本库的内容合并到一个分支中。即将util-branch分支的数据作为子目录加入到master分支中。