我们在做稍微大一点的项目一般都会分模块去开发,一个模块如果功能很复杂,这个模块还会安排多个开发人员共同参与开发,此时,我们最好是从 develop 分支单独切一个分支出来,命名为 feature/模块名称,参与这个模块开发的人都在这个分支上进行代码提交(不要直接以 develop 为源新建各自的分支,然后各自开发并提交至 develop 分支),这样可以最大程度地保证独立模块的开发不影响到 develop 分支。当然每天还是要跟 develop 同步一次,具体频率视情况而定。
git工作流
1. 以 develop 为源创建新分支(三种方式)
- 先切到 develop 分支上,拉取最新代码,再新建一个分支并切换
$ git checkout develop $ git pull --rebase $ git checkout -b feature/模块名称 // checkout -b 是新建分支branch与切换分支checkout的缩写 - 直接以 develop 为源,新建并切换
$ git checkout -b feature/模块名称 origin/develop
前面两种方式是先创建本地分支,远程仓库中并没有对应的同名远程分支,如何新建对应的同名远程分支,并建立两者的追踪关系,参考《新建本地分支后,如何推送到远程仓库上》
-
直接在 gitlab 页面上点击 New branch
注意一定要选择以 develop 分支为源
第三种方式是先在gitlab页面上操作新建的远程分支,此时不能像前两种方式那样使用 git checkout -b feature/模块名称 origin/feature/模块名称,需要先fetch该远程分支,参考《git 拉取指定的远程分支到本地》
新建分支时注意命名规范,请参考《如何优雅地命名git分支》
2. 大家在新建的分支(feature/模块名称)上进行开发与代码提交
$ git add .
$ git commit -m "完成了什么功能or修复了什么bug"
$ git push
3. 每天上班到工位或者需要从 develop 分支上更新时
先确保本地代码已提交,两种方式
- 先切换至 develop 本地分支
这样本地的 develop 分支已经更新,切回本地的模块分支,在本地的模块分支上去合并本地 develop 分支上的代码$ git checkout develop $ git pull --rebase$ git checkout feature/模块名称 $ git merge develop - 在当前模块分支上直接以 develop 为源进行 rebase 拉取
$ git pull --rebase origin develop
--rebase的重要性
当我们在 push 本地分支的代码时,要先pull一次远程分支的代码,git pull 与 git pull --rebase 的区别你知道吗?
$ git pull // 相当于 git fetch + git merge
$ git pull --rebase // 相当于 git fetch + git rebase
两者的区别在于 git pull 之后 merge 与 rebase 的不同
提交树的不同
假设当前 develop 分支的提交记录如下
stateDiagram-v2
direction LR
commitId1 --> commitId2
commitId2 --> commitId3
commitId3 --> commitId4
commitId4 --> commitId5
如果我们在 commitId2 处切了一个新分支 temp 分支进行开发,有2次提交记录(commitId20,commitId21)
stateDiagram-v2
direction LR
commitId2 --> commitId20
commitId20 --> commitId21
commitId1 --> commitId2
commitId2 --> commitId3
commitId3 --> commitId4
commitId4 --> commitId5
在 temp 分支上开发完后,我们要合并至 develop 分支,先切到 develop 分支
- 在 develop 分支上执行
git merge temp,就会得到如下的结果
merge新增了一次提交记录commitId6stateDiagram-v2 direction LR commitId2 --> commitId20 commitId20 --> commitId21 commitId21 --> commitId6 commitId1 --> commitId2 commitId2 --> commitId3 commitId3 --> commitId4 commitId4 --> commitId5 commitId5 --> commitId6 - 在 develop 分支上执行
git rebase temp,得到的是如下的结果
rebase没有产生新的节点stateDiagram-v2 direction LR commitId1 --> commitId2 commitId2 --> commitId20 commitId20 --> commitId21 commitId21 --> commitId3' commitId3' --> commitId4' commitId4' --> commitId5'
使用rebase的git演进路线(提交树)是一直向前的,这样在版本回退时也很容易,用merge的git路线是跳跃的,如果版本回退你也找不到自己想要的版本
遇到冲突时的操作不同
- merge 操作遇到冲突的时候,当前 merge 不能继续进行下去,手动修改冲突内容后,add 修改冲突后的内容,commit 就可以了
- rebase 操作的话,会中断 rebase,同时会提示去解决冲突
- 解决冲突后, 再执行
git rebase –continue继续操作,再 push - 或者执行
git rebase –skip忽略冲突
- 解决冲突后, 再执行
综上所述,想要更好的提交树,建议使用 rebase 操作会更好一点,这样可以线性地看到每一次提交,并且没有增加提交节点