如题

Git 权限管理工具

Git 仓库的权限管理,我们可以手动直接通过 ssh key 进行管理和配置,也可以通过其他辅助工具。
在 Git 服务管理工具这个领域,主要有三种流行的方案,它们分别是:

  1. Gitosis - 轻量级, 开源项目,使用SSH公钥认证,只能做到库级的权限控制。目前项目已经停止开发,不再维护。
  2. Gitolite - 轻量级,开源项目,使用SSH公钥认证,能做到分支级的权限控制。
  3. Git + Repo + Gerrit - 超级重量级,集版本控制,库管理和代码审核为一身。可管理大型及超大型项目。

    大名鼎鼎的 Android 平台就是使用的 Git + Repo + Gerrit。对于个人,中小型企业及一些开源项目而言,如果没有特殊的要求,其 Gitolite 提供的服务已经足够用了。

下面将详细讲解怎么搭建 Gitolite 服务器。

创建管理项目用的组 ggit 和用户 ugit

建一个git用户组和用户,用来运行git服务
ggit 前面的 g 代表 group, ugit 前面的 u 代表 user,组名和用户名都加前缀,以示区别。

1
2
3
4
groupadd ggit
mkdir -p /work
useradd ugit -g ggit -d /work/ugit # /work 为单独的分区,代码放到这个目录下更加安全,可避免由于操作系统出错导致的数据丢失
passwd ugit

安装 Gitolite

参考官方文档,下面有详细的安装步骤,这里的文档可忽略

客户端:在管理员电脑 win10 上,生成 SSH key 备用

  • 在管理员电脑上操作,以下为 win10 操作系统下的 Git Bash

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    $ ssh-keygen -t rsa -C "1614923608@qq.com"
    Generating public/private rsa key pair.
    Enter file in which to save the key (/c/Users/AndyChen/.ssh/id_rsa):
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    Your identification has been saved in /c/Users/AndyChen/.ssh/id_rsa.
    Your public key has been saved in /c/Users/AndyChen/.ssh/id_rsa.pub.
    The key fingerprint is:
    SHA256:gLOgJmZI4T5Z769yTwiSee3Ig7O/9MbNn04L0MGN0nY 1614923608@qq.com
    The key's randomart image is:
    +---[RSA 2048]----+
    | . |
    |. . .o o |
    | o..o..* E |
    |+.=.oo+.o |
    |+@ o.+ .S |
    |= * = o |
    | o =.+oo . |
    | +.o+ooo o |
    | ..o=oooo= |
    +----[SHA256]-----+
    $
  • 运行命令后,根据相关提示,输入路径和密码,如果用默认路径,如果不设置密码,则一路回车,直到生成 key。生成的 id_rsa.pub 文件备用。

服务器端:用管理员 SSH public key 来安装配置 gitolite

  1. 以 ugit 的身份登录。
  2. 确保在 ugit 用户根目录(登录之后默认就在用户根目录)。
  3. 上传上一步在 win10 下生成的公匙文件 id_rsa.pub,如我的位于:C:\Users\AndyChen\.ssh,其中 AndyChen 是计算机用户名。上传之后更改为管理员用户名。

    1
    [ugit@centOS7BasicForTest ~]$ mv id_rsa.pub andy.pub
  4. 拉取 gitolite 代码并安装

    1
    2
    3
    4
    git clone https://github.com/sitaramc/gitolite
    mkdir -p ~/bin
    ~/gitolite/install -to ~/bin
    ./bin/gitolite setup -pk andy.pub

    第一次执行,会提示:

    1
    2
    3
    4
    5
    6
    Initialized empty Git repository in /work/ugit/repositories/gitolite-admin.git/
    Initialized empty Git repository in /work/ugit/repositories/testing.git/
    WARNING: /work/ugit/.ssh missing; creating a new one
    (this is normal on a brand new install)
    WARNING: /work/ugit/.ssh/authorized_keys missing; creating a new one
    (this is normal on a brand new install)
    > 上面的警告,提示 .ssh 目录不存在并已经创建了,以及在该目录下不存在文件 authorized_keys,并创建了该文件。再次执行 `./bin/gitolite setup -pk andy.pub` ,因为已经存在目录和文件,所以不会再报警告。
    
  5. ./bin/gitolite setup -pk andy.pub 命令执行之后,会在 repositories 目录生成两个默认的仓库,其中 gitolite-admin 为远程管理的仓库,下面的介绍会用到。
    1
    2
    3
    4
    5
    6
    [ugit@centOS7BasicForTest ~]$ cd repositories/
    [ugit@centOS7BasicForTest repositories]$ ll
    total 8
    drwx------ 8 ugit ggit 4096 Jun 2 21:05 gitolite-admin.git
    drwx------ 7 ugit ggit 4096 Jun 2 21:05 testing.git
    [ugit@centOS7BasicForTest repositories]$

到这里,安装就算完成了,下面是讲如何管理(配置)项目(仓库)。

项目权限管理(配置)

如果服务器在公网,可以设置域名指向服务 ip,用域名即可

clone gitolite-admin

项目 clone, 一定要用 Git Bash(git clone …) 来操作,我试图用 TortoiseGit 客户端可视化界面来操作,提示输入密码,输入之后,提示 clone 失败,没做深入研究

  1. 接下来,管理员把远程管理仓库 gitolite-admin clone 到本地,用管理这个仓库的方式来管理 Git 项目(仓库),包括用户权限。
    • ugit@code.apg.com:gitolite-admin.git,仓库目录后面的 .git 可以省略,可写成:ugit@code.apg.com:gitolite-admin
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      # 下载远程管理仓库, 请把 code.apg.com 换成你自己服务器的域名或者 ip
      $ git clone ugit@code.apg.com:gitolite-admin.git
      Cloning into 'gitolite-admin'...
      The authenticity of host 'code.apg.com (192.168.1.91)' can't be established.
      ECDSA key fingerprint is SHA256:njf9IMbOojDSgS2lA2EEYxD2J5pPfPqaCDKIsO7iamA.
      Are you sure you want to continue connecting (yes/no)? yes
      Warning: Permanently added 'code.apg.com,192.168.1.91' (ECDSA) to the list of known hosts.
      Enter passphrase for key '/c/Users/AndyChen/.ssh/id_rsa': # ssh key 生成时,设置了密码,所以,在 clone 时需要输入密码,否则不会。
      remote: Counting objects: 10, done.
      remote: Compressing objects: 100% (7/7), done.
      remote: Total 10 (delta 1), reused 0 (delta 0)
      Receiving objects: 100% (10/10), done.
      Resolving deltas: 100% (1/1), done.
      $

注意,命令里的 ugit 是用户名。命令结构: git clone 用户名@ip/domain:项目名,一个项目对应一个以 .git 为后缀的目录名,clone 时,可不用写 .git 后缀。
下面这张截图特意去掉项目名后面的 .git 作了测试。

添加其他开发小伙伴

  1. 其他开发小伙伴,打开 Git Bash,用命令 ssh-keygen -t rsa -C “<邮箱>” 生成 SSH key 后,将 key 文件发给管理员。建议把<邮箱>换成真实的。
  2. 管理员将各开发伙伴的 key 文件(id_rsa.pub)添加到 gitolite-admin 仓库的 keydir 目录下,并根据不同人员重新命名,注意文件名字格式为 userName.pub,userName 是配置权限时要用到的用户名。

    管理员的 key 文件默认已经添加至该目录。

  3. 项目配置信息,通过文件 gitolite.conf 来配置(管理)。
  4. 第一次用 IDEA commit 代码时,会要求填写用户名和邮箱,写自己的账户名和邮箱即可,主要是为了方便代码管理,方便通过用户名或邮箱能识别到相应的开发人员。

通过文件 gitolite.conf 配置(管理)项目

配置用户对仓库的读写权限,直接修改 conf 文件夹下的 gitolite.conf 文件。

  1. repo:项目(仓库)名,如果新添加一个 repo,在 push 之后,服务端会自动新建一个对应的同名空仓库。
  2. RW:可读可写。
  3. @all:所有人。
  4. master 和 dev 为相应的分支。

参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@admin = andy
@dev = tom jeery rose

repo gitolite-admin # 定义了版本库 gitolite-admin。
RW+ = andy # 指定只有用户 andy 才能够访问,并拥有读(R)写(W)和强制更新(+)的权限。

repo temp/.+ # 通过正则表达式定义了一组版本库,即在 temp/ 目录下的所有版本库。
C = @admin # 用户组 @admin 中的用户,可以在 temp/ 目录下创建版本库。创建版本库的用户,具有对版本库操作的所有权限。
RW = @all # 所有用户都可以读写 temp 目录下的版本库,但不能强制更新。

repo projectName # 定义的 projectName 版本库授权使用了引用授权语法。
RW+ = @admin # 用户组 @admin 对所有的分支和里程碑拥有读写、重置、添加和删除的授权。
RW master = tom # 用户 tom 可以读写 master 分支。(还包括名字以 master 开头的其他分支,如果有的话)。
RW+ dev = @dev # 用户组 @dev 可以读写、强制更新、创建以及删除 dev 开头的分支。
RW test$ = jeery # 用户 jeery 可以读写 test 分支。 (仅此分支,精确匹配)。
RW refs/tags/v[0-9] = rose # 用户 rose 可以创建以 v+数字0到9的分支

更详细的请参考官方文档

注意事项

  1. 在 CentOS 上创建公钥,将 id_rsa.pub 改名,如改为 utomcat.pub,git clone,提示:fatal: Could not read from remote repository.
    • 解决办法,重新生成名为 id_rsa.pub 的公钥,或者将 utomcat.pub 再改回成 id_rsa.pub。
  2. 如果需要在多台服务器上,以不同的用户提供 ssh key,那么,需要创建不同的用户,分别生成公钥,shell 脚本在执行的时候,可以指定用户,这样即可达到目的。
    如,以 root 的身份执行的脚本,在脚本里再以 utomcat 的身份执行别的脚本文件,指令如下:

    1
    su - utomcat -lc "sh /home/utomcat/shell-script/startTomcat.sh"

    这可是血的教训,在测试环境上执行同步代码至 gitee 项目时,因为没配置好,让好几个同事等待了 10 多 20 分钟。

用 TortoiseGit clone 项目的坑

因为 gitolite 配置的是 ssh 公钥认证的方式,而 TortoiseGit 走用户名密码的方式,所以会要求输入密码,而 gitolite 的机制天生就不是针对用户名密码认证方式,所以行不通。

*会失败,不过还是记录一下,以免看官走弯路。

  1. 以下提示框,点【yes】

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #---------------------------
    TortoiseGitPlink Security Alert
    #---------------------------
    The server's host key is not cached in the registry. You
    have no guarantee that the server is the computer you
    think it is.
    The server's ssh-ed25519 key fingerprint is:
    ssh-ed25519 256 f7:4e:73:7b:fb:eb:4d:48:19:14:86:b0:16:3a:47:1e
    If you trust this host, hit Yes to add the key to
    PuTTY's cache and carry on connecting.
    If you want to carry on connecting just once, without
    adding the key to the cache, hit No.
    If you do not trust this host, hit Cancel to abandon the
    connection.

    #---------------------------
    Yes No Cancel
    #---------------------------


  2. 接下来,输入密码,输入用户 ugit 的密码,但提示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    git.exe clone --progress -v "ugit@code.apg.com:gitolite-admin.git" "C:\workspace\gitolite-admin"

    Cloning into 'C:\workspace\gitolite-admin'...
    fatal: 'gitolite-admin.git' does not appear to be a git repository
    fatal: Could not read from remote repository.

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

    git did not exit cleanly (exit code 128) (109219 ms @ 2018-06-03 9:07:57 AM)

  3. 密码说明
    • 此处确定是输入 ugit 的密码,而非 ssh 公匙的密码。
    • 如果随便输入,会提示认证失败,需要再次输入,输入 ugit 的密码,则直接输入操作结果,不过,这个结果是 clone 失败。
    • 同样的执行命令,即:git clone –progress -v “ugit@code.apg.com:testing” “C:\workspace\testing”,在 Git Bash 执行,能正常 clone,可能是 TortoiseGit 的某种机制导致了这种操作的失败,没有深入研究。

切换管理员

  1. 重新在管理员电脑上生成 SSH key

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    $ ssh-keygen -t rsa -C "552087293@qq.com"
    Generating public/private rsa key pair.
    Enter file in which to save the key (/c/Users/AndyChen/.ssh/id_rsa):
    /c/Users/AndyChen/.ssh/id_rsa already exists.
    Overwrite (y/n)? y
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    Your identification has been saved in /c/Users/AndyChen/.ssh/id_rsa.
    Your public key has been saved in /c/Users/AndyChen/.ssh/id_rsa.pub.
    The key fingerprint is:
    SHA256:F46f/NUi3nDqIpVhTnMsM224TeiXuksjttk+YLIe4Hw 552087293@qq.com
    The key's randomart image is:
    +---[RSA 2048]----+
    | |
    | |
    | .= |
    | o@.* |
    | . S=o& . |
    | o .. o+*.+ . |
    | o E+oo*oo + .|
    | ..o.*++ B . |
    | .. oo=*= . |
    +----[SHA256]-----+
  2. 将新生成的 SSH key 改成管理员的用户名,比如我的,改为:andy.pub,覆盖到 gitolite-admin 项目的 keydir 目录下的同名文件。

  3. 这时候直接 commit,push,会要求输入 ugit 的密码,而且 push 的时候,直接提示 push 失败。接着按下面的步骤操作。
  4. 以 ugit 的身份登录 Gitolite 所在服务器,删除之前的 SSH key,再上传上一步新生成的 id_rsa.pub,更名为管理员用户名(也许这一步非必须,感兴趣的童鞋自己试一下)mv id_rsa.pub andy.pub,再执行 ./bin/gitolite setup -pk andy.pub。因为之前执行该命令配置过项目,所以本次不会有任何提示,第一次会有提示,请看上面有关第一次配置的操作描述。
  5. 再次 push gitolite-admin 的更改,不会再要求输入 ugit 用户密码,push 成功。获取其它项目的最新,也成功了,说明管理员切换成功。

切换管理员之后记

如果管理员邮箱变了,相当于重新设置管理员。切换管理员之后,将生成的 id_rsa.pub 文件替换到 Gitolite 所在服务器的 ugit 根目录下并执行 ./bin/gitolite setup -pk andy.pub 即可,不用更新到 keydir 下也可正常 push 和 pull。

以下提示,可不管:

1
2
3
4
5
6
AndyChens-MacBook-Air-on-lenovo:temp andy$ git clone ugit@code.apg.com:exam
Cloning into 'exam'...
The authenticity of host 'code.apg.com (192.168.1.91)' can't be established.
ECDSA key fingerprint is SHA256:njf9IMbOojDSgS2lA2EEYxD2J5pPfPqaCDKIsO7iamA.
Are you sure you want to continue connecting (yes/no)? yes
...

其实在本地搭建 git 服务端,邮箱的真实性是无关紧要的。但是,如果我们想要借助 gitee 上线至生产环境,就需要把项目同步到 gitee 上的私有项目,这样的话,可以在 gitee 上查看提交情况,配置 SSH key 时用的邮箱地址会与 gitee 账号的邮箱地址匹配,这样,就知道是谁在什么时候提交了什么代码了,同时也支持不在办公室的环境下也能提交代码并最终同步至办公室的 git 环境,非常方便远程项目协作和远程项目管理。

管理员 clone gitolite-admin 的坑

git describe failed; cannot deduce version number

运行 ~/gitolite/install -to ~/bin 时提示 git describe failed; cannot deduce version number

git clone 的时候,我为了加快下载速度,用了参数 --depth 1 导致。

1
git clone --depth 1 https://github.com/sitaramc/gitolite

换成:

1
git clone https://github.com/sitaramc/gitolite

要求输入密码

此错误发生在 2019-08-30,新创建 git server 的过程中。之前按上面说明操作,非常顺利,这次操作花费了一个周末的时间也没能找到原因,汗~~。我只是换了一种思路满足了我的需求。

在管理员的电脑上(workstation),clone gitolite-admin 项目时,要求输入密码

1
2
3
$ git clone ugit@192.168.1.168:gitolite-admin
Cloning into 'gitolite-admin'...
ugit@192.168.1.168's password:

相关官方文档:appendix 1: ssh daemon asks for a password

输入 ugit 用户密码进行尝试(看过官方文档才知道,这种尝试是多余的)

在输入 ugit 用户密码后,提示:’gitolite-admin.git’ does not appear to be a git repository

1
2
3
4
5
6
7
8
$ git clone ugit@192.168.1.168:gitolite-admin.git
Cloning into 'gitolite-admin'...
ugit@192.168.1.168's password:
fatal: 'gitolite-admin.git' does not appear to be a git repository
fatal: Could not read from remote repository.

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

继续搜索解决方案,将项目名带上路径:repositories/gitolite-admin.git

1
2
3
4
5
6
7
8
9
$ git clone ugit@192.168.1.168:repositories/gitolite-admin.git
Cloning into 'gitolite-admin'...
ugit@192.168.1.168's password:
remote: Enumerating objects: 10, done.
remote: Counting objects: 100% (10/10), done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 10 (delta 1), reused 0 (delta 0)
Receiving objects: 100% (10/10), done.
Resolving deltas: 100% (1/1), done.

可以 clone 了,但是,push 时会报错,看了官方文档,如果在管理员电脑上(上传 ssh key 的电脑) clone gitolite-admin 项目时,提示需要密码,那一定是不正常的,即使通过添加项目路径成功 clone,在 push 时一样会报错,所以,这并不是解决方案。

push 报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ git push
ugit@192.168.1.168's password:
Counting objects: 6, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 811 bytes | 270.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
remote: Empty compile time value given to use lib at hooks/update line 6.
remote: Use of uninitialized value in require at hooks/update line 7.
remote: Can't locate Gitolite/Hooks/Update.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_per l /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at hooks/update line 7.
remote: BEGIN failed--compilation aborted at hooks/update line 7.
remote: error: hook declined to update refs/heads/master
To 192.168.1.168:repositories/gitolite-admin
! [remote rejected] master -> master (hook declined)
error: failed to push some refs to 'ugit@192.168.1.168:repositories/gitolite-admin'

官网相关错误的帮助说明https://gitolite.com/gitolite/emergencies.html#ce
摘抄如下:

  • common errors
    • WARNING: keydir/.pub duplicates a non-gitolite key, sshd will ignore it
      You used a key that is already set to give you shell access. You cannot use the same key to get shell access as well as access gitolite repos.
      Solution: use a different keypair for gitolite. There’s a wee bit more on this in the setup section of the install page. Also see why bypassing causes a problem and both the pages linked from ssh for background.
    • Empty compile time value given to use lib at hooks/update line 6
      (followed by Can’t locate Gitolite/Hooks/Update.pm in @INC a couple of lines later).
      You’re bypassing gitolite. You cloned the repo using the full path (i.e., including the repositories/ prefix), either directly on the server, or via ssh with a key that gives you shell access.
      Solution: same as for the previous bullet.
      NOTE: If you really must do it, and this is on the server and is a one-time thing, you can try gitolite push instead of git push. BUT… this defeats all gitolite access control, so if you’re going to do this often, maybe you don’t need gitolite!
  • why bypassing causes a problem

不算解决方案的解决方案

有关要求输入密码的官方文档https://gitolite.com/gitolite/sts#appendix-1-ssh-daemon-asks-for-a-password

看了很蒙,照着可能的方案操作,均以失败告终。比如:

  • 在 windows10 上新创建一个不同的管理员来生成密钥,用于管理 gitolite,失败。
  • 在 CentOS7 上创建一个新用户 ugitadmin 来生成密钥,用于管理 gitolite,失败。
  • 删除 ugit 用户,重新操作,失败。
  • 反复检查操作步骤,重新操作多次,均以失败告终。

于是

  • 我开始怀疑以前的操作步骤是否还适用于当前的 gitolite 版本。就差怀疑人生了~~
  • 反复看官方文档反复确认,为了验证文档的正确性,我在用于测试的虚拟机上按照文档操作,非常顺利,说明操作步骤是没有问题的,当然,文档本身也是没有问题的。
  • 尝试到这里,想起并进一步深刻的体会到那句业内流行的话了:如果系统有问题,终极解决方案就是重装系统,如果一次不能解决,那就再来一次,还不行,那就再重装~~
    • 估计我操作的那台 CentOS7 服务器,重新安装后再操作,一定就象我在虚拟机上操作一样顺利。
    • 不过,一想到重装,连带的软件以及项目环境都要从头配置,脑壳就开始痛了~~
  • 继续在服务器 CentOS7 上操作。后面的操作干脆彻底换一个用户名来安装 gitolite,管理 gitolite-admin 的用户也从 windows 上换到 CentOS7 上了,然后终于“大功告成”。

我的方案

原因分析

  • 也许是 ugit 这个用户本身的问题,哪怕删除再重新创建都不行,期间还重启之后再创建也不行。
  • 也许是另外一个用户 utomcat 影响到了,这个用户设置了 ssh 密钥并上传到 gitee.com 上,用于自动部署 gitee.com 上的项目。

删除旧用户,用新用户来配置

在 CentOS7 服务器上,删除用户 ugit 和 utomcat(删除前备份 utomcat home 目录下的文件),创建用户 git 用于安装 gitolite,创建用户 gitadmin 用来管理 gitolite-admin,成功!成功之后,再次创建用户 utomcat,用于管理 java 项目,创建之后,恢复该用户之前的文件,简单配置之后,utomcat 又重见天日了,就象未曾删除过一样,并且,重点是,对 gitolite 并无影响。

以下是操作步骤,用户目录采用默认配置:

1
2
useradd git
useradd gitadmin

以 gitadmin 身份登录,生成 ssh 密钥,不设置访问密码,一路回车,将 id_rsa.pub 存到 windows10,并重命名为 gitadmin.pub

1
ssh-keygen -t rsa

以 git 身份登录,上传 gitadmin.pub 到根目录

1
2
3
4
git clone https://github.com/sitaramc/gitolite
mkdir -p ~/bin
~/gitolite/install -to ~/bin
./bin/gitolite setup -pk gitadmin.pub

切换到 gitadmin,执行 git ls-remote git@127.0.0.1:gitolite-admin.git,没有要求输入密码,显示如下,则表示配置成功。

1
2
3
[gitadmin@localhost ~]$ git ls-remote git@127.0.0.1:gitolite-admin.git
dee261b6777ebd135be021f7d47ce41995a4a005 HEAD
dee261b6777ebd135be021f7d47ce41995a4a005 refs/heads/master

查看安装的 gitolite 版本

1
2
3
4
5
[gitadmin@localhost ~]$ ssh git@127.0.0.1 info
hello gitadmin, this is git@localhost running gitolite3 v3.6.11-4-gef9ab68 on git 2.22.1

R W gitolite-admin
R W testing

进一步测试:

  • 在 CentOS7 服务器上以 gitadmin 身份登录,clone gitolite-admin 项目,并修改 gitolite-admin/conf/gitolite.conf,添加内容:

    1
    2
    3
    4
    5
    repo mis-ui
    RW+ = @all

    repo mis-api
    RW+ = @all
  • 把 windows10 上的 id_rsa.pub 上传至 gitolite-admin/keydir 下,并重命名为 andy.pub。

  • 提交修改(commit + push)。
  • 在 windows10 上 clone 新配置的两个项目,均未要求输入密码,说明配置成功:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    AndyChen@AndyChen MINGW64 /c/study/temp
    $ git clone git@192.168.1.168:mis-api
    Cloning into 'mis-api'...
    warning: You appear to have cloned an empty repository.

    AndyChen@AndyChen MINGW64 /c/study/temp
    $ git clone git@192.168.1.168:mis-ui
    Cloning into 'mis-ui'...
    warning: You appear to have cloned an empty repository.

替换管理员私匙

重新生成私匙,上传到服务器 ugit 目录下,替换原来的管理员的 key,执行 ./bin/gitolite setup -pk andy.pub,正常情况下,gitolite-admin 项目就可以正常 push 了。

查看 key 的设置情况:

1
cat .ssh/authorized_keys

遇到的坑

更新 gitolite-admin 项目的时候,keydir 目录下的 key 文件名与项目配置的用户名没有统一,push 之后,发现其他项目不能正常 pull 和 push 了,报权限错误。

于是,修改 key 文件名,保持与配置的用户名一致,却发现提交不了,报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
S C:\workspace\frontend\gitolite-admin> git pull
FATAL: R any gitolite-admin andy DENIED by fallthru
fatal: Could not read from remote repository.

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

PS C:\workspace\frontend\gitolite-admin> git push
FATAL: W any gitolite-admin andy DENIED by fallthru
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.

# clone 也报错
andy@DESKTOP-8U87P36 MINGW64 /c/workspace/markdown
$ git clone ugit@your.domain:gitolite-admin

Cloning into 'gitolite-admin'...
FATAL: R any gitolite-admin andy DENIED by fallthru
(or you mis-spelled the reponame)
fatal: Could not read from remote repository.

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

尝试重新生成新的 key,上传到 ugit 目录替换原来的 key,执行 ./bin/gitolite setup -pk andy.pub,重新 push gitolite-admin 项目的修改,还是失败,这就有点无头绪了,感觉无解了,只能寻求直接在服务器上操作的方案了

原来,在服务器上,管理项目的配置有专门的目录,在 ugit 根目录下\.gitolite,是隐藏了的,所以不能直接看到,进入这个目录,查看目录文件,原来所有配置及 key 文件都在,这就好办了,修改配置文件里的用户名,保持与 key 名对应上,应该就可以了。

1
2
3
4
5
6
7
8
9
[ugit@k8s-oc7qvhje9m-nat-vm-0 .gitolite]$ ll
total 8
drwx------ 2 ugit ggit 74 Sep 10 11:10 conf
drwx------ 4 ugit ggit 40 Nov 24 2023 hooks
drwx------ 2 ugit ggit 70 Sep 10 11:07 keydir
drwx------ 2 ugit ggit 4096 Sep 2 08:38 logs
-rw------- 1 ugit ggit 1721 Sep 3 11:49 redme.md
[ugit@k8s-oc7qvhje9m-nat-vm-0 .gitolite]$ pwd
/work/ugit/.gitolite

直接在服务器上修改好之后,本地项目,因为有过几次修改,本地已经 commit 了,只是没有 push 到服务器,所以,这个时候直接 push 会报错

1
2
3
4
5
6
7
8
9
PS C:\workspace\frontend\gitolite-admin> git push
To your.domain:gitolite-admin
! [rejected] master -> master (fetch first)
error: failed to push some refs to 'your.domain:gitolite-admin'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

因为已经在服务器上直接修改过了,重新 clone 到本地再修改即可

后记

主要的配置在

  • $HOME/.gitolite
  • $HOME/.gitolite.rc
  • .ssh/authorized_keys

当提交 gitolite-admin 的代码,key 名与配置里的用户名不符,会导致用户没有权限,或者管理员对应的权限配错,git pull 时,会报:FATAL: R any gitolite-admin admin DENIED by fallthru

修改 ~/.gitolite/conf/gitolite.conf,把管理员权限加上

如果还报 FATAL: R any gitolite-admin admin DENIED by fallthru,可以执行 gitolite compile 后再试,一般会得到解决

查看 gitolite 帮助

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[ugit@k8s-oc7qvhje9m-nat-vm-0 conf]$ gitolite -h

Usage: gitolite [sub-command] [options]

The following built-in subcommands are available; they should all respond to
'-h' if you want further details on each:

setup 1st run: initial setup; all runs: hook fixups
compile compile gitolite.conf

query-rc get values of rc variables

list-groups list all group names in conf
list-users list all users/user groups in conf
list-repos list all repos/repo groups in conf
list-phy-repos list all repos actually on disk
list-memberships list all groups a name is a member of
list-members list all members of a group

Warnings:
- list-users is disk bound and could take a while on sites with 1000s of repos
- list-memberships does not check if the name is known; unknown names come
back with 2 answers: the name itself and '@all'

In addition, running 'gitolite help' should give you a list of custom commands
available. They may or may not respond to '-h', depending on how they were
written.