本篇文章是走进git时代系列之二,如何迁移到GIT的教程, 不了解GIT的同学可以先看系列一《走进git时代系列一》 你该怎么玩?
本文分为以下几部分内容:
- SVN 迁移到 Git 的简单原理
- 图文教程从TaoCode SVN 迁移到 YunCode Git
- 如何混用SVN+GIT
SVN 迁移到 Git 的简单原理
- 本文所涉及的工具只有一个 git-svn , 包含在1.7.1以上的git客户端版本内, 该工具详细介绍见: https://www.kernel.org/pub/software/scm/git/docs/git-svn.html
- 那么, 有了这个工具, svn to git 就变的没那么复杂了, 基本的思路如下:
- 初始化本地代码库:
git svn clone -s svn-repository-url
- 建立分支,切换,提交,合并等纯git操作
- 推送到远端Git 仓库中
- 当前分支和远程SVN同步:
git svn rebase
。 当同步SVN时出现冲突,需要手动修改冲突,git add 添加后继续rebase:git svn rebase --continue
- 或者提交到远端的SVN仓库中,假如你本地是git , 远端是SVN,
git svn dcommit
- svn和git的工作原理毕竟不同,git对代码提交的非线性特性在svn中难以再现,如果使用了git-merge或者git-pull,再提交到svn,相关分支上的提交历史有可能无法体现在svn上。从svn的使用者的角度,无法辨别这是一个提交还是一次合并,所以在和svn协作过程中,尽量让代码库保持线性。
-
尽量保持git代码库的线性特征。比如在new_branch分支中,先和master做rebase,再合并到master分支中:
- git rebase master
- git checkout master
- git merge new_branch
- 然后在master上做dcommit,就可以在svn代码库中看到完整的提交历史
图文教程从TaoCode SVN 迁移到 YunCode Git
- 下面进入正题部分, 我将演示如何从一个SVN仓库迁移到GIT仓库中, 演示过程中的代码库均为开源代码,大家可以直接下载来练习:
- SVN 地址为淘蝌蚪开源社区中的一个推荐仓库: http://code.taobao.org/svn/QLExpress/
- 首先我们看一下本地的SVN和GIT客户端版本:
- 使用命令
git svn clone -s http://code.taobao.org/svn/QLExpress/
, 为什么要加-s , 因为这个仓库是按照标准的tags、trunk、branches结构划分的,则git svn会将对应的分支、标签识别存放到git的结构中。 如果不加-s,不会将tags、branch按照git的结构进行划分 。
- 从图中可以看到, git svn 是将每次svn 的提交计算出来写入git的每一个commit version, 所以, 如果你的SVN代码库Version 非常多, 这个过程会很慢, 那么,我们可以通过
git svn clone -s -r$REVNUMBER:HEAD http://svnurl/yourrepo
来检出最后的几个版本。 举个栗子: - 先通过
svn log http://svnurl/yourrepo| tail -4 | head -1
获取当前仓库的起始Version,假设是r10, 那我们如果要检出所有版本,命令为git svn clone -s -r10:HEAD http://svnurl/yourrepo
- 再通过
svn info http://svnurl/yourrepo | grep Revision
获取最新的SVN版本号,假设我们要最后10个版本,则命令为git svn clone -s --prefix=svn/ -r90:HEAD http://svnurl/yourrepo
, 示例图如下 :
- 这里我们将全部version 都检出,经过几分钟的过程,我们可以看到此目录下同时具备svn和git的一些信息:(注:截图里st=status , br=branch)
- SVN的信息:
- 通过
git show-ref
可以看到有master这个本地分支,同时有remote 分支trunk , 1.4.1, 2.1.0 等, 通过Git Version 发现trunk 和 Master分支的版本是一样的, 其他几个分支和SVN客户端branches 目录下的结构是一样的。 说明 git svn 将svn的主干和其他分支 转换为了git的 master 和其他branch 。
- 假如你的SVN仓库是非标结构的,也可以用“-T 主干名 -b 分支名 -t 标签名”参数分别指定归类,
- 例1:
git svn clone http://svnurl/yourrepo -T trunk -b branches -t release
这里制定了release是一个标签集。 - 例2:
git svn clone http://svnurl/yourrepo/project1 -T rpm -b branches -t release
这里指定了svn库中的rpm目录是主干、branches目录是分支集,release目录是标签集,而project1下的其他目录会被忽视。 - 这时我们发现有一些remote 分支,不是本地仓库的分支, 我们还没有设置remote, 那就需要执行以下的命令将remote 分支移回本地分支。
cp -Rf .git/refs/remotes/tags/* .git/refs/tags/
rm -Rf .git/refs/remotes/tags
cp -Rf .git/refs/remotes/* .git/refs/heads/
rm -Rf .git/refs/remotes
- 这个示例仓库没有tag ,只有branch ,所以只要把branch 挪到本地即可, 执行后效果如下:
- 这时我们就需要一个真正远程的Git 仓库了, 我们使用https://code.aliyun.com 来创建。 首先使用阿里云账户登录code.aliyun.com , 然后在左侧导航内“个人资料设置” --> “SSH 秘钥” 这里添加一个我本地的公钥,本地公私钥 通过
ssh-keygen
命令 一路回车后创建, 然后将~/.ssh/id_rsa.pub的内容粘贴到下图中:
- 现在回到网址首页,创建一个同名为QLExpress 的开源代码库:
- 先在我本地做git 的基本全局设置:
git config --global user.name "tangrong.lx"
git config --global user.email "tangrong.lx@taobao.com"
- 可以看到这是一个空的git代码库:
- 在本地的仓库中,增加远程git remote 地址:
git remote add origin git@code.aliyun.com:tangrong111/QLExpress.git
, 这些命令在云code 中创建代码库后页面里有提示,可以直接复制,当然我这个是从svn 倒过来的代码库,只需要这一个远程地址即可,不需要git 初始化之类的操作:
- 这时,我们通过
git status
查看一下,避免本地有其他不小心的修改, 然后再执行git push origin --all
, 就可以鉴证这伟大的时刻了:
- 同样通过
git log
可以看到每一个commit 都有记录 对应的svn版本地址, 而且svn的 commit log 也被转换为了 git的commit log, 是不是很神奇。 这时,我们刷新一下https://code.aliyun.com/tangrong111/QLExpress 这个页面,代码库已经被推送上来,并记录了大小,分支,提交次数等信息:
- 看下文件列表:
- 最后看一下commit 记录, 可以查看每个分支的,每个记录都有,是不是很帅! 从此就可以快乐的在yuncode上玩耍了!
如何混用SVN+GIT
- 最后我介绍一下, 如何在本地使用git, 同时远程有git和svn并存的情况,以及没有远程Git只有远程SVN,但你本地又想用Git的情况(这种属于公司内只有SVN,你又是个git死忠,当然你可以推荐你们公司使用yuncode ,也有saas版可以单独部署的哦)
- 远程Git和SVN都使用,流程如下:
git branch -m svn
git remote add origin git@github.com:yourname/yourrepo.git
git checkout master
那么本地svn分支对应svn的远程仓库,本地master分支对应git的远程仓库
你可以继续创建本地分支进行开发, 当要提交到远程git时,切换到master分支下, 合并你的分支, git push 到git远端上
如果代码要更新到svn上:
git checkout svn
git merge master
git svn dcommit
- 如果没有远程Git仓库, 那么:
修改本地代码后, 通过 git add/commit
提交到本地git库
定期rebase 获取svn, 定期 dcommit 提交到svn库
Just redo this tripple:
git svn fetch
git svn rebase
git svn dcommit 如果要给svn库建分支:
git svn branch xxxxx 如果要给svn打tag :
git svn tag 0.1
- 冲突与解决
假设其他同学也在同时开发,已经提交了新版本到SVN中, 当你git svn dcommit 的时候提示本地文件已经过期
你通过 git svn rebase 获取SVN的最新文件版本, 导致文件出现冲突
不过这个时候SVN的版本信息已经添加到本地的git库里, 通过git log 可以看到
那么,打开冲突文件,修改代码,解决冲突。 执行
git rebase --continue
提示You must edit all merge conflicts and then mark them as resolved using git add 执行 git add xxxx 后,再次执行
git rebase --continue 提示'Applying: xxxxxxxxx'
此时git的版本成功加入到本地版本库, 可以通过git log 查看。
执行 git svn dcommit
把解决后的文件同步到SVN远程库中,到此算是完成一次冲突解决。
写在最后
- 其实, 你如果对svn 的log 不是那么看中, 最简单的就是在 code.aliyun.com 上创建一个git 仓库,然后代码拷贝过去, 从第一个version 开始新的里程 ~~
- 假设你看完这篇文章明白了 怎么从svn 迁移到 git 中, 那么就敬请期待 走进Git 时代的系列三 :
《玩转云Code最佳实践》
吧 !