gitosis 安装使用及错误整理

为了代码托管,自己利用vps建立了git托管服务器,作为自己使用原本可以直接登录管理,但是为了体验powerful的具有权限管理的git管理工具——gitosis,也是花了好几天时间来摸索。此篇文章有自己整理资料,根据安装使用可能遇到的问题,汇总网络资料而成,主要参考引用:

git:gitosis官方资料

csdn:git错误大汇总

  • gitosis安装教程

Gitosis

把所有用户的公钥保存在 authorized_keys 文件的做法,只能凑和一阵子,当用户数量达到几百人的规模时,管理起来就会十分痛苦。每次改删用户都必须登录服务器不去说,这种做法还缺少必要的权限管理 — 每个人都对所有项目拥有完整的读写权限。

幸好我们还可以选择应用广泛的 Gitosis 项目。简单地说,Gitosis 就是一套用来管理 authorized_keys文件和实现简单连接限制的脚本。有趣的是,用来添加用户和设定权限的并非通过网页程序,而只是管理一个特殊的 Git 仓库。你只需要在这个特殊仓库内做好相应的设定,然后推送到服务器上,Gitosis 就会随之改变运行策略,听起来就很酷,对吧?

Gitosis 的安装算不上傻瓜化,但也不算太难。用 Linux 服务器架设起来最简单 — 以下例子中,我们使用装有 Ubuntu 8.10 系统的服务器。

Gitosis 的工作依赖于某些 Python 工具,所以首先要安装 Python 的 setuptools 包,在 Ubuntu 上称为 python-setuptools:

$ apt-get install python-setuptools

接下来,从 Gitosis 项目主页克隆并安装:

$ git clone https://github.com/tv42/gitosis.git
$ cd gitosis
$ sudo python setup.py install

这会安装几个供 Gitosis 使用的工具。默认 Gitosis 会把 /home/git 作为存储所有 Git 仓库的根目录,这没什么不好,不过我们之前已经把项目仓库都放在 /opt/git 里面了,所以为方便起见,我们可以做一个符号连接,直接划转过去,而不必重新配置:

$ ln -s /opt/git /home/git/repositories

Gitosis 将会帮我们管理用户公钥,所以先把当前控制文件改名备份,以便稍后重新添加,准备好让 Gitosis 自动管理 authorized_keys 文件:

$ mv /home/git/.ssh/authorized_keys /home/git/.ssh/ak.bak

接下来,如果之前把 git 用户的登录 shell 改为 git-shell 命令的话,先恢复 'git' 用户的登录 shell。改过之后,大家仍然无法通过该帐号登录(译注:因为 authorized_keys 文件已经没有了。),不过不用担心,这会交给 Gitosis 来实现。所以现在先打开 /etc/passwd 文件,把这行:

git:x:1000:1000::/home/git:/usr/bin/git-shell

改回:

git:x:1000:1000::/home/git:/bin/sh

好了,现在可以初始化 Gitosis 了。你可以用自己的公钥执行 gitosis-init 命令,要是公钥不在服务器上,先临时复制一份:

$ sudo -H -u git gitosis-init < /tmp/id_dsa.pub
Initialized empty Git repository in /opt/git/gitosis-admin.git/
Reinitialized existing Git repository in /opt/git/gitosis-admin.git/

这样该公钥的拥有者就能修改用于配置 Gitosis 的那个特殊 Git 仓库了。接下来,需要手工对该仓库中的 post-update 脚本加上可执行权限:

$ sudo chmod 755 /opt/git/gitosis-admin.git/hooks/post-update

基本上就算是好了。如果设定过程没出什么差错,现在可以试一下用初始化 Gitosis 的公钥的拥有者身份 SSH 登录服务器,应该会看到类似下面这样:

$ ssh git@gitserver
PTY allocation request failed on channel 0
ERROR:gitosis.serve.main:Need SSH_ORIGINAL_COMMAND in environment.
  Connection to gitserver closed.

说明 Gitosis 认出了该用户的身份,但由于没有运行任何 Git 命令,所以它切断了连接。那么,现在运行一个实际的 Git 命令 — 克隆 Gitosis 的控制仓库:

# 在你本地计算机上
$ git clone git@gitserver:gitosis-admin.git

这会得到一个名为 gitosis-admin 的工作目录,主要由两部分组成:

$ cd gitosis-admin
$ find .
./gitosis.conf
./keydir
./keydir/scott.pub

gitosis.conf 文件是用来设置用户、仓库和权限的控制文件。keydir 目录则是保存所有具有访问权限用户公钥的地方— 每人一个。在 keydir 里的文件名(比如上面的 scott.pub)应该跟你的不一样 — Gitosis 会自动从使用 gitosis-init 脚本导入的公钥尾部的描述中获取该名字。

看一下 gitosis.conf 文件的内容,它应该只包含与刚刚克隆的 gitosis-admin 相关的信息:

$ cat gitosis.conf
[gitosis]

[group gitosis-admin]
members = scott
writable = gitosis-admin

它显示用户 scott — 初始化 Gitosis 公钥的拥有者 — 是唯一能管理 gitosis-admin 项目的人。

现在我们来添加一个新项目。为此我们要建立一个名为 mobile 的新段落,在其中罗列手机开发团队的开发者,以及他们拥有写权限的项目。由于 'scott' 是系统中的唯一用户,我们把他设为唯一用户,并允许他读写名为 iphone_project 的新项目:

[group mobile]
members = scott
writable = iphone_project

修改完之后,提交 gitosis-admin 里的改动,并推送到服务器使其生效:

$ git commit -am 'add iphone_project and mobile group'
[master 8962da8] add iphone_project and mobile group
 1 file changed, 4 insertions(+)
$ git push origin master
Counting objects: 5, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 272 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@gitserver:gitosis-admin.git
   fb27aec..8962da8  master -> master

在新工程 iphone_project 里首次推送数据到服务器前,得先设定该服务器地址为远程仓库。但你不用事先到服务器上手工创建该项目的裸仓库— Gitosis 会在第一次遇到推送时自动创建:

$ git remote add origin git@gitserver:iphone_project.git
$ git push origin master
Initialized empty Git repository in /opt/git/iphone_project.git/
Counting objects: 3, done.
Writing objects: 100% (3/3), 230 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@gitserver:iphone_project.git
 * [new branch]      master -> master

请注意,这里不用指明完整路径(实际上,如果加上反而没用),只需要一个冒号加项目名字即可 — Gitosis 会自动帮你映射到实际位置。

要和朋友们在一个项目上协同工作,就得重新添加他们的公钥。不过这次不用在服务器上一个一个手工添加到 ~/.ssh/authorized_keys 文件末端,而只需管理 keydir 目录中的公钥文件。文件的命名将决定在 gitosis.conf 中对用户的标识。现在我们为 John,Josie 和 Jessica 添加公钥:

$ cp /tmp/id_rsa.john.pub keydir/john.pub
$ cp /tmp/id_rsa.josie.pub keydir/josie.pub
$ cp /tmp/id_rsa.jessica.pub keydir/jessica.pub

然后把他们都加进 'mobile' 团队,让他们对 iphone_project 具有读写权限:

[group mobile]
members = scott john josie jessica
writable = iphone_project

如果你提交并推送这个修改,四个用户将同时具有该项目的读写权限。

Gitosis 也具有简单的访问控制功能。如果想让 John 只有读权限,可以这样做:

[group mobile]
members = scott josie jessica
writable = iphone_project

[group mobile_ro]
members = john
readonly = iphone_project

现在 John 可以克隆和获取更新,但 Gitosis 不会允许他向项目推送任何内容。像这样的组可以随意创建,多少不限,每个都可以包含若干不同的用户和项目。甚至还可以指定某个组为成员之一(在组名前加上 @前缀),自动继承该组的成员:

[group mobile_committers]
members = scott josie jessica

[group mobile]
members   = @mobile_committers
writable  = iphone_project

[group mobile_2]
members   = @mobile_committers john
writable  = another_iphone_project

如果遇到意外问题,试试看把 loglevel=DEBUG 加到 [gitosis] 的段落(译注:把日志设置为调试级别,记录更详细的运行信息。)。如果一不小心搞错了配置,失去了推送权限,也可以手工修改服务器上的 /home/git/.gitosis.conf 文件 — Gitosis 实际是从该文件读取信息的。它在得到推送数据时,会把新的 gitosis.conf 存到该路径上。所以如果你手工编辑该文件的话,它会一直保持到下次向 gitosis-admin 推送新版本的配置内容为止。

********gitosis 权限管理和项目管理

在建立好gitosis服务器之后,即可通过本地gitosis-admin.git 中的gitosis.conf和keydir来进行权限管理和项目管理了。

权限管理可以通过添加members和设置writable\readonly等进行设置,以及通过本地即可添加ssh-key,无需登录git服务器。

项目管理也是通过gitosis-admin即可添加新的git,在gitosis.conf里面添加新的group,push到服务器,然后在本地建立git,进行push即可在服务器端建立相应的git。

例如:

我们要建立一个名为 mobile 的新段落,在其中罗列手机开发团队的开发者,以及他们拥有写权限的项目。由于 'scott' 是系统中的唯一用户,我们把他设为唯一用户,并允许他读写名为 iphone_project 的新项目:

[group mobile]
members = scott
writable = iphone_project

修改完之后,提交 gitosis-admin 里的改动,并推送到服务器使其生效:

$ git commit -am 'add iphone_project and mobile group'
[master 8962da8] add iphone_project and mobile group
 1 file changed, 4 insertions(+)
$ git push origin master
Counting objects: 5, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 272 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@gitserver:gitosis-admin.git
   fb27aec..8962da8  master -> master

在新工程 iphone_project 里首次推送数据到服务器前,得先设定该服务器地址为远程仓库。但你不用事先到服务器上手工创建该项目的裸仓库— Gitosis 会在第一次遇到推送时自动创建:

$ git remote add origin git@gitserver:iphone_project.git
$ git push origin master
Initialized empty Git repository in /opt/git/iphone_project.git/
Counting objects: 3, done.
Writing objects: 100% (3/3), 230 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@gitserver:iphone_project.git
 * [new branch]      master -> master

切记:设置的remote的url格式一定要对,如果出现错误:

$ git push git master
ERROR:gitosis.serve.main:Repository read access denied

fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

请查阅下一部分错误汇总4


  • gitosis错误汇总

1.Untracked working tree file 'external/broadcom/Android.mk' would be overwritten by merge.  Aborting

需要执行下面的命令才能修复:

[html]  view plain  copy
  1. git reset --hard HEAD    
  2. git clean -f -d    
  3. git pull    
2.Please, commit your changes or stash them before you can merge.

如果希望保留生产服务器上所做的改动,仅仅并入新配置项, 处理方法如下:

git stash
git pull
git stash pop

然后可以使用git diff -w +文件名 来确认代码自动合并的情况.

反过来,如果希望用代码库中的文件完全覆盖本地工作版本. 方法如下:

git reset --hard
git pull

其中git reset是针对版本,如果想针对文件回退本地修改,使用

[html]  view plain  copy
  1. git checkout HEAD file/to/restore    
3.does not appear to be a git repository

路径错误,可以分别尝试绝对路径或者相对路径

如果是把另一个服务器的纯仓库弄到服务器,也会出现这种情况。我的临时做法是把另一个服务器的内容clone到本地服务器,然后在本地服务器创建纯仓库,放到repository的路径下,就可以了。有关这个错误,我在这篇文章里尝试寻找原因:

http://blog.csdn.net/xzongyuan/article/details/9366873

4.ERROR:gitosis.serve.main:Repository read access denied

修改本地gitosis-admin的gitosis-conf后(如下),push到仓库中,还会遇到该问题

[group customer]
members = nexus b

readonly = box_4.2

***该错误特别容易出现在通过ssh非默认端口(22)访问git服务器,具体可参加git 命令格式:

The following syntaxes may be used with them:

  • ssh://[user@]host.xz[:port]/path/to/repo.git/

  • git://host.xz[:port]/path/to/repo.git/

  • http[s]://host.xz[:port]/path/to/repo.git/

  • ftp[s]://host.xz[:port]/path/to/repo.git/

在设置git remote add 时,也应注意此格式,与GitHub格式区分开。

****

原因1 gitosis.conf写错:
gitosis.conf中的members与keydir中的用户名不一致,如gitosis中的members = foo@bar,但keydir中的公密名却叫foo.pub
解决
使keydir的名称与gitosis中members所指的名称一致。

改为members = foo 或 公密名称改为[email protected]

参考
http://blog.csdn.net/lixinso/article/details/6526643

注意,中间如果遇到这样的错误,很可能是gitosis.conf配置的不对
ERROR:gitosis.serve.main:Repository read access denied
fatal: The remote end hung up unexpectedly

有可能是:
1. gitosis 中写的用户名,和keydir里面的key的名字没有完全对应上

2. 有的地方写错了,比如把members写成了member

3.注意:members添加的方法为=后面多个赋值,通过空格间隔。例如

members = John@Win10  Tom@Mac Test@test

不可写成:

members = John@Win10

members = Tom@Mac

切记keydir中公钥名称与members名称相同。 [email protected]  [email protected]

也可全部写成 John Tom Test,省去@。


原因2 地址错误:

虽然有时候,地址错误时,会提示did not apear to be a git repositry。但我也遇到这个错误,写错了相对路径,就会提示没有权限,因为gitosis.conf根本就没有这个文件的配置嘛。可以看看我的记录:

第一次,写错相对路径,自己不知道:

norton@norton-laptop:~/work$ git clone [email protected]:/repositories/gitosis-admin.git
Initialized empty Git repository in /home/norton/work/gitosis-admin/.git/
ERROR:gitosis.serve.main:Repository read access denied
fatal: The remote end hung up unexpectedly

第二次,故意写个不存在的路径

norton@norton-laptop:~/work$ git clone [email protected]:/repositories/gitosis-admin.git2
Initialized empty Git repository in /home/norton/work/gitosis-admin.git2/.git/
ERROR:gitosis.serve.main:Repository read access denied
fatal: The remote end hung up unexpectedly

第三次,写对相对路径。可见,相对路径的根目录是/home/git/repositories,记得不要多写了不必要的路径。提示一下,repositories是在初始化gitosis前就已经手动建立的,是一个软链接,链接到/home/repo。如果没做这一步,初始化的时候就会建立一个repositories文件夹,那么gitosis-admin这个仓库就会在这个实在的文件夹下,而不会通过软连接放到/home/repo中

norton@norton-laptop:~/work$ git clone [email protected]:gitosis-admin.git

Initialized empty Git repository in /home/norton/work/gitosis-admin/.git/
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 5 (delta 0), reused 5 (delta 0)
Receiving objects: 100% (5/5), done.

原因3:开错账户

有时候,头脑不清醒了,就会弄错账户,所以犯这个错,要思考下是不是搞错账户了,在主帐号admin中,不断地测试下载,而我的目的其实是用b的帐号测试下载。如配置如下(并没有给admin读取teamwork的权限,而我却一直在clone teamwork)

[gitosis]

[group gitosis-admin]
members = admin
writable = gitosis-admin test

[group RK_Download]
members = b nexus
readonly = teamwork box_4.2  

~                                                                               
~                                    

测试结果

admin@admin:~/work/test$ git clone [email protected]:test.git
Initialized empty Git repository in /home/admin/work/test/test/.git/
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.

admin@admin:~/work/test$ git clone [email protected]:teamwork.git
Initialized empty Git repository in /home/admin/work/test/teamwork/.git/
ERROR:gitosis.serve.main:Repository read access denied
fatal: The remote end hung up unexpectedly

admin@admin:~/work/test$ git clone [email protected]:teamwork.git
Initialized empty Git repository in /home/admin/work/test/teamwork/.git/
ERROR:gitosis.serve.main:Repository read access denied
fatal: The remote end hung up unexpectedly

admin@admin:~/work/test$ git clone [email protected]:teamwork.git
Initialized empty Git repository in /home/admin/work/test/teamwork/.git/
ERROR:gitosis.serve.main:Repository read access denied
fatal: The remote end hung up unexpectedly 


$ git clone [email protected]:test.git
Initialized empty Git repository in /tmp/test/.git/
ERROR:gitosis.serve.main:Repository read access denied
fatal: The remote end hung up unexpectedly

修改后
Initialized empty Git repository in /tmp/teamwork/test/.git/
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.

原因4: 不能写绝对路径

暂时不知道为啥,反正路径写了git@:/home/repo/xxx.git就会出现这个错误。貌似如果你如果密钥验证失败,要求你输入密码的情况下,是输入绝对路径的,而如果密钥验证成功,输入绝对路径,它就不认了。我想,这是为了保证系统安全,不让客户端用git账户乱clone不在repositories下的文件,即限定在repositories下了,所以只能用相对路径。

5.SSH: The authenticity of host can't be established
0 down vote

This message is just SSH telling you that it's never seen this particular host key before, so it isn't able to truly verify that you're connecting to the host you think you are. When you say "Yes" it puts the ssh key into your known_hosts file, and then on subsequent connections will compare the key it gets from the host to the one in the known_hosts file.

There was a related article on stack overflow showing how to disable this warning,http://stackoverflow.com/questions/3663895/ssh-the-authenticity-of-host-hostname-cant-be-established.


6.unrecognized command 'gitosis-serve b' && 每次登录要求输入密码

$ git clone [email protected]:/home/repo/teamwork.git
Initialized empty Git repository in /home/b/work/teamwork/.git/
fatal: unrecognized command 'gitosis-serve b'
fatal: The remote end hung up unexpectedly

遇到这个问题,b是我一个普通账户,而另一个admin每次登录都要求输入密码(ssh有两种登录方式:要求输入密码,和不需要输入密码——利用密钥),我就怀疑,gitosis的配置已经给我弄乱了,所以无法识别正确的密钥。
这个时候,我已经改了好多次密钥对,gitosis已经配置过好多次。通过gitosis-init是不会修复该问题的,于是,我删掉/home/git/下和repository有关的文件夹,包括.ssh下的authoritykey。还要删掉在/home/repo下的gitosis-admin.git。这样重新gitosis-init一下,就可以了。

如果server端的/etc/passwd中git的账户设置中,git使用的是/usr/bin/git-shell,而不是/bin/sh,也会报这个错误。

7.Agent admitted failure to sign using the key.

通过图形界面切换到b用户时,遇到这个问题,在原来到界面中,su b是可以clone的。

解決方式 使用 ssh-add 指令将私钥 加进来 (根据个人的密匙命名不同更改 id_rsa)
# ssh-add   ~/.ssh/id_rsa 

你可能感兴趣的:(git)