免搭gitlab快速创建私有仓库

没有gitlab,如何创建git远程中央仓库

众所周知,在我们使用git进行开发协作时,不可避免的需要一个中央仓库来完成多人代码的同步。一般我们通常是由项目的管理员在github/gitlab上预先创建一个仓库,对于公司内的私有项目一般是搭建一套 gitlab 的私有仓库系统。

而实际上,git的中央仓库也是一个git程序管理的数据而已,他是git程序所具有的基本功能,他跟你本地看到的git仓库本质上是一样的。gitlab这些系统也仅仅是在git程序的基础上做了一些UI界面来简化中央仓库查看、编辑的操作而已。如果你希望学习怎样搭建一套完备的私有化仓库,可以参考我的另外一篇博客基于CentOS7安装基于Gogs的git平台

因此,gitlab能做的,本质上 git命令 也能做。本节我们就使用git命令来完成服务端中央仓库的创建,实现不搭建gitlab也能进行私有仓库的创建。由于github等服务的私有仓库都是收费的,所以这在你自己仅仅希望快速做一个私有仓库(但又不想搭建复杂的gitlab)是非常有用的。

操作步骤

在操作系统上创建git用户

为了方便客户端拉取和同步git代码仓库,且不干扰正常的linux用户,需要建立一个专门的无法登录shell的git用户. 我们的私有仓库就放在这个git用户的家目录里面,以后客户端去克隆时,也是使用git这个用户来认证。这跟 github 或 gitlab 采用的方式都是一样的。

1
2
3
4
5
6
7
# 添加git用户
useradd git
passwd git
# 禁止git用户登录,修改内容为: git:x:500:500::/home/git:/usr/bin/git-shell
vim /etc/passwd
# 修改服务器上git仓库的权限
chown -R git:git repository.git

我们的git用户已经设置为无法登陆shell,如果你强行ssh登陆,会有如下提示:

1
2
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.

登录服务器 创建私有远程仓库

1
2
ssh user@host
git init --bare /path/to/repo.git

其中 repo.git 里面的 .git 扩展名是一个惯例,执行以上命令其实会创建一个 path/to/repo.git的目录,目录内存放了git中央仓库相关的配置文件。

1
branches  config  description  HEAD  hooks  info  objects  refs

这样会建立一个裸的仓库。一个远程仓库通常就只是一个裸仓库(bare repository)— 即一个没有当前工作目录的仓库。 因为该仓库仅仅作为合作媒介,不需要从磁碟检查快照;存放的只有 git 的数据资料。 简单的说,裸仓库就是你工程目录内的 .git 子目录内容,不包含其他资料。之所以叫裸仓库是因为这个仓库只保存git历史提交的版本信息,而不允许用户在上面进行各种git操作,如果你硬要操作的话,只会得到下面的错误

This operation must be run in a work tree

这个就是最好把远端仓库初始化成bare仓库的原因。说白了,就是会创建一个裸仓库,裸仓库没有工作区,服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区

接下来,你可以在本地克隆本仓库,或者把已有的仓库跟该中央仓库建立映射关系

SSH公钥配置

由于服务器初始化了一个git仓库,并没有提供任何http访问的基础设施,因此我们只能通过SSH协议进行克隆和push。此时,你需要把自己本机的公钥放到服务器上,实现公钥认证。 否则会提示你:

Please make sure you have the correct access rights

公钥配置步骤如下:

  1. 先看自己本机是否已经有生成过公钥
    1
    2
    3
    4
    $ cd ~/.ssh
    $ ls
    authorized_keys2 id_rsa known_hosts
    config id_rsa.pub

没有的话,可以生成下:

1
2
#邮箱可以随便填
$ ssh-keygen -t rsa -C "xx@xx.com"

  1. 如果有 *.pub 扩展名的文件(尤其是 id_rsa.pub),说明已经有RSA算法的公钥了. 接下来就是把公钥传到远程服务器的 git 用户家目录下的 ~/.ssh/authorized_keys 里面。
1
2
3
4
5
$ ssh-copy-id user@host

$ scp -P 22 id_rsa.pub root@192.168.1.77:/root/.ssh/authorized_keys
或追加
$ cat ~/.ssh/id_rsa.pub|ssh -p 22 root@192.168.1.91 `cat - >> ~/.ssh/authorized_keys`

看下自己的authorized_keys文件权限,一般要把非 git 用户的权限去掉.

1
$ chmod 600 ~/git/.ssh/authorized_keys

注意: 本方式不要跟gogs平台混用一个git账户,容易出问题。

克隆远程仓库

对于一个已经创建好的远程仓库,你可以直接克隆到本地。对于github/gitlab上的项目我们通常是这样做的:

1
git clone git@git.limefe.com:limegou/home.git

实际上,他的含义是:

使用git用户ssh登录git.limefe.com并拉取其用户目录下的limegou目录下的home.git仓库

这句命令也可以修改为:

1
2
3
git clone ssh://git@git.limefe.com:36000/limegou/home.git

git clone git@git.limefe.com:limegou/home.git

加上 ssh:// 这样就强制规定了git使用ssh协议拉取后面的url地址,这种方式要符合ssh url的规范,所以可以方便修改ssh的默认端口号。 (因为默认情况下git是使用 22 端口号连接远程ssh)。而 `git@git.limefe.com:limegou/home.git这种是scp的语法规范。这两种写法均可,SSH协议标准URL写法稍嫌复杂,但是对于非标准SSH端口(非22端口),可以通过URL给出端口号。否则你需要修改~/.git/config` 来修改git使用的默认ssh端口

当不使用 ssh:// 的时候,那么可以直接在host后面的冒号后加上git仓库所在的目录(`git@git.limefe.com:limegou/home.git),这里不用按照ssh url的规范来写,也可以加上斜线:git clone git@git.limefe.com:/limegou/home.git, 两种方式我亲测都是可以的. 但是使用ssh://协议的话,就要在url的最后面严格写明服务器上的路径,对于/home/git/gitrepo/test.git` 这样的路径,可以使用以下2种写法:

1
2
$ git clone ssh://git@git.limefe.com:36000/home/git/gitrepo/test.git
$ git clone ssh://git@git.limefe.com:36000/~/gitrepo/test.git

关于git ssh语法规范和原理,可以看下这篇文章 使用SSH协议

关联一个远程仓库

跟github的使用方式一样,你除了可以直接克隆远程仓库之外,还可以将本地初始化之后的仓库与远程服务器的仓库建立起关联。步骤如下:

首先,假设你刚初始化一个本地仓库

1
git init

这条命令会在当前目录下创建一个 .git的隐藏文件。 此时这个目录就会变成可以被本机的git程序进行跟踪的一个目录,通过执行其他的git命令操作(如 git add),你可以向本目录的这个git仓库提交代码变更记录。

通过以下命令,把本地 git init出来的仓库跟远程仓库关联起来:

1
git remote add origin git@github.com:michaelliao/learngit.git

关联完成后,本地进行了代码更改后则可以提交到本地版本库,然后再push到origin代号的远程仓库即可(用ssh协议push需要提前进行ssh的免密认证设置):

1
2
3
git add .
git commit -m "your msg"
git push -u origin master

其中 -u表示把本地的当前所在分支与远程的master分支关联起来,这样以后就可以无须指定远程origin名称来执行push命令了(因为git已经知道你当前分支所关联的远程分支)

同一台机器进行克隆仓库

如果你在服务器上创建了中央仓库之后,你希望在服务器上的另外一个目录进行开发。这时你的开发目录与中央仓库属于同一台服务器,他们之间是 本地克隆 的关系。

此时,你可以

1
2
3
git clone /opt/git/project.git

git remote add local_proj /opt/git/project.git

url就是一个磁盘路径。不过我们一般很少这样用。

总结

使用以上方式建立的私有仓库,跟你使用gitlab等建立的私有仓库使用方法是一样的。只是使用gitlab等平台会适合真正的团队协作,它提供了更多的团队协作相关的功能和建议的UI界面以及https方式的访问和认证机制。