您的位置:首页 > 其它

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

2018-02-06 07:39 483 查看

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://root@192.168.163.154: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://root@192.168.163.154: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://root@192.168.163.154: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://root@192.168.163.154: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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: