gitolite是基于ssh+git钩子的perl权限层,非git自带功能;其核心在于gitolite-shell拦截认证与权限控制,setup必须以git用户身份执行且公钥路径需可读,authorized_keys须含正确command前缀,克隆依赖ssh密钥匹配而非host别名,rw+允许强制推送而rw仅限fast-forward,配置中用户名必须与keydir下.pub文件名严格一致。

gitolite 不是 Git 自带功能,也不是靠改 authorized_keys 手动维护就能搞定的权限系统。它本质是一个基于 SSH + Git 钩子的 Perl 脚本层,所有权限逻辑都由 gitolite-shell 在服务端拦截并执行。直接上手容易卡在“克隆失败”“Permission denied”“fatal: Could not read from remote repository”这类错误上——问题通常不出在 Git,而在于 SSH 认证链或 gitolite setup 的上下文没对齐。
gitolite setup -pk 必须用 git 用户身份执行
很多人在 root 下把公钥传到 /tmp/admin.pub,然后切回 git 用户执行 gitolite setup -pk /tmp/admin.pub,结果 gitolite-admin.git 仓库创建了,但 ~/.ssh/authorized_keys 里没生成对应行,或者生成了却带了错误的命令前缀。
- 必须确保当前 shell 是
git用户(用su - git或sudo -u git -i),不能只是sudo -u git gitolite setup ... -
-pk路径必须是 git 用户能读的(/tmp下的文件,git 用户默认无权读;建议先cp /tmp/admin.pub ~/.ssh/再执行) - 执行后检查
~/.ssh/authorized_keys:开头几行应该有类似command="/home/git/bin/gitolite-shell admin",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty的条目
克隆 gitolite-admin 时 host 别名不是必需的,但 identityfile 必须匹配
很多教程教你在 ~/.ssh/config 里配 host git-server,再用 git clone git-server:gitolite-admin.git。这没问题,但不是必须。真正决定走哪把私钥的是 SSH 连接时的实际用户+主机+端口三元组,和你本地 config 里怎么 alias 无关。
- 如果没配 config,就老实用完整地址:
git clone git@your-server-ip:gitolite-admin.git - 此时 SSH 会默认尝试
~/.ssh/id_rsa;如果你管理员密钥叫admin,就必须加-i:ssh -i ~/.ssh/admin git@your-server-ip测试通了,git clone才可能成功 - Git 本身不读
~/.ssh/config的identityfile,它依赖底层 SSH;所以 config 写错、或私钥权限不对(必须600),都会导致 “Permission denied (publickey)”
conf/gitolite.conf 里 RW+ 和 RW 的区别直接影响 push 是否被拒
新手常以为 RW 就是“能推”,结果提交后 git push 报错 remote: FATAL: W access for 'refs/heads/master' denied to user。这是因为 RW 默认只允许 fast-forward 合并,不允许 force-push、删除分支、重写历史;而 RW+ 才放开这些操作。
-
RW→ 允许普通 push(前提是目标 ref 已存在且是 fast-forward) -
RW+→ 允许 push --force、push --delete、创建新分支、覆盖已有分支 - 权限行顺序重要:规则从上到下匹配,第一条命中即生效;不要把宽泛规则(如
RW+ = @all)写在具体规则前面 - 组定义必须在
conf/gitolite.conf顶部,例如:repo testing\n RW+ = admin\n RW = dev,其中admin和dev必须已在keydir/下有对应.pub文件
keydir/ 下公钥文件名必须和 conf 中用户名完全一致
这是最隐蔽也最常踩的坑。gitolite 不解析公钥内容,只按文件名匹配用户。你把 alice.pub 放进 keydir/,但在 gitolite.conf 里写 RW = alice123,那她永远没权限。
- 文件名就是用户名,不含
.pub后缀;alice.pub对应用户alice,不是alice@host或alice.pub - 上传后必须
git add keydir/alice.pub && git commit -m "add alice",否则服务端不会加载该密钥 - 修改已有用户公钥?直接替换
keydir/alice.pub文件内容,再 commit 推送即可;不需要重新 runsetup - 别手动编辑
~/.ssh/authorized_keys——gitolite每次 pushgitolite-admin都会全量重写它,手改会被清掉
实际跑通的关键,往往不在“会不会装”,而在于确认 SSH 认证是否真抵达了 gitolite-shell,以及 gitolite.conf 的语法和命名是否被严格遵循。任何一步跳过验证(比如没用 ssh -T git@server 看返回信息),后面都可能变成黑盒调试。











