本文原本打算按照介绍功能方式来写,但是写了一部分发现也没啥可写的。功能放在那有点经验的都会用,所以决定重新来过从使用场景角度来介绍gogs。
简介
Git代码托管平台最著名的当属GitHub,国内的也有码云可以使用。如果自己想搭建一个Git托管平台,最著名的就是使用GitLab。但是出于简单易用的考虑我们公司最终选择了Gogs作为了自己的Git托管平台。
Gogs (Go Git Service) 是一款极易搭建的自助 Git 服务。Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自助 Git 服务。使用 Go 语言开发使得 Gogs 能够通过独立的二进制分发,并且支持 Go 语言支持的 所有平台,包括 Linux、Mac OS X、Windows 以及 ARM 平台。
Gogs提供了最简单易用的Git项目组多人协作管理系统。其主要功能包括仓库管理、组织管理、用户管理、代码权限管理、代码提交管理、及行为记录等功能。
官网:https://gogs.io/
安装与配置
安装与配置官网上提供了比较详细的介绍,况且不同版本的配置情况也可能不同。
所以只给出官网说明链接
官方说明:https://gogs.io/docs/intro
协作方式
本人觉得在说明之前有必要讨论一下项目的协作方式。
我们将项目组分为两个组织,接口组和手机客户端组。每个组内根据仓库数量决定团队数量,也就是每个仓库由一个团队负责。仓库中创建一个master分支作为生产上线分支,上线前将测试过的开发分支代码合并到master分支并创建tag进行版本标记。每个仓库可能有多个开发分支,管理并行开发的业务模块。程序员只有业务分支的提交权限,主干由开发组长统一管理。
管理研发团队
我们使用gogs首先要做的就是将自己的研发团队录入进来,并进行有效的分类与组织。
下面分步骤说明一下大致过程
1、创建用户
为项目组成员创建gogs账户。我们一般会将“最大允许创建仓库数量”数量设置为0不允许程序员自己创建远程仓库。
创建完成后需要团队成员在“用户设置”中,填写自定义名称、上传头像、设置自己的密码、配置SSH公钥等操作。
2、创建组织
组织的创建仁者见仁智者见智。如果项目组比较小则建立一个组织分配几个团队即可,机构繁杂的话可以多建几个组织。每个组织都拥有自己的一些仓库,如果各个部门不需要共用仓库则可以分开建立组织。比如我们公司就创建了两个组织即接口组和手机客户端组,这两个组织的仓库没有交集。
3、创建团队
团队成员拥有同样的协作仓库和同样的仓库读写权限。我理解类似于一种角色定义。团队的建立主要建立在不同仓库和不同读写权限的基础上。git不能够按照目录来分配权限(用惯了SVN这点比较蛋疼),所以显然共用同一仓库的程序员不需要建两个团队。我们公司业务组两个仓库接口和管理后台,我们就建立两个团队进行管理,当然团队成员是可以重复的。
4、增加团队成员
可以在现有用户中选择团队成员。团队成员添加后自动成为组织成员。
分配仓库权限
1、创建仓库
创建仓库的所有人可以是一个用户或一个组织。如果是一个组织该组织管理员则对该仓库存在管理权限。
仓库可以设置为共有或私有。共有项目类似于开源的性质,所有用户都可以clone。所以我们的仓库全部都是私有的,只给需要的人添加协作关系。
2、分配团队仓库
一个团队如果分配了某个仓库那么,该仓库将成为团队内所有成员的协作仓库。
3、分配用户仓库
我们也可以将一个仓库设置为某个人的协作仓库。一般都是通过团队分配仓库,除非某一个人对仓库的权限与其他人不同这时我们可以在这里单独配置。常见情况就是开发组长要拥有仓库的管理权限,在这里单独配置。
4、仓库权限
仓库权限主要分为读取权限、写入权限、管理权限。
读取权限:拥有查看和克隆所属仓库的权限。
写入权限:拥有查看、克隆和推送所属仓库的权限。
管理权限:拥有查看、克隆、推送和添加其他组织成员到团队的权限。
程序员一般分配写入权限,项目组长分配管理权限。
(这里需要注意拥有了仓库的读写权限也是有可能无法推送的,因为分支是可以限制推送的,之后的分支部分详细说明)
分支管理
1、创建分支
仓库创建好了之后会创建一个默认分支master。但是gogs并没有提供创建分支的功能(至少我用的版本没有)。如果我们需要创建一个dev分支就需要在本地先创建一个dev分支,然后推送到gogs远程仓库中。
$ git branch dev$ git push -u origin dev:dev
2、保护分支
保护分支是很重要的,因为你无法限制程序员的水平和细心程度。程序员就有分支提交错误或误删分支的可能性,我们要将出错的可能性限制在最小。
下图显示了我们能够在分支保护中限制的内容
我们的做法是将生产分支(master)勾选第一和第三项,并选择开发组长为可推送代码的成员,这样就保证只有开发组长能够变更生产分支代码。而将开发分支(dev)勾选第一项,避免程序员误删分支。
冲突处理
处理冲突是本人比较头痛的事情,也可能是学艺不精吧。以前公司就经常有处理冲突把代码弄丢的情况,所以处理冲突最好还是小心再小心。
1、代码commit前冲突处理
这冲情况一般就是两个程序员从同一节点pull代码,然后又修改了同一个文件。
如果我们在commit代码之前pull分支,系统会提示文件将会被覆盖,请提交或储藏他们。
error: Your local changes to the following files would be overwritten bymerge:README.mdPleasecommityour changesorstash thembeforeyou merge.
这时我们可以使用命令git stash储藏工作,查看储藏区git stash list。
$ git stashSaved working directory and index state WIP on dev: 7725ccf 2018年4月2日09:20:15$ git stash liststash@{0}: WIP on dev: 7725ccf 2018年4月2日09:20:15
然后再进行pull。成功pull后我们要恢复储藏区内容git stash pop --index
$ git stash pop--indexAuto-merging README.mdCONFLICT (content):MergeconflictinREADME.mdIndexwasnotunstashed.
恢复时提示那些文件合并冲突,这时我们就要手动解决冲突。
之后git add .将合并后的工作提交到暂存区。至此冲突解决完成。
$ git add .$ git statusOn branch devYour branch is ahead of 'origin/dev' by 20 commits. (use"git push"topublish yourlocalcommits)Changestobe committed: (use"git reset HEAD
2、代码commit后冲突处理
如果我们在commit代码之后pull分支,系统会要求我们处理冲突。
CONFLICT (content):MergeconflictinREADME.mdAutomaticmergefailed; fix conflicts and thencommitthe result.
然后我们手动进行冲突处理。
之后git add .将合并后的工作提交到暂存区。至此冲突解决完成。
$ git add .$ git statusOn branch devYour branch is ahead of 'origin/dev' by 20 commits. (use"git push"topublish yourlocalcommits)Changestobe committed: (use"git reset HEAD
3、主干合并冲突处理
我们在使用不同开发分支向主干master合并(rebase)的时候,如果不同开发分支修改了同一文件则会产生冲突。
rebase 时系统提示合并产生冲突错误
First, rewinding head to replay your work on top of it...Applying: 测试上传error: Failed tomergeinthe changes.Usingindexinfotoreconstruct a base tree...M README.mdFalling backtopatching baseand3-way merge...Auto-merging README.mdCONFLICT (content):MergeconflictinREADME.mdPatchfailedat0001测试上传The copyofthepatchthatfailedisfoundin: .git/rebase-apply/patchWhenyou have resolved this problem, run"git rebase --continue".Ifyou prefertoskipthispatch, run"git rebase --skip"instead.Tocheckoutthe original branchandstoprebasing, run"git rebase --abort".
手动解决冲突后git add . 并继续变基 git rebase --continue
$git rebase --continueApplying: 2018年4月2日09:20:15
如果文件被修改多次则变基时每次都会提示冲突,我们就要一次次修改并继续。
虽然我们已经在master分支处理了冲突,但是“补丁分支”代码仍然存在冲突。为了避免下次还要处理这些冲突,我们最好重新生成开发分支,使开发分支代码与最新的master一致后再进行后续开发。
生产上线
当开发分支通过测试满足上线要求时,我们通过变基方式将开发分支合并到master分支,然后在master分支打标签确定上线版本。
1、开发组长将最新的开发分支和master分支pull到本地。
$ git pull
2、然后切换到开发分支执行变基
$ git checkout masterSwitched to branch 'master'$ git rebase devFirst, rewinding head to replay your work on top of it...Fast-forwarded master to dev.
3、创建上线标签
$git tag -a v3.5.0 -m"v3.5.0 go live"$ git tag -nv3.5.0 v3.5.0 go live
4、将变基后的代码和标签推送到远程仓库
$ git pushCounting objects: 113,done.Delta compression using up to 8 threads.Compressing objects: 100% (113/113),done.Writing objects: 100% (113/113), 9.66 KiB | 0 bytes/s,done.Total 113 (delta 72), reused 0 (delta 0)To ssh://192.168.17.247:10022/PL_service_department/pmall.git 8866a0b..c7a8275 master -> master
5、服务器使用生成的标签部署服务
修改生产bug
在生产中修改bug时,我们需要在开发分支修复测试后再同步到生产中去。
显然一次提交不可能同时存在于分叉的分支中,这里我们需要使用cherry-pick
1、从生产分支创建生产bug分支
gitbranch bug1
2、在生产bug分支上修改代码
3、修改完成后cherry-pick到dev开发分支
$ git checkout dev$ git cherry-pick f8d2c51e2230e04dfa81e52458d662afd18ec085$ git push
4、测试开发分支
5、测试通过后将bug分支推送到远程仓库
$ git checkout bug1Switched to branch'bug1'$ git push -u origin bug1:bug1Total0(delta0), reused0(delta0)To ssh://192.168.17.247:10022/PL_service_department/pmall.git* [newbranch] bug1 -> bug1Branch bug1setup to track remote branch bug1fromorigin.
6、开发组长获取bug1分支并且合并到master进行生产部署
$ git rebase origin/bug1First, rewinding head to replay your work on top of it...Fast-forwarded master to origin/bug1.$ git pushTotal 0 (delta 0), reused 0 (delta 0)To ssh://192.168.17.247:10022/PL_service_department/pmall.git c7a8275..9bbeea4 master -> master
7、删除远程bug分支
$ git push origin:bug1Tossh://192.168.17.247:10022/PL_service_department/pmall.git - [deleted] bug1
合并提交(交互式变基)
我们在本地开发代码时会经历多次提交,但是这些提交过程对于远程仓库显然是没有意义的。远程仓库只希望得到最后提交的总体信息。所以我们就要进行和并提交。
1、首先我们在本地进行多次commit
2、进入编辑模式git rebase -i HEAD^^^
$git rebase -i HEAD^^^
3、此时我们将除第一次提交以外的提交设置为squash(简写s)并保存,squash代表跟随之前的提交
4、然后系统提示合并前几次提交的说明
5、最后我们使用git log查看提交日志发现已经进行了合并