Git, Gerrit, Hudson (2) -- 使用GIT

fbfsber00 2012-03-05

1. 拷贝远程库

在 Git bash 中,使用以下命令拷贝远程库:

git clone review:<repository_name>

<repository_name> 是远程库的名称,例如:远程库叫 "ProjectA",使用以下命令:

git clone review:ProjectA

但是,如果使用的是 Tortoise 将不能使用这种简写的形式,得使用 URL 链接:

ssh://<username>@<Gerrit_host_name>:29418/ProjectA

注意:以上步骤并不能把 ProjectA 直接下下来,而是建立了连接,后面还需若干步骤来下载代码。

2. 建立“钩子”

你需要取得 Gerrit 的 Change-Id 的钩子(hook)。使用 Git bash 输入以下命令:

# 进入到刚才拷贝下来的远程库目录
cd ProjectA
# 从 server 上下载 “钩子”
scp -p review:hooks/commit-msg .git/hooks/

一个叫 "commit-msg" 的文件会被下载下来。

hooks 实际上是包含一系列命令的脚本,该脚本在 commit 时会被自动调用,你可以在服务器上放置这样的脚本,以统一客户端的提交行为 (或者其它需要统一的事情 )。

3. 可视化组件

git 有一个可视化工具:gitk,它可以展示每次的提交,也可以看到哪些被 merge ,以及 branch 上的情况,在命令行下输入以下命令:

# 显示当前所在分支( Branch )上的所有提交
gitk
# 显示所有分支的所有提交
gitk --all

4. 创建跟踪分支(Tracking Branches)

在第 1 步中的 git clone 命令会自动在本地创建一个叫 'master' 的分支跟踪远端库中的 master (即 'origin/master' )。而后可以使用 git branch 在本地创建分支来跟踪服务器上的远端分支( Remote Branches )。我们称这种本地分支为 Tracking Branch 。创建跟踪分支的命令如下:

git branch <tracking_branch> -t origin/<remote_branch>

例如:

git branch 1.0.0 -t origin/1.0.0

以上命令为:在本地创建 1.0.0 的分支来跟踪远端 1.0.0 分支( 即 'origin/1.0.0 )。然后,可以使用 checkout 命令将当前目录切换到 1.0.0 上去。

git checkout 1.0.0

以上两步可以合并为一步,创建 Tracking Branch 同时切过去:

git checkout -b 1.0.0 -t origin/1.0.0

注意:与 SVN 不同,checkout 在 git 中不是签出,而是切换到指定分支。签出是 git pull 。

5. 从 server 上更新

如果要从 server 上签出更新。首先,切换到想签出的分支上(如果当前不在该分支上),然后签出:

git checkout 1.0.0
git pull

git pull 针对于 Tracking Branch,对特征分支( Feature Branch ),需使用 git rebase 。

6. 创建特征分支( Feature Branch )

无论何时要对代码进行修改,总是应该先创建特征分支,然后在特征分支上进行修改。

首先,切换到跟踪分支上( 如果当前不在该分支上 ),签出更新:

git checkout 1.0.0
git pull

然后,在该跟踪分支上创建特征分支并切换到上面:

git checkout -b <feature_branch>

例如:

git checkout -b FixForBug1922

此处创建了一个叫 'FixForBug1922' 的特征分支。特征分支的应该总是取有意义的名字,最好能够概括本次修改的目的。远端服务器并不知道这个特征分支的存在,所以如果要对它进行更新,需要使用 git rebase 命令。

7.  备份特征分支

特征分支存于本地,如果需要把它备份到服务器上,使用如下命令:

git push origin +FixForBug1922:features/abc/FixForBug1922

该命令会将特征分支 'FixForBug1922' 备份至服务器,并称之为 'features/abc/FixForBug1922' 。

注意:此处的 '+' 号。在你 rebase 或 修改了本地代码后,希望再次备份时会产生作用。因为这意味着需要抛弃以前提交的备份,服务器需要知道你确切地知道自己在做什么。如果是第一次备份或没做任何修改,则不需要 '+' 号。

如果你要删除某特征分支,也可以选择相应的删除远端的备份:

# 删除本地的特征分支
git branch -D FixForBug1922

# 删除远端的对应备份
git push origin :features/abc/FixForBug1922

注意:删除远端备份也使用 push ,只不过这次将空 push 到了远端。

8.  提交文件

提交分为两步。首先,将要提交的文件加入( add )到临时区域( staging area )。这使你可以选择性提交( git 甚至允许只提交文件内的某些修改,参见 Pro GIT )。与 SVN 不同,无论对修改的还是新增的文件,都需要执行 add 命令。对 EGit 和 Tortoise 来说,当你选者文件并 commit 的时候,add 会被自动执行。

git add file1
git add file2
git commit

如果你十分有把握,目前所有的变化都是要提交的,可以使用一句话的简写:

git commit -a

注意:commit 只是提交到本地库。签入到 server 还需要其它步骤。下一步将看到如何修改提交。

9. 修改/撤销提交

如果是在同一个工作任务中,最好是修改以前的提交。这样在 code review 时因为只有一次提交需要审查,可以减少审查者的工作量。甚至在 review 以后,如果修改了代码也要修改前一次的提交( 针对同一次任务 )。因为此时你的修改会被放在同一提交中被 review,所有以前的 comments 都会被保留下来,并且还能比较前后的异同。

git add file1
git add file2
git commit --amend

如果要恢复已修改(但还未添加add)的文件,使用git checkout恢复:

git checkout -- <file_name>

如果要撤销已添加(但还未提交commit)的修改,使用git reset恢复:

git reset HEAD <file_name>

如果要撤回已提交(commit)的修改,使用git revert恢复:

# 恢复到最近一次提交
git revert HEAD
# 恢复到指定版本
git revert <commit_id>

10. 重新放置( rebase )特征分支

rebase 会将你的修改重新放置到一个更新的代码基础上。更多详情参见 Pro GIT

首先,从 server 上更新跟踪分支:

git checkout 1.0.1
git pull

然后重新放置特征分支:

git checkout FixForBug1922
git rebase 1.0.1

以上命令首先切换到特征分支 'FixForBug1922',然后将该特征分支上新的提交( commit )应用到 1.0.1 上去。

有可能会有冲突,如果需要,合并冲突,然后:

git commit
git add conflicted/file/1
git add another/conflicted/file
git rebase --continue

11. 签入代码,进行 review

代码提交完成后就可以上传代码至 Gerrit 并进行 review。Gerrit 是一款 review 工具,同时它也是中心库。命令如下:

git push origin FixForBug1922:refs/for/1.0.1/FixForBug1922

注意:如果在 master 上签入,则为:

git push origin master:refs/for/master
  • "git push origin": 告诉 git 上传更改至 server 上的某个 branch 。
  • "FixForBug1922:refs/for/1.0.1/FixForBug1922": 告诉 git 将本地的 'FixForBug1922' 的更改提交到服务器上 'refs/for/1.0.1/FixForBug1922' 分支上去。 

如果我们不需要 review ,可以将代码提交到 'refs/heads/1.0.1' 分支上。

  • "refs/for/1.0.1": 这告诉 Gerrit 有更改需要被 review ,如果 review 通过,代码将被合入到分支 '1.0.1' 中去。
  • "/FixForBug1922": 这是一个可选标签,它能将一系列的 review 组到一起( 如果它们确实应该分在一起 )。

注意:你的特征分支是从哪个分支创建的,就要提交到哪个分支上,否则 Gerrit 会认为你想把一个分支上的所有提交都合并到另一个分支上。

12. 向上合并更新

如果要避免一次艰难痛苦的合并,最好的办法是经常合并

我们应该避免只更新部分版本,并且最好是整个分支的进行合并。基于这个理由我们应该总是向上合并而不是向下合并。

例如:你可以合并整个 '1.0.1' 分支到 'master' ,因为 'master' 应该总是包含了 '1.0.1' 分支中的所有更改,而不应该从 'master' 到 '1.0.1' 分支,因为 'master' 中可能包含了很多不稳定的代码。( 假设 '1.0.1' 已经是一个稳定版本 )

所以,在开发中应该遵循以下原则:

  1. 经常合并。最理想的情况是每一个稳定的提交都进行合并。
  2. 如果需要更改( 例如需要修正一个 bug ,该 bug 是先前的分支就有了只是现在才发现 )。从尽可能早的版本开始更改,合并。
  3. 沿着版本号挨个向上合并。例如:合并从 1.0.1 -> 1.0.2 -> 1.0.3 -> master ;而不是直接从 1.0.1 -> master 。
  4. 不要挑着更改,合并。

合并命令如下:

# 切换到目标分支
git checkout master
# 创建并切换到特征分支
git checkout -b toMergeBugFix1922
# 执行合并
git merge 1.0.1

# 如果出现冲突,解决冲突,然后:
# 1. 使用 add 命令告诉 git 我们已经解决了冲突
git add conflictedfile.txt
git add conflictcode.java
# 2. 提交合并
git commit

# 将合并提交 review
git push origin toMergeBugFix1922:refs/for/master

# 让某些人来做 review

相关推荐