SVN迁移到git
如果不需要 SVN 仓库的历史提交记录,则只需要将最新的代码下载到本地,然后将相关的代码 push 到 git 服务器仓库即可. 这里重点说明如何同时将SVN的提交记录迁移到 git 仓库.
1. 创建用户映射
在 Subversion,每个提交者在都在主机上有一个用户名,记录在提交信息中. 比如 blame 的输出以及 git svn log。如果想让这条信息更好的映射到 Git 作者数据里,则需要从 SVN 用户名到 Git 作者的一个映射关系建立一个叫做 user.txt 的文件,用如下格式表示映射关系:
zhangsan = Zhang San <zhangsan@testin.cn>
lixiaoming = Li Xiaoming <lixiaoming@testin.cn>
通过该命令可以获得 SVN 作者的列表:
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 参数
git svn clone svn://xxxx --authors-file=users.txt --no-metadata -s my_project
现在 my_project 目录下导入的 Subversion 应该比原来整洁多了. 原来的 commit 看上去是这样:
commit 37efa680e8473b615de980fa935944215428a35a
Author: zhangsan <zhangsan@4c93b258-373f-11de-be05-5f7a86268029>
Date: Sun May 3 00:12:22 2009 +0000
fixed install - go to trunk
git-svn-id: https://my-project.googlecode.com/svn/trunk@94 4c93b258-373f-11de-
be05-5f7a86268029
现在是这样:
commit 03a8785f44c8ea5cdb0e8834b7c8e6c469be2ff2
Author: Zhang San <zhangsan@testin.cn>
Date: Sun May 3 00:12:22 2009 +0000
fixed install - go to trunk
不仅作者一项干净了不少,git-svn-id 也就此消失了.
3. 转化成Git的仓库格式(tags 和 branches)
SVN 中是常见的 “trunk/branches/tags” 目录结构,所以需要将 SVN 的 branches 和标签 tags 生成对应的git的分支和标签.
处理branches:
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:
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 仓库,会生成如下的仓库地址:
git@192.168.1.93:crash-sdk/android.git
http://prj.testin.cn:8200/crash-sdk/android.git
建议使用第一种地址,它通过SSH协议进行代码传输. 添加本地的SSH公钥到 GitLab 服务器之后,便可以省去频繁的用户名/密码等的输入.
生成SSH公钥
在终端中敲下面的命令,第一步会生成一对私钥和公钥,分别存在 ~/.ssh/id_rsa和~/.ssh/id_rsa.pub中.
第二步查看公钥字符串. 在生成key的过程,建议一直回车,不设置任何密码等信息,以防在和 Git 服务器仓库交互过程中,总是提示输入密码等信息.
ssh-keygen -t rsa -C "zhangsan@testin.cn"
cat ~/.ssh/id_rsa.pub
保存sshkey到gitlab
在面板上依次点击Profile Settings –> SSH Keys –> Add SSH Keys. 然后把上一步中的id_rsa.pub中的内容拷贝出来粘贴到输入框中,保存.
5. 添加远程git仓库
在本地,将上面创建的仓库服务器添加为远程服务器并且向它推送。下面是新增远程服务器的例子:
git remote add origin git@192.168.1.93:crash-sdk/android.git
6. 提交代码到git仓库
通过以下命令将本地代码提交到远程git仓库:
git push origin master
Git 基础
这里讲解Git的基本使用,一些高级的使用方法,请参考官方文档。
1. Git 安装
- 在类 Linux 系统下,有下面两种方法
yum install git-core
apt-get install git
- 在 Mac 上安装 Git 有两种方式。最容易的当属使用图形化的 Git 安装工具,下载地址在:
http://sourceforge.net/projects/git-osx-installer/
另一种是通过 MacPorts (http://www.macports.org) 安装。如果已经装好了 MacPorts,用下面的命令安装 Git:
sudo port install git-core +svn +doc +bash_completion +gitweb
- 在 Windows 上安装Git,可以使用一个叫做 msysGit 项目提供的安装包. exe按照文件下载地址:
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 提交时都会引用这两条信息,说明是谁提交了更新,所以会随更新内容一起被永久纳入历史记录:
git config --global user.name "Zhang San"
git config --global user.email zhangsan@testin.cn
建议使用 --global 选项,这样,以后你所有的项目都会默认使用这里配置的用户信息。
Git命令别名
为了方面使用Git命令,建议设置Git别名,比如:
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
配置忽略文件
在开发过程中,可能会产生一些临时文件,这些文件不需要提交到代码库中进行管理,这时就需要通过添加.gitignore文件来配置忽略哪些文件. 文件匹配规则, 这里不做详述.
其他配置
在开发过程中,经常需要做diff和merge操作,可以配置相应的工具来完成,比如使用P4Merge工具。当然Git也有默认工具来完成这个工作。
3. 常用Git命令
这里重点列举自己在项目中常用的Git命令,还有很多实用的命令, 可以根据自己的喜好使用, 请参考官方文档。
- git fetch
该命令用来拉取远程分支到本地,比如拉取远程仓库的release-2.0.6
git fetch origin release-2.0.6:release-2.0.6
冒号后面的release-2.0.6是指拉取远程分支到本地后的分支名称,可以随意命名,但是建议保持和远程仓库同名。
- git checkout
该命令主要用来切换分支, 比如
git checkout release-2.0.6
除此之外,还会经常用该命令来撤销对文件的修改,比如
git checkout -- test.txt
- git branch
该命令用来查看本地或远程分支,也可以用来创建本地分支
$ git branch
master
release-2.0.2
release-2.0.3
release-2.0.4
task/R15081
task/R15099
$ git branch -r
origin/HEAD -> origin/master
origin/master
origin/release-2.0.2
origin/release-2.0.3
origin/release-2.0.4
$ git branch task/test
$ git branch
master
release-2.0.2
release-2.0.3
release-2.0.4
task/R15081
task/R15099
task/test
- git diff
该命令主要用来查看文件修改内容 - git add
该命令将当前更改或者新增的文件加入到Git的索引中,加入到Git的索引中就表示记入了版本历史中,这也是提交之前所需要执行的一步. - git status
该命令用来查看本地git仓库状态, 比如
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: libs/testinagent_debug.jar
modified: src/com/testin/apm/demo/MainActivity.java
Untracked files:
(use "git add <file>..." to include in what will be committed)
log.log
- git commit
该命令提交当前工作空间的修改内容, 提交的时候必须用-m来输入一条提交信息,该功能类似于SVN的commit, 比如
git commit -m 'Just for test'
- git log
该命令用来查看历史提交记录, 比如
$ git log -n 2
commit 6e7e855f025c9f64be687d1a893da306bf6b321d
Author: Zhang San <zhangsan@testin.cn>
Date: Wed Sep 9 15:24:42 2015 +0800
R17065: Keep Breadcrumb function in thread-safe mode
commit 996bba84015759ac70b83f72b308ff185bf9ee58
Author: Zhang San <zhangsan@testin.cn>
Date: Wed Sep 9 12:11:19 2015 +0800
R17706: Remove the network interface
Just comment the code not remove since we may reuse it in the future
- git push
该命令将本地commit的代码更新到远程版本库中, 比如将本地的release-2.0.6分支的代码更新到远程origin仓库.
$ git push origin release-2.0.6
- git pull
该命令从远程服务器仓库将代码更新到本地,比如将origin服务起仓库的代码更新到本地的master主分支,该功能类似于SVN的update
git pull origin master
- git merge
该命令将指定分支与当前分支进行合并, 比如将task/test分支合并到当前所在的release-2.0.6分支
$ git merge task/test
- git rebase -i
该命令可以用来合并历史提交并重写comments, 比如将最后两次的提交合并一次
$ git log -n 3
commit e81df4372c2a385fe9ce6b2c32f59d4493340ce2
Author: Zhang San <zhangsan@testin.cn>
Date: Tue Sep 15 13:57:19 2015 +0800
test
commit 53d2078dd0e19f9441f331a5cfb2893e766a40ab
Author: Zhang San <zhangsan@testin.cn>
Date: Tue Sep 15 13:56:34 2015 +0800
Add the interface to check app update
commit 3b46a6ec03ff145e7fa767d9aded0539029eeb17
Merge: 43044aa 6e7e855
Author: Zhang San <zhangsan@testin.cn>
Date: Fri Sep 11 11:03:15 2015 +0800
Merge branch 'release-2.0.7' into 'master'
Release 2.0.7
See merge request !7
$ git rebase -i 3b46a6ec03ff145e7fa767d9aded0539029eeb17
$ git log -n 3
commit d139ac4e822aab5de4e09801cbf7f3c9de124c76
Author: Zhang San <zhangsan@testin.cn>
Date: Tue Sep 15 13:56:34 2015 +0800
Add the interface to check app update
commit 3b46a6ec03ff145e7fa767d9aded0539029eeb17
Merge: 43044aa 6e7e855
Author: Zhang San <zhangsan@testin.cn>
Date: Fri Sep 11 11:03:15 2015 +0800
Merge branch 'release-2.0.7' into 'master'
Release 2.0.7
See merge request !7
commit 6e7e855f025c9f64be687d1a893da306bf6b321d
Author: Zhang San <zhangsan@testin.cn>
Date: Wed Sep 9 15:24:42 2015 +0800
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
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.
REVIEWBOARD_URL = 'http://prj.testin.cn:9000/'
REPOSITORY = 'APM-Android-Git'
2. 提交review
RBtool提交 review 主要使用 rbt post 命令来完成, 它有很多参数, 可以应对各种情况, 这里只做简单演示. 需要强调的是, RBtool 工具的本质就是将一个 diff 文件提交到 review board 上面展示, 参数的不同就是为了形成不同的 diff 文件.
- 首次提交review
一般建议在独立的 task 分支进行开发, 在合并到 release 或者 master 等分支之前, 需要提交 review.
rbt post --tracking-branch=release-2.0.6
上面的命令将当前分支(task/test)相对于release-2.0.6分支的diff提交review.
- 重复提交review
在 review 的过程, 难免会根据 review 提出的问题进行修改. 在修改完成以后, 需要再次提交 review, 这时需要提交到和之前同一个 review 地址. 假如之前提交的 review 号为737, 并且提交历史如下
$ git log -n 2
commit d139ac4e822aab5de4e09801cbf7f3c9de124c76
Author: Zhang San <zhangsan@testin.cn>
Date: Tue Sep 15 13:56:34 2015 +0800
Add the interface to check app update
commit 6e7e855f025c9f64be687d1a893da306bf6b321d
Author: Zhang San <zhangsan@testin.cn>
Date: Wed Sep 9 15:24:42 2015 +0800
R17065: Keep Breadcrumb function in thread-safe mode
即上一次 review 对应的提交是 6e7e855f025c9f64be687d1a893da306bf6b321d, 本次根据 review 修改后的提交为 d139ac4e822aab5de4e09801cbf7f3c9de124c76. 如此, 提交 review 的命令应该为:
rbt post -r 737 --parent=6e7e855f025c9f64be687d1a893da306bf6b321d
3. Review 流程
下面说明 Review 的整个流程, 从发布 review 到 关闭 review的整个过程.
- 发布review
通过 rbt post 命令之后, 会输出两个url地址, 第一个就是 review 发布的地址, 第二个地址可以查看本次 diff 文件内容.
$ rbt post --tracking-branch=release-2.0.5
Review request #745 posted.
http://prj.testin.cn:9000/r/745/
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.