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"]
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