Gerrit : Code Review Tool based on Git

Gerrit Code Review for Git:
http://gerrit-documentation.googlecode.com/svn/Documentation/2.4.2/index.html

git post of mine:
http://wuaner.iteye.com/blog/1681983


Git workflow:
http://nvie.com/posts/a-successful-git-branching-model/
http://danielkummer.github.io/git-flow-cheatsheet/
https://www.atlassian.com/git/tutorials/comparing-workflows
http://scottchacon.com/2011/08/31/github-flow.html
http://openwares.net/linux/git_brantch_model.html
http://openwares.net/linux/gerrit_workflow.html


权限控制:
http://openwares.net/linux/gerrit_privilege_setup.html


Rebase or Merge for team workflows? that's a problem:
http://stackoverflow.com/questions/457927/git-workflow-and-rebase-vs-merge-questions
http://stackoverflow.com/questions/804115/when-do-you-use-git-rebase-instead-of-git-merge
http://blogs.atlassian.com/2013/10/git-team-workflows-merge-or-rebase/



ssh 登录注意事项:
# 生成 ssh public & private keys (一路回车即可):
$ ssh-keygen -t rsa
# cat ~/.ssh/id_rsa.pub 的内容,将结果拷到 gerrit - settings - "SSH public keys":
$ cat ~/.ssh/id_rsa.pub
# 你的 id_rsa.pub 的内容应该已经被追加到了远程 gerrit server 上的 ~/.ssh/authorized_keys 中。对远程主机上的 authorized_keys 文件,确保除当前用户外无任何其他用户拥有对该文件的写权限(在 ubuntu 下同组用户会拥有写权限)。否则更改其权限(原因见 man sshd -> If this file(~/.ssh/authorized_keys), the ~/.ssh directory, or the user's home directory are writable by other users, then the file could be modified or replaced by unauthorized users.  In this case, sshd will not allow it to be used unless the StrictModes option has been set to “no” ):
$ chmod g-w(或 600 也可, 总之确保其他用户无写权限,另外注意是检查 gerrit server 上的 authorized_keys,不是在你本地创建/检查这个文件!) ~/.ssh/authorized_keys 
# 做完上面这些后,如果通过 ssh clone 项目时报 Agent admitted failure to sign using the key,原因是刚生成的私钥尚未被 sshd 认可。此时的解决办法可以是重启系统,也可以是通过调用下面的脚本将刚生成的私钥手动添加到认可的私钥列表中(参见:http://www.cyberciti.biz/faq/unix-appleosx-linux-bsd-agent-admitted-failuretosignusingkey/):
$ ssh-add
# 查看 gerrit server 对外开放的端口号(默认为 29418)
$ curl http://hostOfGerritServer:port/ssh_info
# Test SSH authentication to gerrit server
$ ssh -vv -p 29418 usernameOfGerritAccount@hostOfGerritServer
关于 SSH 参考:
http://support.suso.com/supki/SSH_Tutorial_for_Linux
https://www.digitalocean.com/community/tutorials/how-to-use-ssh-to-connect-to-a-remote-server-in-ubuntu
引用
Your public key can be put on the machines you want to connect to in a file called .ssh/authorized_keys
# 如果想要 ssh localhost,在本地需要:
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
为了通过 ssh 免密码登陆远程主机 192.168.x.y,可以通过配置 config 的方式。一个典型的 ~/.ssh/config 配置:
Host host_x.y
    User userOf[192.168.x.y]
    Hostname 192.168.x.y
    IdentityFile ~/.ssh/id_rsa
# 使用 ssh-copy-id 将本地的 id_rsa.pub 追加到远程主机的 ~/.ssh/authorized_keys 文件中:
$ ssh-copy-id [email protected]



gerrit不允许你使用
git push origin master
将本地的tracking brancn直接bush到Remote Repo的master分支,你需要使用
git push origin HEAD:refs/for/master
做push操作。
http://stackoverflow.com/questions/10461214/why-do-git-push-gerrit-headrefs-for-master-instead-of-git-push-origin-master



gerrit 下也 可以拿到别人提交的、尚未被review的commit对象(通过 refs/changes):
$ git fetch ssh://[email protected]:29418/projectName refs/changes/79/3179/3 && git checkout FETCH_HEAD
$ git checkout -b <a_new_branch_point_to_unreviewd_commit>



对纯使用git的push,push完后本地的remote-tracking branch(如origin/master)会自动的moving到与当前的tracking branch(如master分支)相同的位置(都指向最新的commit对象);但是使用gerrit,做完 ”git push origin HEAD:refs/for/master“后,本地的remote-tracking branch不会移动,仍然保持在原来的指向,致使git status总是提示:
Your branch is ahead of 'origin/master' by X commit
必须等有相应权限的reviewer review并批准了你的commit后,你才能在本地通过fetch/pull origin来使remote-tracking branch移动。(在未被review&批准前,你fetch/pull是无法让其移动的。)
之所以出现这种问题,其实上面的图就说明了一切:你push入的是一个叫做padding changes的区域,push的commit对象是要被review通过才能进入到Authoritative Repository里的;而你fetch/pull取的是Authoritative Repository里的东西。



Problems Summary:
1 checkout remote的一个分支,本地出现了一个叫做(no branch)的分支,并且HEAD指向了它:
$ git checkout origin/master
说明:
(no branch)表示当前HEAD指针没有指向任何一个branch的 tip,是一个detached HEAD,关于detached HEAD详见本博git篇。
origin/master是remote-tracking branch(有时候简称为remote branch),是origin这个remote Reop的master分支(某一时期)的状态在你本地Repo中的体现;remote-tracking branch与local branch的区别在于,remote-tracking branch对你来说是只读的(而local branch是可写的(可写自然也可读))
http://stackoverflow.com/questions/2498458/why-did-git-set-us-on-no-branch
所以正确的做法应该是checkout -b(或checkout --track) 到一个Local branch:
$ git checkout -b aBranch origin/master
#本地已有一个clone来的master分支的话,则--track的方式是不行的,因为名为master的local branch已存在:
$ git checkout --track origin/master

2
$ git push origin HEAD:refs/for/master
时出现错误:
missing Change-Id in commit message。
http://gerrit-documentation.googlecode.com/svn/Documentation/2.4.2/error-missing-changeid.html
http://gerrit-documentation.googlecode.com/svn/Documentation/2.4.2/user-changeid.html#_creation
http://stackoverflow.com/questions/8845658/gerrit-error-when-change-id-in-commit-messages-are-missing
出现该错误的原因是gerrit server端配置了每个commit的message里必须有Change-Id(is a SHA1 of the first version of the reviewed commit)。
解决方法:通过 git commit --amend -m 或 git rebase -i 修改commit message,使其包含Change-Id信息。
    Add more ignores in .gitignore
    Change-Id: I849fc7309f25eb4175fce67418e177a1bc5555ae

为避免再次发生,需要为本地的git repo添加一个commit-msg hook:
引用
关于git hooks:钩子(hooks)是一些在"$GIT-DIR/hooks"目录的脚本, 在被特定的事件(certain points)触发后被调用。当"git init"命令被调用后, 一些非常有用的示例钩子文件(hooks)被拷到新仓库的hooks目录中; 但是在默认情况下这些钩子(hooks)是不生效的。 把这些钩子文件(hooks)的".sample"文件名后缀去掉就可以使它们生效了。

commit-msg hook的添加方法两种:
$ scp -p -P 29418 [email protected]:hooks/commit-msg .git/hooks/
$ curl http://review.example.com/tools/hooks/commit-msg
在.got/hooks/目录下添加完hook文件后,一定记得将该文件的权限设为可执行!否则会出现hook文件不起作用的问题。
使用commit --amend时如果加了 -m 参数,commit-msg hook会为该commit生成一个新的Change-Id;所以, gerrit下做提交不要git commit --amend -m,因为这样新的commit对象会有不同的change-Id,而gerrit服务器是通过change-Id区别commit对象的;请使用git commit --amend(没有-m参数),并不要改变编辑窗口中的change-Id。
引用
Rule of a thumb: Don't use --amend -m with gerrit
http://stackoverflow.com/questions/7893854/gerrit-recreating-change-ids

3 gerrit 报错: " you are not allowed to upload merges"
如果你是直接在本地的master分支上做commit,并且当前master is ahead of origin/master,则当你git pull,且有别人的commit被从remote那下来,git自然会尝试合并你master当前所在的commit和pull下来的remote commit(因为使用的是pull嘛),从而生成一个新的merge之后的commit对象,master这个local branch指向它,这个merge出来的commit对象是没有change-id的。需要说明的是,gerrit不允许你直接push merge出来的commit对象,即使你通过git commit --amend为它生成了gerrit提交需要的change-id(起码在我所在的工作环境下gerrit服务器是这样配置的,不过这个选项应该是可以在gerrit服务器端配置的)。所以如果你尝试push该merge出来的commit对象,就会报上面的错误:
http://gerrit.googlecode.com/svn/documentation/2.2.1/error-not-allowed-to-upload-merges.html
4 gerrit 报错: "change <change-id_of_commit> closed"
报这个错误的原因是因为你提交的commit对象的change-id同一个已经merge入 gerrit remote repo master分支的commit对象有相同的change-id。之所以出现这种有相同change-id的情况,可能是因为你本地曾经基于repo master分支的那个commit对象作为commit --amend操作:
http://gerrit.googlecode.com/svn-history/r6114/documentation/2.1.7/error-change-closed.html
5 gerrit 下,是不可以直接通过 git push 命令新建 remote branch 的;如果想要为由 gerrit 管理的项目新建 remote branch,需要 有相应权限的人,在 gerrit 的 admin UI(即http://review.example.com) 的 Projects -> nameOfProject -> Branches 下通过点 Create Branches 来做。远程分支一旦建立起来,client唯一需要做的,就是在 master 分支下通过 git pull 将该新建的 remote branch 拿下来。如果想提交某 commit对象 到新建的 remote branch 下,同 git push origin HEAD:refs/for/master 一样,只需指定该新建的 remote branch 作为 push 的目标即可:
# 假设新建的 remote branch 在本地的 remote-tracking branch 叫 remotes/origin/bugfix
git push origin HEAD:refs/for/bugfix

猜你喜欢

转载自wuaner.iteye.com/blog/1683282