本文介绍通过搭建git服务器实现提交代码到master分支时完成网站应用代码的部署。

创建SSH-Public-Key

本地计算机需要创建SSH公钥与服务器通信。使用ssh-keygen生产公钥以及私钥。

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/finalize/.ssh/id_rsa): demo 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in demo.
Your public key has been saved in demo.pub.
The key fingerprint is:
6d:07:2c:56:48:aa:0d:08:ad:c1:db:ce:0f:bf:4e:6b finalize@junjie
The key's randomart image is:
+--[ RSA 2048]----+
|o.     ....      |
|.o..   ..o       |
| o+ . . o o      |
|.. . + . o .     |
|  o . . S o .    |
|   +     . .     |
|    +.           |
|    .E.          |
|    o+.          |
+-----------------+

然后在ssh的配置文件中加入demo.pub的配置

$ vi ~/.ssh/config
$ chmod 600 ~/.ssh/config

创建或加入以下内容

Host your_server_name
    User git
    IdentityFile ~/.ssh/demo

安装 Git Server

首先得安装git

$ sudo apt-get install git

然后创建git用户,并将本地电脑的SSH public key存入authorized_keys

$ sudo adduser git
$ su git
$ cd
$ mkdir .ssh
$ cat /path/to/public/key >> ~/.ssh/authorized_keys

然后更改.ssh文件夹的权限

$ chmod -R go= ~/.ssh

接下来禁止git用户登陆

$ sudo vim /etc/passwd

在底部形如下面的内容处,将/bin/sh改为/usr/bin/git-shell

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

这样就不能用git登陆了

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

测试git提交

在服务器上创建一个git仓库,其中user指的是你当前登陆的用户名

$ sudo mkdir -p /srv/git
$ cd /srv/git
$ sudo mkdir demo.git
$ sudo chown -R user:user demo.git/
$ git init --bare
Initialized empty Git repository in /srv/git/demo.git/

$ sudo chown -R git:git demo.git/

在本地电脑上创建一个demo.txt并提交到服务器

$ git clone git@your_server_name:/srv/git/demo.git
Cloning into 'demo'...
warning: You appear to have cloned an empty repository.
Checking connectivity... done.

$ cd demo
$ echo 'Hello Git!' >> demo.txt
$ git add demo.txt
$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 219 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@lotusland.club:/srv/git/demo.git
 * [new branch]      master -> master

查看提交内容

demo.txt以及提交到了服务器,那么应该怎样查看呢?那就把仓库在服务器上也克隆一份吧。

先创建SSH key

$ ssh-keygen
$ vi ~/.ssh/config
$ cat ~/.ssh/config
Host localhost
    User git
    IdentityFile ~/.ssh/local-git

$ chmod 600 ~/.ssh/config

然后将公钥放入git用户的authorized_keys中。user表示当前用户

$ sudo chown -R abuntu:abuntu /home/git/.ssh/
$ sudo cat /home/user/.ssh/local-git.pub >> /home/git/.ssh/authorized_keys
$ sudo chown -R git:git /home/git/.ssh/

克隆仓库

$ git clone git@localhost:/srv/git/demo.git
Cloning into 'demo'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.
Checking connectivity... done.

发现之前提交的demo.txt以及在里面了

$ cd demo/
$ ls
demo.txt
$ cat demo.txt
Hello Git!

配置Git hook

我们需要在提交到master branch时自动部署代码,于是需要配置git hook

根据官方文档,可以知道当push完成时,会触发post-receive。但是并不会有参数传入,而是会传到stdin。也就是当在脚本中请求从标准输入流读取数据时才会把参数传进。

It executes on the remote repository once after all the refs have been updated.

下面测试以下传入的参数 - The old revision where that branch was - The new revision being pushed - The name of the reference being pushed to

$ cd /srv/git/demo.git/hooks/
$ sudo vi post-receive
$ cat post-receive
#!/bin/sh
read refname oldrev newrev
echo $refname $oldrev $newrev

$ sudo chmod a+x post-receive

在本地测试提交一下

$ git push origin master
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 300 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: 33fc2dec3acadf968006b225c94c7a24f98bc4a9 6dae42286273bfaba994ac828d9cbb74ca086e05 refs/heads/master
To git@lotusland.club:/srv/git/demo.git
   33fc2de..6dae422  master -> master

发现remote的输出为

remote: 33fc2dec3acadf968006b225c94c7a24f98bc4a9 6dae42286273bfaba994ac828d9cbb74ca086e05 refs/heads/master

也就是说只需要判断第三个参数就能识别master分支

#!/bin/sh
read oldrev newrev refname

if [ "$refname" = "refs/heads/master" ] ; then
    # do something
    echo "Received $newrev to MSATER"

    # checkout branch master to server
    GIT_WORK_TREE=/home/abuntu/demo git checkout -f
else
    echo "Received $newrev to $refname"
fi

我们只需要在#do some thing之后加入我们要执行的部署代码了。注意,该脚本的执行者是git,可能会出现权限问题。

$ git push origin master
Counting objects: 1, done.
Writing objects: 100% (1/1), 185 bytes | 0 bytes/s, done.
Total 1 (delta 0), reused 0 (delta 0)
remote: Received fc12978d8f64b59586096ec6a3576a2bc42a6bd3 to MSATER
To git@lotusland.club:/srv/git/demo.git
   010588d..fc12978  master -> master