1

Git 入门指南-协议

前言

讲到Git协议,通常情况下我们需要与其他人的git仓库进行推送或拉取资料,与别人通信是需要使用到协议。

最佳协作实践

建立一个你与合作者们都有权利访问,且可从那里推送和拉取资料的共用仓库。

注意:使用git,技术上是可以实现,从个人仓库进行推送(push)和拉取(pull)来修改内容,但不方便。

Git中的四种主要协议

  • 本地协议(Local)
  • HTTP 协议
  • SSH(Secure Shell)协议
  • Git 协议。

    在此,我们将会讨论那些协议及哪些情形应该使用(或避免使用)他们。

本地协议

版本库就是硬盘内的另一个目录。

你可以像下面这样:

git clone /git/project.git # clone一个本地项目到新的目录。
git remote add local_proj /git/project.git # 添加project为当前库的远程库(本地引用local_proj)

优点

简单,直接使用现有的文件权限,速度快(不进行远程操作的话,就是磁盘的读写速度),

缺点

建立版本库协作需要共享文件系统,不方便从多个物理位置访问(家,公司,出差点等)。

值得一提的是,如果你使用的是类似于共享挂载的文件系统进行远程协作时,这个方法不一定是最快的。 访问本地版本库的速度与你访问数据的速度是一样的。 在同一个服务器上,如果允许 Git 访问本地硬盘,一般的通过 NFS 访问版本库要比通过 SSH 访问慢。

最终,这个协议并不保护仓库避免意外的损坏。 每一个用户都有“远程”目录的完整 shell 权限,没有方法可以阻止他们修改或删除 Git 内部文件和损坏仓库。

HTTP协议

Git 通过 HTTP 通信有两种模式。 在 Git 1.6.6 版本之前只有一个方式可用,十分简单并且通常是只读模式的。 Git 1.6.6 版本引入了一种新的、更智能的协议,让 Git 可以像通过 SSH 那样智能的协商和传输数据。新版本的 HTTP 协议一般被称为“智能” HTTP 协议,旧版本的一般被称为“哑” HTTP 协议。

智能(Smart) HTTP 协议

“智能” HTTP 协议运行在标准的 HTTP/S 端口上并且可以使用各种 HTTP 验证机制,这意味着使用起来会比 SSH 协议简单的多,比如可以使用 HTTP 协议的用户名/密码的基础授权,免去设置 SSH 公钥。

智能 HTTP 协议即支持像 git:// 协议一样设置匿名服务,也可以像 SSH 协议一样提供传输时的授权和加密。 而且只用一个 URL 就可以都做到,省去了为不同的需求设置不同的 URL。 如果你要推送到一个需要授权的服务器上(一般来讲都需要),服务器会提示你输入用户名和密码。 从服务器获取数据时也一样。

事实上,类似 GitHub 的服务,你在网页上看到的 URL (比如, https://github.com/schacon/simple.git),和你在克隆、推送(如果你有权限)时使用的是一样的。

哑(Dumb) HTTP 协议

SSH 协议

架设 Git 服务器时常用 SSH 协议作为传输协议。 因为大多数环境下已经支持通过 SSH 访问 —— 即使没有也比较容易架设。 SSH 协议也是一个验证授权的网络协议;并且,因为其普遍性,架设和使用都很容易。

通过 SSH 协议克隆版本库,你可以指定一个 ssh:// 的 URL:

$ git clone ssh://user@server/project.git

你也可以不指定用户,Git 会使用当前登录的用户名。

优势

SSH 架设相对简单,使用广泛,多数操作系统都包含了它及相关的管理工具,安全,会压缩数据。

缺点

不能匿名只读访问。

所以,即便只要读取数据,使用者也要有通过 SSH 访问你的主机的权限,这使得 SSH 协议不利于开源的项目。 如果你只在公司网络使用,SSH 协议可能是你唯一要用到的协议。 如果你要同时提供匿名只读访问和 SSH 协议,那么你除了为自己推送架设 SSH 服务以外,还得架设一个可以让其他人访问的服务。

Git 协议

Git 里的一个特殊的守护进程;它监听端口(9418),类似于 SSH 服务,但是访问无需任何授权。 要让版本库支持 Git 协议,需要先创建一个 git-daemon-export-ok 文件 —— 它是 Git 协议守护进程为这个版本库提供服务的必要条件 —— 但是除此之外没有任何安全措施。 要么谁都可以克隆这个版本库,要么谁也不能。 这意味着,通常不能通过 Git 协议推送。 由于没有授权机制,一旦你开放推送操作,意味着网络上知道这个项目 URL 的人都可以向项目推送数据。 不用说,极少会有人这么做。

优点

目前,Git 协议是 Git 使用的网络传输协议里最快的。 如果你的项目有很大的访问量,或者你的项目很庞大并且不需要为写进行用户授权,架设 Git 守护进程来提供服务是不错的选择。 它使用与 SSH 相同的数据传输机制,但是省去了加密和授权的开销。

缺点

Git 协议缺点是缺乏授权机制。 把 Git 协议作为访问项目版本库的唯一手段是不可取的。 一般的做法里,会同时提供 SSH 或者 HTTPS 协议的访问服务,只让少数几个开发者有推送(写)权限,其他人通过 git:// 访问只有读权限。 Git 协议也许也是最难架设的。 它要求有自己的守护进程,这就要配置 xinetd 或者其他的程序,这些工作并不简单。 它还要求防火墙开放 9418 端口,但是企业防火墙一般不会开放这个非标准端口。 而大型的企业防火墙通常会封锁这个端口。

在代码托管服务使用SSH协议协作

使用SSH协议,你可以连接和验证远程服务器和服务。使用SSH秘钥,你可以在每次连接GitHub或者Gitlab时,不需要用户名和密码。

检查是否已经存在SSH秘钥?

在生成新的SSH秘钥对之前我们应该检查一下我们的系统中是否已经有生成过秘钥,因为没有特别用途我们没有必要使用多对秘钥,如果没有找到秘钥对,那就需要新生成秘钥。

cd ~/.ssh/ 目录我们可以查看到已经生成过的秘钥对。

Note: 公钥可能被命名为以.pub为扩展的文件名,如下:

id_dsa.pub
id_ecdsa.pub
id_ed25519.pub

新生成秘钥

使用你的邮箱生成一个新的秘钥。

ssh-keygen -t rsa -C "your.email@example.com" -b 4096

这里会有几个提问:

  1. Enter file in which to save the key (/Users/rs/.ssh/id_rsa)?

键入你想把秘钥保存在哪(/Users/rs/.ssh/id_rsa)?

解释:括号中是一个默认路径/Users/rs/.ssh/和文件名id_rsa, 键入enter就会使用默认,这里需要注意,如果使用建议路径,SSH客户端将自动找到配置文件,否则可能需要自己调整配置。

另外,如果你建议路径已经有秘钥对,你将需要键入一个新的秘钥路径,并在./ssh/config文件中配置哪一个SSH秘钥对用在那个host上, 比如下面配置。

# GitLab.com server

Host gitlab.com
RSAAuthentication yes
IdentityFile ~/.ssh/config/private-key-filename-01

# Private GitLab server

Host gitlab.company.com
RSAAuthentication yes
IdentityFile ~/.ssh/config/private-key-filename
  1. Enter passphrase (empty for no passphrase)?

    键入访问私钥需要的密码,留空代表不需要密码,一般情况我们秘钥都在自己个人电脑上,无需加密,省去加密过程,留空,键入enter。

这样我们就在~/.ssh目录下生成了id_rsa私钥和id_rsa.pub公钥这样一对秘钥,我们复制id_rsa.pub的文件内容到剪贴板。

打开公司的gitlab网站,输入自己的用户名和密码,进入自己的账号页面,找到账号的配置页面,找到SSH Keys标签页,将我们复制的内容粘贴到Key下面的输入框中, 如下图,注意请用自己的邮箱生成秘钥,我这里使用的是示例邮箱。

image-20181015173217998.png
clipboard.png

这样我们就配置完成了SSHkey了

该如何使用SSH来推送更新呢

当我们配置好SSH后,我们找到我们的项目,比如这里我以git项目为例,选择SSH,然后我们就可以获取到一个SSH协议的git仓库地址,点击地址后面的复制按钮,将仓库地址复制到剪贴板中。

clipboard.png

将项目克隆到本地

在电脑本地的一个目录中

git clone ssh://git@git.xes.com/courseware/share-plane/git.git

然后第一次连接会出现让确认主机:

大概意思是,无法确认host主机的真实性,只知道它的公钥指纹,问你还想继续连接吗?

所谓"公钥指纹",是指公钥长度较长(这里采用RSA算法,长达1024位),很难比对,所以对其进行SHA256计算,将它变成一个256位的指纹。上例中是SHA256:wixrNcpES0GdcUsWCvjbYYuanhmaMvgvmDSHZA9u+dA,再进行比较,就容易多了。

很自然的一个问题就是,用户怎么知道远程主机的公钥指纹应该是多少?回答是没有好办法,远程主机必须在自己的网站上贴出公钥指纹,以便用户自行核对。

没有找到我们公司公布的git.xes.com这个域名下的SSH指纹信息,但是类似的比如GitHub我们可以找到公布的指纹信息如下图:

clipboard.png

我们接受这个指纹(一般情况内网没有坏人)继续向下走.

系统会出现一句提示,表示host主机已经得到认可。

Warning: Permanently added 'host,12.18.429.21' (RSA) to the list of known hosts.

然后,会要求输入密码,如果你在生成秘钥对的时候对私钥进行加密了,就需要输入密码。

Password: (enter password)

如果密码正确,就可以登录了。

当远程主机的公钥被接受以后,它就会被保存在文件$HOME/.ssh/known_hosts之中。下次再连接这台主机,系统就会认出它的公钥已经保存在本地了,从而跳过警告部分,直接提示输入密码。

这样配置之后,我们便可以在本地进行ssh连接仓库, 这也是大多数开发者会使用的最通用最普遍的方式,也是github和gitlab推荐的方式。

其他的连接方案

url带授权信息

当然更简单的方式,使用智能HTTP的方式进行登录和推送内容:

比如: https://username:password@git.xes.com/courseware/share-plane/git.git

这样做的唯一的缺点就是,别人通过你本地电脑可能不小心看到你的密码哦。

git config配置缓存认证信息

git config --global credential.helper store


言月
1.8k 声望490 粉丝

从有技术广度到技术深度的转变,这样才能被自己迷恋