
先讲个我亲眼见过的场景。同事大清早来找我说 push 不上去报错Permission denied (publickey)。一问才知道他昨晚换了新电脑SSH 私钥只躺在旧机器的~/.ssh目录里新机器上连 key 都没生成。这时候最稳的解法不是现场配 SSH而是先把 Git 远程地址从gitgithub.com:xxx/xxx.git切到 HTTPS用 PATPersonal Access Token个人访问令牌把推拉能力恢复等有空了再慢慢配 SSH key。这件事看着小真踩上去能卡掉半天。我遇到过太多次clone 的时候默认走了 SSH后来换电脑密钥没带过来或者反过来公司 GitLab 统一要求 HTTPS PAT 认证我却一直用 SSH key 走天下。所以“Git 远程地址在 SSH 与 HTTPS 之间切换”其实是每个 Git 用户早晚都会碰到的必修课。这篇文章就把这件事一次讲透。先搞清楚 SSH 和 HTTPS 在 Git 里到底差在哪再说远程地址怎么改才安全然后重点讲 HTTPS 下 PAT 的创建、使用与安全边界最后分享切换之后常见的坑和排查思路。适合刚用 Git 不久、对 remote 和认证方式还有点绕的同学也适合被 PAT 过期坑过的老手当速查表。整个切换过程不影响你的本地提交和分支放心操作。1. 为什么要在 SSH 与 HTTPS 之间来回切换1.1 SSH 与 HTTPS 的本质差异在 Git 里远程地址本质上就是一个 URL协议不同认证方式、默认端口、使用体验都会差很多。SSH 走的是传输层安全通道默认端口是 22认证靠的是公钥和私钥这把“钥匙对”。你需要把公钥上传到 GitHub、GitLab 或 Gitee 的 SSH Keys 设置页私钥留在本地~/.ssh里。推送拉取时Git 会通过私钥证明“我是我”全程不需要输入账号密码。HTTPS 走的是 443 端口认证方式是“用户名 令牌”也就是本文要重点讲的 PAT。以前很多平台支持账号密码直接推送但现在主流平台都关掉了这个口子统一要求用 PAT 或者 SSH key。两者对比起来是这样的对比维度SSHHTTPS认证方式公私钥对用户名 PAT默认端口22443是否要生成密钥是不需要换电脑成本需要迁移私钥重新配置凭据即可首次配置复杂度稍高简单直接适合场景固定开发机、长期使用多设备切换、受限网络环境我自己的体会是SSH 配好之后一劳永逸特别适合个人主力电脑HTTPS 则更适合“哪里都能用”的场景只要 PAT 没过期、凭据管理器里存好换任何一台机器都能立刻推拉代码。1.2 真实场景什么时候你必须切换很多人以为 remote 地址设好后就永远不用动了但实际上切换需求远比想象中频繁。我把这两年遇到的情况归类一下换电脑或者重装系统是最常见的。SSH 私钥没有同步到新机器push 直接报权限问题。这时候与其折腾密钥迁移不如先切到 HTTPS用 PAT 恢复开发节奏之后再决定要不要重新配 SSH。公司安全策略也会逼你切换。有的公司 GitLab 只开放 HTTPS 认证有的反过来要求统一用 SSH。我见过一个团队平台升级后账号密码认证被禁用几十号人都在 push 时报错最后统一切到 HTTPS PAT 才解决问题的。反过来也有公司要求所有机器必须配 SSH key这时候又得切回 SSH。网络环境同样重要。办公网、校园网这类受控网络环境经常只放行 443 端口的流量。SSH 默认走 22 端口有时候会连不上或者超时。这种时候把远程地址切到 HTTPS推送拉取往往立刻恢复正常。还有多平台混用的场景。个人 GitHub 用 SSH公司 GitLab 用 HTTPS PAT同一台机器上两套协议并存这是最标准的配置方式。你会切换就不会在换项目时傻眼。1.3 PAT 在切换中扮演的角色PAT 的本质是平台给你签发的一串“带权限的临时密码”。它替代了传统的账号密码认证专门用于 HTTPS 方式的 Git 操作。为什么会有这个东西原因很直接密码的泄露面太大你只要在某个第三方平台输入过账号密码就有被记录的风险。而且现在两步验证2FA普及之后平台根本没法靠“账号 静态密码”来安全识别你的身份。PAT 的好处在于可以细粒度授权、可以单独撤销、可以设置有效期。就算某台机器上的 PAT 泄露了你只需要去平台后台把它 revoke 掉其他机器完全不受影响。GitHub 从 2021 年 8 月起就正式不再支持用账号密码 push/pullGitLab、Gitee 也都有对应的令牌机制。所以现在说“HTTPS 认证”基本就等于“HTTPS PAT”。2. 远程地址切换实操三种方法按需选择2.1 先看清现状git remote -v 怎么看动手改之前第一步永远是先看清楚当前远程地址是什么。在仓库根目录执行git remote -v正常会输出类似这样的内容origin gitgithub.com:yourname/yourrepo.git (fetch) origin gitgithub.com:yourname/yourrepo.git (push)origin是远程仓库在本地的别名后面跟的才是真正的远程地址。注意看两行一个是 fetch拉取一个是 push推送。大部分情况下两者一样但也有特殊情况——如果仓库配置了单独的 pushurlfetch 走一个协议、push 走另一个协议那就需要两个都看全不能只改其中一个。顺便说一句我见过有人看到remote: Support for password authentication was removed这种报错后以为是数据问题围着仓库转了半天其实只是远程地址还是 HTTPS而密码认证已经被平台停用了而已。所以第一步永远是git remote -v确认现状再动手。2.2 最常用git remote set-url切换到 HTTPS 的标准命令git remote set-url origin https://github.com/yourname/yourrepo.git切换到 SSH 的命令就是反过来git remote set-url origin gitgithub.com:yourname/yourrepo.git为什么我强烈推荐set-url而不是先把 remote 删掉再add因为 git 的 remote 配置不止 URL 这一个字段还包括 refspec、tagOpt、pushurl 等。用git remote remove origin会把整个 remote 配置连根拔起重新 add 后这些额外配置全部丢失有些隐藏问题要过很久你才会发现。而set-url只改 URL其他一律不动安全得多。执行完记得再用git remote -v确认一遍。这个习惯能避免很多低级错误比如改错了 remote 名字、协议切换反了。2.3 直接改 .git/config第二种方式更底层直接打开.git/config文件修改。文件里对应的段落长这样[remote origin] url https://github.com/yourname/yourrepo.git fetch refs/heads/*:refs/remotes/origin/*把url这一行替换成你想要的地址保存即可。这种方式适合你已经很熟悉 Git 内部结构的情况或者set-url因为某些原因不生效时直接手动改。改完之后不用执行其他命令Git 读取的是这份配置。不过说实话日常操作我还是建议用命令。直接改文件容易手滑而且如果你用的编辑器配了自动格式化还可能引入莫名其妙的空白字符到时候排查起来更浪费时间。值得一提的是你也可以通过命令直接设置效果等同于改文件git config remote.origin.url gitgithub.com:yourname/yourrepo.git2.4 常见平台的远程地址格式对照不同平台的远程地址格式略有差异尤其是自建 GitLab端口号、子路径都可能不一样。我整理了一个对照表平台SSH 格式HTTPS 格式GitHubgitgithub.com:user/repo.githttps://github.com/user/repo.gitGitLab官方gitgitlab.com:user/repo.githttps://gitlab.com/user/repo.gitGiteegitgitee.com:user/repo.githttps://gitee.com/user/repo.git自建 GitLabssh://gitgitlab.example.com:2222/user/repo.githttps://gitlab.example.com/user/repo.git注意自建 GitLab 的端口问题。如果 SSH 走的是非标准端口比如 2222那地址必须写成ssh://格式并显式带上端口写成gitgitlab.example.com:2222/user/repo.git反而会被解析成错误路径。这是我实际踩过的坑多花了十分钟才反应过来。我的经验是个人项目优先考虑 SSH省去每次输凭据的麻烦但如果你的工作环境经常换电脑、网络受限HTTPS PAT 配合系统凭据管理器反而更省心。切换不是二选一而是看场景按需选。3. HTTPS 认证的核心PAT 创建、使用与安全3.1 为什么传统密码行不通了很多刚接触 PAT 的人第一反应是我直接用账号密码不行吗在 GitHub 上已经不行了。平台在 2021 年 8 月之后全面移除了密码认证。GitLab 和 Gitee 虽然政策略有不同但同样推荐用令牌。原因其实不复杂密码是一次性的全局凭证一旦泄露攻击者就能拿着它访问你所有的仓库、配置、甚至开启两步验证的账号信息而 PAT 可以限定权限、限定有效期、单独撤销泄露后一颗老鼠屎不会坏了一锅汤。另外如果你开启了 2FA 登录认证传统的“账号 密码”在 Git 命令里根本没法用。因为 Git 没法让你输入动态验证码。PAT 可以看作是解决方案的一部分它在服务端就已经完成了 2FA 验证之后在 Git 命令里就只需要这一串令牌。3.2 以 GitHub 为例创建 PAT 的完整流程GitHub 目前提供两种 PAT经典令牌classic和细粒度令牌fine-grained。经典令牌的创建路径是头像菜单 - Settings - Developer settings - Personal access tokens - Tokens (classic)。点 Generate new token会让你选择权限范围常见的几个repo仓库读写权限基本属于“全量权限”workflow允许更新 GitHub Actions 工作流文件read:org读取组织信息选完后点生成页面会显示一串以ghp_开头的字符串。这里要特别记住这串 token 只显示一次关掉页面就再也看不到了必须立刻复制保存。细粒度令牌的入口在 Tokens (Fine-grained)。它的好处是权限可以精细到具体仓库。比如你只在某个项目上做代码推拉就可以选择 Only select repositories 勾选那个仓库权限只勾Contents: Read and write。这样做的好处是即使这个 token 泄露了攻击者也只能操作这一个仓库翻不了其他家底。细粒度令牌默认强制设置过期时间目前可以从 30 天选到一年。经典令牌理论上可以不设过期时间但我强烈不建议“永久不过期”。创建完成后我的习惯是立刻把 token 存进密码管理器并备注清楚用途比如“Windows 笔记本 - 公司 GitHub - 2025 年下半年”。这样半年后看后台列表一眼就能认出这个令牌是给谁用的。3.3 把 PAT 用起来三种使用方式对比PAT 生成后在 Git 命令里怎么用起来有三种方式。第一种是临时粘贴。在 HTTPS 远程地址下执行 pushGit 会提示输入用户名和密码。用户名填你的 GitHub 用户名密码那一栏填 PAT不是账号密码。这种方式适合偶尔使用缺点是每次 push 都要手动粘贴。第二种是写进远程 URL。远程地址可以写成这种格式git remote set-url origin https://USERNAME:TOKENgithub.com/user/repo.git这种方式虽然能自动认证但我会明确警告个人开发机上别这么干。因为 token 会明文存在.git/config里等于把钥匙挂在门上。不过 CI/CD 流水线场景很常见配合受保护的变量或者 Secrets 使用是标准的自动化做法。第三种是 credential helper 持久化也是我最推荐的方式。先设置凭据助手# Windows 上新版 Git 自带 Git Credential Manager git config --global credential.helper manager-core # macOS 上使用系统钥匙串 git config --global credential.helper osxkeychain # Linux 上如果坚持用 store记得它会明文存 git config --global credential.helper store设置完成后再执行一次 push系统会弹出窗口或者提示输入用户名和 PAT输入一次之后后续所有 Git 操作都会自动使用保存的凭据不需要再重复输入。我个人在 Windows 和 macOS 上都用的系统凭据管理器因为它们是操作系统级的安全存储token 不是明文躺在文件里的。Linux 上如果实在要用store注意~/.git-credentials文件的权限要设成只有自己可读写。3.4 PAT 安全实践与权限边界PAT 这个东西用起来方便泄露起来也快。我分享几个自己长期执行的安全习惯最小权限原则是第一条。只需要拉取代码就只给拖代码的最小权限没必要给整个仓库的写权限。尤其是细粒度令牌可以精确到仓库和权限类型多用它会少很多风险。设置有效期并定期轮换。PAT 就像食品有保质期。我所有平台的 PAT 都不会超过 180 天并在日历里记好到期前一个月的提醒到时间就去平台后台重新生成、更新凭据管理器里的值。命名清晰方便追溯。token 名称里带上设备、用途、时间比如dev-mac-2025-h1这样平台后台一长串令牌列表里你也能一眼找到对应那条。万一泄露立刻 revoke。如果你发现 token 可能出现在了不该出现的地方比如截图发聊天群、写进了配置仓库不要犹豫直接到平台后台删除重新生成。revoke 操作是即时的比改密码快得多。不要把 PAT 提交到仓库。这个虽然听起来像常识但由于 URL 带 token 的写法很容易顺手就把整个 remote 配置一起提交了。提交后哪怕你后悔删掉历史记录里也还留着等于又泄露了一次。所以提交前一定要检查有没有敏感信息。4. 切换后必踩的坑与排查指南4.1 认证失败与凭据冲突切完协议后最容易出问题的就是认证。我整理了一张速查表基本覆盖了常见情况报错或现象可能原因解决办法Permission denied (publickey)SSH 私钥不存在、未加载或与平台不一致执行ssh -T gitgithub.com验证重新生成并配置 keyAuthentication failed for https://...用户名或 PAT 错误或 PAT 已过期重新确认用户名重新生成 PAT检查凭据管理器Support for password authentication was removed还在用账号密码走 HTTPS改用 PAT 或切到 SSH弹窗循环要求输入密码系统凭据管理器里存了旧密码或旧 PAT删除对应凭据条目后重新 pushSSL certificate problem自建 GitLab 证书不受信任检查证书链或让管理员处理受损证书这里我要重点讲一个我自己踩过的坑。之前在 Windows 上一直用旧 PAT 推代码后来 PAT 过期了我执行 push 时系统不报“token 过期”这种明确的错而是反复弹一个输入密码的窗口感觉就像密码输错了一样。我一度以为是远程地址写错了反复改了 remote URL 也没用。最后才反应过来是系统的“凭据管理器”里存了旧 tokenGit 每次都拿旧值去认证根本轮不到我输入新 token。解决办法也很直接控制面板 - 凭据管理器 - Windows 凭据找到git:https://github.com那条删掉然后重新执行一次 push就会弹出输入框让你粘贴新 PAT。macOS 同理在“钥匙串访问”里找到对应条目删除后重新触发认证即可。这个坑在网络上一搜一大把但第一次碰到的人都会懵好久。4.2 换协议后要不要重新 clone每次切换协议都让团队重新 clone 的话那成本和混乱程度我都不敢想。好消息是完全不需要。原理很简单。remote在 Git 里只是一段配置字符串它告诉 Git“远端地址在哪”。你的本地对象库、所有分支、未推送的 commit、工作区文件都保存在本地的.git目录和相关文件中。切换 remote 只是改了一下推送目标的“门牌号”仓库里的东西一个都不会动。所以切换之后直接执行git fetch origin查看远程分支是否正常拉取就可以验证切换是否成功了。紧张感完全没必要。4.3 多平台多账号的切换策略有人会问我同时用个人 GitHub、公司 GitLab甚至还有自建的 Gitea地址切来切去会不会乱答案是只要协议地址清晰同一台机器完全可以并行使用。我的默认配置是 GitHub 走 SSH公司 GitLab 走 HTTPS PAT。clone 的时候每个仓库的 remote 地址自带协议信息Git 会根据地址自动选择认证方式互不干扰。但在同一个平台下有多个账号情况就不一样了。比如你有一个个人 GitHub 账号和一个工作 GitHub 账号。都走 SSH 的话因为本地同一把私钥对应同一个 GitHub 账号你没法直接切换。解决方式是给~/.ssh/config配置别名Host github-work HostName github.com User git IdentityFile ~/.ssh/id_ed25519_work这样你把远程地址里gitgithub.com换成gitgithub-workGit 就会自动使用另一把私钥。同理把项目地址写成git remote set-url origin gitgithub-work:user/repo.git如果你两个账号都想走 HTTPS那就得小心凭据管理器里的冲突同一个域名github.com只会保存一套凭据。这种情况下最稳妥的办法就是故意让一个账号走 SSH、另一个走 HTTPS从协议层面天然隔离免得凭据打架。4.4 一个实用的验证流程速查切换完成后我建议按这个顺序做一遍验证确认万无一失第一步确认地址git remote -v如果 fetch 和 push 两行的地址协议一致说明基础配置没问题。第二步如果是 HTTPS执行git ls-remote origin这条命令不拉取整仓代码只查询远程分支信息能最快触发一次认证并验证 PAT 是否有效。如果命令返回了分支列表说明认证已经通过。第三步如果是 SSH执行ssh -T gitgithub.comGitHub 会返回类似Hi username! Youve successfully authenticated...的信息。GitLab 返回的是Welcome to GitLab, username!。看到这些输出SSH key 就确认没问题了。第四步真正拉取一次执行git pull或者git fetch正常返回且没有报错整个切换就算完成了。整个过程两分钟不到但能避免后面推代码时才发现问题。最后再分享一点个人习惯。我现在的新项目策略是先不管什么平台clone 之后第一个动作就是根据当前场景把git remote set-url切换到合适的协议个人 GitHub 保持 SSH公司 GitLab 统一 HTTPS PAT。另外我不再追求 token 有很长的有效期全部控制在 180 天以内并在日历里标记到期提醒养成定期轮换的习惯。这样做的代价是每半年要花几分钟更新一次凭据换来的是即便某台机器上的 token 真泄露了影响范围也被控制得很小。如果你经常要在两种协议之间切来切去可以自己包一个 shell 函数把git remote set-url origin封装成一键切换小工具配合git remote -v确认结果能省下不少重复操作的时间。