Git 远程命令深度剖析:从 git remote add 到 HTTPS 与 SSH
你提出的问题 git remote add origin https://github.com/user/repo.git 本质是做了什么? 从ssh开始给我剖析 触及了 Git 的两个核心概念:1) 本地仓库如何"记住"远程仓库;2) 它如何与远程仓库安全地通信。
我们将一步步拆解这个过程。
第一部分:命令的本质 ------ git remote add ... 做了什么?
首先,我们来分析你输入的这条命令本身:
bash
git remote add origin [https://github.com/user/repo.git](https://github.com/user/repo.git)
核心答案是:这条命令几乎什么也没做。
- 它没有联网: 它不会以任何方式联系
github.com。 - 它没有验证: 它不会检查那个 URL 是否有效,仓库是否存在,或者你是否有权限。
它唯一的动作是:修改你本地仓库中的一个配置文件。
这个文件位于你的项目目录下的 .git/config。
在执行该命令之前,你的 .git/config 文件可能看起来像这样:
ini
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
...
执行 git remote add origin ... 之后,Git 会在这个文件的末尾添加一个新段落:
ini
[core]
...
[remote "origin"]
url = [https://github.com/user/repo.git](https://github.com/user/repo.git)
fetch = +refs/heads/*:refs/remotes/origin/*
命令拆解:
git remote add:- 这是一个"配置"命令。它告诉 Git:"嘿,我要在我的本地配置里,添加(
add)一个远程(remote)仓库的记录。"
- 这是一个"配置"命令。它告诉 Git:"嘿,我要在我的本地配置里,添加(
origin:- 这是你给这个远程仓库起的本地昵称(alias)。
- 这纯粹是为了方便。当你想从这个远程仓库拉取(pull)或推送(push)时,你不用再输入那个长长的 URL,你只需要说
git push origin main即可。 origin是一个约定俗成的名字,代表你"主要"的远程仓库,但你完全可以叫它github、backup或任何你喜欢的名字。
https://...:- 这是那个远程仓库的地址(URL)。
- 这是最重要的部分,它告诉 Git 在未来需要通信时(例如
git fetch),应该去哪里以及使用什么协议。
总结:git remote add 的本质就是一个"书签"或"通讯录"操作。 你在本地的 .git/config 文件里,给一个复杂的 URL (https://...) 关联上了一个简单的昵称 (origin)。仅此而已。
第二部分:通信的发生 ------ git push/pull 时发生了什么?
真正的网络通信发生在你执行 git fetch, git pull 或 git push 时。
这时,Git 会查看 .git/config 文件,找到你指定的昵称(比如 origin),然后读取它关联的 url,并根据 URL 的协议头 (https:// 或 git@)来决定如何通信。
下面我们就来对比你命令中的 HTTPS 协议,和你特别要求剖析的 SSH 协议。
场景一:使用 HTTPS 协议(你命令中的例子)
当 url 以 https:// 开头时,Git 的行为就像一个浏览器(但没有图形界面)。
- 连接 :Git 客户端(你的电脑)会通过 443 端口 向
github.com服务器发起一个标准的 HTTPS 请求。 - 加密 :连接是通过 SSL/TLS 加密的。这意味着你的电脑和 GitHub 服务器之间的数据传输是安全的,可以防止中间人窃听和篡改。你的电脑会验证 GitHub 的 SSL 证书,确保你连接的是真正的 GitHub。
- 鉴权 (Authentication) :这是关键。当你尝试
git push(推送,需要写权限)时,GitHub 服务器会回复:"OK,我收到了你的请求,但你是谁?请证明你有权限写入这个仓库。"- 方式 :Git 会弹出一个提示框或在命令行中提示你输入用户名和密码。
- 注意 :对于 GitHub、GitLab 等现代 Git 托管平台,你在此处输入的"密码"不再是你的账户登录密码。
- 你必须输入的是:Personal Access Token (PAT,个人访问令牌) 。你需要在 GitHub (或 GitLab/Bitbucket) 的开发者设置中生成一个 PAT,并授予它
repo(仓库读写)权限。 - 凭据存储:你不需要每次都输入。操作系统(如 Windows 凭据管理器、macOS 钥匙串)或 Git 自身(Git Credential Manager)会自动帮你缓存这个令牌。
HTTPS 总结:
- 优点:非常"防火墙友好"(几乎所有网络都开放 443 端口),设置简单(只需一个 PAT)。
- 缺点:每次推送/拉取都需要进行一次 HTTP 请求和鉴权,速度可能稍慢。如果凭据缓存失败,反复输入 PAT 很麻烦。
场景二:使用 SSH 协议(你要求剖析的)
如果当初你添加远程仓库的命令是这样的:
bash
# 注意 URL 格式完全不同
git remote add origin git@github.com:user/repo.git
那么,当你在未来执行 git push/pull 时,一切都将不同。Git 将使用 SSH (Secure Shell) 协议。
- 连接 :Git 客户端(通过你电脑上的
ssh程序)会通过 22 端口 尝试连接到github.com服务器。它会以 URL 中@符号前的用户名(即git)来请求登录。- 题外话:为什么是
git用户? 这是一个"虚拟"用户。GitHub 的所有 SSH 连接都使用这个git用户,GitHub 服务器内部会再根据你提供的"密钥"来识别你是哪一个 GitHub 注册用户。
- 题外话:为什么是
- 鉴权 (Authentication) :这是 SSH 的核心,它完全不使用密码或令牌 。它使用公钥/私钥加密。
SSH 鉴权详细步骤:
A. 准备工作(一次性设置)
-
生成密钥对 :你需要在你的本地电脑 上运行
ssh-keygen命令。bashssh-keygen -t rsa -b 4096 -C "your_email@example.com" -
得到两个文件 :这个命令会生成一个密钥对 ,通常在
~/.ssh/目录下:id_rsa:私钥 (Private Key) 。这是你的绝密凭证,永远、绝对不能泄露给任何人。它留在你的电脑上。id_rsa.pub:公钥 (Public Key) 。这是你的"身份标识",可以安全地分享给任何人。.pub就是 "public" 的意思。
-
在 GitHub 注册公钥 :你登录 GitHub,进入 "Settings" -> "SSH and GPG keys",点击 "New SSH key",然后将你
id_rsa.pub文件的全部内容复制并粘贴进去。
B. 实际通信(每次 git push/pull)
当你执行 git push origin main 时:
- 发起连接 :你的 Git 客户端(通过
ssh)对github.com的 22 端口说:"你好,我是用户git,我想连接。" - 服务器质询 (Challenge) :GitHub 服务器说:"哦?用户
git?我收到了。我这里注册了一堆公钥。我现在用你的公钥加密一条随机消息,发回给你。你解密了再发给我,我就信你。" - 本地解密 (Response) :
- GitHub 服务器从你账户里找到它存的你的公钥 (
id_rsa.pub),用它加密一个"挑战"(比如 "hello")。 - 这个加密后的消息被发送回你的电脑。
- 你的
ssh客户端自动在~/.ssh/目录中寻找你的私钥 (id_rsa)。 - 数学奇迹发生:只有这个私钥能解开对应公钥加密的消息。
- 你的客户端成功解密,得到了原文 "hello"。
- (如果你的私钥有密码,此时会提示你输入私钥的密码来"解锁"私钥,
ssh-agent可以帮你记住这个密码)。
- GitHub 服务器从你账户里找到它存的你的公钥 (
- 鉴权成功:你的客户端将解密后的 "hello" 发回给服务器。
- 验证通过 :GitHub 服务器收到 "hello",与它发出的原文一致。它说:"验证通过。你确实是这个公钥的主人(也就是 XXXX 用户),你有这个仓库的写入权限。连接建立,数据通道已加密。请开始你的
push吧。" - 数据传输:Git 开始通过这个已加密的 SSH 通道传输数据。
SSH 总结:
- 优点:极其安全。一次设置,终身(只要私钥不丢)免密登录,非常方便。通常比 HTTPS 快一点,因为连接是持久的。
- 缺点:初始设置相对复杂(需要生成密钥、复制公钥)。22 端口可能在某些严格的公司或公共 Wi-Fi 防火墙中被禁用。
最终对比:HTTPS vs. SSH
| 特性 | HTTPS 协议 (https://...) |
SSH 协议 (git@...) |
|---|---|---|
| URL 格式 | https://github.com/user/repo.git |
git@github.com:user/repo.git |
| 默认端口 | 443 | 22 |
| 鉴权方式 | 个人访问令牌 (PAT) (在密码提示框中输入) | SSH 密钥对 (公钥/私钥) |
| 设置 | 简单:在 GitHub 生成一个 PAT 即可。 | 复杂:本地生成密钥对,再把公钥上传到 GitHub。 |
| 日常使用 | 第一次需要输入 PAT,后续靠凭据管理器缓存。 | "Set it and forget it." 设置一次后,基本无需再管。 |
| 安全性 | 安全 (TLS 加密) | 非常安全 (SSH 协议加密) |
| 防火墙 | 非常友好 (443 端口几乎总是开放) | 可能被阻止 (22 端口在某些网络中被禁用) |
结论:
- 你执行的
git remote add ... https://...命令,本质上只是在本地.git/config文件里增加了一条配置记录(一个书签)。 - 它使用 HTTPS 协议 ,这意味着在未来的
push/pull操作中,你将使用 PAT(个人访问令牌) 来进行身份验证。 - 你要求的从 SSH 剖析 ,则是另一种完全不同的通信方式。它不使用 PAT,而是使用在你本地电脑上生成的私钥 和上传到 GitHub 的公钥来进行数学加密验证,实现"免密"登录。