Git 分支模型与开发规范

GitHub Flow & Git Flow 基于Git 的两种协做开发模式html

0一、分支模型

devprocess.png

  • master:长期分支,通常用于管理对外发布版本,每一个 commit 对一个 tag,也就是一个发布版本
  • develop:长期分支,通常用于做为平常开发汇总,即开发版的代码
  • feature: 短时间分支,通常用于一个新功能的开发
  • hotfix :短时间分支 ,通常用于正式发布之后,出现 bug,须要建立一个分支,进行 bug 修补。
  • release :短时间分支,通常用于发布正式版本以前(即合并到 master 分支以前),须要有的预发布的版本进行测试。

master和develop做为主要分支。git

新功能的开发在feature上进行,该分支从develop分支派生,功能开发完毕后merge到develop分支。 通常feature分支都存在与开发者本地,除非该分支须要多方合做才提交到远程仓库。安全

如何保证和develop分支的代码同步?天天从develop分支拉去最新的代码,使用rebase命令 不要使用pull,每次合并上游更改时feature 分支都会引入一个外来的合并提交,使用pull会生成一个新的合并commit。app

在将其余分支的代码合并到当前分支时,若是那个分支是当前分支的父分支,为了保持图表的可读性和可追踪性,能够考虑用 git rebase 来代替 git merge;反过来或者不是父子关系的两个分支以及互相已经 git merge 过的分支,就不要采用 git rebase 了,避免出现重复的冲突和提交节点。工具

release分支是从develop分支派生, bug fix只在release分支上进行,该分支也是QA的测试分支,开发结束后同时合并进develop和master分支post

使用merge request将release分支的提交合并master分支,并打上tag。测试

hotfix能够单独出一个分支,也能够直接在release分支上进行。spa

全部master上的代码都是从release分支合并进去的。code

追踪远程develop分支

git checkout -b develop origin/develop

 

feature 分支操做

获取dev分支最新代码htm

$ git pull --rebase origin dev
或者
$ git rebase dev

$ git checkout -b myfeature develop

$ git checkout develop
Switched to branch 'develop'

$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Summary of changes)

$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).

$ git push origin develop

 

rebase最大的好处是你的项目历史会很是整洁。首先,它不像git merge 那样引入没必要要的合并提交。其次,如上图所示,rebase致使最后的项目历史呈现出完美的线性——你能够从项目终点到起点浏览而不须要任何的Fork。这让你更容易使用git log 、git bisect 和gitk 来查看项目历史。 不过,这种简单的提交历史会带来两个后果:安全性和可跟踪性。若是你违反了Rebase黄金法则,重写项目历史可能会给你的协做工做流带来灾难性的影响。此外,rebase不会有合并提交中附带的信息——你看不到feature分支中并入了上游的哪些更改。

rebase的黄金法则
git rebase 的黄金法则即是,毫不要在公共的分支上使用它。 好比说,若是你把master分支rebase到你的feature分支上会发生什么

 

场景:你在feature上开发了一些功能尚未可以提交,如今有个Bug须要在develop分支上fix,怎么操做?

在feature分支上 执行 add & stash ,将当前的更新暂存起来

切换到develop分支,fix bug,commit & push(也能够不push)

切换到feature分支,rebase develop分支,发现冲突就解决冲突

最后 git stash pop ,弹出以前暂存的内容,这时也可能发生冲突,也比较好解决

这里主要就是应用了stash的功能,防止在feature上开发的功能还未可以提交,同时又有紧急的bug须要fix。

 

release 分支操做

# 合并到master
$ git checkout master
Switched to branch 'master'

$ git merge --no-ff release-1.2
Merge made by recursive.
(Summary of changes)

$ git tag -a 1.2

# 合并到develop
$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff release-1.2

# 删除release分支
$ git branch -d release-1.2

 

hotfix 分支操做

当产品发布出去以后,有紧急的bug,就须要从master分支中拉出一个hot fix分支。 这么作的好处是develop分支上的同事能够继续进行开发,另外一个团队则能够在master分支上进行一个产品修复更新。 修复好以后,合并到mater分支和develop分支。

这里有一个特殊状况,若是当时的release分支还存在,那么hotfix的更新须要merge到相应的release分支上。 若是release分支已经不存在了,那么就只须要merge到master分支和develop分支。

建立远程分支

git push origin local_branch:remote_branch
local_branch必须为你本地存在的分支,remote_branch为远程分支,若是remote_branch不存在则会自动建立分支。

 

0二、开发规范

commit规范

只要坚持作到如下几点就 OK 了:

  1. 提交时的粒度是一个小功能点或者一个 bug fix,这样进行恢复等的操做时可以将「误伤」减到最低;
  2. 用一句简练的话写在第一行,而后空一行稍微详细阐述该提交所增长或修改的地方;
  3. 不要每提交一次就推送一次,多积攒几个提交后一次性推送,这样能够避免在进行一次提交后发现代码中还有小错误。

谁说历史不可篡改了?前提是,想要合并的那几回提交尚未推送到远程!

Commit Message 格式

<type>(<scope>): <subject> <空行> <body> <空行> <footer>

type

  • feat:新功能(feature)
  • fix:修补bug
  • docs:文档(documentation)
  • style: 格式(不影响代码运行的变更)
  • refactor:重构(即不是新增功能,也不是修改bug的代码变更)
  • test:增长测试
  • chore:构建过程或辅助工具的变更

Scope
用来讲明本次Commit影响的范围,即简要说明修改会涉及的部分。这个原本是选填项,但从AngularJS实际项目中能够看出基本上也成了必填项了。

Subject

用来简要描述本次改动,概述就行了,由于后面还会在Body里给出具体信息。而且最好遵循下面三条:

  • 以动词开头,使用第一人称如今时,好比change,而不是changed或changes
  • 首字母不要大写
  • 结尾不用句号(.)

Body

<body>里的内容是对上面subject里内容的展开,在此作更加详尽的描述,内容里应该包含修改动机和修改先后的对比。

Footer

footer里的主要放置不兼容变动和Issue关闭的信息

Revert

此外若是须要撤销以前的Commit,那么本次Commit Message中必须以revert:开头,后面紧跟前面描述的Header部分,格式不变。而且,Body部分的格式也是固定的,必需要记录撤销前Commit的SHA值。

 

提交

在具体开发工做中主要须要遵照的原则就是「使每次提交都有质量」,只要坚持作到如下几点就 OK 了:
1. 提交时的粒度是一个小功能点或者一个 bug fix,这样进行恢复等的操做时可以将「误伤」减到最低;
2. 用一句简练的话写在第一行,而后空一行稍微详细阐述该提交所增长或修改的地方;
3. 不要每提交一次就推送一次,多积攒几个提交后一次性推送,这样能够避免在进行一次提交后发现代码中还有小错误。
 
假如已经把代码提交了,对此次提交的内容进行检查时发现里面有个变量单词拼错了或者其余失误,只要尚未推送到远程,就有一个不被他人发觉你的疏忽的补救方法——
使用 git rebase -i [SHA] , 具体参考,link
 

推送

当本身一我的进行开发时,在功能完成以前不要急着建立远程分支。
 

拉取

git pull --rebase
1. 把本地repo从上次pull以后的变动暂存起来
2. 恢复到上次pull时的状况
3. 套用远端的变动
4. 最后再套用刚暂存下来的本地变动
 
有冲突怎么办?
rebase跟merge相似,出现conflict会暂停rebase动做,须要你手动修复后,而后才能够继续动做。这也是rebase比merge复杂一点的地方:merge若是发生conflict,你只须要解决冲突一次,而后commit出去就完成了。而rebase的conflict可能会发生在上述步骤4的每一次从新套用上,因此可能须要解决冲突好几回。
 
到底何时用merge?何时用rebase?
若是你修改比较多,预期会有较多的conflict,建议用merge。(不过,若是是屡次大范围的主题式修改,那是否是应该一开始就多开一个branch来作呢?)。
若是改动范围较小,不太预期有conflict,则建议能够加上rebase参数。
 
若是想要把 rebase 當作 git pull 的預設值,能够在專案的 .git/config 加上
[branch "master"]
remote = origin
merge = refs/heads/master
rebase = true
 
也能够直接加到 ~/.gitconfig 讓全部的 tracked branches 都自動套用這個設定:
[branch]
autosetuprebase = always
 

合并

在将其余分支的代码合并到当前分支时,若是那个分支是当前分支的父分支,为了保持图表的可读性和可追踪性,能够考虑用 git rebase 来代替 git merge;反过来或者不是父子关系的两个分支以及互相已经 git merge 过的分支,就不要采用 git rebase 了,避免出现重复的冲突和提交节点。

分支命名

除了主要分支的名字是固定的以外,派生分支是须要本身命名的,这里就要有个命名规范了。强烈推荐用以下形式:
feature——按照功能点(而不是需求)命名;
release——用发布时间命名,能够加上适当的前缀;
hotfix——GitLab 的 issue 编号或 bug 性质等。

另外还有 tag,用语义化的版本号命名。

 

0三、连接

相关文章
相关标签/搜索