用rebase得到线性历史
本地工作
一个任务用一个分支,可以提交多次。
git checkout -b 1-add-a-py
vi a.py
git add a.py
git commit -m'add a.py'
vi a.py
git add a.py
git commit -m'print hello world'
push到服务器
git push origin HEAD:refs/for/master //评审系统中生成一条评审记录,评审的代码就是当前工作中的分支(HEAD)。本地分支1-add-a-py => 远端评审系统 => 远端master
第一个任务还在评审时,开始做第二个任务
git fetch
git checkout -b 2-add-b-py origin/master
vi b.py
git add b.py
git commit -m'add b.py'
git gpush origin master
看一下2个任务(分支),1-add-a-py产生了2个commits,2-add-b-py产生了1个commit
$ git lola
* ad11f1b - (HEAD -> 2-add-b-py) add b.py
* | * 6a14db7 - (1-add-a-py) say hello
* | * 6e8d6e2 - add a.py
* |/
* * 98cb99d - (origin/master, master)
我们可以反复的在1-add-a-py和2-add-b-py这2个分支上git commit和gpush,更新代码,直到达到提交准入的要求。
这个过程中,如果有人更新了远端的master,可能会跟我们的修改冲突。解决办法是在本地仓库先合并一次。
git checkout 1-add-a-py
git pull origin master
... 修改有冲突的文件 ...
git commit
git push origin HEAD:refs/for/master
提交远端master
最后,在网页上提交我们的2个任务
在评审网页上找到标题为add b.py和add b.py的这个2评审,点【合入】
提交是在远端服务器发生的,我们把更新pull回来看看
$ git checkout master
$ git pull
$ git lola
* a5080bc - (HEAD -> master, origin/master) Merge changes from topic '1-add-a-py'
* |\
* | * 6a14db7 - (1-add-a-py) say hello
* | * 6e8d6e2 - add a.py
* * | ad11f1b - (2-add-b-py) add b.py
* |/
* * 98cb99d
* $ git branch -d 1-add-a-py 2-add-b-py #分支合入master时候就可以删掉了,下次有需要再新建
master已经更新了。百度效率云-DevOps自动合并了2个任务的分支。
保持线性历史(可选)
上面是基本的提交流程,容易上手,但是master历史会比较杂乱。有2类commits混在历史里面:
评审不通过的中间commit,如上面例子的6e8d6e2,它的质量是不合格的 Merge commit,如上面例子的a5080bc,它没有贡献任何代码,却让代码历史变成了2条支线,变复杂了 重演刚才的情景,回到我们2个任务的起点,使用下面的方法就能消除这2类不受欢迎的commits,得到一条线性历史的master。
$ git lola
* ad11f1b - (2-add-b-py) add b.py
* | * 6e8d6e2 - (HEAD -> 1-add-a-py) add a.py
* |/
* * 98cb99d - (origin/master, master)
用amend删除评审不通过的commit
先提交a.py,这次的目标是去掉中间版本。关键操作是commit --amend,它把旧版commit(6e8d6e2 )给丢弃掉了。
$ git checkout 1-add-a-py
... vi ...
$ git add a.py
$ git commit --amend --no-edit #更新前一个commit的内容,保留提交日志不变
$ git lol 6e8d6e2
* 0c1cd2a - (HEAD -> 1-add-a-py) add a.py
* | * 6e8d6e2 - add a.py
* |/
* * 98cb99d (origin/master, master)
$ git push origin HEAD:refs/for/master
由于0c1cd2a是amend了6e8d6e2而产生的commit,提交日志不变,iCode通过识别2个commit提交日志中的Change-Id,知道他们属于一次评审的2个patch。
因此,我们就可以在百度效率云-DevOps网页上看到1-add-a-py所有amend的历史版本,同时又把这些历史版本都排除出master的历史。
我们可以一直amend 1-add-a-py直到满意为止,然后在网页上将它【合入】master。
用rebase去除merge commit
接下来再提交2-add-b-py,这次的目标是不要产生merge commit。关键操作是pull --rebase,它将2-add-b-py的修改在1-add-a-py上重演了一次,避免了merge commit。
$ git checkout 2-add-b-py
$ git fetch
$ git lola
* 0c1cd2a - (origin/master, master, 1-add-a-py) add a.py
| * ad11f1b - (HEAD -> 2-add-b-py) add b.py
|/
* 98cb99d
$ git pull origin master --rebase
$ git lol
* f2cbe49 - (HEAD -> 2-add-b-py) add b.py
* 0c1cd2a - (master, 1-add-a-py) add a.py
* 98cb99d
$ git push origin HEAD:refs/for/master
这样,就得到了线性的历史,2个commits,分别是1-add-a-py和2-add-by-py的修改;同时每一个commit都是一个逻辑完整的小功能。