版本管理之gitlab实践教程:进阶篇(2)

github flow实践

git flow的问题

git flow是一个较早的版本管理模型,但是也有一些实际在使用上的问题。第一个常见的问题就是因为git flow的模型设计是围绕着release进行的,所以master成为了一个
用于保存向生产环境发布代码的分支,而真正的主分支我们使用的是develop分支而不是master分支,但是无论是交流上还是一些工具的缺省设定,一般都会直接使用master,
这跟我们通常的说法不同,所以每次都需要解释:这种分支模型的develop分支就是经常意义上的master主分支。
而另外一个问题则是git flow模型还是较为复杂,对于缺乏版本管理知识的普通开发者来说,学习曲线和使用成本较高。
随着持续集成和持续部署在很多项目中的推动,项目越来越多进行持续的发布,而像传统的开发方式那样,同时多功能合并在一个大版本中一起发布的情形越来越少,
取而代之的则是小步快跑,持续集成结合继续部署,使得传统模式下复杂分支管理的需求变得越来越少,很多时候只需要一个master分支即可,而正是这种情况则是github flow提出的原因。

github flow产生的契机

正如Scott Chacon在他的文章中提到的那样:既然已经有git flow了,为什么github不是直接用git flow就好了呢?这个模型过于复杂,项目实际需要的似乎比其简单的多。
于是在这个基础之上,在github,他们没有使用git flow,而是使用了一个更加简单的git工作流程,这个简化的模型就是github flow。
而且更为重要的原因,围绕着release设计的fit flow模型对github来说缺乏吸引力的重要原因是release对github来说从来都不是问题而也也没有成为问题过,每天github都可以release多次,
他们甚至可以通过hobot机器人自动做到这些,整个部署的流程对每个开发者来说都不是什么问题,持续集成的基础已经非常的好,所以在这个基础之上,会理所当然地认为更为简单的模型就能够解决这个问题。
这里写图片描述

git flow的主要特点

长期分支

github flow只有一条master长期分支用于管理随时可以进行发布的分支,在master分支上的一切都被认为是可以随时可以进行部署到生产环境的内容。

临时分支

github flow不同于git flow存在release/hotfix/feature三类分支,github flow只有一种分支就是特性分支。无论是bug修正还是特性开发在github flow中都是特性分支。

Pull Request

github的Pull Request分支提供了一种review和合并的机制,在gitflow中,这种机制也被使用地淋漓尽致。github flow使用Pull Request用于取得feedback以及合并。

github flow使用方式

github flow在使用时主要遵循如下方式:
第一:只有可以部署的内容才会放到master分支上,所以master分支上的任何内容都是可部署的。

第二:特性分支的创建需要以master为基础,同时特性分支的命名需要意义清晰,容易理解。

第三:特性分支需要经常更新到远程仓库中,远程仓库中的特性分支应与本地特性分支名称相同。

第四:当需要反馈或者帮助的时候,或者当分支已经可以进行合并的时候,随时可以开启一个pull request。

第五:仅当pull request通过review之后才进行合并。

第六:一旦合并之后并推送到master分支,则意味着此内容已经随时可以进行部署,根据持续集成的原则,可以也应当立即进行部署。

github flow的模拟使用

接下来我们使用gitlab10.4.2以及git1.8.3.1来模拟一下github flow开发的流程。

创建一个项目

首先我们使用gitlab的restapi创建一个项目,当然也可以直接在gitlab上进行图形界面操作,具体命令如下,请根据自己的gitlab的URL和token进行修改, 另外jq命令如果没有可以不使用,对结果不产生影响,仅仅对结果的显示格式进行整形而已

执行命令

curl –request POST –header “PRIVATE-TOKEN: sqiSUhn3tHYXe8nSGRDi” –data “name=githubflowmodel” “http://127.0.0.1:32001/api/v4/projects” |jq .

执行log

[root@devops ~]# curl --request POST --header "PRIVATE-TOKEN: sqiSUhn3tHYXe8nSGRDi" --data "name=githubflowmodel" "http://127.0.0.1:32001/api/v4/projects" |jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1931  100  1911  100    20   1139     11  0:00:01  0:00:01 --:--:--  1140
{
  "id": 3,
  "description": null,
  "name": "githubflowmodel",
  "name_with_namespace": "Administrator / githubflowmodel",
  "path": "githubflowmodel",
  "path_with_namespace": "root/githubflowmodel",
  "created_at": "2018-02-04T19:15:18.826Z",
  "default_branch": null,
  "tag_list": [],
  "ssh_url_to_repo": "git@3ff5a6afdc80:root/githubflowmodel.git",
  "http_url_to_repo": "http://3ff5a6afdc80/root/githubflowmodel.git",
  "web_url": "http://3ff5a6afdc80/root/githubflowmodel",
  "avatar_url": null,
  "star_count": 0,
  "forks_count": 0,
  "last_activity_at": "2018-02-04T19:15:18.826Z",
  "_links": {
    "self": "http://3ff5a6afdc80/api/v4/projects/3",
    "issues": "http://3ff5a6afdc80/api/v4/projects/3/issues",
    "merge_requests": "http://3ff5a6afdc80/api/v4/projects/3/merge_requests",
    "repo_branches": "http://3ff5a6afdc80/api/v4/projects/3/repository/branches",
    "labels": "http://3ff5a6afdc80/api/v4/projects/3/labels",
    "events": "http://3ff5a6afdc80/api/v4/projects/3/events",
    "members": "http://3ff5a6afdc80/api/v4/projects/3/members"
  },
  "archived": false,
  "visibility": "private",
  "owner": {
    "id": 1,
    "name": "Administrator",
    "username": "root",
    "state": "active",
    "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
    "web_url": "http://3ff5a6afdc80/root"
  },
  "resolve_outdated_diff_discussions": false,
  "container_registry_enabled": true,
  "issues_enabled": true,
  "merge_requests_enabled": true,
  "wiki_enabled": true,
  "jobs_enabled": true,
  "snippets_enabled": true,
  "shared_runners_enabled": true,
  "lfs_enabled": true,
  "creator_id": 1,
  "namespace": {
    "id": 1,
    "name": "root",
    "path": "root",
    "kind": "user",
    "full_path": "root",
    "parent_id": null
  },
  "import_status": "none",
  "import_error": null,
  "open_issues_count": 0,
  "runners_token": "Bw4ms91w3U2U1TcsdHzM",
  "public_jobs": true,
  "ci_config_path": null,
  "shared_with_groups": [],
  "only_allow_merge_if_pipeline_succeeds": false,
  "request_access_enabled": false,
  "only_allow_merge_if_all_discussions_are_resolved": false,
  "printing_merge_request_link_enabled": true
}
[root@devops ~]# 

这样我们就创建了一个名为githubflowmodel的gitlab项目了。

初期化项目

初期化master分支

git clone远程仓库内容,进行结果确认

[root@devops ~]# git clone http://192.168.163.154:32001/root/githubflowmodel.git
Cloning into 'githubflowmodel'...
Username for 'http://192.168.163.154:32001': root
Password for 'http://[email protected]:32001': 
warning: You appear to have cloned an empty repository.
[root@devops ~]# cd githubflowmodel/
[root@devops githubflowmodel]# git branch
[root@devops githubflowmodel]# git remote -v
origin  http://192.168.163.154:32001/root/githubflowmodel.git (fetch)
origin  http://192.168.163.154:32001/root/githubflowmodel.git (push)
[root@devops githubflowmodel]# 
[root@devops githubflowmodel]#

对项目进行初期化,创建master分支,在master分支上添加一个文件C1,并将此文件推送到远端仓库。

[root@devops githubflowmodel]# touch C1; git add C1; git commit -m "add C1";
[master (root-commit) d432a66] add C1
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 C1
[root@devops githubflowmodel]# git push origin master
Username for 'http://192.168.163.154:32001': root
Password for 'http://[email protected]:32001': 
Counting objects: 3, done.
Writing objects: 100% (3/3), 199 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To http://192.168.163.154:32001/root/githubflowmodel.git
 * [new branch]      master -> master
[root@devops githubflowmodel]#

以master为基础创建特性分支add-navigation

[root@devops githubflowmodel]# git checkout -b add-navigation master
Switched to a new branch 'add-navigation'
[root@devops githubflowmodel]# 

向新分支内添加文件C2

[root@devops githubflowmodel]# touch C2; git add C2; git commit -m "add C2";
[add-navigation c910267] add C2
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 C2
[root@devops githubflowmodel]#

创建Merge Request

github的PR(Pull Request),在gitlab中称为MR(Merge Request),这里创建一个MR以便进行评审或者合并

执行命令:curl –request POST –header “PRIVATE-TOKEN: sqiSUhn3tHYXe8nSGRDi” –data “id=3&source_branch=add-navigation&target_branch=master&title=MergeRequestOfNewBranch” “http://127.0.0.1:32001/api/v4/projects/3/merge_requests” |jq .

[root@devops githubflowmodel]# curl --request POST --header "PRIVATE-TOKEN: sqiSUhn3tHYXe8nSGRDi" --data "id=3&source_branch=add-navigation&target_branch=master&title=MergeRequestOfNewBranch" "http://127.0.0.1:32001/api/v4/projects/3/merge_requests" |jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1106  100  1022  100    84   2861    235 --:--:-- --:--:-- --:--:--  2870
{
  "id": 1,
  "iid": 1,
  "project_id": 3,
  "title": "MergeRequestOfNewBranch",
  "description": null,
  "state": "opened",
  "created_at": "2018-02-04T19:26:14.543Z",
  "updated_at": "2018-02-04T19:26:14.543Z",
  "target_branch": "master",
  "source_branch": "add-navigation",
  "upvotes": 0,
  "downvotes": 0,
  "author": {
    "id": 1,
    "name": "Administrator",
    "username": "root",
    "state": "active",
    "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
    "web_url": "http://3ff5a6afdc80/root"
  },
  "assignee": null,
  "source_project_id": 3,
  "target_project_id": 3,
  "labels": [],
  "work_in_progress": false,
  "milestone": null,
  "merge_when_pipeline_succeeds": false,
  "merge_status": "unchecked",
  "sha": null,
  "merge_commit_sha": null,
  "user_notes_count": 0,
  "discussion_locked": null,
  "should_remove_source_branch": null,
  "force_remove_source_branch": null,
  "web_url": "http://3ff5a6afdc80/root/githubflowmodel/merge_requests/1",
  "time_stats": {
    "time_estimate": 0,
    "total_time_spent": 0,
    "human_time_estimate": null,
    "human_total_time_spent": null
  },
  "subscribed": true,
  "changes_count": null
}
[root@devops githubflowmodel]#

#

[root@devops githubflowmodel]# git branch
* add-navigation
  master
[root@devops githubflowmodel]# git push origin add-navigation
Username for 'http://192.168.163.154:32001': root
Password for 'http://[email protected]:32001': 
Counting objects: 3, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 225 bytes | 0 bytes/s, done.
Total 2 (delta 0), reused 0 (delta 0)
remote: 
remote: View merge request for add-navigation:
remote:   http://3ff5a6afdc80/root/githubflowmodel/merge_requests/1
remote: 
To http://192.168.163.154:32001/root/githubflowmodel.git
 * [new branch]      add-navigation -> add-navigation
[root@devops githubflowmodel]# 

Accept MR

执行命令:curl –request PUT –header “PRIVATE-TOKEN: sqiSUhn3tHYXe8nSGRDi” –data “id=3&merge_request_iid=1” “http://127.0.0.1:32001/api/v4/projects/3/merge_requests/1/merge” |jq .

执行日志

[root@devops githubflowmodel]# curl --request PUT --header "PRIVATE-TOKEN: sqiSUhn3tHYXe8nSGRDi" --data "id=3&merge_request_iid=1" "http://127.0.0.1:32001/api/v4/projects/3/merge_requests/1/merge" |jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1125  100  1101  100    24   2240     48 --:--:-- --:--:-- --:--:--  2242
{
  "id": 1,
  "iid": 1,
  "project_id": 3,
  "title": "MergeRequestOfNewBranch",
  "description": null,
  "state": "merged",
  "created_at": "2018-02-04T19:26:14.543Z",
  "updated_at": "2018-02-04T19:37:41.705Z",
  "target_branch": "master",
  "source_branch": "add-navigation",
  "upvotes": 0,
  "downvotes": 0,
  "author": {
    "id": 1,
    "name": "Administrator",
    "username": "root",
    "state": "active",
    "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
    "web_url": "http://3ff5a6afdc80/root"
  },
  "assignee": null,
  "source_project_id": 3,
  "target_project_id": 3,
  "labels": [],
  "work_in_progress": false,
  "milestone": null,
  "merge_when_pipeline_succeeds": false,
  "merge_status": "can_be_merged",
  "sha": "c910267404bba74b86ad9b63ea79b350b559c71d",
  "merge_commit_sha": "069cdb85e6c5097f960c3f77e7e9791f3225c224",
  "user_notes_count": 0,
  "discussion_locked": null,
  "should_remove_source_branch": null,
  "force_remove_source_branch": null,
  "web_url": "http://3ff5a6afdc80/root/githubflowmodel/merge_requests/1",
  "time_stats": {
    "time_estimate": 0,
    "total_time_spent": 0,
    "human_time_estimate": null,
    "human_total_time_spent": null
  },
  "subscribed": true,
  "changes_count": "1"
}
[root@devops githubflowmodel]#

结果确认

本地状态确认

[root@devops githubflowmodel]# git log --graph --pretty=oneline
* c910267404bba74b86ad9b63ea79b350b559c71d add C2
* d432a6654faa78d46a67249ebfb59c230804e512 add C1
[root@devops githubflowmodel]# 
[root@devops githubflowmodel]# git checkout master
Switched to branch 'master'
[root@devops githubflowmodel]# git log --graph --pretty=oneline
* d432a6654faa78d46a67249ebfb59c230804e512 add C1
[root@devops githubflowmodel]# git pull
Username for 'http://192.168.163.154:32001': root
Password for 'http://[email protected]:32001': 
remote: Counting objects: 1, done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (1/1), done.
From http://192.168.163.154:32001/root/githubflowmodel
   d432a66..069cdb8  master     -> origin/master
Updating d432a66..069cdb8
Fast-forward
 C2 | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 C2
[root@devops githubflowmodel]# git log --graph --pretty=oneline
*   069cdb85e6c5097f960c3f77e7e9791f3225c224 Merge branch 'add-navigation' into 'master'
|\  
| * c910267404bba74b86ad9b63ea79b350b559c71d add C2
|/  
* d432a6654faa78d46a67249ebfb59c230804e512 add C1
[root@devops githubflowmodel]#
[root@devops githubflowmodel]# ls
C1  C2
[root@devops githubflowmodel]#

通过确认可以返现,merge操作是直接对远程仓库的操作本地库没有同步发生变化,取到远端仓库的最新信息之后,可以看到merge reqeust的对应从结果上来说与git merge –no-ff方式是基本一致,都会产生一个合并的节点,另外需要合并的新的分支的内容也已经合并进来了。

远程结果确认

确认所创建的名为githubflowmodel的project的merge信息,可以确认到标题为MergeRequestOfNewBranch的MR,此时已经是merged状态。
这里写图片描述

总结

github flow相对于两条长期存在的主分支和三类临时性分支构成的git flow来说,算是一个非常简单的git的工作流程模型,此模型只有一个主分支为master为长期存在,而其他情形都可以使用临时分支来进行对应,通过活用PR或者MR进行沟通和评审以及合并,结合Webhook自动调用jenkins的job来实现持续集成和持续交付会有很好的效果。

参考文章

http://scottchacon.com/2011/08/31/github-flow.html

猜你喜欢

转载自blog.csdn.net/liumiaocn/article/details/79266541