CentOS服务器上安装git(运维向)
(1).参考文献
官网在线教程:https://git-scm.com/book/zh/v2
官方网站:https://git-scm.com/
git源码包下载地址:https://www.kernel.org/pub/software/scm/git/
(2).实验环境
2核2G CentOS7.9.2009
注意:2.50.x及以上需要升级系统内核,2.46.x及以上版本需要升级 libcurl 7.30.0以上版本,剩余版本需要手动设置docbook2X的软连接。
(3).安装git
1)yum或dnf安装
[root@localhost ~]# dnf -y install git-all
2)源码安装
想快速安装的请安装2.45.x及一下版本。我这里安装的是2.49.1版本,不升级内核,其他的报错尽量展示。
注意:默认配置了阿里云yum源和yum -y install epel-release。
安装依赖包,注意:如果git装在/usr目录下无需执行yum -y remove git。
[root@localhost ~]# yum -y install dnf
[root@localhost ~]# dnf -y install dh-autoreconf curl-devel expat-devel gettext-devel openssl-devel perl-devel zlib-devel #这一步会装一个git-1.8.3.1-25.el7_9.x86_64
[root@localhost ~]# yum -y remove git #去除自动安装的git
#为了添加文档的多种格式(doc、html、info),需要以下附加依赖
[root@localhost ~]# dnf -y install asciidoc xmlto docbook2X
编译安装
[root@localhost ~]# tar xvf git-2.49.1.tar.xz
[root@localhost ~]# cd git-2.49.1
[root@localhost git-2.49.1]# make configure
GIT_VERSION = 2.49.1
GEN configure
#如直接使用/usr那么git安装后的文件将会合并到/usr/bin、/usr/libexec、/usr/share目录下,好处是无需改动环境变量PATH,坏处是不好单独删,但可覆盖
[root@localhost git-2.49.1]# ./configure --prefix=/usr
[root@localhost git-2.49.1]# echo $? #检查上一个命令是否有异常
0
[root@localhost git-2.49.1]# make all doc info
In file included from /usr/include/curl/curl.h:2251:0,
from git-curl-compat.h:3,
from http.c:5:
http.c: In function ‘set_proxyauth_name_password’:
http.c:645:28: error: ‘CURLOPT_PROXYHEADER’ undeclared (first use in this function)
curl_easy_setopt(result, CURLOPT_PROXYHEADER,
^
http.c:645:28: note: each undeclared identifier is reported only once for each function it appears in
http.c: In function ‘get_curl_http_version_opt’:
http.c:988:15: error: ‘CURL_HTTP_VERSION_2’ undeclared (first use in this function)
{ "HTTP/2" , CURL_HTTP_VERSION_2 }
^
In file included from /usr/include/curl/curl.h:2251:0,
from git-curl-compat.h:3,
from http.c:5:
http.c: In function ‘get_curl_handle’:
http.c:1048:49: error: ‘CURLSSLOPT_NO_REVOKE’ undeclared (first use in this function)
curl_easy_setopt(result, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
^
http.c:1089:28: error: ‘CURLOPT_PINNEDPUBLICKEY’ undeclared (first use in this function)
curl_easy_setopt(result, CURLOPT_PINNEDPUBLICKEY, ssl_pinnedkey);
^
http.c:1089:3: error: invalid initializer
curl_easy_setopt(result, CURLOPT_PINNEDPUBLICKEY, ssl_pinnedkey);
^
In file included from /usr/include/curl/curl.h:2251:0,
from git-curl-compat.h:3,
from http.c:5:
http.c:1089:3: error: incompatible type for argument 2 of ‘curl_easy_setopt’
curl_easy_setopt(result, CURLOPT_PINNEDPUBLICKEY, ssl_pinnedkey);
^
In file included from /usr/include/curl/curl.h:2244:0,
from git-curl-compat.h:3,
from http.c:5:
/usr/include/curl/easy.h:29:22: note: expected ‘CURLoption’ but argument is of type ‘ struct *’
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
^
In file included from /usr/include/curl/curl.h:2251:0,
from git-curl-compat.h:3,
from http.c:5:
http.c:1093:28: error: ‘CURLOPT_PROXY_CAINFO’ undeclared (first use in this function)
curl_easy_setopt(result, CURLOPT_PROXY_CAINFO, NULL);
^
http.c:1093:3: error: invalid initializer
curl_easy_setopt(result, CURLOPT_PROXY_CAINFO, NULL);
^
In file included from /usr/include/curl/curl.h:2251:0,
from git-curl-compat.h:3,
from http.c:5:
http.c:1093:3: error: incompatible type for argument 2 of ‘curl_easy_setopt’
curl_easy_setopt(result, CURLOPT_PROXY_CAINFO, NULL);
^
In file included from /usr/include/curl/curl.h:2244:0,
from git-curl-compat.h:3,
from http.c:5:
/usr/include/curl/easy.h:29:22: note: expected ‘CURLoption’ but argument is of type ‘ struct *’
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
^
http.c:1098:4: error: invalid initializer
curl_easy_setopt(result, CURLOPT_PROXY_CAINFO, http_proxy_ssl_ca_info);
^
In file included from /usr/include/curl/curl.h:2251:0,
from git-curl-compat.h:3,
from http.c:5:
http.c:1098:4: error: incompatible type for argument 2 of ‘curl_easy_setopt’
curl_easy_setopt(result, CURLOPT_PROXY_CAINFO, http_proxy_ssl_ca_info);
^
In file included from /usr/include/curl/curl.h:2244:0,
from git-curl-compat.h:3,
from http.c:5:
/usr/include/curl/easy.h:29:22: note: expected ‘CURLoption’ but argument is of type ‘ struct *’
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
^
In file included from /usr/include/curl/curl.h:2251:0,
from git-curl-compat.h:3,
from http.c:5:
http.c:1195:48: error: ‘CURLPROXY_HTTPS’ undeclared (first use in this function)
curl_easy_setopt(result, CURLOPT_PROXYTYPE, CURLPROXY_HTTPS);
^
http.c:1198:30: error: ‘CURLOPT_PROXY_SSLCERT’ undeclared (first use in this function)
curl_easy_setopt(result, CURLOPT_PROXY_SSLCERT, http_proxy_ssl_cert);
^
http.c:1198:5: error: invalid initializer
curl_easy_setopt(result, CURLOPT_PROXY_SSLCERT, http_proxy_ssl_cert);
^
In file included from /usr/include/curl/curl.h:2251:0,
from git-curl-compat.h:3,
from http.c:5:
http.c:1198:5: error: incompatible type for argument 2 of ‘curl_easy_setopt’
curl_easy_setopt(result, CURLOPT_PROXY_SSLCERT, http_proxy_ssl_cert);
^
In file included from /usr/include/curl/curl.h:2244:0,
from git-curl-compat.h:3,
from http.c:5:
/usr/include/curl/easy.h:29:22: note: expected ‘CURLoption’ but argument is of type ‘ struct *’
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
^
In file included from /usr/include/curl/curl.h:2251:0,
from git-curl-compat.h:3,
from http.c:5:
http.c:1201:30: error: ‘CURLOPT_PROXY_SSLKEY’ undeclared (first use in this function)
curl_easy_setopt(result, CURLOPT_PROXY_SSLKEY, http_proxy_ssl_key);
^
http.c:1201:5: error: invalid initializer
curl_easy_setopt(result, CURLOPT_PROXY_SSLKEY, http_proxy_ssl_key);
^
In file included from /usr/include/curl/curl.h:2251:0,
from git-curl-compat.h:3,
from http.c:5:
http.c:1201:5: error: incompatible type for argument 2 of ‘curl_easy_setopt’
curl_easy_setopt(result, CURLOPT_PROXY_SSLKEY, http_proxy_ssl_key);
^
In file included from /usr/include/curl/curl.h:2244:0,
from git-curl-compat.h:3,
from http.c:5:
/usr/include/curl/easy.h:29:22: note: expected ‘CURLoption’ but argument is of type ‘ struct *’
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
^
In file included from /usr/include/curl/curl.h:2251:0,
from git-curl-compat.h:3,
from http.c:5:
http.c:1204:30: error: ‘CURLOPT_PROXY_KEYPASSWD’ undeclared (first use in this function)
curl_easy_setopt(result, CURLOPT_PROXY_KEYPASSWD, proxy_cert_auth.password);
^
http.c:1204:5: error: invalid initializer
curl_easy_setopt(result, CURLOPT_PROXY_KEYPASSWD, proxy_cert_auth.password);
^
In file included from /usr/include/curl/curl.h:2251:0,
from git-curl-compat.h:3,
from http.c:5:
http.c:1204:5: error: incompatible type for argument 2 of ‘curl_easy_setopt’
curl_easy_setopt(result, CURLOPT_PROXY_KEYPASSWD, proxy_cert_auth.password);
^
In file included from /usr/include/curl/curl.h:2244:0,
from git-curl-compat.h:3,
from http.c:5:
/usr/include/curl/easy.h:29:22: note: expected ‘CURLoption’ but argument is of type ‘ struct *’
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
^
http.c: In function ‘http_init’:
http.c:1280:3: error: unknown type name ‘curl_ssl_backend’
const curl_ssl_backend **backends;
^
http.c:1284:3: warning: implicit declaration of function ‘curl_global_sslset’ [-Wimplicit-function-declaration]
switch (curl_global_sslset(-1, http_ssl_backend, &backends)) {
^
http.c:1285:8: error: ‘CURLSSLSET_UNKNOWN_BACKEND’ undeclared (first use in this function)
case CURLSSLSET_UNKNOWN_BACKEND:
^
http.c:1290:44: error: request for member ‘name’ in something not a structure or union
strbuf_addf(&buf, "\n\t%s" , backends[i]->name);
^
http.c:1292:8: error: ‘CURLSSLSET_NO_BACKENDS’ undeclared (first use in this function)
case CURLSSLSET_NO_BACKENDS:
^
http.c:1296:8: error: ‘CURLSSLSET_TOO_LATE’ undeclared (first use in this function)
case CURLSSLSET_TOO_LATE:
^
http.c:1299:8: error: ‘CURLSSLSET_OK’ undeclared (first use in this function)
case CURLSSLSET_OK:
^
http.c: In function ‘handle_curl_result’:
http.c:1799:37: error: ‘CURLE_SSL_PINNEDPUBKEYNOTMATCH’ undeclared (first use in this function)
} else if (results->curl_result == CURLE_SSL_PINNEDPUBKEYNOTMATCH) {
^
http.c:1799:34: warning: comparison between pointer and integer [enabled by default ]
} else if (results->curl_result == CURLE_SSL_PINNEDPUBKEYNOTMATCH) {
^
make: *** [http.o] Error 1
这里有一长串的报错,都是由于libcurl版本过低导致的。CentOS7官方支持的版本只到curl 7.29.0 ,所以需要进行源码编译安装,包下载地址:https://curl.se/download/。
另外高版本的curl需要依赖高版本的OpenSSL,请参照CentOS7升级OpenSSL3.5.4 - 苦逼运维 - 博客园对OpenSSL进行升级。注意:yum -y groupinstall "Development Tools"这一步会安装上git,需要多运行一步yum -y remove git。
[root@localhost ~]# yum -y remove git [root@localhost ~]# yum -y install libpsl libpsl-devel #安装依赖 [root@localhost ~]# tar xvf curl-8.18.0.tar.xz [root@localhost ~]# cd curl-8.18.0 [root@localhost curl-8.18.0]# ./configure --with-openssl=/usr/local/openssl-3.5.4 --prefix=/usr/local/curl-8.18.0 [root@localhost curl-8.18.0]# echo $? #检查上一个命令是否有异常 0 [root@localhost curl-8.18.0]# make -j$(nproc) #最大内核数进行编译 [root@localhost curl-8.18.0]# echo $? #检查上一个命令是否有异常 0 [root@localhost curl-8.18.0]# make install [root@localhost curl-8.18.0]# echo $? #检查上一个命令是否有异常 0 [root@localhost curl-8.18.0]# echo "export PATH=/usr/local/curl-8.18.0/bin:$PATH" >>/etc/profile [root@localhost curl-8.18.0]# source /etc/profile [root@localhost curl-8.18.0]# curl --version #验证 curl 8.18.0 (x86_64-pc-linux-gnu) libcurl/8.18.0 OpenSSL/3.5.4 zlib/1.2.7 libpsl/0.7.0 (+libicu/50.1.2) Release-Date: 2026-01-07 Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp ws wss Features: alt-svc AsynchDNS HSTS HTTPS-proxy IPv6 Largefile libz NTLM PSL SSL threadsafe TLS-SRP UnixSockets
接着回到git目录下,重新编译
[root@localhost curl-8.18.0]# cd ../git-2.49.1 [root@localhost git-2.49.1]# ./configure --with-curl=/usr/local/curl-8.18.0 --prefix=/usr/local/git-2.49.1 [root@localhost git-2.49.1]# echo $? #检查上一个命令是否有异常 0 [root@localhost git-2.49.1]# make all doc info /bin/sh: docbook2x-texi: command not found make[1]: *** [user-manual.texi] Error 127 make[1]: Leaving directory `/root/git-2.49.1/Documentation' make: *** [info] Error 2
此时可以看到会报错"docbook2x-texi: command not found",我查了一圈发现,实际上已经安装(docbook2X),这里只需要设置一个软链接。
[root@localhost git-2.49.1]# ln -s /usr/bin/db2x_docbook2texi /usr/bin/docbook2x-texi
之后,重新执行"make all doc info",并继续安装
[root@localhost git-2.49.1]# make all doc info [root@localhost git-2.49.1]# echo $? #检查上一个命令是否有异常 0 [root@localhost git-2.49.1]# make install install-doc install-html install-info [root@localhost git-2.49.1]# echo $? #检查上一个命令是否有异常 0 [root@localhost git-2.49.1]# echo "export PATH=/usr/local/git-2.49.1/bin:$PATH" >>/etc/profile #添加环境变量 [root@localhost git-2.49.1]# source /etc/profile [root@localhost git-2.49.1]# git --version #查看版本是否正确 git version 2.49.1
以上就安装好了。
(4).配置服务器仓库
我个人认为一般会存在两种情况:1、先开发后搭建git服务器(这个情况我估计应该少很多了);2、先搭建git服务器后开发
其他的先不说,先在服务器上新建一个git专属用户,专门管理git。
[root@localhost ~]# groupadd git [root@localhost ~]# useradd git -g git [root@localhost ~]# passwd git Changing password for user git. New password: Retype new password: passwd: all authentication tokens updated successfully.
a.第一种情况模拟,我在个人的window系统上创建一个my_project目录,并在其中新增test1.txt、test2.sql。
目录空白位置右键,点击”Open Git Bash Here“,打开命令行工具。然后执行如下命令:
$ git config --global user.name "John Doe" #配置用户名
64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project (master)
$ git config --global user.email johndoe@example.com #配置邮箱地址
64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project (master)
$ git init #初始化仓库
hint: Using 'master' as the name for the initial branch. This default branch name
hint: will change to "main" in Git 3.0. To configure the initial branch name
hint: to use in all of your new repositories, which will suppress this warning,
hint: call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
hint:
hint: Disable this message with "git config set advice.defaultBranchName false"
Initialized empty Git repository in C:/Users/64267/Desktop/my_project/.git/
64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project (master)
$ ll -a
total 8
drwxr-xr-x 1 64267 197609 0 Jan 14 21:14 ./
drwxr-xr-x 1 64267 197609 0 Jan 14 21:12 ../
drwxr-xr-x 1 64267 197609 0 Jan 14 21:14 .git/
-rw-r--r-- 1 64267 197609 0 Jan 14 20:56 test1.txt
-rw-r--r-- 1 64267 197609 0 Jan 14 20:56 test2.sql
64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project (master)
$ git status #查看状态
On branch master
No commits yet
Untracked files: #未跟踪的文件
(use "git add ..." to include in what will be committed)
test1.txt
test2.sql
nothing added to commit but untracked files present (use "git add" to track)
64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project (master)
$ git add . #将当前目录下所有文件进行跟踪,也可以跟随文件名进行单点添加
64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project (master)
$ git status #查看状态
On branch master
No commits yet
Changes to be committed: #要提交的更改
(use "git rm --cached ..." to unstage)
new file: test1.txt
new file: test2.sql
64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project (master)
$ git commit -m 'initial project version' #提交并备注
[master (root-commit) 59a2071] initial project version
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test1.txt
create mode 100644 test2.sql
64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project (master)
$ cd .. #返回上一层
64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop
$ git clone --bare my_project my_project.git #克隆一个裸仓
Cloning into bare repository 'my_project.git' ...
done.
64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop
$ scp -r my_project.git git@[服务器地址]:/home/git/my_project.git #将裸仓上传至服务器端
The authenticity of host '192.168.142.101 (192.168.142.101)' can't be established.
ED25519 key fingerprint is: SHA256:G5Bqj7K2SG1CGxyk4p4AyCWqBOe+9fxRBG8hpZVb0vE
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.142.101' (ED25519) to the list of known hosts.
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
git@192.168.142.101's password:
config 100% 163 96.0KB/s 00:00
description 100% 73 85.2KB/s 00:00
HEAD 100% 23 32.4KB/s 00:00
applypatch-msg.sample 100% 478 810.7KB/s 00:00
commit-msg.sample 100% 896 1.5MB/s 00:00
fsmonitor-watchman.sample 100% 4726 6.2MB/s 00:00
post-update.sample 100% 189 246.2KB/s 00:00
pre-applypatch.sample 100% 424 595.8KB/s 00:00
pre-commit.sample 100% 1649 2.2MB/s 00:00
pre-merge-commit.sample 100% 416 552.3KB/s 00:00
pre-push.sample 100% 1374 1.6MB/s 00:00
pre-rebase.sample 100% 4898 1.4MB/s 00:00
pre-receive.sample 100% 544 820.3KB/s 00:00
prepare-commit-msg.sample 100% 1492 1.9MB/s 00:00
push-to-checkout.sample 100% 2783 3.8MB/s 00:00
sendemail-validate.sample 100% 2308 2.0MB/s 00:00
update.sample 100% 3650 4.9MB/s 00:00
exclude 100% 240 443.0KB/s 00:00
54ae5be93c6478b2da71e5e142adb156cc07ef 100% 64 111.2KB/s 00:00
49973e2e839000f52a02e7c9f0e936cf7258c8 100% 137 197.3KB/s 00:00
9de29bb2d1d6434b8b29ae775ad8c2e48c5391 100% 15 7.2KB/s 00:00
packed-refs 100% 105 161.6KB/s 00:00
64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop
到服务器上看下,裸仓是否存在。
[root@localhost ~]# su git [git@localhost root]$ cd [git@localhost ~]$ ll total 0 drwxr-xr-x. 6 git git 122 Jan 14 21:34 my_project.git [git@localhost ~]$ ls my_project.git/ config description HEAD hooks info objects packed-refs refs
这就完成了,下面我们做一下测试。将my_project目录下的文件删除,接着从服务器上将文件clone下来。(还是接着上面的window命令行,我们当前的地址是在~/Desktop/目录下)
$ cd my_project 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project (master) $ rm -rf .git/ 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project $ rm -rf test1.txt test2.sql 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project $ ll -a total 4 drwxr-xr-x 1 64267 197609 0 Jan 14 21:43 ./ drwxr-xr-x 1 64267 197609 0 Jan 14 21:27 ../ 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project $ cd .. 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop $ git clone git@192.168.142.101:my_project.git Cloning into 'my_project'... ** WARNING: connection is not using a post-quantum key exchange algorithm. ** This session may be vulnerable to "store now, decrypt later" attacks. ** The server may need to be upgraded. See https://openssh.com/pq.html git@192.168.142.101's password: remote: Counting objects: 3, done. remote: Compressing objects: 100% (2/2), done. remote: Total 3 (delta 0), reused 0 (delta 0) Receiving objects: 100% (3/3), done. 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop $ cd my_project 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project (master) $ ls -a ./ ../ .git/ test1.txt test2.sql 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project (master)
测试完美通过。
b.第二种情况模拟,这种情况才是大多数情况,并且由于工具的普及,直接敲代码的情况可能已经较少了。
直接在服务器上创建裸仓。
[git@localhost ~]$ pwd /home/git [git@localhost ~]$ git init --bare my_project2.git Initialized empty Git repository in /home/git/my_project2.git/ [git@localhost ~]$ ls my_project2.git my_project.git [git@localhost ~]$ ls my_project2.git/ branches config description HEAD hooks info objects refs
本地直接clone,之后进行开发
$ pwd /c/Users/64267/Desktop/my_project 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project (master) $ cd .. 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop $ git clone git@192.168.142.101:my_project2.git Cloning into 'my_project2'... ** WARNING: connection is not using a post-quantum key exchange algorithm. ** This session may be vulnerable to "store now, decrypt later" attacks. ** The server may need to be upgraded. See https://openssh.com/pq.html git@192.168.142.101's password: warning: You appear to have cloned an empty repository. hint: Using 'master' as the name for the initial branch. This default branch name hint: will change to "main" in Git 3.0. To configure the initial branch name hint: to use in all of your new repositories, which will suppress this warning, hint: call: hint: hint: git config --global init.defaultBranch <name> hint: hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and hint: 'development'. The just-created branch can be renamed via this command: hint: hint: git branch -m <name> hint: hint: Disable this message with "git config set advice.defaultBranchName false" 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop $ cd my_project2/ 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project2 (master) $ ll -a total 8 drwxr-xr-x 1 64267 197609 0 Jan 14 21:48 ./ drwxr-xr-x 1 64267 197609 0 Jan 14 21:48 ../ drwxr-xr-x 1 64267 197609 0 Jan 14 21:48 .git/ 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project2 (master)
(5).传输协议的相关配置
Git可以使用四种不同的协议来传输资料:本地协议(Local),HTTP 协议,SSH(Secure Shell)协议及 Git 协议。 它们各有优缺点,但据我所知多数情况下采用SSH协议或HTTP协议。优缺点详见官方文档:https://git-scm.com/book/zh/v2/%e6%9c%8d%e5%8a%a1%e5%99%a8%e4%b8%8a%e7%9a%84-Git-%e5%8d%8f%e8%ae%ae
1)SSH协议上面已经用到了,但是实际情况下,并不会将服务器密码告知开发人员,此时就需要SSH公私钥对。
首先,你需要确认个人是否已经拥有密钥。 默认情况下,用户的 SSH 密钥存储在其 ~/.ssh 目录下。还是通过Window上的git_bash,进入该目录并列出其中内容,你便可以快速确认自己是否已拥有密钥:
$ cd ~/.ssh/ 64267@LAPTOP-TDH6F977 MINGW64 ~/.ssh $ ls -a ./ ../ id_ed25519 id_ed25519.pub known_hosts known_hosts.old
其中id_ed25529和id_ed25519.pub就是一对公私钥对,.pub文件为本地的公钥,对应的另一个为私钥。 如果找不到这样的文件(或者根本没有 .ssh 目录),你可以通过运行 ssh-keygen 程序来创建它们。 在 Linux/macOS 系统中,ssh-keygen 随 SSH 软件包提供;在 Windows 上,该程序包含于 MSysGit 软件包中。我这里使用的是Windows系统,git_bash的命令行:
$ ssh-keygen.exe -o Generating public / private ed25519 key pair. Enter file in which to save the key (/c/Users/64267/.ssh/id_ed25519): Enter passphrase for "/c/Users/admin/.ssh/id_ed25519" (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /c/Users/admin/.ssh/id_ed25519 Your public key has been saved in /c/Users/admin/.ssh/id_ed25519.pub The key fingerprint is : SHA256:cUJipY/OfsEfq25aCOh+34O1KT79Ya/3KG4eTe883SQ admin@DESKTOP-4CERLUK The key's randomart image is : +--[ED25519 256]--+ | o.o | | . + | | . o . | | . o + | | . . ..S . | | . + .+ .o .E .| | . ++.=+o. .+.| | . ..+oB.=+.+. o| | .. o=B+B=+o.+. | +----[SHA256]-----+ 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project2 (master)
ssh-keygen 会确认密钥的存储位置(默认是 .ssh/id_rsa),然后它会要求你输入两次密钥口令。 如果你不想在使用密钥时输入口令,将其留空即可。 然而,如果你使用了密码,那么请确保添加了 -o 选项,它会以比默认格式更能抗暴力破解的格式保存私钥。 你也可以用 ssh-agent 工具来避免每次都要输入密码。
接着将公钥配置到服务器上。注意:我们在原本的公钥前面添加 no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty 用来限制ssh端口转发访问服务器。
[git@localhost ~]$ mkdir .ssh [git@localhost ~]$ chmod 700 .ssh [git@localhost ~]$ touch .ssh/authorized_keys [git@localhost ~]$ chmod 600 .ssh/authorized_keys [git@localhost ~]$ vim .ssh/authorized_keys no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty [公钥内容]
进行测试,将Windows电脑上的my_project目录删除,重新clone:
$ cd 64267@LAPTOP-TDH6F977 MINGW64 ~ $ git clone git@[服务器地址]:my_project Cloning into 'my_project' ... ** WARNING: connection is not using a post-quantum key exchange algorithm. ** This session may be vulnerable to "store now, decrypt later" attacks. ** The server may need to be upgraded. See https://openssh.com/pq.html remote: Counting objects: 3, done. #可以看到直接开始clone,不需要输入密码了 remote: Compressing objects: 100% (2/2), done. remote: Total 3 (delta 0), reused 0 (delta 0) Receiving objects: 100% (3/3), done. 64267@LAPTOP-TDH6F977 MINGW64 ~
注意:目前测试是通过了,但是也造成了开发人员可以免密登录服务器,所以还需要进行进一步的设置。
借助一个名为 git-shell 的受限 shell 工具,你可以方便地将用户 git 的活动限制在与 Git 相关的范围内。 该工具随 Git 软件包一同提供。如果将 git-shell 设置为用户 git 的登录 shell(login shell), 那么该用户便不能获得此服务器的普通 shell 访问权限。 若要使用 git-shell,需要用它替换掉 bash 或 csh,使其成为该用户的登录 shell。为进行上述操作,首先你必须确保 git-shell 的完整路径名已存在于 /etc/shells 文件中,如果没有就添加一下。
[root@localhost ~]# cat /etc/shells /bin/sh /bin/bash /usr/bin/sh /usr/bin/bash [root@localhost ~]# which git-shell /usr/bin/git-shell [root@localhost ~]# echo '/usr/bin/git-shell' >> /etc/shells
确认没有问题后才可以使用 chsh <username> -s <shell> 命令修改系统用户的 默认登录shell。或者直接vim /etc/passwd,将git用户登录模式改为/usr/bin/git-shell。
[root@localhost ~]# chsh git -s $(which git-shell) #我这里与chsh git -s /usr/bin/git-shell等价 Changing shell for git. Shell changed.
最后测试一下是否被限制。在windows系统上使用git的命令行尝试。
$ ssh git@[服务器地址] ** WARNING: connection is not using a post-quantum key exchange algorithm. ** This session may be vulnerable to "store now, decrypt later" attacks. ** The server may need to be upgraded. See https://openssh.com/pq.html PTY allocation request failed on channel 0 fatal: Interactive git shell is not enabled. hint: ~/git-shell-commands should exist and have read and execute access. Connection to 192.168.142.101 closed. 64267@LAPTOP-TDH6F977 MINGW64 ~
2)HTTP协议
我们一般通过SSH进行授权访问,通过git://进行无授权访问,但HTTP协议可以同时实现以上两种方式的访问。而配置一个轻量级http服务器一般只需要在服务器上启动Git自带的名为git-http-backend的CGI脚本。该 CGI 脚本将会读取由 git fetch 或 git push 命令向 HTTP URL 发送的请求路径和头部信息, 来判断该客户端是否支持 HTTP 通信(不低于 1.6.6 版本的客户端支持此特性)。如果 CGI 发现该客户端支持智能(Smart)模式,它将会以智能模式与它进行通信, 否则它将会回落到哑(Dumb)模式下(因此它可以对某些老的客户端实现向下兼容)。
这里采用Apache来作为CGI服务器,如果没有Apache可以执行如下命令:
[root@localhost ~]# dnf -y install httpd httpd-tools [root@localhost ~]# httpd -M | grep -E 'cgi|alias|env' #查看Apache启用模块 AH00558: httpd: Could not reliably determine the server 's fully qualified domain name, using ::1. Set the ' ServerName' directive globally to suppress this message alias_module (shared) env_module (shared) setenvif_module (shared) vhost_alias_module (shared) proxy_fcgi_module (shared) proxy_scgi_module (shared) cgi_module (shared) #如果缺少以上任意一种可以使用以下命令安装 [root@localhost ~]# dnf -y install cgi_module alias_module env_module
该操作将会启用 cgi_module, alias_module 和 env_module 等 Apache 模块, 这些模块都是使该功能正常工作所必须的。
还要将裸仓的上级目录(例如上文中的/home/git)的用户组设置为apache(注意:这里是apache的用户组,不同系统可能不一样),这样 Web 服务器才能读写该仓库, 因为运行 CGI 脚本的 Apache 实例默认会以该用户的权限运行。因为这里不用ssh认证,所以我将裸仓的上级目录改到/srv/git,操作如下:
[root@localhost ~]# mkdir -p /srv/git
接着修改Apache的配置文件,我这里直接新增一个配置文件到/etc/httpd/conf.d/目录下,因为/etc/httpd/conf/httpd.conf中存在"IncludeOptional conf.d/*.conf"(IncludeOptional引用的路径有问题时会被忽略,不会报错)引用了/etc/httpd/conf.d/目录下所有.conf文件。命令如下:
[root@localhost ~]# vim /etc/httpd/conf.d/git.conf
# 监听8989端口
Listen 8989
# git仓库路径设置
SetEnv GIT_PROJECT_ROOT /srv/git
# 仓库公开策略。如果没有下面这一行,那么无授权客户端只能访问带 git-daemon-export-ok 文件的版本库;如果有,那么Git将会公开服务器上所有的仓库
SetEnv GIT_HTTP_EXPORT_ALL
# 将以/git/开头的请求映射到git-http-backend这个CGI脚本
ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
# 匹配目录
<directory "/usr/libexec/git-core">
# 匹配文件名
<files "git-http-backend">
# 用户认证类型
AuthType Basic
# 设置授权领域的名称
AuthName "Git Access"
# 设置用于身份验证的用户的账号密码地址
AuthUserFile /srv/git/.htpasswd
Require expr !(%{QUERY_STRING} -strmatch '*service=git-receive-pack*' || %{REQUEST_URI} =~ m#/git-receive-pack$#)
# 强制用户必须身份验证才能访问受保护的资源
Require valid-user
</files>
</directory>
<directory "/srv/git">
#启用 CGI 脚本的执行权限
Options +ExecCGI
#忽略.htaccess 文件
AllowOverride None
#授权所有用户访问当前目录下的所有文件
Require all granted
</directory>
[root@localhost ~]# systemctl restart httpd
注意:不同系统git-http-backend的CGI脚本路径可能不一样,根据实际情况修改。CentOS是/usr/libexec/git-core/git-http-backend,有些liinux系统是/usr/lib/git-core/git-http-backend。
Require expr !(%{QUERY_STRING} -strmatch '*service=git-receive-pack*' || %{REQUEST_URI} =~ m#/git-receive-pack$#) 配置说明:
%{QUERY_STRING} 这是HTTP请求的查询字符串部分,即URL中问号后面的参数部分;
%{QUERY_STRING} -strmatch '*service=git-receive-pack*' 这部分表示查询字符串中是否包含`service=git-receive-pack`。`-strmatch`表示字符串匹配,`*service=git-receive-pack*`表示允许前后有任意字符的匹配条件;
|| 这是逻辑或操作符,表示两个条件中的任意一个满足即可;
%{REQUEST_URI} =~ m#/git-receive-pack$# 这部分检查请求的URI(路径部分)是否以`/git-receive-pack`结尾。`=~`表示正则表达式匹配,`m#...#`是正则表达式的模式,而`$`表示匹配字符串的末尾。
因此,整个 Require 表达式的含义是:仅当查询字符串包含`service=git-receive-pack`或URI以`/git-receive-pack`结尾时,这部分规则才会被触发。(即在上传时需要进行身份验证)
更多Apache授权访问配置请查看官网文档:https://httpd.apache.org/docs/current/howto/auth.html
创建一个授权账号,如下:
[root@localhost ~]# htpasswd -c /srv/git/.htpasswd testuser New password: Re-type new password: Adding password for user testuser [root@localhost ~]# chgrp apache /srv/git/.htpasswd
创建仓库便于进行测试:
[root@localhost conf]# cd /srv/git/ [root@localhost git]# git init --bare my_project3.git #创建裸仓 Initialized empty Git repository in /srv/git/my_project3.git/ [root@localhost git]# git init --bare my_project4.git #创建无授权客户可以访问的裸仓 Initialized empty Git repository in /srv/git/my_project4.git/ [root@localhost git]# touch my_project4.git/git-daemon-export-ok #也可以chown -R apache:apache /srv/git将个人与组都改为apache [root@localhost git]# chgrp -R apache /srv/git [root@localhost git]# chmod -R g+w /srv/git/ [root@localhost git]# ll total 0 drwxrwxr-x. 7 root apache 119 Jan 14 22:58 my_project3.git drwxrwxr-x. 7 root apache 147 Jan 14 22:58 my_project4.git
将服务器端 /etc/httpd/conf.d/git.conf 配置文件中的 "SetEnv GIT_HTTP_EXPORT_ALL"删除或注释,之后进行clone测试(Windows客户端):
64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop $ git clone http://[服务器地址]:8989/git/my_project3.git Cloning into 'my_project3'... fatal: repository 'http://192.168.142.101:8989/git/my_project3.git/' not found 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop $ git clone http://[服务器地址]:8989/git/my_project4.git Cloning into 'my_project4'... warning: You appear to have cloned an empty repository. hint: Using 'master' as the name for the initial branch. This default branch name hint: will change to "main" in Git 3.0. To configure the initial branch name hint: to use in all of your new repositories, which will suppress this warning, hint: call: hint: hint: git config --global init.defaultBranch <name> hint: hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and hint: 'development'. The just-created branch can be renamed via this command: hint: hint: git branch -m <name> hint: hint: Disable this message with "git config set advice.defaultBranchName false" 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop
可以看到my_project3无法找到,但my_project4正常clone,接着将配置还原,再试一次:
$ rm -rf my_project4/ 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop $ git clone http://[服务器地址]:8989/git/my_project3.git Cloning into 'my_project3'... warning: You appear to have cloned an empty repository. hint: Using 'master' as the name for the initial branch. This default branch name hint: will change to "main" in Git 3.0. To configure the initial branch name hint: to use in all of your new repositories, which will suppress this warning, hint: call: hint: hint: git config --global init.defaultBranch <name> hint: hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and hint: 'development'. The just-created branch can be renamed via this command: hint: hint: git branch -m <name> hint: hint: Disable this message with "git config set advice.defaultBranchName false" 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop $ git clone http://[服务器地址]:8989/git/my_project4.git Cloning into 'my_project4'... warning: You appear to have cloned an empty repository. hint: Using 'master' as the name for the initial branch. This default branch name hint: will change to "main" in Git 3.0. To configure the initial branch name hint: to use in all of your new repositories, which will suppress this warning, hint: call: hint: hint: git config --global init.defaultBranch <name> hint: hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and hint: 'development'. The just-created branch can be renamed via this command: hint: hint: git branch -m <name> hint: hint: Disable this message with "git config set advice.defaultBranchName false" 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop
再进行push测试,git push时会从弹出输入账号密码的界面,如下图:
$ echo "my_project3" > my_project3/file.txt 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop $ cd my_project3/ 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project3 (master) $ git add . warning: in the working copy of 'file.txt', LF will be replaced by CRLF the next time Git touches it 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project3 (master) $ git commit -m "Initial commit" [master (root-commit) eacb335] Initial commit 1 file changed, 1 insertion(+) create mode 100644 file.txt 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project3 (master) $ git push Enumerating objects: 3, done. Counting objects: 100% (3/3), done. Writing objects: 100% (3/3), 225 bytes | 225.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0) To http://[服务器地址]:8989/git/my_project3.git * [new branch] master -> master 64267@LAPTOP-TDH6F977 MINGW64 ~/Desktop/my_project3 (master)

这样就完成了。
参考资料:https://www.cnblogs.com/Kyle023/p/14746741.html
https://blog.csdn.net/GTOFEI013/article/details/89519104
https://blog.csdn.net/weixin_30570101/article/details/95021329
https://www.cnblogs.com/Undefined443/p/18524222

浙公网安备 33010602011771号