Gitolite权限配置

基本含义:

C 代表创建,仅在通配符版本库授权是使用,用于指定谁可以创建与通配符匹配的版本库
R RW RW+ R为只读,RW为读写权限,RW+代表除了拥有读写权限,还可以强制执行推送
RWC RW+C
RWD RW+D D代表允许删除和正则匹配的引用
RWCD RW+CD

传统模式的引用授权
传统模式的引用授权指的是在授权指令中只采用R、RW和RW+的传统授权关键字,而不包括后面介绍的扩展授权指令。传统的授权指令没有把分支的创建和分支删除权限细分,而是和写操作及强制推送操作混杂在一起。

1 @administrators = jiangxin admin
2 @dev = dev1 dev2 badboy
3 @test = test1 test2
4
5 repo test/repo1
6 RW+ = @administrators
7 RW master refs/heads/feature/ = @dev
8 R = @test

关于授权的说明:
– 第6行,对于版本库test/repo1,管理员组用户jiangxin和admin可以读写任意分支、强制推送,以及创建和删除引用。
– 第7行,用户组@dev除了对master和refs/heads/feature/开头的引用具有读写权限外,实际上可以读取所有引用。这是因为读取操作授权阶段无法获知引用。
– 第8行,用户组@test对版本库拥有只读授权。

扩展模式的引用授权
扩展模式的引用授权,指的是该版本库的授权指令出现了下列授权关键字中的一个或多个:RWC、RWD、RWCD、RW+C、RW+D、RW+CD,将分支的创建权限和删除权限从读写权限中分离出来,从而可对分支进行更为精细的权限控制。
– 非快进式推送必须拥有上述关键字中的+方可授权。
– 创建引用必须拥有上述关键字中的C方可授权。
– 删除引用必须拥有上述关键字中的D方可授权。
即引用的创建和删除使用了单独的授权关键字,和写权限和强制推送权限分开。

1 repo test/repo2
2 RW+C = @administrators
3 RW+ = @dev
4 RW = @test
5
6 repo test/repo3
7 RW+CD = @administrators
8 RW+C = @dev
9 RW = @test
通过上面的配置文件,对于版本

库test/repo2.git具有如下的授权:
第2行,用户组@administrators中的用户,具有创建和删除引用的权限,并且能强制推送。
其中创建引用来自授权关键字中的C,删除引用来自授权关键中的+,因为该版本库授权指令中没有出现D,因而删除应用授权沿用传统授权关键字。
第3行,用户组@dev中的用户,不能创建引用,但可以删除引用,并且可以强制推送。
因为第2行授权关键字中字符C的出现,使得创建引用采用扩展授权关键字,因而用户组@dev不具有创建引用的权限。
第4行,用户组@test中的用户,拥有读写权限,但是不能创建引用,不能删除引用,也不能强制推送。
通过上面的配置文件,对于版本库test/repo3.git具有如下的授权:
第7行,用户组@administrators中的用户,具有创建和删除引用的权限,并且能强制推送。
其中创建引用来自授权关键字中的C,删除引用来自授权关键中的D。 –
第8行,用户组@dev中的用户,可以创建引用,并能够强制推送,但不能删除引用。
因为第7行授权关键字中字符C和D的出现,使得创建和删除引用都采用扩展授权关键字,因而用户组@dev不具有删除引用的权限。
第9行,用户组@test中的用户,可以推送到任何引用,但是不能创建引用,不能删除引用,也不能强制推送。
对路径的写授权

在授权文件中,如果一个版本库的授权指令中的正则引用字段出现了以NAME/开头的引用,则表明该授权指令是针对路径进行的写授权,并且该版本库要进行基于路径的写授权判断。

1 repo foo
2 RW = @junior_devs @senior_devs
3
4 RW NAME/ = @senior_devs
5 – NAME/Makefile = @junior_devs
6 RW NAME/ = @junior_devs

关于授权的说明:
– 第2行,初级程序员@junior_devs和高级程序员@senior_devs可以对版本库foo进行读写操作。
– 第4行,设定高级程序员@senior_devs对所有文件(NAME/)进行写操作。
– 第5行和第6行,设定初级程序员@junior_devs对除了根目录的Makefile文件外的其他文件具有写权限。

开发时关于git分支控制的一些心得

开发时关于git分支控制的一些心得(master-hotfix-develop-release)

项目代码正在重构,原来为了个人开发方便,都是从master分支(或一个中间分支)上建立一个自己的分支用于开发,开发完毕后将自己的分支merge到master分支(或一个中间分支),结束自己的分支。

在大量的提交后,会导致一些问题:

并没有版本上的控制,看起来就像一个版本一直在开发一样,不存在一个稳定的版本分支(或者master分支落后很多)。
个人的分支没有得到很好的测试,合并到master分支上可能有一些隐藏bug,导致master分支一直都处于不稳定的状态,出现棘手的问题时无法回退到一个稳定版本。
每个人的开发进度不一样,在merge到master分支时导致很多冲突。
在排查错误时,由于merge参数不统一导致master分支上有超级多的commit,只能在master分支上一点一点的回退版本,执行起来很麻烦。
个人的分支上传到GitHub上,导致远程仓库的分支杂乱无章。
参考了一个成功的git分支模型,对现在的git分支管理进行一些调整,便于规范开发。以本人目前开发的项目为例,项目名是visom-server。

一共有五种分支:master、hotfix、develop、release、self分支。master分支是一个主分支,主要提供一个稳定的版本,时刻都是稳定的保证随时可以上线应用。develop分支是一个和master分支并行的分支,用于主开发的分支。hotfix分支是热修复分支,主要用于修复master分支出现的意料之外的bug,属于临时分支,命名以”hotfix-xxx”为准。release分支是发布版本分支,在develop开发完成后做一些版本信息的或细节调整的分支,也属于临时分支,命名以”release-xxx”为准,xxx表示版本号。self分支是个人开发用的分支,命名无特殊要求。
master、develop分支是核心分支,是并行的一直存在在远程仓库的分支,分别提供稳定版本和主开发的作用。下面说一下完整的开发流程。整个流程相对于上面的参考博客比较,关于版本号的自动创建、规范以及其他版本相关的内容还没有完全吃透,所以对这部分和不适合本人公司开发情况的会有些删减,大家可以多提供意见,谢谢。(本人是使用vscode开发的,有些命令可以用vscode功能代替,比如创建、切换分支等)
master、develop分支
首先基于master分支建立一个develop分支,并将develop分支push到远程仓库里,做为开发的核心分支。
>git checkout -b develop master
>git push

基于develop分支建立自己的分支,做一些开发改动,完成后merge到develop分支而不是master分支。develop分支上有每一次改动提交的记录,所以注意merge时的参数。
>git checkout -b zhengsy develop // 基于develop分支创建并切换到zhengsy分支(自己开发的分支)
>git commit -a -m ‘修复project.index传参bug’ //开发代码后,将所有改动储存到本地并加以描述(分多次提交)
>git checkout develop // 切换到develop分支
>git merge –no-ff zhengsy //将zhengsy分支毫无保留的融合到develop分支
>git branch -d zhengsy // 删除zhengsy分支
// 整个过程中自己的分支并没有推送到远程仓库只存在与自己的本地。
// 如果有问题需要协助请推送到远程仓库,最后完成开发任务时请删除远程分支。

hotfix分支
master分支遇到紧急修复的bug时,请使用hotfix分支。hotfix分支也不会出现在远程仓库,只是一个本地的临时分支,融合时请保留提交记录。具体流程如下:

>git checkout -b hotfix-indexbug master // 基于master分支建立一个hotfix-indexbug分支,用于紧急修复
>git commit -a -m ‘修复index传参bug’ // 修复后,将所有改动储存到本地并加以描述(因为master分支是稳定的出现bug,也改动不大,一次性提交即可)
>
>更新master分支!!!!
>git checkout master // 切换到master分支(版本是v1.0.0)
>git merge –no-ff hotfix-indexbug // 将hotfix-indexbug分支融合到master分支
>git tag -a v1.0.1 -m ‘修复index的bug’ // 在本地有打一个版本的标签。(作用不是很明显)
>
>更新develop分支!!!!
>git check develop // 切换到develop分支
>git merge –no-ff hotfix-indexbug // 将hotfix-indexbug分支融合到develop分支
>
>删除hotfix分支
>git branch -d hotfix-indexbug

release分支(暂时作用不明显)
develop分支完成了版本升级任务,即可以给master分支提供下一个稳定版本时,请使用release分支。可能因为develop分支已经完成了该版本开发任务,可以执行下一个开发版本任务了,但为了使开发人员和版本维护人员可以并行,即开发人员继续使用develop分支开发下一个版本,版本维护人员使用release分支撰写该版本的一些信息和应付一些意料不到的小问题,所以使用release分支作为中转。使用release分支和hotfix分支类似,就不再重复命令了,注意分支命名规范。

有一点需要特殊说明的是,release分支融合到master分支时,请使用–squash参数;release分支融合到develop分支时,请使用–no-ff参数。即:

>// 将release-xxx分支融合到master分支
>git checkout master
>git merge –squash release-xxx
>
>// 将release-xxx分支融合到develop分支
>git checkout develop
>git merge –no-ff release-xxx

以上就是本人的一点心得,仍有不完善的地方比如版本说明方面的说明等,感觉版本方面还是使用GitHub上那种的比较好,即完成一个版本就在GitHub上生成一个版本,自己的本地tag更多的是自己方便一些。欢迎大家多提意见。以后有更完善的方案再来补充。

head,master,origin区别

HEAD: the current commit your repo is on. Most of the time HEAD points to the latest commit in your branch, but that doesn’t have to be the case. HEAD really just means “what is my repo currently pointing at”. Thanks svick for the heads up on this one (no pun intended)

In the event that the commit HEAD refers to is not the tip of any branch, this is called a “detached head”.

master: The name of the default branch that git creates for you when first creating a repo. In most cases, “master” means “the main branch”. Most shops have everyone pushing to master, and master is considered the definitive view of the repo. But it’s also common for release branches to be made off of master for releasing. Your local repo has its own master branch, that almost always follows the master of a remote repo.

origin: The default name that git gives to your main remote repo. Your box has its own repo, and you most likely push out to some remote repo that you and all your coworkers push to. That remote repo is almost always called origin, but it doesn’t have to be.

HEAD is an official notion in git, HEAD always has a well defined meaning. master and origin are common names usually used in git but they don’t have to be.

Git rebase的作用

多人在同一个分支上协作时,很容易出现冲突。即使没有冲突,后push的童鞋不得不先pull,在本地合并,然后才能push成功。

每次合并再push后,分支变成了这样:

$ git log –graph –pretty=oneline –abbrev-commit
* d1be385 (HEAD -> master, origin/master) init hello
* e5e69f1 Merge branch ‘dev’
|\
| * 57c53ab (origin/dev, dev) fix env conflict
| |\
| | * 7a5e5dd add env
| * | 7bd91f1 add new env
| |/
* | 12a631b merged bug fix 101
|\ \
| * | 4c805e2 fix bug 101
|/ /
* | e1e9c68 merge with no-ff
|\ \
| |/
| * f52c633 add merge
|/
* cf810e4 conflict fixed
总之看上去很乱,有强迫症的童鞋会问:为什么Git的提交历史不能是一条干净的直线?

其实是可以做到的!

Git有一种称为rebase的操作,有人把它翻译成“变基”。

rebase

我们从实际问题出发,看看怎么把分叉的提交变成直线。

在和远程分支同步后,我们对hello.py这个文件做了两次提交。用git log命令看看:

$ git log –graph –pretty=oneline –abbrev-commit
* 582d922 (HEAD -> master) add author
* 8875536 add comment
* d1be385 (origin/master) init hello
* e5e69f1 Merge branch ‘dev’
|\
| * 57c53ab (origin/dev, dev) fix env conflict
| |\
| | * 7a5e5dd add env
| * | 7bd91f1 add new env

注意到Git用(HEAD -> master)和(origin/master)标识出当前分支的HEAD和远程origin的位置分别是582d922 add author和d1be385 init hello,本地分支比远程分支快两个提交。

现在我们尝试推送本地分支:

$ git push origin master
To github.com:michaelliao/learngit.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to ‘git@github.com:michaelliao/learngit.git’
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., ‘git pull …’) before pushing again.
hint: See the ‘Note about fast-forwards’ in ‘git push –help’ for details.
很不幸,失败了,这说明有人先于我们推送了远程分支。按照经验,先pull一下:

$ git pull
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 3 (delta 1), reused 3 (delta 1), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:michaelliao/learngit
d1be385..f005ed4 master -> origin/master
* [new tag] v1.0 -> v1.0
Auto-merging hello.py
Merge made by the ‘recursive’ strategy.
hello.py | 1 +
1 file changed, 1 insertion(+)
再用git status看看状态:

$ git status
On branch master
Your branch is ahead of ‘origin/master’ by 3 commits.
(use “git push” to publish your local commits)

nothing to commit, working tree clean
加上刚才合并的提交,现在我们本地分支比远程分支超前3个提交。

用git log看看:

$ git log –graph –pretty=oneline –abbrev-commit
* e0ea545 (HEAD -> master) Merge branch ‘master’ of github.com:michaelliao/learngit
|\
| * f005ed4 (origin/master) set exit=1
* | 582d922 add author
* | 8875536 add comment
|/
* d1be385 init hello

对强迫症童鞋来说,现在事情有点不对头,提交历史分叉了。如果现在把本地分支push到远程,有没有问题?

有!

什么问题?

不好看!

有没有解决方法?

有!

这个时候,rebase就派上了用场。我们输入命令git rebase试试:

$ git rebase
First, rewinding head to replay your work on top of it…
Applying: add comment
Using index info to reconstruct a base tree…
M hello.py
Falling back to patching base and 3-way merge…
Auto-merging hello.py
Applying: add author
Using index info to reconstruct a base tree…
M hello.py
Falling back to patching base and 3-way merge…
Auto-merging hello.py
输出了一大堆操作,到底是啥效果?再用git log看看:

$ git log –graph –pretty=oneline –abbrev-commit
* 7e61ed4 (HEAD -> master) add author
* 3611cfe add comment
* f005ed4 (origin/master) set exit=1
* d1be385 init hello

原本分叉的提交现在变成一条直线了!这种神奇的操作是怎么实现的?其实原理非常简单。我们注意观察,发现Git把我们本地的提交“挪动”了位置,放到了f005ed4 (origin/master) set exit=1之后,这样,整个提交历史就成了一条直线。rebase操作前后,最终的提交内容是一致的,但是,我们本地的commit修改内容已经变化了,它们的修改不再基于d1be385 init hello,而是基于f005ed4 (origin/master) set exit=1,但最后的提交7e61ed4内容是一致的。

这就是rebase操作的特点:把分叉的提交历史“整理”成一条直线,看上去更直观。缺点是本地的分叉提交已经被修改过了。

最后,通过push操作把本地分支推送到远程:

Mac:~/learngit michael$ git push origin master
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 576 bytes | 576.00 KiB/s, done.
Total 6 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 1 local object.
To github.com:michaelliao/learngit.git
f005ed4..7e61ed4 master -> master
再用git log看看效果:

$ git log –graph –pretty=oneline –abbrev-commit
* 7e61ed4 (HEAD -> master, origin/master) add author
* 3611cfe add comment
* f005ed4 set exit=1
* d1be385 init hello

远程分支的提交历史也是一条直线。