ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Git SSH免密配置实战:从密钥生成到clone与push全流程

Git SSH免密配置实战:从密钥生成到clone与push全流程 很多人在用Git和GitHub Desktop的时候都遇到过这个场景用HTTPS方式clone或者push终端里反复弹窗要输入用户名和密码一旦开启了双重认证还得去生成Personal Access Token粘来粘去非常麻烦换成GitHub Desktop倒是能记住账号但偶尔也会莫名弹出一个授权窗口点了又报错。折腾一圈下来仓库还没提交几次时间全耗在认证上了。这篇文章我把整个流程重新捋了一遍从零开始讲怎么用SSH方式把你本地环境、Git命令行、GitHub Desktop三者串起来。配置完成后clone、pull、push全程免密不用再反复输入账号密码也不用手动去填token。文章适合刚接触Git的初学者也适合已经用了HTTPS一段时间、想彻底切换到SSH的老手。我会把每一步为什么要这么做、底层发生了什么、踩过的坑是什么都交代清楚你照着做基本一次就能通。1. 先说清楚SSH到底是什么为什么值得折腾1.1 HTTPS和SSH两种方式的区别Git在访问远程仓库的时候官方支持两种主流的传输协议一个是HTTPS一个是SSH。很多人在本地clone仓库的时候直接复制了网页上的HTTPS链接默认就走到了用户名密码认证的路子上。HTTPS的认证逻辑在本地环境里是一个“每次都要验证身份”的模式。如果你是普通账号每次push都要输入用户名和密码如果你开启了双重认证密码还不好使得去GitHub设置页面生成一个token把这个token当成密码来用。这个token有过期时间到期了又得重新生成。GitHub Desktop稍微聪明一点它能帮你记住token所以在桌面上操作感觉没那么烦。但只要你在终端里用git命令或者在另一台电脑上操作麻烦就全回来了。SSH的方式完全不一样。它不靠用户名密码而是靠一对密钥私钥留在你本机公钥放到GitHub账号里。本地请求连接的时候GitHub根据公钥生成一个挑战只有持有对应私钥的电脑才能解开。这个机制说白了一句话只要你的电脑上有那把对的私钥服务器就认你全程不需要再输密码。打个比方可能更好理解。HTTPS就是每次进小区大门都要掏身份证登记保安一眼一眼地查SSH是你去物业办了一张门禁卡卡里写着你家的楼栋和门牌号以后刷卡直接就进。第一次办卡稍微麻烦一点但之后每次进出都省事。1.2 为什么推荐SSH而不是继续用HTTPS我个人的实际体验主要有三个理由。第一是免密。配置好之后Git命令行里的fetch、pull、push全程不弹窗。GitHub Desktop同样受益它调用的是系统里的SSH能力不需要再额外管理token。第二是安全。私钥始终保存在你本地不会在网络上传输入密码也不会因为token在某个第三方工具里泄露而被人拿去乱推代码。你可以在GitHub账号设置里随时删除某台电脑的公钥相当于吊销了那台设备的访问权限。第三是跨平台一致。SSH的配置方式在Windows、macOS、Linux上都差不多。你在这台电脑上配置好了换一台电脑只要把私钥拿过去或者重新生成一对流程完全一样。而token在不同系统上的体验差异就比较明显尤其Windows的终端复制粘贴token有时候还会多出换行符导致认证失败。当然SSH也不是没有门槛。它的密钥生成、权限设置、ssh-agent管理这些概念第一次接触的人容易懵。这篇文章后续的内容就是把这一步一步拆开每一句命令都解释清楚。1.3 准备工作Git与GitHub Desktop的安装确认在开始生成密钥之前先确认你本地的环境是完整的不然到后面经常会出现“命令找不到”这类低级问题。如果你用的是Windows强烈建议直接安装Git for Windows。这个安装包自带了一个Git Bash终端后面的所有命令我都在Git Bash里执行。为什么不用系统自带的cmd或者PowerShell因为Git Bash里模拟了Linux环境很多命令比如cat、ssh-keygen、ssh-agent的路径和参数都是处理好的直接能用不用额外配环境变量。下载地址就是Git官网或者国内镜像站安装的时候一路Next就行唯一要注意的是安装过程中有一个选择编辑器、调整PATH环境变量的步骤保持默认选项即可。安装完之后打开Git Bash输入git --version能看到版本号就说明Git本体没问题。这个输出结果的版本信息后面排查问题的时候有用比如有些老版本的Git在SSH密钥算法支持上会有差异如果版本太旧比如2.x早期版本建议升级到最新稳定版。GitHub Desktop的安装更简单直接去GitHub Desktop官网下载对应平台的安装包。Windows版本装完之后会自动检测系统里的Git不需要你手动指定路径。装好之后先用你的GitHub账号登录一次这一步会引导你授权Desktop访问账号信息。需要提醒的是Desktop登录用的是OAuth授权和你后面配置的SSH密钥是两套东西互不冲突别混在一起理解。另外Windows用户还需要提前确认一个服务是否在运行这个服务叫OpenSSH Authentication Agent也就是ssh-agent。很多人在配置完密钥之后还是被要求输入密码或者GitHub Desktop一直报错问题就出在这个服务没启动。我在后面章节会专门讲它的启动方法这里先有一个印象SSH私钥不是直接裸给Git用的它要先注册到ssh-agent这个“钥匙串”里系统才能在你发起请求的时候自动取出私钥去完成认证。2. 生成SSH密钥这一步是整个配置的地基2.1 用ssh-keygen生成你的专属密钥对打开Git Bash输入下面这条命令然后一路回车ssh-keygen -t ed25519 -C 你的邮箱注意这里的邮箱建议写你注册GitHub账号时用的邮箱这样密钥和账号之间有一个明确的对应关系方便以后在GitHub后台辨认。不过严格来说邮箱只是密钥的备注信息写不写、写什么都没关系它不会参与认证逻辑。如果之前没有生成过SSH密钥系统会提示你选择保存位置默认路径是~/.ssh/id_ed25519。这里直接回车确认就行不要自己改路径。改路径之后后续的ssh-agent查找、Git的默认配置都要跟着改徒增麻烦。如果之前生成过系统会提示文件已存在问你要不要覆盖。这时候要小心如果你确实需要保留原来的密钥就先把这个文件重命名备份再生成新的。接下来有一个设置passphrase的步骤就是给私钥加一层口令保护。这里我建议初学者直接留空按回车跳过。原因很简单如果你设置了passphrase每次使用私钥时都需要输入这个口令虽然ssh-agent可以帮你记住一次但在一些特殊场景比如GitHub Desktop调用密钥还是会弹出来体验反而更繁琐。等你自己对SSH机制足够熟悉了再考虑给私钥加口令也不迟。生成成功之后你会看到类似这样的输出里面有一个像涂鸦一样的图案那叫randomart image是密钥指纹的图形化表示用来让你快速辨认密钥是否被改动过不用去解读它。2.2 私钥和公钥哪个能给别人哪个绝对不能很多新手在这一步就懵了生成完之后~/.ssh目录下多了两个文件一个叫id_ed25519一个叫id_ed25519.pub这俩到底有什么区别简单来说id_ed25519是私钥绝对不能泄露给任何人。它在文件系统里的权限应该是只有你当前用户能读写Windows上Git Bash会自动处理macOS和Linux上需要你手动检查一下权限是否符合要求。如果私钥被别有用心的人拿到就相当于他拿到了你所有配置了对应公钥的服务器、GitHub账号的访问权。id_ed25519.pub是公钥这个就是要放到GitHub服务器上的内容。公钥可以放心给别人看它的作用只是让服务器验证“你确实持有那把对应的私钥”本身不含任何敏感信息。用小区门禁来类比公钥就是门禁系统里登记的你那张卡片的ID私钥就是你口袋里的那张卡片。别人就算知道你的卡片ID没有卡也刷不进来。而门禁系统验证的时候并不是把整个卡号输过来对一遍而是通过一系列数学运算确认你手里的卡对应着登记过的那个ID。2.3 把私钥注册到ssh-agent密钥生成之后还需要让本机的SSH客户端认识它。这个过程在Windows上分两步。第一步确保系统中OpenSSH Authentication Agent服务正在运行。在开始菜单里搜索“服务”打开服务管理器找到OpenSSH Authentication Agent如果状态不是“正在运行”就右键启动并且把启动类型改为“自动”省得每次开机都要手动来一遍。也可以通过PowerShell管理员模式执行下面的命令Get-Service ssh-agent Set-Service -Name ssh-agent -StartupType Automatic Start-Service ssh-agent第二步回到Git Bash把私钥加载进agenteval $(ssh-agent -s) ssh-add ~/.ssh/id_ed25519第一条命令的作用是启动一个ssh-agent进程并且把环境变量设置好。第二条命令把私钥加入agent的钥匙串里。如果你在前面生成密钥的时候设置了passphrase这一步会要求你输入一次之后就不用再输入了。这里有个细节值得说一下eval $(ssh-agent -s)中的eval是让shell执行命令的输出结果。ssh-agent启动后输出的是一堆环境变量赋值语句比如SSH_AUTH_SOCK...通过eval才能让这些变量在当前终端会话中生效。如果你直接运行ssh-agent -s你会看到一堆输出但这些输出不会保留在你当前的shell环境里后面ssh-add就找不到这个agent进程了。配置完成之后可以用下面的命令确认私钥已经加进agent里了ssh-add -l如果输出里有256 SHA256:...之类的指纹信息就说明私钥已经在钥匙串里了。这一步是后面所有免密操作的前提也是最多人忽略的一步。3. 把公钥交给GitHub给账号配上“门禁卡”3.1 在GitHub网页端添加SSH公钥到这一步你本地的密钥对已经准备好了接下来要做的就是把公钥内容贴到GitHub账号的对应位置。先在Git Bash里查看公钥内容cat ~/.ssh/id_ed25519.pub输出是一行以ssh-ed25519开头的字符串后面跟着一串编码最后是你生成密钥时写的邮箱备注。把这整行内容完整复制下来。注意要复制完整不要换行不要缺字符很多人卡在这一步是因为只复制了一部分。然后登录GitHub网站点击右上角头像进入Settings。在左侧边栏找到SSH and GPG keys点击右上角的New SSH key按钮。Title栏随便填一个能让你记住这台设备的名字比如“My Windows Laptop”Key栏粘贴刚才复制的公钥内容最后点击Add SSH key。如果GitHub要求你确认密码输入账号密码即可。这里有一个小技巧如果你有多台设备每台设备单独生成一对密钥然后给每台设备的公钥取一个容易辨认的名字。这样以后你在GitHub后台看到某个key异常可以快速定位是那台机器出了问题直接删除对应公钥就能吊销那台设备的访问权限。3.2 命令行验证确认免密连接已经打通公钥添加完成之后先别急着clone仓库先在终端里验证一下SSH连接是否正常。在Git Bash里执行ssh -T gitgithub.com如果你是第一次连接GitHub终端会显示一条host key验证提示大意是“无法确认github.com的真实性是否仍要继续连接”。输入yes回车。这里输入的yes会记录在~/.ssh/known_hosts文件里下次再连接就不会问了。连接成功之后GitHub会返回一段欢迎信息类似下面这样Hi your-username! Youve successfully authenticated, but GitHub does not provide shell access.看到这个提示就说明本地的私钥和GitHub上的公钥已经匹配成功你本地这台设备已经获得了GitHub账号的访问许可。如果这个过程中报错了最常见的报错就是Permission denied (publickey)。这个错误表示GitHub没有认可你提供的公钥信息。排查思路很简单第一确认刚才把公钥贴到了GitHub的Settings里而不是某个独立仓库的设置里第二确认你贴的是.pub文件里的公钥而不是id_ed25519私钥的内容第三确认ssh-agent里确实加载了私钥用ssh-add -l再检查一遍第四确认你不是用sudo或者管理员身份运行Git Bash——有时候权限过高反而会让ssh找不到正确的文件路径。4. Git仓库的SSH配置与下载上传实操4.1 设置Git的用户名和邮箱SSH连接打通了接下来就是正式用Git操作仓库了。但先别急在第一次提交之前还要给Git配置最基本的身份信息。执行下面两条命令git config --global user.name 你的名字 git config --global user.email 你的邮箱这里的user.name和user.email会写入你每一次提交commit的元数据里远端仓库的提交记录上会显示这个信息。它不是认证信息不参与账号校验但如果你用的是GitHub建议把邮箱写成GitHub注册邮箱这样你的提交可以直接关联到你的GitHub头像和主页。如果你不想暴露私人邮箱可以在GitHub后台开启Keep my email addresses private功能然后把生成的users.noreply.github.com邮箱填在这里。4.2 用SSH地址clone仓库从这里开始就不需要密码了现在找一个仓库来测试。打开GitHub上任意一个仓库页面点击绿色Code按钮再点击SSH标签页你会看到仓库的SSH地址格式是gitgithub.com:用户名/仓库名.git。复制这个地址。在Git Bash里找一个合适的目录执行clone命令git clone gitgithub.com:用户名/仓库名.git命令执行后如果一切正常你会看到终端开始下载对象并且全程没有任何密码提示。这就是SSH生效的直接体现。这里顺便说明一下如果你之前已经用HTTPS方式clone过一个仓库现在想切换到SSH不需要重新clone一遍只需要修改远程地址就行。进入那个仓库目录执行git remote set-url origin gitgithub.com:用户名/仓库名.git然后可以用git remote -v确认一下当前远程地址看到的是gitgithub.com:开头就说明切换成功了。4.3 上传修改的完整流程从add到pushclone下来之后你可以在本地修改文件。为了演示完整流程我以一个简单的场景为例在仓库根目录创建一个新文件然后把这个文件提交到远端。第一步查看仓库状态git status这一步我建议每次都先执行。它能让你看清当前仓库处于什么分支、哪些文件被修改过、哪些文件还没被跟踪。在终端输出里红色文件名代表已修改还没暂存绿色文件名代表已暂存还没提交。第二步把文件加入暂存区git add 文件名如果你有很多文件要提交可以用git add .把所有修改都加入暂存区。但我不推荐add .尤其是在多人协作的仓库里很容易把一些本不该提交的文件比如本地的配置文件、log文件一起加进去。手动指定文件名更稳妥。第三步提交git commit -m 提交说明这里-m后面的内容是这次提交的说明文字。好的提交说明应该清楚描述这次改动做了什么比如“修复登录页面的按钮样式”或者“新增导出Excel功能”不要写“更新”或者“修改”这种没有信息量的话。如果在commit的时候报错提示Please tell me who you are说明你跳过了第4.1小节的用户名和邮箱配置回去设置一下再commit就行。第四步推送git push origin main这里的origin是远程仓库的默认别名main是分支名。如果你的默认分支叫master那就把最后的main改成master或者在仓库里用git branch查看当前分支名。推送成功后你会在终端看到类似这样的输出Enumerating objects: 5, done. Writing objects: 100% (3/3), 323 bytes | 323.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0), reused 0... To github.com:用户名/仓库名.git abc1234..def5678 main - main看到main - main说明本地的提交已经成功推送到GitHub远程仓库。再补充一个场景如果你编辑的是仓库里已经存在的文件流程也是一样git status查状态git add暂存git commit提交git push推送。区别只是文件内容被修改保存后git status会显示这个文件是modified状态而不是untracked。5. GitHub Desktop中的SSH配置与使用细节5.1 GitHub Desktop与系统SSH的关系有人可能会问既然Git命令行已经配置好SSH了GitHub Desktop还需要单独配置吗答案是不需要单独配置但前提是系统层面的ssh-agent必须正常运行。GitHub Desktop的做法是它不自带一套独立的SSH密钥管理系统而是直接调用操作系统底层的SSH组件。在Windows上它调用的是OpenSSH以及系统服务里的ssh-agent在macOS上它调用的是系统自带的SSH。这也就是说只要你在命令行里已经把SSH配好了Desktop就能天然复用这同一套密钥不需要在Desktop的设置里做任何额外操作。但这里有一个非常典型的坑如果Windows的ssh-agent服务没有启动你会发现终端里的git命令用起来一切正常但在GitHub Desktop里clone或者push却一直转圈最后报错说认证失败。原因就是你在某个终端里手动执行过eval $(ssh-agent -s)那个agent进程只在那一个终端会话里有效Desktop启动之后根本找不到这个agent进程自然也就拿不到私钥。解决方式就是我前面提过的把Windows系统的OpenSSH Authentication Agent服务设为自动启动让系统在开机时就运行一个全局的agent这样不管是终端还是Desktop都能正常访问。5.2 用GitHub Desktop完成clone和push操作在Desktop里clone一个SSH仓库有两种方式。第一种在GitHub网页上打开仓库点击Code选择SSH标签页复制gitgithub.com:用户名/仓库名.git这个地址然后回到Desktop点击File菜单选择Clone repository在弹出的窗口里点击URL标签页把地址粘贴进去选择本地存储路径点击Clone。Desktop会直接按照SSH地址克隆仓库到本地。第二种方式更直接在Desktop的主界面左侧点击Your repositories列表里会显示你账号下所有仓库。但要注意这个列表是通过GitHub API拉取的它和SSH没太大关系Desktop会在克隆的时候自动选择用HTTPS还是SSH。如果你发现用这种方式clone下来之后Desktop里显示仓库正常但你想在终端里push却需要密码那说明仓库的remote地址被设成了HTTPS格式。这时候可以在终端进到那个仓库目录手动把remote地址改成SSH格式方法就是第4.2小节里说的git remote set-url。clone完成之后你在Desktop里对仓库的任何操作本质上就是调用git命令。修改本地文件后Desktop会自动检测到变化左侧会显示文件列表和改动摘要。输入commit message点击Commit to main再点击Push origin内容就上传到GitHub了。整个过程中你完全不会感觉到SSH的存在因为一切都是自动完成的。如果push失败了Desktop会弹出错误提示窗口点开详细日志里面会有具体的报错信息方便排查。5.3 Desktop里的常见坑第一个坑是密码短语问题。如果你在生成密钥时设置了passphrase那么在GitHub Desktop首次使用SSH密钥时可能会有两种情况一种是Desktop直接弹窗要你输入这个密码短语另一种是静默失败Desktop一直转圈但没有任何提示。我遇到过的情况是Windows系统会在后台弹出一个类似“Enter passphrase”的小窗口但焦点不在上面用户根本没注意到。这个问题的根治办法就是前面说的在生成密钥时留空passphrase或者你已经设置了就把私钥从ssh-agent里移除后重新添加让它记住一次。第二个坑是known_hosts文件权限问题。如果你在Windows上用过WSL或者虚拟机或者手动复制过~/.ssh目录到别的电脑known_hosts文件的权限可能不对。这会导致SSH连接时提示“Host key verification failed”。解决办法是删除~/.ssh/known_hosts中对应GitHub的那一行或者直接删掉整个文件下次连接时会重新询问并写入。第三个坑是Desktop的默认仓库拉取方式。你通过GitHub Desktop的Your repositories克隆下来的仓库它的remote地址不一定是你期望的SSH地址。去终端跑一下git remote -v看一下子最清楚。如果显示的是https://github.com/...那说明Desktop用的是HTTPS。虽然Desktop内部有自己的凭证管理你在Desktop里push可能是正常的但终端里就会要求你输入账号。这种情况就是我上面说的手动改一下remote地址让终端和Desktop行为统一。6. 常见问题与排查技巧实录6.1 高频报错速查表这里把我在配置过程中遇到过的、以及身边同事经常碰到的问题整理成一张速查表。报错信息原因解决方法Permission denied (publickey)GitHub没识别到你的公钥或者私钥没加载进agent确认公钥已添加到GitHub确认ssh-add -l能看到私钥确认用的是.pub公钥内容Host key verification failedknown_hosts里没有对应主机的指纹记录或指纹不匹配输入yes确认连接如果反复出现删除known_hosts中对应行connect to host github.com port 22: Connection timed out22端口被防火墙屏蔽或者网络环境不允许用443端口方案配置~/.ssh/configRepository not found仓库不存在或你没有访问权限确认仓库地址正确确认账号有访问权限如果用公司网络可能是端口问题Authentication failed远程地址还是HTTPS或者token失效修改remote地址为SSH格式或改用SSH方式认证6.2 22端口被封锁时如何切换到443端口方案有些网络环境比如公司防火墙会封掉SSH默认的22端口这时候你会发现ssh -T gitgithub.com一直卡住或者直接超时。GitHub官方其实提供了一个备用方案通过443端口访问SSH服务。方法是创建或编辑~/.ssh/config文件加入以下内容Host github.com HostName ssh.github.com Port 443 User git保存之后测试一下连接ssh -T gitgithub.com如果走443能成功后续的所有git操作都会自动走这个配置不需要再改remote地址。这里有一个需要注意的地方配置完这个之后gitgithub.com:用户名/仓库名.git这种地址依然有效因为Git会根据Host段匹配到config里对应的HostName和Port实际连的是ssh.github.com的443端口而不是直接连github.com的22端口。这个方案实测在很多受限网络环境下都能生效。6.3 多账号、多密钥的config管理有些人工作账号和个人账号分开在两个GitHub账号下都有仓库还有人同时使用GitHub、GitLab、Gitee每个平台一套密钥。这时候如果还是用一个默认的id_ed25519私钥就会发生冲突你在甲平台上传了公钥用乙平台的时候Git默认还是会拿同一把私钥去尝试当然会被拒绝。解决办法是多生成几对密钥然后通过~/.ssh/config文件做区分。比如生成一个专门给工作用的密钥ssh-keygen -t ed25519 -C 工作邮箱 -f ~/.ssh/id_ed25519_work生成之后在~/.ssh/config文件里增加这样的配置Host github-work HostName github.com User git IdentityFile ~/.ssh/id_ed25519_work配置完成之后你在clone仓库的时候如果用默认的gitgithub.com:用户名/仓库名.git会走默认密钥如果用gitgithub-work:用户名/仓库名.git就会走id_ed25519_work这把私钥。注意这里Host部分改成自定义别名之后Git会按照config里的HostName去寻找真实地址。这个方案初看有点绕但实际用起来很方便。它让你在一台电脑上同时管理多个账号的多个仓库互不干扰也不用来回更换密钥。最后分享一个我自己的小习惯每次配置完新机器我都先跑一遍ssh -T gitgithub.com确认返回的是successfully authenticated之后再试着clone一个仓库测试全流程。如果卡在哪一步就只排查那一步不要东一下西一下地改配置。SSH的整个链路其实很清晰本地私钥、agent注册、远程公钥、网络连通、仓库地址五个环节逐一排除问题总能定位到。按这个思路走绝大多数配置问题能在十分钟内解决。
返回列表