在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版Git | WSL里的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 "default@example.com" cd ~/workspace/work-project git config user.name "工作身份" git config user.email "work@example.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配置成功了。这时候再执行clone:
git 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的文本文件默认用回车加换行(CRLF),Linux和macOS默认只用换行(LF)。Git有个自动转换机制,但经常造成"我什么都没改,怎么一堆文件都显示修改"的诡异现象。
WSL里我推荐一套很少出问题的配置:
git config --global core.autocrlf input含义是:提交时把CRLF转成LF,检出时不做转换。由于WSL内本身就是LF环境,这个配置最适合跨Windows编辑、Linux提交的场景。
但更稳的方案是在仓库根目录放.gitattributes,把规则固定下来,团队所有人都遵守同一套规则。一个常见的模板:
* text=auto *.sh text eol=lf *.bat text eol=crlf *.ps1 text eol=crlftext=auto让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 --chmod=+x deploy.sh让Git在索引中记录该文件的执行位变化,提交后就能在团队中正确传播。
如果你的文件确实存放在/mnt/c下,可以在/etc/wsl.conf里配置挂载选项,给Windows盘加上完整的Linux权限语义。一个参考配置:
[automount] enabled = true options = "metadata,umask=022,uid=1000,gid=1000"设置完成后在Windows终端执行wsl --shutdown重启WSL生效。metadata让WSL能为Windows文件记录Linux权限元数据,umask=022确保新建文件默认没有组外写权限。
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 --chmod=+x 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 --decorate"git 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在某仓库里指定哪些文件走LFS:
git 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 --filter=blob:none --sparse git@你的托管平台域名:组织/项目.git cd 项目 git sparse-checkout set 某模块--filter=blob: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配置不是一锤子买卖,换项目、换团队、换机器时,这些规则都能迁移复用。希望这份步骤和踩坑记录能让你少走几段弯路。