坑死人不偿命,Svn 迁移到 Git

用git的人非常鄙视用svn的。因为要不断的开分支。而且也没有本地的分支这个概念。

但是git 作为一项技术,是一定可以被svn替代的。当然替代的方法是否繁琐另当别论,但一定是能被替代。svn同样也能被git替代。大概所有的技术都是一样。都
能相互替代,只是你要为替代本身花费多长时间。

git作为一种同步工具好用吗?其实真不好用。我梦想的工具一定是可以帮我自动完成merge过程的,永远不用开分支,永远不用告诉我链表头在哪里,以及怎么rese
t, 什么时候rebase, 什么时候打tag.
一个工具让使用者一直在思考,那一定不是好工具。我那锤子砸钉子的时候也没有先按几个按钮。当然svn也不是啥好工具。

所以本文的观点是站在我们开发的场景中从一种不好用的工具向着另外一种不好用的工具迁移。如同砸钉子的时候,始终没有找到锤子,只找到了瑞士军刀和扳手。没办法还是要
砸。

svn 迁移到git上遇到非常多的坑。大家要是开发任务紧急,就等不急的时候再迁移吧。

这里也不在意你到底使用的gerrit还是gitlab还是github. 反正都不好迁移。

一般使用的命令

1
2

git svn clone [某分支] --authors-file=users.txt --no-metadata -s (这里的分支是/trunk的上一层)

另外还可以是:

1
2

git svn clone -r383874:HEAD [你的分支] --authors-file=users.txt --no-metadata --trunk=trunk --tags=milestones --branches=branches

第二条命令是带上版本号的。也可以指定什么分支会变成git的trunk,什么分支会变成git的tag等等。
这里的users.txt内容是:
[svn的名字] = [git上的名字] <[git上的email]>
例如:
aa=bb[email protected]
tt=ee[email protected]
细数一下我自己遇到的问题:

1. ** Can’t locate Term/ReadKey.pm in @INC ** 。 不要听网上说的装什么cpan,
也不要装什么其他的软件。直接执行 svn co [一个分支]。 输入以下自己的用户名密码,然后这个问题就不存在了。

1.1 如果输入密码后,还是不行。 删除这个文件 $HOME/.subversion/auth/svn.simple/* 。 然后再 svn co , 再
git svn clone.
2. ** Do not be alarmed at the above message git-svn is just searching
aggressively for old history. ** 遇到这个提示…这个提示是吓唬你的.

3. ** Author: xx not defined in users.txt file **
这是你的users.txt里面没有某些用户。可能这些用户过于久远,你忘记加入了。

4.系统文件没有找到条目。会有下面的错误:

1
2
3
4
5
6

Initializing parent: refs/remotes/origin/trunk@22086
W: Ignoring error from SVN, path probably does not exist: (160013): 文件系统没有条目: 找不到路径 “/xxx/ooo/101”: 额外错误:: File not found: revision 101, path '/txx/slsl/'
W: Do not be alarmed at the above message git-svn is just searching aggressively for old history.
This may take a while on large repositories

这说有些 svn 版本信息太古老了。实在没有找到对应的diff啥的。也可能被svn管理员早就删除了。所以执行 git svn clone的时候最好带上
-r[A version]:[B version]

1
2

git svn clone -r20202:HEAD [某分支] --authors-file=users.txt --no-metadata -s

5. ** Use of uninitialized value $u in substitution (s///) ** 某些git
svn版本代码写的搓。只好手工改代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

vi /usr/lib/perl5/vendor_perl/5.14/Git/SVN.pm
修改
$u =~ s!^\Q$url\E(/|$)!! or die
"$refname: '$url' not found in '$u'\n";

改成:
if(!$u) {
$u = $pathname;
}else {
$u =~ s!^\Q$url\E(/|$)!! or die
"$refname: '$url' not found in '$u'\n";
}
然后重新运行。

6. git svn clone 结束后, 执行一下 git branch -a, 发现没有一些之前开的分支。例如我们的milestone分支都叫
/milestoneXXX. 是之前git svn clone的命令的问题。 应该改为:

1
2

git svn clone -r383874:HEAD [你的分支] --authors-file=users.txt --no-metadata --trunk=trunk --tags=milestones --branches=branches

另外 git TAG和 svn开一个tag的性质不是很一致。 git tag依附于某一个commit. 而且是不变化的,从这个点开出来的所有分支,都从属于这
个TAG。svn的tag就是开了分支,可以从这个分支随意提交代码。从svn的这个TAG开出来的所有分支和这个svn TAG毛关系都没有。

好吧。说了这么多,其实我们项目就像钉子,而svn/git都不是锤子。虽然是钉子,但是钉子数目很多。遇到以上坑的,看到这篇文章希望能很快的跳过坑去~~