2020-10-29 init
2020-11-06 更新基础使用规则
2020-11-25 添加 进阶2. 更换账户
2020-12-17 添加 进阶3. 拉取线上代码
基础
1. pull
1.1 情景还原
gerrit如何拉代码?当前分支,存在并行开发,A已经完成评审并合入分支,B仍在开发未合入分支,且存在一个或多个提交,需要拉取A的代码接入到当前分支,怎么办?
1.2 解决办法
例如拉取分支dev_branch
git pull --rebase origin dev_branch
git status // 看有没有冲突
git add -u // 一键添加冲突项
git rebase --continue // 处理完冲突继续rebase
git rebase --abort // 我不处理了,放弃pull
git rebase --skip // 抛弃冲突项,pull到的内容就是不完整的了
2. push
2.1 情景还原
gerrit我该怎么push?代码怎么让别人评审?
2.2 解决办法
例如上传dev_branch
git push origin HEAD:refs/for/dev_branch
3. 根据review意见更新代码
3.1 情景还原
我的代码被评审提出了一系列修改意见,修改后,我是像gitlab/github那样再创建一个新的commit提交吗?
3.2 解决办法
不是的,这就是gerrit和gitlab/github不同的地方了,前者将多次提交看做同一主题的commit,使用patch概念管理,例如对于commit A,评审给出review意见,开发者按照意见进行修改,修改的部分作为同一个commit的patch,而如何判断同一个commit,就是commit id
了,需要添加个钩子hook
才会自动生成,不同的patch拥有相同的commit id
;后者使用merge-request策略,修改好后,作为新的提交再扔给服务器,然后提出合并请求,审批人根据diff同意或打回请求。两者各有优缺,但我属于old style,个人还是喜欢gerrit的patch管理思想。
例如上传dev_branch
git add -u // 一键添加修改的部分
git commit --amend // 作为补丁,将新的修改点加入到commit里
git push origin HEAD:refs/for/dev_branch // 跟push相同
进阶
1. 分支合并
1.1 情景还原
使用git merge
在本地执行分支合并操作,git push origin HEAD:refs/for/dev
到gerrit 上评审入库,提示:
! [remote rejected] HEAD -> refs/for/dev (no new changes)
1.2 原因
没有新的commit,使用git log
也可以看到,并没有类似Merge remote-tracking branch
,即这个合并,是线性的合并,那些需要合并的commit节点,在gerrit上都已经提交评审过了,所以本次merge并没有commit。
1.3 解决办法
方法1: 使用git merge --no-ff
,强制让git生成一个新的commit,这样就可以提交了
方法2:不经过gerrit,直接git push
入远程库,这个branch就会乱掉。
2. 更换账户
2.1 情景还原
我换了账户,也切了config,操作为:git config --global user.name
与git config --global user.email
,已经与gerrit服务器上的信息对上了,但在git push
的时候还是报错如下:
remote: ERROR: In commit xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
remote: ERROR: committer email address my_email@email.com
remote: ERROR: does not match your user account.
remote: ERROR:
remote: ERROR: The following addresses are currently registered:
remote: ERROR: previous_email@email.com
remote: ERROR:
remote: ERROR: To register an email address, please visit:
remote: ERROR: https://my_gerrit.com/#/settings/contact
remote:
remote:
To http://my_gerrit.com:1234/my_repo
! [remote rejected] HEAD -> refs/for/my_branch (invalid committer)
error: failed to push some refs to 'http://my_gerrit.com:1234/my_repo'
2.2 原因
很大概率你是使用的macOS的,macOS保存了登录gerrit的登录记录,把它清掉就好。
2.3 解决办法
Launchpad -> Other -> Keychain Access
直接搜索gerrit字样,就可以看到登录信息了,改成自己的id就可。
3. 如何在本地review别人的代码/拉取未合入的代码
3.1 情景还原
帮着别人调代码,由于这份提交有bug,不能合入到分支中,那该怎么搞到他的代码呢?
3.2 解决办法
3.2.1 等级一
git diff (your commit hash code) >> mycode.patch # 将本次提交与主干相比较,并输出到后缀为".patch"的文本文件中
# 将这个".patch"发给对方
git apply mycode.patch # 在对方的代码上应用本次提交
如果存在多个分支、多次提交,对方必须拥有跟你上次提交一模一样的代码,即相同的分支,相同的提交记录,而且还要发来发去,一点都不优雅。既然自己的代码已经push到了服务器等待大佬合并,那为啥不能从gerrit服务器直接拉取代码呢?
3.2.2 等级二
在gerrit页面上,是可以看到自己待review的提交的,进入提交详情页面,右上角有个download选项,点开就可以看到各种拉代码的方法了:
- Checkout,把自己的分支全部都拉下来
- Cherry Pick,把自己的提交拉下来,并且接在本地的分支头上
- Format Patch,就是控制打前几个patch,这里的patch就是gerrit特有的内容了
- Pull,跟Checkout有点像,区别跟普通的checkout和pull差不多
- Patch-File,跟diff法子一样,然后再apply
- Archive,把仓库的代码全部下下来,慎点,仓库很大的话就会下很久
我一般使用的是Checkout
,它对应的代码如下,可以看到,其内容实际上是git fetch
和git checkout
的组合,里面的refs/changes/233/2333/1
的最后一个数1
实际上对应着当前拉取的patch是本次commit的第1个patch,因此在这里控制后面的这个数,也就跟Patch-File
的行为差不多了。
Checkout
与Format Patch
、Pull
的行为差不多,需要注意的是Cherry Pick
,它内部执行的git cherry-pick
是将本次commit接在本地分支的头上,所以有可能,本地分支是超前与本次提交或者落后于本次提交,前者会出冲突,后者可能会丢失某些comit。
git fetch ssh://xxx@xxx.gerrit.com:1234/target_repos refs/changes/233/2333/1 && git checkout FETCH_HEAD