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