WSL下配置Git完整指南:解决换行符、SSH与跨系统难题
在Windows上折腾开发环境的人多少都经历过这种拧巴代码在Windows里改得好好的一提交到Linux环境构建就出问题脚本换行符、文件权限、路径分隔符全是坑。后来我把日常开发迁到WSL里第一步就是把Git配置理顺。这里说的WSL下配置Git不是简单敲个git --version就算完而是要解决身份、密钥、换行符、跨系统文件访问这些真正影响日常使用的问题。这篇文章我打算从为什么要在WSL里配Git讲起把整个配置过程和踩过的坑都写出来给正在从Windows转向WSL的开发者一份可以直接照着做的参考资料。1. 先搞明白这套Git配置到底解决什么问题1.1 两个Git并存的纠结很多人第一步就想错了Windows下装Git的方式很多最直接的是装Windows版Git装上之后有git bash、有图形界面日常提交拉取完全够用。但你要是和我一样需要在项目里跑Linux下才会执行的脚本、需要在提交前触发同一套hook钩子、或者想让自己本地的开发环境尽量贴近线上部署环境Windows版Git就会暴露出各种差异路径大小写不敏感、换行符自动转换、bash环境是模拟出来的、文件权限语义和真实Linux不一样。WSL里再配置一套Git不是闲着没事折腾而是让你在本地就能有一个和服务器行为基本一致的Git环境。项目里写好的pre-commit钩子、CI里跑的shell脚本、依赖Linux命令的自动化流程在WSL里才能真正调试好。省下的是未来反复在本地通过、线上失败之间循环的抓狂时间。1.2 它和Windows版Git本质上是两套环境我用一张对照表把两者最核心的差异列出来方便你判断自己到底需要哪套对比维度Windows版GitWSL里的Git运行环境Windows下模拟的bash真实的Linux环境文件路径C:\xxx/home/你的用户名/xxx换行符行为容易自动转成CRLF默认LF更接近服务器脚本执行部分Linux命令缺失能在WSL内直接运行文件权限无法完整表达chmod语义和服务器一致与编辑器的联动走Windows路径走Linux路径但可互访如果你只是写写简单的代码、不依赖任何Linux特有工具Windows版Git确实够用。反过来一旦项目开始依赖自动化脚本、容器构建、远程部署建议直接用WSL里的Git作为主力Windows侧可以完全卸掉相关依赖避免每次操作都要思考我现在用的是哪个Git。1.3 这套配置适合什么人我的建议很直接常用命令行、要参与前后端或服务端项目开发的人值得完整配置一遍如果团队明确使用Linux作为构建或部署环境那这套配置几乎是刚需。过程中你会接触到SSH密钥、凭据管理、换行符策略这些核心概念一次性理顺后面换机器、换发行版都能快速复制经验。2. 动手前检查WSL环境五分钟避免后面踩坑2.1 确认WSL版本和内核状态在配置Git之前第一步不是急着装软件而是确认WSL本身是正常可用的。我见过有人直接在某旧版本WSL上配置结果文件监听、网络转发各种问题最后全算在Git头上。打开Windows终端依次执行wsl --version wsl --status wsl --update第一条命令能看到WSL的版本号wsl --status显示当前默认发行版和内核状态。如果提示需要更新先执行更新再继续。高版本的WSL带了完整的Linux内核很多Git相关特性比如文件监听、子模块行为更正常。2.2 选择合适的发行版并初始化用户WSL支持多个Linux发行版。我实际使用中建议优先选Debian系发行版理由不算玄学文档多、遇到问题搜出来的解决方案基本适用、默认软件源里Git等开发工具更新及时。这里不对发行版本身做太多推荐重点是选完发行版后进入系统。进入WSL终端后你会以普通用户身份操作。确认当前用户名whoami绝大多数Git配置都只需要在用户级完成不需要动系统级配置这点很多人容易搞混。比如后面要配置的~/.gitconfig、~/.ssh都只影响当前用户干净又安全。2.3 更新系统包并安装基础依赖新装的WSL一般比较干净先做一次系统更新避免之后装Git时因为软件源索引陈旧而失败sudo apt update sudo apt upgrade -y然后安装后面会用到的几个基础工具sudo apt install -y git curl ca-certificates build-essential这里curl用于测试密钥和下载资源ca-certificates保证Git连接托管平台时证书校验正常build-essential包含编译工具链很多项目的钩子脚本或附加组件会用到。有人会问我只装Git行不行当然可以但缺了这些工具后面遇到莫名其妙的问题排查起来反而更费劲。2.4 建立干净的开发目录Windows用户的习惯是直接放桌面或者某个盘符下但在WSL里这不是好习惯。建议在WSL文件系统内建一个独立的开发目录mkdir -p ~/workspace cd ~/workspace以后所有代码仓库都放这里。为什么我反复强调不要放在/mnt/c/...下后面第4章会详细展开这里先记住结论面向Linux的工作目录就放在WSL自己的文件系统里性能和行为都更正确。提示WSL和Windows文件系统是可以互访的但不是所有操作都适合跨文件系统干。Git仓库放在Linux侧日常编辑则可以通过Windows侧的工具打开这是最舒服的组合。3. 安装Git和把身份、密钥一次配好3.1 安装并验证Git版本如果你按上一节做了现在Git大概率已经装好了。没装的执行sudo apt install -y git验证安装结果git --version能看到具体版本号就可以。WSL里Git的更新跟着系统的软件源走不需要像Windows那样单独下载安装包。3.2 配置身份信息全局生效还是仓库独立Git提交记录里必须要有用户名和邮箱否则提交时会报错。最基础的配置是全局级git config --global user.name 你的名字 git config --global user.email 你的邮箱但实际工作中公事和私事往往需要不同的提交身份。我不建议只配一套全局身份而是用一套主身份作为默认值再按仓库目录覆盖。比如git config --global user.name 默认开发者 git config --global user.email defaultexample.com cd ~/workspace/work-project git config user.name 工作身份 git config user.email workexample.com全局配置写在~/.gitconfig仓库级配置写在项目里的.git/config。后者优先级高。这样不同的项目自然使用不同身份不需要每次改来改去。3.3 SSH密钥生成这是连接托管平台的关键现代代码托管平台基本都支持SSH协议比HTTP方式更稳定也省得反复输入账号密码。首选的密钥类型是ed25519安全性和性能都优于老旧的RSA而且生成速度快ssh-keygen -t ed25519 -C 你的邮箱或备注执行过程中会问保存路径和密码短语。保存路径我建议直接用默认的~/.ssh/id_ed25519密码短语看个人需求本地开发机可以留空公司或公用机器建议设置。生成的公钥文件是~/.ssh/id_ed25519.pub查看内容cat ~/.ssh/id_ed25519.pub把这段内容完整复制添加到你的代码托管平台账户里。这一步在不同平台位置略有不同一般都在设置 / SSH公钥的地方。3.4 启动ssh-agent并让密钥常驻WSL每次打开一个新终端SSH agent默认不会自动加载密钥。为了避免每次push都提示输入密钥密码需要把ssh-agent跑起来并添加密钥eval $(ssh-agent -s) ssh-add ~/.ssh/id_ed25519考虑到重启终端就要重新执行我习惯把这段逻辑加到~/.bashrc里。打开配置文件nano ~/.bashrc在文件末尾加入if [ -z $SSH_AUTH_SOCK ]; then eval $(ssh-agent -s) ssh-add ~/.ssh/id_ed25519 2/dev/null fi这样每次进入WSL终端agent会自动启动密钥自动加载。2/dev/null的意思是如果密钥不存在或已加载就安静跳过不刷错误信息。3.5 用测试命令验证整条链路配完之后不要直接clone代码先验证SSH链路是否通。不同托管平台的验证命令略有差别但通用的形式是把git换成托管平台的域名前缀ssh -T git你的托管平台域名第一次连接会有指纹确认提示输入yes回车。如果看到欢迎信息或者你的用户名就说明SSH配置成功了。这时候再执行clonegit clone git你的托管平台域名:某个组织/某个项目.git建议找一个真实项目测试一下能正常拉下来就算通关。3.6 顺手设置默认分支名和编辑器现代Git仓库默认分支已经从master迁移到main但如果你用老版本Git新建仓库默认可能还是master。统一设置git config --global init.defaultBranch main git config --global core.editor nanocore.editor决定你执行git commit时没有带-m参数用什么编辑器写提交信息。新手我建议用nano比vi/vim友好得多。4. 打通WSL与Windows文件位置、换行符和权限的协作规则4.1 两边文件系统到底怎么互访WSL和Windows不是孤立的。从WSL里能看到Windows的全部盘符路径在/mnt/c、/mnt/d下从Windows里访问WSL文件系统则可以通过资源管理器地址栏输入\\wsl$进入。这意味着你可以用Windows上的编辑器或IDE直接打开WSL里的代码目录也可以用Windows命令访问WSL里的文件。很多现代编辑器都内置了远程开发能力可以直接在Windows界面里编辑WSL文件系统上的项目体验接近无缝。4.2 仓库放哪边性能和正确性差别很大这是配置WSL Git时最容易忽略、也最影响幸福感的一个决定。不要为了图省事把仓库放在/mnt/c下再用WSL操作。原因是WSL访问Windows文件系统要在两边做协议转换性能差而且某些Linux能力比如文件监听、权限属性在跨文件系统时无法完整表达。正确做法是仓库放在WSL侧比如~/workspace/...日常使用WSL里的Git处理提交、拉取、合并需要图形化编辑时用Windows工具打开WSL侧文件这样Git工作在Linux原生文件系统上默认权限和行为都正常性能也最好。4.3 换行符问题CRLF和LF的统一方案Windows的文本文件默认用回车加换行CRLFLinux和macOS默认只用换行LF。Git有个自动转换机制但经常造成我什么都没改怎么一堆文件都显示修改的诡异现象。WSL里我推荐一套很少出问题的配置git config --global core.autocrlf input含义是提交时把CRLF转成LF检出时不做转换。由于WSL内本身就是LF环境这个配置最适合跨Windows编辑、Linux提交的场景。但更稳的方案是在仓库根目录放.gitattributes把规则固定下来团队所有人都遵守同一套规则。一个常见的模板* textauto *.sh text eollf *.bat text eolcrlf *.ps1 text eolcrlftextauto让Git根据内容自动判断是否要按文本处理.sh脚本强制LF保证在Linux里可以直接执行Windows相关脚本则强制CRLF。这个文件比任何个人配置都可靠因为它是跟着仓库走的。4.4 文件权限让WSL正确认Windows文件的执行位从Windows侧复制或创建的文件进入WSL后经常权限不对。比如一个deploy.sh在Windows里看着没问题到WSL里执行却提示Permission denied。如果仓库已经挂载到了WSL侧给脚本加执行权限很简单chmod x deploy.sh但权限信息在Git里如何体现某些情况下即使你本地加了执行权限commit之后别人clone下来可能又没了。这时可以用git update-index --chmodx deploy.sh让Git在索引中记录该文件的执行位变化提交后就能在团队中正确传播。如果你的文件确实存放在/mnt/c下可以在/etc/wsl.conf里配置挂载选项给Windows盘加上完整的Linux权限语义。一个参考配置[automount] enabled true options metadata,umask022,uid1000,gid1000设置完成后在Windows终端执行wsl --shutdown重启WSL生效。metadata让WSL能为Windows文件记录Linux权限元数据umask022确保新建文件默认没有组外写权限。4.5 不同工具链之间的衔接实际使用中你很可能在WSL里用Git在Windows侧用原来的编辑器、文件管理器甚至其他工具。一个很自然的工作流是在Windows里用编辑器打开\\wsl$\你的发行版\home\用户名\workspace\项目然后在WSL终端里操作Git。两边操作同一个文件不需要复制来复制去。需要注意这种模式下的文件监听事件可能不完全一致。比如编辑器自动保存后WSL里某些监听文件变化的工具可能反应不及时。遇到这类问题优先把仓库放到WSL侧再用Windows工具访问而不是反过来。5. 五个高频坑附完整排查链路和修复命令5.1 git status慢到怀疑人生仓库放错位置了现象在/mnt/c下的项目里执行git status每次要等好几秒甚至更久git add也明显卡顿。排查链路先执行pwd确认是不是在Windows盘符路径下。执行df -T .查看文件系统类型如果显示是drvfs或9p就是跨文件系统。到WSL本地路径建立一个空仓库测试对比速度差异。修复把仓库迁移到WSL侧。不需要重新clone直接移动mv /mnt/c/Users/你的用户名/projects/my-project ~/workspace/然后把Windows侧的旧目录清理掉以后所有Git操作都在新路径下执行。5.2 明明没改文件却显示所有文件都被修改换行符在捣乱现象从Windows那边拷入或clone的项目执行git status后大量文件显示为modified但打开文件看内容完全没变。排查链路随便挑一个文件执行git diff看不到实质内容变化。执行file 文件名查看两端换行符类型。执行git config --get core.autocrlf确认当前转换策略。修复统一换行符规则。先执行git add --renormalize .再为仓库补上.gitattributes按4.3节的模板固定规则。提交一次后续就不会反复出现这个幻觉了。注意这类问题一旦出现在已有历史记录的仓库里要特别小心。--renormalize只影响索引不改变历史文件可以放心使用但如果已经错误提交过很多次需要评估是否用.gitattributes做一次历史清理这属于进阶操作建议在分支上先实验。5.3 Permission denied (publickey)密钥权限或agent问题现象执行ssh -T git托管平台域名提示权限拒绝但密钥公钥确实已经添加过。排查链路执行ls -l ~/.ssh/id_ed25519查看私钥权限。如果显示-rw-r--r--权限过宽SSH会直接拒绝使用。执行ssh-add -l确认密钥是否已加载。执行ssh -vT git托管平台域名查看详细日志重点看Offering public key阶段。修复修改权限并重新加载密钥chmod 700 ~/.ssh chmod 600 ~/.ssh/id_ed25519 ssh-add ~/.ssh/id_ed25519如果是从Windows复制过来的密钥文件第一步检查权限几乎必做因为Windows文件系统不区分那么细复制过来经常是全组可读的。5.4 脚本clone下来没有执行权限现象项目里的run.sh、deploy.sh在同事电脑上可以执行自己clone下来提示Permission denied。排查链路执行git ls-files -s run.sh查看索引里记录的权限位。看输出前几位有没有100755。如果是100644说明仓库里根本没存执行位。修复让Git记录执行权限chmod x run.sh git add run.sh git update-index --chmodx run.sh git commit -m fix: 标记脚本为可执行这里的关键是update-index它能直接修正索引中的权限位即使本地文件权限已经正确也能生成一次有效提交。5.5 多账号多平台用了一把钥匙全乱套现象同时要用公司托管平台和个人托管平台但只有一把默认密钥两边要求不同的邮箱经常推送失败。排查链路确认不同平台是否使用相同邮箱。如果邮箱不同Git提交身份、SSH密钥都要区分。修复为不同平台配置不同的SSH密钥并在~/.ssh/config里按域名指定。例如Host work HostName 公司托管平台域名 User git IdentityFile ~/.ssh/id_ed25519_work Host personal HostName 个人托管平台域名 User git IdentityFile ~/.ssh/id_ed25519_personalclone时把原来的域名替换成别名git clone work:组织/项目.git同时利用3.2节的身份配置每个仓库单独设置user.name和user.email就不会混用了。6. 配完基础项后值得顺手做的进阶功能6.1 让常用Git命令短一些自定义别名日常高频命令别名能省不少事git config --global alias.st status git config --global alias.co checkout git config --global alias.br branch git config --global alias.lg log --oneline --graph --all --decorategit lg是我个人最常用的命令提交历史树一眼看明白。保存完直接生效不需要额外工具。6.2 提交签名让历史记录可验证如果你的团队或项目要求提交信息可信可以开GPG签名。WSL里一样配置先生成GPG密钥gpg --full-generate-key拿到密钥ID后git config --global user.signingkey 密钥ID git config --global commit.gpgsign true配置完之后git commit会自动对提交签名。这个机制能很大程度上防止冒充身份的提交在开源协作或合规要求严格的团队里非常有价值。6.3 大文件管理Git LFS项目里的二进制资源设计稿、模型文件、大压缩包不适合直接塞进普通Git仓库否则历史体积会膨胀到难以忍受。Git LFS是在Git之上管理大文件的标准方案sudo apt install -y git-lfs git lfs install在某仓库里指定哪些文件走LFSgit lfs track *.psd git lfs track *.zip git add .gitattributes仓库克隆下来后普通文件照常大文件按需下载配合WSL使用完全没问题。6.4 多身份自动切换includeIf之前我提到身份配置可以按仓库单独覆盖更自动化的方式是用includeIf。在~/.gitconfig里写[includeIf gitdir:~/workspace/work/] path ~/.gitconfig-work [includeIf gitdir:~/workspace/personal/] path ~/.gitconfig-personal然后在对应的配置文件里写各自的user.name和user.email。只要仓库路径在某个目录下Git会自动加载对应身份配置完全不需要手动干预。这个技巧强烈推荐。6.5 大仓库瘦身稀疏检出和部分克隆大仓库全量拉下来很痛苦WSL里可以用Git自带的稀疏检出能力只检出需要的子目录git clone --filterblob:none --sparse git你的托管平台域名:组织/项目.git cd 项目 git sparse-checkout set 某模块--filterblob:none避免下载历史文件快照sparse-checkout只保留需要的目录。对大单体仓库来说体验提升非常明显。6.6 终端提示符显示当前分支最后这是个体验向的小配置。在~/.bashrc里加一个函数让终端提示符直接显示当前Git分支parse_git_branch() { git branch 2/dev/null | grep ^\* | cut -d -f2 } PS1\u\h:\w\[\033[32m\]$(parse_git_branch)\[\033[00m\]\$ 重开终端后每个目录下都能直接看到当前分支名切换目录也不容易搞混状态。这个配置占用极小但每天都能用到。我自己的习惯是先把第4章的.gitattributes和跨系统文件规则定下来再看心情加别名和终端提示符。WSL下的Git配置不是一锤子买卖换项目、换团队、换机器时这些规则都能迁移复用。希望这份步骤和踩坑记录能让你少走几段弯路。