環境是CentOS 7.4 64位
主要參考:在服務器上搭建 Git
0. 預備
- 安裝git
yum install git
1. 開發者-生成個人SSH公鑰
p.s. 書中的4.3節是【生成個人的SSH公鑰】,網站版本卻是【服務器上的 Git - 生成 SSH 公鑰】,因為是用戶的公鑰,所以還是書中名字較合適
在本地win10上測試,沒有裝Git則下載安裝Git for windows
打開git Bash, ssh-keygen
回車幾次就生成了(默認在/c/Users/用戶名/.ssh/id_rsa)
(*nix用戶直接使用ssh-keygen)
將id_rsa.pub
或者id_dsa.pub
發給管理員,需放置到服務器上。
2. 服務端-服務器上的Git,設置服務器
$ sudo adduser git
$ su git
$ cd
$ mkdir .ssh && chmod 700 .ssh
$ touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys
將開發者*.pub
文件內容,追加進~/.ssh/authorized_keys
中。
在/opt/git
下建立裸倉庫,
-
將現有倉庫導出為一個新的裸倉庫
git clone --bare https://github.com/onionc/Laravel-Messages.git messages.git
-
或者
git init --bare
初始化一個目錄
cd /opt/git
mkdir messages.git
cd messages.git
git init --bare
看一下目錄,用現有倉庫的話配置文件里面多了幾行,有遠程分支url
[root@x messages.git]# ll
total 36
drwxr-xr-x 2 root root 4096 Apr 22 15:26 branches
-rw-r--r-- 1 root root 138 Apr 22 15:26 config
-rw-r--r-- 1 root root 73 Apr 22 15:26 description
-rw-r--r-- 1 root root 23 Apr 22 15:27 HEAD
drwxr-xr-x 2 root root 4096 Apr 22 15:26 hooks
drwxr-xr-x 2 root root 4096 Apr 22 15:36 info
drwxr-xr-x 4 root root 4096 Apr 22 15:26 objects
-rw-r--r-- 1 root root 98 Apr 22 15:27 packed-refs
drwxr-xr-x 4 root root 4096 Apr 22 15:26 refs
[root@x my_project.git]# cat config
[core]
repositoryformatversion = 0
filemode = true
bare = true
[remote "origin"]
url = https://github.com/onionc/Laravel-Messages.git
這樣就創建了(舍去工作目錄的)一個新的目錄。
3. 將自己的代碼推上去
由於我本地的已經有一個github遠程庫,所以用git remote add
添加一個遠程倉庫。可參考 2.5 Git 基礎 - 遠程倉庫的使用
建遠程倉庫(需確保opt/git目錄權限為git)
git remote add tx-origin git@111.111.111.111:/opt/git/messages.git
推數據
git push tx-origin master
4. 克隆
換個目錄克隆一下
$ git clone git@111.111.111.111:/opt/git/messages.git
Cloning into 'messages'...
git@111.111.111.111's password:
remote: Counting objects: 200, done.
remote: Compressing objects: 100% (155/155), done.
remote: Total 200 (delta 25), reused 196 (delta 24)
Receiving objects: 100% (200/200), 1.17 MiB | 122.00 KiB/s, done.
Resolving deltas: 100% (25/25), done.
成功。試着修改一個文件,提交成功
$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
$ git add README.md
$ git commit -m '2'
[master 10c25ba] 2
1 file changed, 1 insertion(+), 1 deletion(-)
$ git push
git@111.111.111.111's password:
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 266 bytes | 266.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To 111.111.111.111:/opt/git/messages.git
2fa76cf..10c25ba master -> master
p.s. 服務器ip 111.111.111.111等隱私均為杜撰,也可用域名。
其他. 疑問:文件存到哪去了?
服務器的messages.git目錄下均未找到項目文件
[git@x messages.git]$ ll
total 32
drwxrwxr-x 2 git git 4096 Apr 22 20:57 branches
-rw-rw-r-- 1 git git 66 Apr 22 20:57 config
-rw-rw-r-- 1 git git 73 Apr 22 20:57 description
-rw-rw-r-- 1 git git 23 Apr 22 20:57 HEAD
drwxrwxr-x 2 git git 4096 Apr 22 20:57 hooks
drwxrwxr-x 2 git git 4096 Apr 22 20:57 info
drwxrwxr-x 7 git git 4096 Apr 22 21:28 objects
drwxrwxr-x 4 git git 4096 Apr 22 20:57 refs
那么項目文件推送到后存儲到哪里去了呢?
找到一個類似的問題:自己搭建git服務器,本地文件為什么push不到服務器上?的答案是:git服務器上那個目錄project001.git 這只是一個倉庫. 你需要找個目錄克隆出來, 才會顯示你push上去的內容的。
可是,到底存到哪里了?( 鴿子為什么這么大?
所有服務端的工作都由hooks目錄下的update(update.sample)腳本文件來完成 - 精通Git Second Edition, 8.4.1
用我這戰五渣英語搜出來一個:
Git Push worked, but files are not on server
回答里說
The files are there, you just don't see them because they are embedded into the Git database. This is the difference between initializing a repository with --bare or without
文件在那里,你只是看不到它們,因為它們被嵌入到Git數據庫中。這是初始化一個l裸存儲庫的不同之處。
這樣啊,放到數據庫中我就不深究了,我這菜逼八成也看不懂了,以后再研究。
回答里留了個參考 What is a bare git repository?
找幾句重要的:
Repositories created with
git init --bare
are called bare repos. They are structured a bit differently from working directories. First off, they contain no working or checked out copy of your source files. And second, bare repos store git revision history of your repo in the root folder of your repository instead of in a .git subfolder.
A bare repository created with git init --bare is for… sharing.
Because git is a distributed version control system, no one will directly edit files in the shared centralized repository.
Because no one ever makes edits directly to files in the shared bare repo, a working tree is not needed. In fact the working tree would just get in way and cause conflicts as users push code to the repository. This is why bare repositories exist and have no working tree.
使用git init --bare
創建的存儲庫稱為裸存儲庫。它們的結構與工作目錄稍有不同。首先,它們不包含任何工作或檢查源文件的副本。其次,在存儲庫的根文件夾中,而不是在一個.git
子文件夾中,僅使用repos存儲您的repo的歷史記錄。
使用git init --bare
創建的一個裸存儲庫用於…共享。
因為git是一個分布式版本控制系統,所以沒有人會直接在共享的集中存儲庫中編輯文件。
因為沒有人直接對共享的裸回文件進行編輯,所以不需要工作樹。實際上,當用戶將代碼推到存儲庫中時,工作樹會導致沖突。這就是為什么裸存儲庫存在且沒有工作樹的原因。
5. 限制 git用戶 權限
首先你必須確保 git-shell 已存在於 /etc/shells 文件中:
$ cat /etc/shells # 查看 git-shell 是否存在,不能存在則
$ which git-shell # 確保安裝了 git-shell, 返回了路徑:/usr/bin/git-shell
$ sudo vim /etc/shells # 將 git-shell 路徑添加到最后
現在你可以使用 chsh
$ sudo chsh git # 然后輸入git-shell的路徑,通常是:/usr/bin/git-shell
這樣,用戶 git 就只能利用 SSH 連接對 Git 倉庫進行推送和拉取操作,而不能登錄機器並取得普通 shell。 如果試圖登錄,你會發現嘗試被拒絕。
6. 安裝 GitWeb 用於在線查看
進入項目路徑下
$ yum install gitweb # 安裝gitweb
$ git instaweb --httpd=webrick #簡易查看
打開瀏覽器查看:
6. 加入虛擬主機
6.1 生成gitweb.cgi
手動生成cgi
$ git clone git://git.kernel.org/pub/scm/git/git.git
$ cd git/
$ make GITWEB_PROJECTROOT="/opt/git" prefix=/usr gitweb
SUBDIR gitweb
SUBDIR ../
make[2]: `GIT-VERSION-FILE' is up to date.
GEN gitweb.cgi
GEN static/gitweb.js
$ sudo cp -Rf gitweb /var/www/
我直接使用yum安裝的gitweb,所以和書中的配置不一樣,手動更改:
$ vim /var/www/git/gitweb.git
80行左右 our $projectroot = "/var/lib/git";
改為我的git項目目錄,our $projectroot = "/opt/git";
nginx配置,提醒錯誤
Access denied.
nginx錯誤日志
FastCGI sent in stderr: "Access to the script '/var/www/git/gitweb.cgi' has been denied
修正半天沒好,應該是fastcgi_pass問題,127.0.0.1:9000是php-fpm的
但是PHP-fpm僅僅是個“PHP Fastcgi 進程管理器”, 它仍會調用PHP解釋器本身來處理請求,PHP解釋器(在Windows下)就是php-cgi.exe.
6.2 在nginx下運行,需要安裝cgi支持
- 首先安裝perl fcgi, 下載生成,遇到錯誤
$ perl Makefile.PL
Can't locate ExtUtils/MakeMaker.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at Makefile.PL line 3.
BEGIN failed--compilation aborted at Makefile.PL line 3.
- 需要安裝perl-ExtUtils-Embed
yum install perl-ExtUtils-Embed -y
(by linux安裝軟件報錯...) - 再次生成,又遇到錯誤
configure: error: C compiler cannot create executables
, 需要gcc, 安裝一個yum install gcc
。
…… 好麻煩,修正,使用apache運行8080端口,用nginx代理
6.3 使用apache吧
查看/etc/httpd/modules/下有mod_cgi.so
mod_cgid.so
, 添加到httpd.conf配置里:
LoadModule cgi_module modules/mod_cgi.so #之后httpd可以看到是內建模塊cgi_module跳過了,可注釋掉
LoadModule cgid_module modules/mod_cgid.so
虛擬主機配置用書中的,但改了端口,因為nginx用着80.
Options行注釋掉是因為錯誤Either all Options must start with + or -, or no Option may
索性注釋掉,全局配置里也有AddHandler那句的,不過沒關系。
<VirtualHost *:8080>
ServerName gitserver
DocumentRoot /var/www/git
<Directory /var/www/git>
#Options ExecCGI +FollowSymLinks +SymLinksIfOwnerMatch
AllowOverride All
order allow,deny
Allow from all
AddHandler cgi-script cgi
DirectoryIndex gitweb.cgi
</Directory>
</VirtualHost>
重啟apacheservice httpd restart
后生效。
之后在nginx添加反向代理:
location /git/ {
proxy_pass http://127.0.0.1:8080;
}
重啟nginxnginx -s reload
后生效。
訪問域名:
p.s. 修改項目目錄下的description則為項目描述。
7. 同時推送多個庫
在.git/config
里面加上遠程倉庫合集
[remote "origin"]
url = https://github.com/onionc/Laravel-Messages.git
fetch = +refs/heads/*:refs/remotes/origin/*
[remote "tx-origin"]
url = git@www.xxxxx.com:/opt/git/messages.git
fetch = +refs/heads/*:refs/remotes/tx-origin/*
[remote "all"]
url = git@www.xxxxx.com:/opt/git/messages.git
url = https://github.com/onionc/Laravel-Messages.git
單獨推送拉取可用origin
(github) tx-origin
(自建私有git) 遠程倉庫,同時推送可用all
(遠程倉庫合集)
修改README.md測試同時推送
$ git add README.md
$ git commit -m '測試多個git庫同時推送'
[master 0949ff9] 測試多個git庫同時推送
1 file changed, 3 insertions(+), 1 deletion(-)
$ git push all master
git@www.xxxxxx.com's password:
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 360 bytes | 360.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To www.xxxxxx.com:/opt/git/messages.git
10c25ba..0949ff9 master -> master
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 360 bytes | 360.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/onionc/Laravel-Messages.git
10c25ba..0949ff9 master -> master
完美!不過推送完私有庫之后卡了一陣才繼續推的github。
其他參考
8. 追加,非智能HTTP協議
Git有兩種不同的協議,智能HTTP協議和非智能HTTP協議(也叫啞HTTP協議)(可參考4.1 服務器上的 Git - 協議)。
上面建的就是智能的,那么非智能優勢是啥:配置簡單,只能拉取不能推(這也算不上優勢了)。
$ cd /var/www/htdocs/
$ git clone --bare /path/to/git_project gitproject.git
$ cd gitproject.git
$ mv hooks/post-update.sample hooks/post-update
$ chmod a+x hooks/post-update
設置一個特定的post-update鈎子函數就可以了,但是我弄完之后,訪問總是403,
Forbidden
You don't have permission to access /xxxxxx.git/ on this server.
然后克隆
$ git clone http://xxx.xxx.xxx.xxx/messages.git
Cloning into 'messages'...
fatal: repository 'http://xxx.xxx.xxx.xxx/messages.git/' not found
也是找不到這個repo, 最后搜到一個例子
A tutorial about Git. Setup remote Git repository on Mac OS X. Includes examples,發現他手動在版本庫下執行了git --bare update-server-info
,我試了一下,果然好使。克隆成功。
比較一下兩種克隆方式
$ git clone http://xxx.xxx.xxx.xxx:8088/messages.git
Cloning into 'messages'...
$ git clone git@xxx.xxx.xxx.xxx:/opt/git/messages.git
Cloning into 'messages'...
git@xxx.xxx.xxx.xxx's password:
remote: Counting objects: 298, done.
remote: Compressing objects: 100% (250/250), done.
remote: Total 298 (delta 90), reused 162 (delta 24)
Receiving objects: 100% (298/298), 1.22 MiB | 27.00 KiB/s, done.
Resolving deltas: 100% (90/90), done.
我還發現一個大問題,配置的SSH公鑰一直沒用到。學藝不精學藝不精。