SVN迁移到git

如果不需要 SVN 仓库的历史提交记录,则只需要将最新的代码下载到本地,然后将相关的代码 push 到 git 服务器仓库即可. 这里重点说明如何同时将SVN的提交记录迁移到 git 仓库.

1. 创建用户映射

在 Subversion,每个提交者在都在主机上有一个用户名,记录在提交信息中. 比如 blame 的输出以及 git svn log。如果想让这条信息更好的映射到 Git 作者数据里,则需要从 SVN 用户名到 Git 作者的一个映射关系建立一个叫做 user.txt 的文件,用如下格式表示映射关系:

  1. zhangsan = Zhang San <zhangsan@testin.cn>
  2. lixiaoming = Li Xiaoming <lixiaoming@testin.cn>

通过该命令可以获得 SVN 作者的列表:

  1. svn log ^/ --xml | grep -P "^<author" | sort -u | perl -pe 's/<author>(.*?)<\/author>/$1 = /' > users.txt

2. 获取SVN的仓库到本地

通过 git svn clone 命令可以把整个 SVN 仓库导入到一个本地的 git 仓库中, 但这样导入的代码提交历史很糟糕, 需要做一些处理. 在 clone 后面添加 --no-metadata 来阻止 git svn 包含那些 SVN 的附加信息。同时为了获得更精确的提交者 ID 和邮箱, 添加 --authors-file 参数

  1. git svn clone svn://xxxx --authors-file=users.txt --no-metadata -s my_project

现在 my_project 目录下导入的 Subversion 应该比原来整洁多了. 原来的 commit 看上去是这样:

  1. commit 37efa680e8473b615de980fa935944215428a35a
  2. Author: zhangsan <zhangsan@4c93b258-373f-11de-be05-5f7a86268029>
  3. Date: Sun May 3 00:12:22 2009 +0000
  4. fixed install - go to trunk
  5. git-svn-id: https://my-project.googlecode.com/svn/trunk@94 4c93b258-373f-11de-
  6. be05-5f7a86268029

现在是这样:

  1. commit 03a8785f44c8ea5cdb0e8834b7c8e6c469be2ff2
  2. Author: Zhang San <zhangsan@testin.cn>
  3. Date: Sun May 3 00:12:22 2009 +0000
  4. fixed install - go to trunk

不仅作者一项干净了不少,git-svn-id 也就此消失了.

3. 转化成Git的仓库格式(tags 和 branches)

SVN 中是常见的 “trunk/branches/tags” 目录结构,所以需要将 SVN 的 branches 和标签 tags 生成对应的git的分支和标签.
处理branches:

  1. git for-each-ref refs/remotes | cut -d / -f 3- | grep -v @ | while read branchname; do git branch "$branchname" "refs/remotes/$branchname"; git branch -r -d "$branchname"; done

处理tags:

  1. git for-each-ref refs/remotes/tags | cut -d / -f 4- | grep -v @ | while read tagname; do git tag "$tagname" "tags/$tagname"; git branch -r -d "tags/$tagname"; done

由于这个转化转化会将及历史上的 branches 和 tags 也都生成一个 Git 的分支和标签,所以还是得清理下你认为不用的分支和标,可能包括:

  • Subversion 历史上错误的 tags
  • Subversion 历史上临时的 branches
  • 冗余的 trunk 分支(其实跟转化后的 Git master 分支一样)

4. 在GitLab上创建Git仓库

为 GitLab 上为 SVN 仓库创建对应的 Git 仓库,会生成如下的仓库地址:

  1. git@192.168.1.93:crash-sdk/android.git
  2. http://prj.testin.cn:8200/crash-sdk/android.git

建议使用第一种地址,它通过SSH协议进行代码传输. 添加本地的SSH公钥到 GitLab 服务器之后,便可以省去频繁的用户名/密码等的输入.

生成SSH公钥
在终端中敲下面的命令,第一步会生成一对私钥和公钥,分别存在 ~/.ssh/id_rsa和~/.ssh/id_rsa.pub中. 第二步查看公钥字符串. 在生成key的过程,建议一直回车,不设置任何密码等信息,以防在和 Git 服务器仓库交互过程中,总是提示输入密码等信息.

  1. ssh-keygen -t rsa -C "zhangsan@testin.cn"
  2. cat ~/.ssh/id_rsa.pub

保存sshkey到gitlab
在面板上依次点击Profile Settings –> SSH Keys –> Add SSH Keys. 然后把上一步中的id_rsa.pub中的内容拷贝出来粘贴到输入框中,保存.

5. 添加远程git仓库

在本地,将上面创建的仓库服务器添加为远程服务器并且向它推送。下面是新增远程服务器的例子:

  1. git remote add origin git@192.168.1.93:crash-sdk/android.git

6. 提交代码到git仓库

通过以下命令将本地代码提交到远程git仓库:

  1. git push origin master

Git 基础

这里讲解Git的基本使用,一些高级的使用方法,请参考官方文档。

1. Git 安装

  • 在类 Linux 系统下,有下面两种方法
  1. yum install git-core
  2. apt-get install git
  • 在 Mac 上安装 Git 有两种方式。最容易的当属使用图形化的 Git 安装工具,下载地址在:
  1. http://sourceforge.net/projects/git-osx-installer/

另一种是通过 MacPorts (http://www.macports.org) 安装。如果已经装好了 MacPorts,用下面的命令安装 Git:

  1. sudo port install git-core +svn +doc +bash_completion +gitweb
  • 在 Windows 上安装Git,可以使用一个叫做 msysGit 项目提供的安装包. exe按照文件下载地址:
  1. http://msysgit.github.com/

该工具自带 ssh 客户端,还有一个图形界面的 Git 项目管理工具。
另外还有很多集成Git的工具,可以根据自己的需要使. 但是建议 Windows 用户, 在 msysGit 提供的 Unix 风格的 shell 来运行 Git.

2. Git使用前的配置

Git 通过 git config 命令来配置或读取相应的工作环境变量,对应有三个不同作用域的配置文件.

  • /etc/gitconfig 文件:系统中对所有用户都普遍适用的配置。若使用 git config 时用 --system 选项,读写的就是这个文件。
  • ~/.gitconfig 文件:用户目录下的配置文件只适用于该用户。若使用 git config 时用 --global 选项,读写的就是这个文件。
  • 当前项目的 Git 目录中的配置文件(也就是工作目录中的 .git/config 文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以 .git/config 里的配置会覆盖 /etc/gitconfig 中的同名变量。

配置开发者信息
第一个要配置的是你个人的用户名称和电子邮件地址。这两条配置很重要,每次 Git 提交时都会引用这两条信息,说明是谁提交了更新,所以会随更新内容一起被永久纳入历史记录:

  1. git config --global user.name "Zhang San"
  2. git config --global user.email zhangsan@testin.cn

建议使用 --global 选项,这样,以后你所有的项目都会默认使用这里配置的用户信息。

Git命令别名
为了方面使用Git命令,建议设置Git别名,比如:

  1. git config --global alias.co checkout
  2. git config --global alias.br branch
  3. git config --global alias.ci commit
  4. git config --global alias.st status

配置忽略文件
在开发过程中,可能会产生一些临时文件,这些文件不需要提交到代码库中进行管理,这时就需要通过添加.gitignore文件来配置忽略哪些文件. 文件匹配规则, 这里不做详述.

其他配置
在开发过程中,经常需要做diff和merge操作,可以配置相应的工具来完成,比如使用P4Merge工具。当然Git也有默认工具来完成这个工作。

3. 常用Git命令

这里重点列举自己在项目中常用的Git命令,还有很多实用的命令, 可以根据自己的喜好使用, 请参考官方文档。

  • git fetch
    该命令用来拉取远程分支到本地,比如拉取远程仓库的release-2.0.6
  1. git fetch origin release-2.0.6:release-2.0.6

冒号后面的release-2.0.6是指拉取远程分支到本地后的分支名称,可以随意命名,但是建议保持和远程仓库同名。

  • git checkout
    该命令主要用来切换分支, 比如
  1. git checkout release-2.0.6

除此之外,还会经常用该命令来撤销对文件的修改,比如

  1. git checkout -- test.txt
  • git branch
    该命令用来查看本地或远程分支,也可以用来创建本地分支
  1. $ git branch
  2. master
  3. release-2.0.2
  4. release-2.0.3
  5. release-2.0.4
  6. task/R15081
  7. task/R15099
  1. $ git branch -r
  2. origin/HEAD -> origin/master
  3. origin/master
  4. origin/release-2.0.2
  5. origin/release-2.0.3
  6. origin/release-2.0.4
  1. $ git branch task/test
  2. $ git branch
  3. master
  4. release-2.0.2
  5. release-2.0.3
  6. release-2.0.4
  7. task/R15081
  8. task/R15099
  9. task/test
  • git diff
    该命令主要用来查看文件修改内容
  • git add
    该命令将当前更改或者新增的文件加入到Git的索引中,加入到Git的索引中就表示记入了版本历史中,这也是提交之前所需要执行的一步.
  • git status
    该命令用来查看本地git仓库状态, 比如
  1. $ git status
  2. On branch master
  3. Changes not staged for commit:
  4. (use "git add <file>..." to update what will be committed)
  5. (use "git checkout -- <file>..." to discard changes in working directory)
  6. modified: libs/testinagent_debug.jar
  7. modified: src/com/testin/apm/demo/MainActivity.java
  8. Untracked files:
  9. (use "git add <file>..." to include in what will be committed)
  10. log.log
  • git commit
    该命令提交当前工作空间的修改内容, 提交的时候必须用-m来输入一条提交信息,该功能类似于SVN的commit, 比如
  1. git commit -m 'Just for test'
  • git log
    该命令用来查看历史提交记录, 比如
  1. $ git log -n 2
  2. commit 6e7e855f025c9f64be687d1a893da306bf6b321d
  3. Author: Zhang San <zhangsan@testin.cn>
  4. Date: Wed Sep 9 15:24:42 2015 +0800
  5. R17065: Keep Breadcrumb function in thread-safe mode
  6. commit 996bba84015759ac70b83f72b308ff185bf9ee58
  7. Author: Zhang San <zhangsan@testin.cn>
  8. Date: Wed Sep 9 12:11:19 2015 +0800
  9. R17706: Remove the network interface
  10. Just comment the code not remove since we may reuse it in the future
  • git push
    该命令将本地commit的代码更新到远程版本库中, 比如将本地的release-2.0.6分支的代码更新到远程origin仓库.
  1. $ git push origin release-2.0.6
  • git pull
    该命令从远程服务器仓库将代码更新到本地,比如将origin服务起仓库的代码更新到本地的master主分支,该功能类似于SVN的update
  1. git pull origin master
  • git merge
    该命令将指定分支与当前分支进行合并, 比如将task/test分支合并到当前所在的release-2.0.6分支
  1. $ git merge task/test
  • git rebase -i
    该命令可以用来合并历史提交并重写comments, 比如将最后两次的提交合并一次
  1. $ git log -n 3
  2. commit e81df4372c2a385fe9ce6b2c32f59d4493340ce2
  3. Author: Zhang San <zhangsan@testin.cn>
  4. Date: Tue Sep 15 13:57:19 2015 +0800
  5. test
  6. commit 53d2078dd0e19f9441f331a5cfb2893e766a40ab
  7. Author: Zhang San <zhangsan@testin.cn>
  8. Date: Tue Sep 15 13:56:34 2015 +0800
  9. Add the interface to check app update
  10. commit 3b46a6ec03ff145e7fa767d9aded0539029eeb17
  11. Merge: 43044aa 6e7e855
  12. Author: Zhang San <zhangsan@testin.cn>
  13. Date: Fri Sep 11 11:03:15 2015 +0800
  14. Merge branch 'release-2.0.7' into 'master'
  15. Release 2.0.7
  16. See merge request !7
  1. $ git rebase -i 3b46a6ec03ff145e7fa767d9aded0539029eeb17
  1. $ git log -n 3
  2. commit d139ac4e822aab5de4e09801cbf7f3c9de124c76
  3. Author: Zhang San <zhangsan@testin.cn>
  4. Date: Tue Sep 15 13:56:34 2015 +0800
  5. Add the interface to check app update
  6. commit 3b46a6ec03ff145e7fa767d9aded0539029eeb17
  7. Merge: 43044aa 6e7e855
  8. Author: Zhang San <zhangsan@testin.cn>
  9. Date: Fri Sep 11 11:03:15 2015 +0800
  10. Merge branch 'release-2.0.7' into 'master'
  11. Release 2.0.7
  12. See merge request !7
  13. commit 6e7e855f025c9f64be687d1a893da306bf6b321d
  14. Author: Zhang San <zhangsan@testin.cn>
  15. Date: Wed Sep 9 15:24:42 2015 +0800
  16. R17065: Keep Breadcrumb function in thread-safe mode

Code Review

使用 review board 和 Git 可以很方便的自动提交 code review。这里需要使用一个工具 RBtool。RBtool 的安装这里不做详述,参看官方文档

安装完RBtool后,可能会遇到下面的错误,参考http://www.111cn.net/phper/python/64627.htm

  1. UnicodeDecodeError: 'ascii' codec can't decode byte 0xe0 in position 0: ordinal not in range(128)

1. 配置

  • 在 Review Board 针对 GitLab 上面的仓库, 创建对应的 review 仓库, 这里由管理员操作, 不做详述
  • 在本地项目根目录下面, 建立 .reviewboardrc 文件。在文件中输入 review board 网址和 review 仓库名称, 这样做是为了避免每一次提交review都需要输入 url 和 repo.
  1. REVIEWBOARD_URL = 'http://prj.testin.cn:9000/'
  2. REPOSITORY = 'APM-Android-Git'

2. 提交review

RBtool提交 review 主要使用 rbt post 命令来完成, 它有很多参数, 可以应对各种情况, 这里只做简单演示. 需要强调的是, RBtool 工具的本质就是将一个 diff 文件提交到 review board 上面展示, 参数的不同就是为了形成不同的 diff 文件.

  • 首次提交review
    一般建议在独立的 task 分支进行开发, 在合并到 release 或者 master 等分支之前, 需要提交 review.
  1. rbt post --tracking-branch=release-2.0.6

上面的命令将当前分支(task/test)相对于release-2.0.6分支的diff提交review.

  • 重复提交review
    在 review 的过程, 难免会根据 review 提出的问题进行修改. 在修改完成以后, 需要再次提交 review, 这时需要提交到和之前同一个 review 地址. 假如之前提交的 review 号为737, 并且提交历史如下
  1. $ git log -n 2
  2. commit d139ac4e822aab5de4e09801cbf7f3c9de124c76
  3. Author: Zhang San <zhangsan@testin.cn>
  4. Date: Tue Sep 15 13:56:34 2015 +0800
  5. Add the interface to check app update
  6. commit 6e7e855f025c9f64be687d1a893da306bf6b321d
  7. Author: Zhang San <zhangsan@testin.cn>
  8. Date: Wed Sep 9 15:24:42 2015 +0800
  9. R17065: Keep Breadcrumb function in thread-safe mode

即上一次 review 对应的提交是 6e7e855f025c9f64be687d1a893da306bf6b321d, 本次根据 review 修改后的提交为 d139ac4e822aab5de4e09801cbf7f3c9de124c76. 如此, 提交 review 的命令应该为:

  1. rbt post -r 737 --parent=6e7e855f025c9f64be687d1a893da306bf6b321d

3. Review 流程

下面说明 Review 的整个流程, 从发布 review 到 关闭 review的整个过程.

  • 发布review
    通过 rbt post 命令之后, 会输出两个url地址, 第一个就是 review 发布的地址, 第二个地址可以查看本次 diff 文件内容.
  1. $ rbt post --tracking-branch=release-2.0.5
  2. Review request #745 posted.
  3. http://prj.testin.cn:9000/r/745/
  4. http://prj.testin.cn:9000/r/745/diff/

打开 review 发布的地址, 添加 reviewer 后, 点击 Publish 即可发布

    • Reviewer 提交 comments
      Comments 主要针对那些非代码缺陷的地方提出问题或者建议, 可以包括:
      1) 可读性不好
      2) 命名不规范
      3) 函数长度太长
      4) 缺少注释或注释不规范
      5) 代码重复, 应该提取为公共类或者公共方法
      6) 代码扩展性不好
      7) 直接提问, 为什么这样设计? 这个接口用来做什么? 等等

    • Reviewer 提交 issues
      Issues 主要针对代码的缺陷或者逻辑错误, 包括:
      1) 明显的代码逻辑错误
      2) 垃圾代码, 调试代码或者 unused 代码
      3) 线程安全问题
      4) 数据一致性问题
      5) 缺少相应的错误或异常处理
      6) 算法或代码性能问题
      7) 内存溢出, 空指针, 死循环等等

    • 作者处理 comments
      由于 comments 指向的都是非代码缺陷, 不影响代码功能, 故作者可以不做回复或处理. 但是强烈建议对所有的 comments 都做出回复, 即使作者认为不需要修改, 也需要给出 reviewer 不做处理的理由.

    • 作者处理 issues
      对于所有的 issues, 作者必须给出处理. 如果认为是一个 issue, 则修改代码进行 fix. 如果认为提出者的理解有问题, 该issue并不是一个真正的 issue, 则需要给出充足的理由和解释. 注意: 所有的 issue必须有提出者关闭, 作者不得自行关闭. 作者修改代码后, 需要按照前面给出的方法, 再一次发布 review.

    • Ship review
      在所有的 issues 都被提出者关闭, 并且没有进一步的问题时, 由项目管理者进行 'Ship it', 表明 review 通过.

    • 关闭 review
      在 review 通过后, 代表作者可以提交代码进行测试, 如果测试通过, 或者上线之后, 便可以关闭review. 如果测试过程又发现新的问题, 则需要重复前面的步骤, 修改代码, 再次发布review.

posted @ 2016-09-29 10:10  一粟沧海  阅读(15)  评论(0编辑  收藏  举报