《走进git时代系列二》 从SVN迁移到GIT教程

本篇文章是走进git时代系列之二,如何迁移到GIT的教程, 不了解GIT的同学可以先看系列一《走进git时代系列一》 你该怎么玩?

本文分为以下几部分内容:


  1. SVN 迁移到 Git 的简单原理
  2. 图文教程从TaoCode SVN 迁移到 YunCode Git
  3. 如何混用SVN+GIT

SVN 迁移到 Git 的简单原理

  1. 初始化本地代码库: git svn clone -s svn-repository-url
  2. 建立分支,切换,提交,合并等纯git操作
  3. 推送到远端Git 仓库中
  4. 当前分支和远程SVN同步: git svn rebase 。 当同步SVN时出现冲突,需要手动修改冲突,git add 添加后继续rebase: git svn rebase --continue
  5. 或者提交到远端的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迁移到GIT教程

  • 使用命令git svn clone -s http://code.taobao.org/svn/QLExpress/ , 为什么要加-s , 因为这个仓库是按照标准的tags、trunk、branches结构划分的,则git svn会将对应的分支、标签识别存放到git的结构中。 如果不加-s,不会将tags、branch按照git的结构进行划分 。

《走进git时代系列二》 从SVN迁移到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 , 示例图如下 :

《走进git时代系列二》 从SVN迁移到GIT教程

  • 这里我们将全部version 都检出,经过几分钟的过程,我们可以看到此目录下同时具备svn和git的一些信息:(注:截图里st=status , br=branch)

《走进git时代系列二》 从SVN迁移到GIT教程

  • SVN的信息:

《走进git时代系列二》 从SVN迁移到GIT教程

  • 通过git show-ref 可以看到有master这个本地分支,同时有remote 分支trunk , 1.4.1, 2.1.0 等, 通过Git Version 发现trunk 和 Master分支的版本是一样的, 其他几个分支和SVN客户端branches 目录下的结构是一样的。 说明 git svn 将svn的主干和其他分支 转换为了git的 master 和其他branch 。

《走进git时代系列二》 从SVN迁移到GIT教程

  • 假如你的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时代系列二》 从SVN迁移到GIT教程

  • 这时我们就需要一个真正远程的Git 仓库了, 我们使用https://code.aliyun.com 来创建。 首先使用阿里云账户登录code.aliyun.com , 然后在左侧导航内“个人资料设置” --> “SSH 秘钥” 这里添加一个我本地的公钥,本地公私钥 通过 ssh-keygen 命令 一路回车后创建, 然后将~/.ssh/id_rsa.pub的内容粘贴到下图中:

《走进git时代系列二》 从SVN迁移到GIT教程


《走进git时代系列二》 从SVN迁移到GIT教程

  • 现在回到网址首页,创建一个同名为QLExpress 的开源代码库:

《走进git时代系列二》 从SVN迁移到GIT教程

  • 先在我本地做git 的基本全局设置:
git config --global user.name "tangrong.lx"
git config --global user.email "tangrong.lx@taobao.com"
  • 可以看到这是一个空的git代码库:

《走进git时代系列二》 从SVN迁移到GIT教程

  • 在本地的仓库中,增加远程git remote 地址:git remote add origin git@code.aliyun.com:tangrong111/QLExpress.git , 这些命令在云code 中创建代码库后页面里有提示,可以直接复制,当然我这个是从svn 倒过来的代码库,只需要这一个远程地址即可,不需要git 初始化之类的操作:

《走进git时代系列二》 从SVN迁移到GIT教程

  • 这时,我们通过git status 查看一下,避免本地有其他不小心的修改, 然后再执行 git push origin --all , 就可以鉴证这伟大的时刻了:

《走进git时代系列二》 从SVN迁移到GIT教程

  • 同样通过git log 可以看到每一个commit 都有记录 对应的svn版本地址, 而且svn的 commit log 也被转换为了 git的commit log, 是不是很神奇。 这时,我们刷新一下https://code.aliyun.com/tangrong111/QLExpress 这个页面,代码库已经被推送上来,并记录了大小,分支,提交次数等信息:

《走进git时代系列二》 从SVN迁移到GIT教程

  • 看下文件列表:

《走进git时代系列二》 从SVN迁移到GIT教程

  • 最后看一下commit 记录, 可以查看每个分支的,每个记录都有,是不是很帅! 从此就可以快乐的在yuncode上玩耍了!

《走进git时代系列二》 从SVN迁移到GIT教程


如何混用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最佳实践》 吧 !
上一篇:阿里云成为MariaDB基金会白金会员 全球唯一入选云计算公司


下一篇:抢占云安全管理高地 启明星辰先发云SOC