ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Windows下Git配置SSH Agent免密:一次设置,彻底告别密码输入

Windows下Git配置SSH Agent免密:一次设置,彻底告别密码输入 先问个事你现在的 git pull 和 git push是不是还经常卡在密码输入框如果用的是公司 GitLab密码三个月一改刚改完又过期那体验真的能把人逼疯。这篇要聊的就是怎么把这件事一次根治在 Windows 上把 git 和 ssh-agent 搭配好日常 clone、pull、push 都不再反复输入密码。这个方案解决的不是什么黑魔法而是把 git 的认证方式从 HTTPS 切换成 SSH同时让 Windows 自带的 ssh-agent 服务负责保管已经解锁的私钥。标题里说的“再也不用输入密码”实际上要堵住两类输入一类是 HTTPS 方式下的账号密码或 Access Token另一类是 SSH 私钥文件上的口令passphrase。两条路都堵上了你才能真正体验到写完代码直接 push 走人的爽快。内容对 Windows 上的开发者非常有用尤其是被 Gitee、GitHub、GitLab 的密码折磨过的朋友。不需要太深的基础命令我会给全原理也会讲明白照着走一遍基本就不会再碰密码输入框了。1. 为什么Windows下Git总是让你输密码先分清楚两类“密码”1.1 HTTPS remote和SSH remote密码体验完全不同很多人在 Windows 上装了 Git 之后clone 项目都是直接复制网页上的 HTTPS 地址。比如 Gitee 上复制下来的是https://gitee.com/用户名/仓库名.gitGitHub 上是https://github.com/用户名/仓库名.git。这种地址走的是 HTTPS 协议git 每次和远程仓库交互时服务器都会问“你是谁”于是终端就弹出账号密码输入框。现代 Git 客户端通常会装 Git Credential Manager它能帮你把密码或者令牌缓存起来第一次输入之后一段时间内不用再输。听着挺美好但实际用起来有太多例外公司 GitLab 改了密码缓存失效Gitee 的私人令牌几个月过期多账号切来切去的时候缓存互相覆盖。于是你就陷入“刚填完密码没过多久又要填”的死循环。SSH 方式就不一样。SSH 地址长这样gitgitee.com:用户名/仓库名.git或者gitgithub.com:用户名/仓库名.git。SSH 协议根本不走账号密码体系它靠的是公私钥对。你本地生成一对密钥把公钥放到托管平台上git 推送时用私钥签名平台用公钥验证。理论上整个过程不需要输入任何密码。但很多人试过 SSH 之后发现还是被要密码。那是因为私钥文件在生成的时候可以设置一个口令也就是 passphrase。只要私钥文件加密了每次使用私钥签名前ssh 客户端都会让你输入这个口令。这正是“SSH 也要输密码”这句话的真正来源。1.2 ssh-agent解决的是私钥口令而不是账号密码ssh-agent 要解决的就是上面这个私钥口令问题。它可以理解成运行在系统后台的一个“钥匙管家”你把私钥添加进去输入一次口令完成解锁之后私钥就一直放在它的内存里。后续 git 需要签名时ssh 客户端会先找这个管家要签名管家自动完成操作不再弹窗问你口令。所以核心链路是这样的git 使用 SSH 协议连接远程仓库SSH 客户端认证时发现 ssh-agent 里有已经解锁的私钥直接完成认证。整个过程你没有输入账号密码也没有输入私钥口令。Windows 系统其实自带 OpenSSH 客户端和 ssh-agent 服务只是默认状态下服务没有启用或者没有设置成开机自启所以大多数人从来感觉不到它的存在。这也是很多教程只说“生成密钥贴公钥”却没有让你配置 ssh-agent 的原因——他们默认你能自己解决后续的口令问题结果新手全卡在每次 push 都要输 passphrase 这一步。2. 环境准备确认Git和OpenSSH都已经可用2.1 检查Git、SSH的版本和来源开始之前先确认环境。打开 PowerShell依次输入下面两条命令git --version ssh -V第一条能看到 Git 版本比如git version 2.47.1.windows.1。如果提示找不到命令说明 Git 还没装或者没加进 PATH先去 Git 官网下载安装包装的时候一路默认即可记得勾选“Add to PATH”。第二条能看到 OpenSSH 版本比如OpenSSH_for_Windows_9.5p1, LibreSSL 3.8.2。如果提示找不到命令说明系统没有安装 OpenSSH 客户端。Win10 1809 之后的系统可以用管理员权限执行下面命令安装Get-WindowsCapability -Online | Where-Object Name -like OpenSSH.Client* Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0这里有个容易踩坑的点Windows 系统自带的 OpenSSH 和 Git for Windows 自带的 OpenSSH 是两套东西。PowerShell 里输入where.exe ssh看看返回的路径。如果看到C:\Windows\System32\OpenSSH\ssh.exe说明你用的是系统版如果看到 Git 安装目录下的ssh.exe说明 PATH 里系统版排在后面。两个版本功能上相差不大但既然我们要用 Windows 的 ssh-agent 服务建议统一让 git 走系统版 OpenSSH。可以执行一行配置git config --global core.ssh C:\Windows\System32\OpenSSH\ssh.exe这样后续所有 git 操作都会调用系统的 ssh.exe和系统 ssh-agent 服务配合最省心。2.2 找出并启动系统里的ssh-agent服务先在 PowerShell 里看服务状态Get-Service ssh-agent正常会看到Name: ssh-agent和Status。多数情况下状态是Stopped启动类型是Manual或者Disabled。要让这个服务跑起来并且之后开机自动启动需要管理员权限的 PowerShell。右键开始菜单选择“终端(管理员)”或者“Windows PowerShell(管理员)”执行Set-Service -Name ssh-agent -StartupType Automatic Start-Service ssh-agent第一条命令把启动类型改成自动第二条命令让当前会话立即启动服务。执行完再执行Get-Service ssh-agent状态应该是Running。这一步是整个免密配置里最容易被忽略的环节。很多人到网上搜“ssh-agent windows 不生效”最后发现就是服务没起来。如果Set-Service报错说服务不存在先回到 2.1 把 OpenSSH 客户端装上如果报错说权限不足检查你是不是真的用管理员身份打开的 PowerShell。3. 生成SSH密钥并配置到托管平台3.1 算法选型和口令策略别上来就一把梭生成密钥前先解决两个问题用什么算法要不要给私钥设口令。算法方面推荐 ed25519速度快、密钥短、安全性高GitHub、Gitee、GitLab 现在都支持。如果你的 GitLab 是公司内部的老版本可能只支持 RSA那就用 RSA 并且指定长度 4096ssh-keygen -t rsa -b 4096 -C 你的备注这里-C后面的备注建议写你的邮箱或者个人标识方便在平台上辨认这把公钥是谁的。口令策略我的建议是一定要设。很多人为了省事把 passphrase 留空确实之后完全不用输任何东西但私钥文件一旦泄露别人拿到就是裸奔的钥匙。笔记本经常带出门的话更不应该冒这个险。有了 ssh-agent 之后设置了口令也只是在添加密钥时输一次日常使用完全无感安全性和便利性可以兼得。实际生成命令ssh-keygen -t ed25519 -C 你的邮箱或备注它会问保存路径默认是C:\Users\你的用户名\.ssh\id_ed25519直接回车用默认路径就好。下一步设置 passphrase输入两次确认建议用一个你记得住但不和其他账号重复的口令。生成完成后.ssh目录下会多出两个文件id_ed25519是私钥绝不能发给任何人也不能上传到任何网站或网盘id_ed25519.pub是公钥这个是可以公开的平时要复制的内容就是它。3.2 把公钥贴到Gitee/GitHub并跑通测试命令查看公钥内容PowerShell 里执行type $env:USERPROFILE\.ssh\id_ed25519.pub会输出一行以ssh-ed25519开头以你的邮箱或备注结尾。把这整行复制下来。然后登录 Gitee进入“设置” - “SSH公钥”把内容粘贴进去保存。GitHub 对应的是 Settings - SSH and GPG keys - New SSH key。公司 GitLab 一般在用户设置里也能找到 SSH Keys 入口。配好之后不要急着用 git 操作先跑通连通性测试。Gitee 的测试命令是ssh -T gitgitee.comGitHub 的测试命令是ssh -T gitgithub.com第一次连接会提示确认远程主机指纹输入yes回车即可。如果配置正确Gitee 会返回类似Hi 用户名! Youve successfully authenticated, but Gitee does not provide shell access.的结果。看到这句话说明密钥认证已经通了。这里有个容易搞错的地方测试命令里的用户名 always 是git不是你 Gitee 的用户名。它是所有 SSH 用户的统一入口写成ssh -T 你的用户名gitee.com反而会报 Permission denied。4. 让ssh-agent开机自启并加载密钥核心配置4.1 两条PowerShell命令让服务永久可用现在 ssh-agent 服务是运行状态但还差一步启动类型设置为自动。上一章已经写了命令这里再强调一下原因。Windows 的很多服务默认是“手动”甚至“禁用”。如果你只执行Start-Service ssh-agent而不改启动类型当时能用重启电脑之后服务又是停的。到时候密钥没地方加载push 又要开始输口令前功尽弃。所以标准做法一定是两条命令一起Set-Service -Name ssh-agent -StartupType Automatic Start-Service ssh-agent改完可以验证一下启动类型Get-CimInstance Win32_Service -Filter Namessh-agent | Select-Object Name, StartMode, State看到StartMode : Auto和State : Running就说明成功了。这个配置项做完之后是持久的不需要每次开机重新设置。它保证了以后每次 Windows 启动ssh-agent 服务都会自动后台运行。4.2 ssh-add只输一次口令后面全靠agent服务跑起来之后要把私钥加载进 ssh-agent。在普通 PowerShell 窗口执行ssh-add $env:USERPROFILE\.ssh\id_ed25519如果你是 Git Bash路径写法不一样要写成ssh-add /c/Users/你的用户名/.ssh/id_ed25519如果私钥设置了 passphrase此时会提示输入一次口令。输入正确后密钥就进入 ssh-agent 内存。之后验证一下ssh-add -l能看到密钥的指纹信息说明加载成功。这时候再去执行ssh -T gitgitee.com会发现不需要输入任何口令直接返回认证成功的提示。git push 也一样不再问密码或者口令。这里要解释清楚一个现象ssh-agent 里的密钥是驻留在内存里的重启电脑后内存清空密钥就不在了。所以开机后第一次使用 git 操作时你还需要再执行一次ssh-add输一次口令。如果你希望“重启后也完全不用输”那么只能不设置 passphrase我个人的建议是设口令代价只是开机后第一次 push 前手动加一次换来私钥文件泄露不裸奔的安全保障。每天输一次口令和每次 push 都输口令体验差距是天壤之别。前者你几乎感觉不到后者会让你烦躁得想砸电脑。4.3 PowerShell、Git Bash、CMD如何共享同一个agentWindows 上的 ssh-agent 是系统级服务意味着同一个系统的 PowerShell、CMD、Git Bash 都能共享它不需要各自启动一个 agent。前提是 ssh.exe 能连上服务。新版 Windows OpenSSH 已经支持通过命名管道连接 ssh-agent所以你在 PowerShell 里ssh-add加载的密钥切到 Git Bash 里直接git push也同样有效。Git Bash 里的操作不需要重新添加因为它用的是同一个系统服务。但如果你在 Git Bash 里手动执行了ssh-agent或者eval $(ssh-agent)那就另起了一个独立进程密钥加载到那个临时 agent 里关掉窗口就失效。很多教程让用户在 Git Bash 里敲ssh-agent bash然后配密钥这种办法在 Git Bash 里能用换一个终端就全失效而且和 Windows 系统服务是两条路线。所以这篇的方法核心就是不要手动去跑 ssh-agent 命令只用 Windows 的系统服务。所有登录操作都通过系统 OpenSSH 完成路径统一行为统一才是真正一劳永逸。5. 现有HTTPS仓库切到SSH顺手清掉旧密码缓存5.1 修改remote地址不用重新clone如果你已经有仓库是用 HTTPS 方式 clone 的不需要删掉重来改一下 remote 地址就行。先看当前地址git remote -v会看到类似这样两行origin https://gitee.com/用户名/仓库名.git (fetch) origin https://gitee.com/用户名/仓库名.git (push)确认现在走的是 HTTPS然后改成 SSH 地址git remote set-url origin gitgitee.com:用户名/仓库名.gitGitHub 仓库对应的格式是gitgithub.com:用户名/仓库名.git。改完再执行git remote -v确认 fetch 和 push 都变成了git开头的地址。如果仓库很多不想一条条改可以设置 URL 自动替换git config --global url.gitgitee.com:.insteadOf https://gitee.com/这行配置的意思是以后所有以https://gitee.com/开头的 git 地址自动替换成gitgitee.com:开头的 SSH 地址。原有的 HTTPS remote 不用改git 会自动走 SSH。GitHub 类似把https://github.com/替换成gitgithub.com:即可。这种全局替换很省事但要注意它的影响范围以后复制 HTTPS 地址 clone 新项目git 也会自动切换成 SSH。习惯上没问题只是如果你某天想刻意走 HTTPS会被这个配置拦截。5.2 Windows凭据管理器里的旧密码不清理会捣乱仓库 remote 改成 SSH 之后大部分人以为完事了结果 push 的时候居然还会弹密码框。这种情况很可能是 Windows 凭据管理器里还存着旧密码。HTTPS 模式下 Git Credential Manager 会把账号信息存进 Windows 凭据管理器。remote 切到 SSH 后按理说 SSH 认证不会去读 HTTPS 凭据但一些 IDE 或者旧版 git 依然会有多余的凭据交互。最干净的办法是把旧凭据清掉。查看当前保存的 git 相关凭据cmdkey /list | findstr -i git会列出类似LegacyGeneric:targetgit:https://gitee.com这样的条目。删除对应条目cmdkey /delete:LegacyGeneric:targetgit:https://gitee.com删除时要完整带上target...这一段。GitHub 的 HTTPS 凭据对应的是git:https://github.com按同样方式删。另外可以把 git 配置里的 credential helper 清掉让它不再主动去读凭据git config --global --unset credential.helper执行完这些再 push 一次就会发现弹出的不是账号密码框而是直接安静地推送成功。到这里HTTPS 那条“密码路线”和 SSH 私钥口令那条“口令路线”都被堵住了。6. 多平台多账号和网络受限场景~/.ssh/config是关键6.1 一个config文件分配不同密钥到不同平台很多人不只用一个代码托管平台Gitee 放公司项目GitHub 放开源项目可能还有公司私有 GitLab。如果每个平台都用同一个默认密钥虽然能用但安全性不够比如离职或者想收回某个平台权限时会比较别扭。更规范的做法是每个平台生成独立密钥然后用~/.ssh/config文件告诉 ssh 客户端连接哪个平台用哪把私钥。在.ssh目录下新建一个文件名字就叫config注意没有扩展名。Windows 下创建的时候容易误存成config.txt需要用 PowerShell 或者编辑器的“另存为”功能确保文件名就是config。在 config 文件里写入Host gitee.com HostName gitee.com User git IdentityFile C:/Users/你的用户名/.ssh/id_ed25519_gitee Host github.com HostName github.com User git IdentityFile C:/Users/你的用户名/.ssh/id_ed25519_githubHost后面跟的是你连接时使用的名称HostName是实际连接的地址。IdentityFile 路径建议用正斜杠避免反斜杠转义问题。这样配置之后ssh -T gitgitee.com会自动使用id_ed25519_giteessh -T gitgithub.com会自动使用id_ed25519_github。如果某个平台的密钥改过名不用 config 的话 ssh 只认默认文件名容易怎么测都是 Permission denied。配好 config 之后这个问题自动消失。6.2 22端口连不上时换成443端口继续用SSHSSH 默认走 22 端口。有些网络环境下 22 端口访问不通或者经常超时但不是所有托管平台都只能走 22。GitHub 官方支持通过 443 端口进行 SSH 连接可以在 config 里直接指定端口Host github.com HostName github.com User git Port 443 IdentityFile C:/Users/你的用户名/.ssh/id_ed25519改完之后ssh -T gitgithub.com会尝试通过 443 端口连接。很多网络环境允许 HTTPS 端口而限制 22 端口这个小技巧能救急。需要注意的一点是不是每个平台都支持 443 端口的 SSHGitee 和部分私有 GitLab 目前并不保证支持。如果遇到支持的平台在 config 里加上一行Port 443即可如果更换端口后连不上先试回 22 端口别把配置留在那里影响日常使用。7. 常见问题排查与速查表7.1 高频报错对照表配置 ssh-agent 的过程中新手最容易碰到下面几个问题。我给你整理成对照表按症状查原因按原因处理。现象大概率原因处理方法ssh-add报错 Could not open a connection to your authentication agentssh-agent 服务没有运行管理员 PowerShell 执行Start-Service ssh-agent顺便设置自动启动ssh -T gitgitee.com返回 Permission denied (publickey)公钥没贴对或者私钥没加载或者用户名不是 git检查公钥是否完整粘贴执行ssh-add -l查看密钥是否在 agent 里确认命令用的是gitgitee.com而不是自己的用户名git push 仍然弹出账号密码框remote 地址还是 HTTPS用git remote -v查看执行git remote set-url origin改成 SSH 地址切换 SSH 后还会偶尔弹密码框Windows 凭据管理器里存了旧 HTTPS 凭据用cmdkey /list找到 git 相关条目并删除ssh 提示 22 端口连接超时网络环境限制 22 端口在~/.ssh/config中为对应平台指定Port 443ssh 提示 known_hosts 权限错误known_hosts 文件权限错乱删除C:\Users\你的用户名\.ssh\known_hosts后重新连接IDEA、VS Code 里提交仍要求密码IDE 没有走系统 OpenSSH 和 ssh-agent将 git 的 SSH executable 设置为系统 OpenSSH或在 IDE 里指定 ssh 路径7.2 我踩坑后总结的几条日常习惯这套配置我用了很久真正稳定下来之后几乎感觉不到 git 认证的存在。但中间踩过的坑让我养成了几个习惯。第一开机后第一次 push 前用ssh-add -l扫一眼确认密钥还在不在。尤其是公司电脑设置了每晚重启、或者经常休眠唤醒的用户agent 里的密钥可能已经没了。看一眼只是顺手的事能避免“明明配好了怎么又要密码”的恐慌。第二不要手动执行ssh-agent命令。Windows 系统服务已经把 agent 管好了手动启一个临时 agent 反而会把密钥加载到错误的地方换终端就失效。我之前有段时间在 Git Bash 里习惯性eval $(ssh-agent)结果 PowerShell 里怎么都免不了密后来发现是两套 agent 在互相打架。统一用系统服务之后就再没出过问题。第三私钥文件只放本地不同步到任何网盘也不放到仓库里。很多人把.ssh目录当作普通目录同步有一天换电脑发现私钥也在云端这是非常危险的操作。私钥的口令虽然能挡住一部分风险但私钥本身流出就意味着攻击者可以对你发起的连接进行签名验证。第四配置完一套新平台的密钥后先跑ssh -T测试再 clone 或 push。测试命令的输出非常明确能直接告诉你公钥是否被服务端接受比盲目 commit 之后再等 push 报错高效得多。另外有个小技巧分享给你。如果你平时主要用 IDEA 或者 VS Code 写代码配完这套之后 IDE 里提交还是频繁问密码大概率是 IDE 自带的 git 没走系统 OpenSSH。IDEA 在 Settings 里搜索 ssh executable改成 OpenSSHVS Code 在设置里搜索 git.sshPath指定到系统 ssh.exe。改完之后IDE 里的 git 操作和终端里一样安静。我个人的体会是这套配置最大的价值不是省几秒钟而是消除提交时的中断感。代码写完了顺手 push不被打断整个工作流是连贯的。新项目一律 SSH clone老项目一条remote set-url切过来之后基本就告别密码输入框了值得花十分钟一次性配好。
返回列表