26.3 多样的git-svn克隆模式

    在前面的git-svn示例中,使用git svn clone命令完成对远程版本库的克隆,实际上git svn clone相当于两条命令,即:


    git svn clone=git svn init+git svn fetch

    命令git svn init只完成两个工作。一是在本地建立一个空的Git版本库,另外是修改.git/config文件,在其中建立Subversion和Git之间的分支映射关系。在实际使用中,我更喜欢使用git svn init命令,因为这样可以对Subversion和Git的分支映射进行手工修改。该命令的用法是:


    用法:git svn init[options]<subversion-url>[local-dir] 可选的主要参数有: —stdlayout,-s —trunk,-T<arg> —branches,—b=s@ —tags,—t=s@ —config-dir<arg> —ignore-paths<arg> —prefix<arg> —username<arg>

    其中—username参数用于设定远程Subversion服务器认证时提供的用户名。参数—prefix用于设置在Git的refs/remotes下保存引用时使用的前缀。参数—ignore-paths后面跟一个正则表达式定义忽略的文件列表,这些文件将不予克隆。

    最常用的参数是-s。该参数和前面演示的git clone命令中的一样,即使用标准的分支/里程碑部署方式克隆Subversion版本库。Subversion约定俗成使用trunk目录跟踪主线的开发,使用branches目录保存各个分支,使用tags目录来记录里程碑。

    即命令:


    $git svn init-s file:///path/to/svn/repos/demo

    和下面的命令等效:


    $git svn init-T trunk-b branches-t tags file:///path/to/svn/repos/demo

    有的Subversion版本库的分支可能分散于不同的目录下,例如有的位于branches目录,有的位于sandbox目录,可以使用下面的命令:


    $git svn init-T trunk-b branches-b sandbox-t tags file:///path/to/svn/repos/demo git-svn-test Initialized empty Git repository in/path/to/my/workspace/git-svn-test/.git/

    查看本地克隆版本库的配置文件:


    $cat git-svn-test/.git/config [core] repositoryformatversion=0 filemode=true bare=false logallrefupdates=true [svn-remote "svn"] url=file:///path/to/svn/repos/demo fetch=trunk:refs/remotes/trunk branches=branches/:refs/remotes/ branches=sandbox/:refs/remotes/ tags=tags/:refs/remotes/tags/

    可以看到在[svn-remote "svn"]小节中包含了两条branches配置,这就会实现将Subversion分散于不同目录的分支都克隆出来。如果担心Subversion的branches目录和sandbox目录下出现同名的分支,从而导致在Git库的refs/remotes/下造成覆盖,可以在版本库尚未执行git svn fetch之前编辑.git/config文件,避免可能出现的覆盖。例如编辑后的[svn-remote "svn"]配置小节:


    [svn-remote "svn"] url=file:///path/to/svn/repos/demo fetch=trunk:refs/remotes/trunk branches=branches/:refs/remotes/branches/ branches=sandbox/:refs/remotes/sandbox/ tags=tags/:refs/remotes/tags/

    如果项目的分支或里程碑非常多,也可以修改[svn-remote "svn"]配置小节中的版本号通配符,使得只获取部分分支或里程碑。例如下面的配置小节:


    [svn-remote "svn"] url=http://server.org/svn fetch=trunk/src:refs/remotes/trunk branches=branches/{red,green}/src:refs/remotes/branches/* tags=tags/{1.0,2.0}/src:refs/remotes/tags/*

    如果只关心Subversion的某个分支甚至某个子目录,而不关心其他分支或目录,那就更简单了,不带参数地执行git svn init针对Subversion的某个具体路径执行初始化就可以了。


    $git svn init file:///path/to/svn/repos/demo/trunk

    有的情况下,版本库太大,而且对历史不感兴趣,可以只克隆最近的部分提交。这时可以通过git svn fetch命令的-r参数实现部分提交的克隆。


    $git svn init file:///path/to/svn/repos/demo/trunk git-svn-test Initialized empty Git repository in/path/to/my/workspace/git-svn-test/.git/ $cd git-svn-test $git svn fetch-r 6:HEAD A README r6=053b641b7edd2f1a59a007f27862d98fe5bcda57(refs/remotes/git-svn) M README r7=75c17ea61d8527334855a51e65ac98c981f545d7(refs/remotes/git-svn) Checked out HEAD: file:///path/to/svn/repos/demo/trunk r7

    当然也可以使用git svn clone命令实现部分克隆:


    $git svn clone-r 6:HEAD\ file:///path/to/svn/repos/demo/trunk git-svn-test Initialized empty Git repository in/path/to/my/workspace/git-svn-test/.git/ A README r6=053b641b7edd2f1a59a007f27862d98fe5bcda57(refs/remotes/git-svn) M README r7=75c17ea61d8527334855a51e65ac98c981f545d7(refs/remotes/git-svn) Checked out HEAD: file:///path/to/svn/repos/demo/trunk r7