1. 为什么我建议你在Windows上认真学一遍Git
老实说,Git 不是那种“看一眼就会”的工具,但它绝对是开发者绕不开的基础设施。无论是个人项目备份、写论文改稿、还是团队协作,Git 能在 Windows 系统上帮你解决同一个问题:记录每一次变更,并且让变更可回溯、可合并、可销毁。
我第一次在 Windows 上用 Git 时,还以为它就是那个右键菜单里出现的“Git Bash Here”,后来踩了无数坑才明白,Git 是一套完整的版本控制方案,远不止一个右键入口。这套方案的核心在于:它不关心你用的是 Windows 还是 Linux,它只关心你的文件在哪个时间点长什么样、是谁改的、改成了什么。
这篇内容我基于多年的实际使用经验,把 Git 在 Windows 上的完整流程拆开讲透:从下载安装、基础配置,到常用命令、真实场景示例、以及我踩过的坑。适合刚接触 Git 的新手,也适合那些用了半年还是只会 commit 和 push 的“半熟手”。文章里所有命令我都以 Windows 环境为准,兼顾 Git Bash 和 CMD 窗口两种执行方式,尽量让不同习惯的人都能顺畅复现。
在正式开始之前,先给你吃一颗定心丸:Git 在 Windows 上的安装配置,远比你想象的简单。真正难的是理解它的运行逻辑。只要把下面的核心概念捋顺,后面所有命令都会变得顺理成章。
2. Git 下载与安装:Windows 系统下的完整流程
2.1 下载渠道与版本选择
去 Git 官网下载页(git-scm.com/downloads),系统会自动识别你的 Windows 版本并给出对应的 64 位安装包。如果你访问官网不方便,也可以从国内镜像站下载,版本会稍旧一点点,但功能上没有任何差别。
这里有一个关键选择:下载时优先选 64 位版本。现在绝大多数 Windows 系统都是 64 位,32 位安装包虽然在老机器上能跑,但性能和兼容性都明显落后。我不知道你现在用的机器有多老,但既然能打开浏览器访问官网,大概率支持 64 位。
另外,Git 的版本迭代速度不算慢,但你不必追求最新。只要不是那种大版本跨度(比如 2.x 到 3.x 这种没发生过的),稳定版本之间差距主要体现在 bug 修复和少量新功能上。一个比较实用的原则:选最新稳定版即可,不要选 RC 预览版,尤其是你在生产环境要用的机器。
2.2 安装过程与关键选项
安装过程整体是“一路 Next”的节奏,但有几个选项需要你停下来想一想。我第一次安装时全部默认,后来发现默认值在某些场景下并不省心,下面这些选项建议手动调整。
第一个值得关注的选项是“Select Components”。这里会勾选是否安装“Git Bash Here”和“Git GUI Here”的右键菜单。两个都建议保留,Windows 下用 Git Bash 是最顺手的方式,尤其是跑 shell 命令时比 CMD 体验好太多。
第二个是默认编辑器,默认用 Vim。如果你不熟悉 Vim,强烈建议在这里改成 VS Code 或者 Notepad++。原因很实际:当 Git 需要你输入提交信息或处理合并冲突时,会弹出这个编辑器,Vim 对新手极不友好,我曾经在 Vim 里卡住不知道怎么退出(先按 Esc,再输入 :wq 回车,这个我现在刻在脑子里了)。
第三个是调整 PATH 环境的选项。安装程序默认选择“Git from the command line and also from 3rd-party software”,这个选项会把 Git 加入系统 PATH,意味着你可以在 CMD、PowerShell 里直接敲 git 命令。不要改成“Use Git Bash only”,否则你会在 CMD 里面对一堆报错。
第四个是换行符处理方式。默认选“Checkout Windows-style, commit Unix-style line endings”,这个我们后面会专门讲,先按默认来,但你要知道这个选项的存在。
安装完成后,打开 Git Bash,输入git --version。如果你看到类似git version 2.41.0的输出,说明安装成功。这一步必须验证,不要跳过,很多后续问题都源于安装不完整。
2.3 安装后的两个“无感但有用”的检查
安装完别着急用,先做两个快速检查,能帮你后面少踩坑。
第一个检查 Git 的安装路径是否正确。打开 CMD,输入where git,正常情况下会输出一个路径,比如C:\Program Files\Git\cmd\git.exe。如果输出为空,说明 PATH 环境变量没配上,需要手动把C:\Program Files\Git\cmd加进系统环境变量。
第二个检查 Git Bash 是否能正常启动并执行命令。打开 Git Bash,输入echo $SHELL,看到类似/usr/bin/bash的输出就正常。这一步其实是在确认 Git 自带的模拟环境完整。如果 Git Bash 一打开就闪退,大概率是系统缺少某些运行库,比如 Microsoft Visual C++ Redistributable,去微软官网装上即可。
3. 初始化配置:不设置这些,后面每一步都别扭
3.1 用户名和邮箱是 Git 的“身份证”
Git 记录每一次提交时,都会带上作者信息。没有这个信息,你根本没法 commit。打开 Git Bash,执行:
git config --global user.name "你的名字" git config --global user.email "你的邮箱"这里有两个容易忽略的细节。第一,--global表示全局生效,也就是当前 Windows 用户的所有仓库都使用这个身份。如果你只想让某个仓库使用不同身份,在该仓库目录下执行同样的命令但去掉--global即可,这就是局部配置。
第二,邮箱填写原则上是“你能收邮件的邮箱”。这关系到 GitHub、GitLab 等平台的提交关联。如果你用 GitHub,建议把邮箱设置成 GitHub 绑定的邮箱,这样提交记录能正确显示在你的贡献图上。也有人为了隐私设置成 noreply 邮箱,GitHub 设置页面会提供专属的 noreply 地址,复制过来用就行。
检查配置是否生效,执行:
git config --global --list它会输出 user.name、user.email 等全局配置项。当你发现自己提交的作者名不对时,先执行这条命令排查,九成是这里出了问题。
3.2 换行符处理:Windows 和 Linux 的“看不见的差异”
Windows 和 Unix 系统使用不同的换行符:Windows 用 CRLF(回车+换行),Linux/macOS 用 LF(仅换行)。Git 默认的换行符策略是:检出到工作区时换成 CRLF,提交到仓库时统一转成 LF。
这个策略本身是合理的,因为它既保证了 Windows 下你用记事本打开文件不乱码,也保证了仓库内所有文件的换行符一致,避免跨平台协作时出现大量差异。这在团队协作场景下尤其重要,不然你明明只改了一行,diff 却显示整个文件全变了。
但默认策略偶尔会给你一句烦人的警告:warning: LF will be replaced by CRLF。这其实不是错误,只是提示你在做的转换。如果这个警告让你不安,可以在提交前统一用以下配置彻底规范化:
git config --global core.autocrlf true这个命令的含义是:检出时自动把 LF 转成 CRLF,提交时自动把 CRLF 转成 LF。对 Windows 用户来说这是最稳妥的设置。如果你是一个纯 Windows 且不跨平台的项目,也可以用core.autocrlf false完全关闭转换,但我不推荐这样做,因为一旦未来有同事用 macOS 或 Linux,你们会因为换行符问题互相折磨。
3.3 让你少打字的别名配置
Git 命令其实有点长,比如git checkout、git commit --amend,每次都敲全名效率很低。配置几个常用别名能显著提升日常操作体验。我自己的配置如下:
git config --global alias.st status git config --global alias.co checkout git config --global alias.br branch git config --global alias.cm "commit -m"配置之后,git st等于git status,git co等于git checkout,git cm "message"等于git commit -m "message"。少敲几个字母看起来不起眼,但当你在高频操作时,这个体验差异是很明显的。
不过这里有个忠告:别自创太多冷门别名,尤其是团队协作时要慎用。你自定义的别名往往只在你自己机器上有效,如果同事用你的别名操作,可能直接报错。手动配置别名的正确姿势是:常用、直观、团队统一。
3.4 SSH 密钥配置:免密推送的关键
如果你要推到 GitHub 或 GitLab,配置 SSH 密钥是第一件需要做的事。它的原理很简单:你在本地生成一对密钥(公钥+私钥),把公钥放到远程平台,之后本地与远程通信就无需每次输入用户名密码。
在 Git Bash 里执行:
ssh-keygen -t rsa -b 4096 -C "你的邮箱"按回车接受默认存放路径,然后设置一个密码短语(也可以留空)。生成完成后,你会得到两个文件:id_rsa是私钥,绝不能泄漏;id_rsa.pub是公钥,需要手动复制到 GitHub 的 Settings -> SSH and GPG keys 页面。
把公钥内容复制出来的方法有两种:用编辑器打开公钥文件全部复制,或在 Git Bash 里执行:
cat ~/.ssh/id_rsa.pub验证是否配置成功,执行:
ssh -T git@github.com第一次连接会提示是否信任该主机,输入 yes 回车即可。如果看到Hi xxx! You've successfully authenticated, but GitHub does not provide shell access,恭喜,SSH 免密配置成功。这个过程中最容易被忽视的是:公钥和私钥放错位置。Windows 下 Git 默认读取C:\Users\你的用户名\.ssh目录,如果你把密钥下载到别处,Git 根本找不到。
4. Git 常用命令精讲:从入门到能干活的距离
4.1 仓库初始化的两种方式
使用 Git 的第一步是获得一个仓库。最常见的两种方式,对应两个最常用的命令。
第一种是自己从零创建仓库。在你项目的根目录打开 Git Bash,执行:
git init执行后这个目录会多一个隐藏的.git文件夹,里面存储着 Git 的版本库数据。注意两点:.git是 Git 的“大脑”,平时不要手动去动它里面的文件;这个目录下所有内容都会默认不跟踪,你需要通过.gitignore文件告诉 Git 哪些文件不需要纳入版本管理(比如node_modules/、.env、编译产物等)。
第二种是从远程仓库克隆已有项目:
git clone https://github.com/用户名/仓库名.git克隆命令会自动完成三件事:把远程仓库内容下载到本地当前目录、创建.git版本库、自动关联远程地址(别名默认是origin)。执行完后,你不需要再手动git remote add,直接就能 pull、push。
这里有一个实践中的提醒:不要在已有的 Git 项目中再执行git init,除非你确定要重新初始化。有些项目管理工具会自动创建.git,你加上一层反而会出问题。
4.2 日常三连:status、add、commit
入门阶段每天做得最多的就是这三个命令。它们的协作关系用一个生活例子解释:写文档就像给文稿拍照版本,git add是把修改过的文件放进一个“待提交筐”,git commit是按下快门给当前一张照片存档。
git status # 查看当前工作区状态 git add . # 把所有修改加入暂存区 git add src/index.js # 只把指定文件加入暂存区 git commit -m "完成用户登录功能"需要特别强调的是git add .的风险。点号表示把所有改动全部加入暂存区,包括你临时创建的、不想提交的文件。我过去就因为这个手滑,把一个含有数据库密码的配置文件提交上去了。好习惯是先git status看清楚改动列表,再用git add 文件路径精准添加。
git commit -m后面跟的是提交信息,写提交信息的建议是:用一句话说明这个提交做了什么,不要写流水账。比如修复登录超时 bug就比update强一百倍。很多团队还有提交规范,比如 Angular 风格的feat: xxx、fix: xxx,可以提前了解你所在团队的约定。
如果你发现刚提交的信息写错了,用:
git commit --amend -m "修正提交信息"这个命令会把你刚才的提交合并进去,并重新生成一条提交记录。注意,这条命令只对最近一次提交有效,而且一旦推送到了远程再 amend,就会产生分叉,后面会讲更安全的处理方式。
4.3 分支与合并:并行开发的基石
分支是 Git 最强大的功能,也是新手最绕不懂的一块。用大白话说:分支就像游戏存档里开了不同的剧情线,每条线的修改互不影响,最后可以合并到一起。
创建并切换到新分支:
git branch feature-login # 创建分支 git checkout feature-login # 切换到该分支两条命令也可以合并成一条:
git checkout -b feature-login查看当前分支及所有分支:
git branch # 本地分支 git branch -a # 本地加远程分支切换分支用git checkout 分支名,Git 2.23 之后也提供了更语义化的git switch 分支名,如果你用的版本较新,建议直接用 switch,因为 checkout 在旧版本里还有恢复文件的作用,语义上有歧义。
合并分支的核心命令是:
git merge 分支名比如你在feature-login分支上开发完了,想合到main上,先切回 main,再执行 merge:
git checkout main git merge feature-login这里最常见的状况是出现合并冲突。冲突的表现是:Git 会在冲突文件里插入类似下面这样的标记:
<<<<<<< HEAD 当前分支的代码 ======= 被合并分支的代码 >>>>>>> feature-login处理方式就是打开文件,人工决定保留哪部分、删除哪些标记,然后重新git add+git commit。新手第一次遇到冲突都很慌,其实只要记住:冲突不可怕,可怕的是不知道冲突标记是给你看的。把这些标记删干净、把代码保留正确即可。
4.4 撤销与回滚:后悔药的正确吃法
先讲一个最重要的认知:Git 的撤销不是一种操作,而是一族操作,什么样的后悔内容决定吃哪种后悔药。
如果只是改了文件但还没git add,想放弃修改,用:
git checkout -- 文件名或者新版更推荐的:
git restore 文件名如果已经git add了,想退出暂存区:
git reset HEAD 文件名老版本中git reset HEAD就是从暂存区撤销,新版里可以用git restore --staged 文件名。
如果已经 commit 了,想撤回最近一次提交但保留文件修改:
git reset --soft HEAD^如果想撤回提交且不保留文件修改:
git reset --hard HEAD^HEAD^表示上一个版本,HEAD~2表示上两个版本。这里的--hard是危险操作,它会丢弃所有未提交的修改,我建议执行前先备份或确认没有未提交的代码需求。
已经推送到远程的内容想撤销,不要用 reset,要尽量用 revert:
git revert HEADrevert 会生成一个新的反向提交来抵消旧的提交,不会重写历史。这在一人独享分支和多人协作分支上都是安全的做法。说句心里话:凡是涉及远程共享分支的撤销,无脑选 revert 就对了,reset 留在本地分支收着用就好。
临时存工作区修改用 stash:
git stash # 保存当前工作区改动,回到干净状态 git stash list # 查看 stash 列表 git stash pop # 恢复最近一次 stash 并删除记录这个命令特别适合这种场景:你正在开发一个功能,突然临时要换到别的分支修一个紧急 bug,但功能代码又没写完。先 stash,切分支、改 bug、提交、切回来,再 pop 恢复现场。
4.5 远程协作:pull、push、fetch 之间的关系
当你第一次把本地仓库关联到远程仓库时,执行:
git remote add origin 远程地址查看远程地址无误后,第一次推送需要设置上游分支:
git push -u origin main这里-u origin main的意思是:把本地 main 分支推送到远程,并记住这个对应关系。之后你再执行git push就不用带参数了。这一点极其实用,我第一次不知道加 -u,每次 push 都带一长串参数,后来明白后就舒服多了。
拉取远程最新代码:
git pullgit pull本质上是git fetch加git merge。fetch 只把远端更新下载到本地远程跟踪分支,比如origin/main,并不会修改你当前的工作区。而 pull 在 fetch 之后直接尝试合并,所以如果你的本地代码和远端改动冲突,pull 会立刻触发冲突。
区分这两个命令的实践价值在于:当你不想立即合并、只想看看远端发生了什么时,用git fetch更安全。当你想直接同步并合并时,用git pull。
日常开发最常见的冲突来源就是远程提交和你本地修改撞车。避免的办法是:每次开始新功能前先 pull 一次,提交后及时 push,把冲突扼杀在萌芽状态。
4.6 查看历史的几条命令
日志是 Git 给我们的“穿越机”,上手期先掌握这几个:
git log # 完整提交历史 git log --oneline # 简洁版,每条只显示一行 git log --graph # 图形化显示分支走向 git log -3 # 只显示最近三条如果你想看某个文件的历史演变,用:
git log -- 文件名如果你想知道某一行的改动是谁在什么时候加的,用:
git blame 文件名这几个命令在排查问题时价值巨大。我处理线上 bug 时,第一件事就是git blame定位这行代码是谁提交的、提交说明是什么,往往能迅速找到上下文。
5. 实战示例:拿一个小项目完整走一遍 Git 流程
5.1 场景设计
我们模拟一个很常见的场景:你有一个 Python 项目,想在本地用 Git 管理起来,并推到 GitHub 远程仓库。下面每一步的命令,你都可以直接复制运行。
在项目根目录打开 Git Bash,执行:
git init创建项目所需的文件,比如main.py和README.md,然后用git status查看状态。此时你会看到这些文件显示为未跟踪的红色状态。
新建一个.gitignore文件,写入内容:
__pycache__/ *.pyc .env然后执行:
git add . git status此时文件变成了绿色,表示已进入暂存区。执行提交:
git commit -m "项目初始化:添加主程序和说明文档"搭建远程仓库的过程不在这里细说,只需记住 GitHub 上创建空仓库后,会给你一个远程地址。在本地执行:
git remote add origin https://github.com/你的用户名/你的仓库名.git git push -u origin main到这里,你已经完成了一个完整的“本地建仓 → 首次提交 → 推送远程”闭环。
5.2 开发新功能时的分支流
现在开始开发一个登录功能。创建一个新分支并切换过去:
git checkout -b feature-login在项目里修改或新增文件,比如新建login.py,然后提交:
git add login.py git commit -m "feat: 增加登录逻辑"开发完成后,切回主分支,把功能分支合并进来:
git checkout main git merge feature-login合并完推送远程,清理本地分支:
git push git branch -d feature-login-d参数是安全删除分支,只有分支已合并时才会成功。如果你想强制删除未合并的分支,用-D,一般不建议轻易用。
5.3 模拟一次撤销操作
假设你刚提交了一个版本,发现引入了一个低级错误。在本地修正后再次提交:
git add . git commit -m "fix: 修复登录接口的空指针异常"此时你会发现git log --oneline里有三条提交记录。如果你想撤销中间那条,用git log找到它的 commit hash,执行:
git revert 提交哈希revert 完成后会自动弹出编辑器让你填提交信息,默认即可,保存退出。再次git log --oneline,你会看到多了一条 revert 提交,而原来的错误提交依然在历史里。这正是 revert 与 reset 的关键差异:历史完整,协作不冲突。
6. 常见问题与排查技巧实录
6.1 中文乱码问题
在 Windows 上使用 Git,中文乱码的场景非常多。最常见的两个位置:提交信息里的中文乱码,以及文件名/文件内容中文乱码。
处理核心思路是统一字符编码。在 Git Bash 里执行:
git config --global core.quotepath false这个配置防止 Git 把中文文件名转义成一堆\xxx的八进制码,执行后 Git 能正常显示中文文件名。
如果 commit 信息里的中文乱码,尝试:
git config --global i18n.commitEncoding utf-8 git config --global i18n.logOutputEncoding utf-8如果你的系统区域是非中文环境,还需要在 Git Bash 里设置环境变量:
export LANG=zh_CN.UTF-8不过这条命令只对当前会话有效,永久写入可以编辑~/.bashrc文件。要注意的是,Windows 系统自带的记事本打开 UTF-8 文件时有时也会乱码,这是 Windows 老版本的记事本编码识别问题,不是因为 Git 配置导致,可以选择 VS Code 打开对比一下。
6.2 换行符引发的“整文件变更”问题
这个问题在团队协作里极其隐蔽:你只改了一行代码,push 之后,review 页面显示整个文件都被修改了。这种情况几乎都是换行符不一致导致的。
排查方法很简单:用编辑器打开文件,查看右下角显示的行尾序列。如果是 CRLF,而仓库统一是 LF,Git 就会认为整个文件都变了。
解决思路有两个方向。一是统一让 Git 自动处理,保持core.autocrlf true;二是给你的仓库加一个.gitattributes文件,强制指定某些文件使用 LF:
*.js text eol=lf *.py text eol=lf.gitattributes是仓库级别的配置,团队内所有人拉下来自动生效,比给每个人设置全局配置可靠得多。我强烈建议做跨平台项目的人尽早用上它。
6.3 git 命令提示“不是内部或外部命令”
在 CMD 里敲git提示“不是内部或外部命令,也不是可运行的程序或批处理文件”,这就是 PATH 环境变量没配好。
打开系统设置 -> 环境变量,在“系统变量”里找到 Path,新增以下路径:
C:\Program Files\Git\cmd C:\Program Files\Git\bin注意具体路径以你实际安装位置为准。修改完环境变量后,记得重新打开 CMD 窗口才生效,因为环境变量在窗口启动时读取。
6.4 SSL 证书问题导致克隆失败
Windows 上有时候克隆远程仓库,会报SSL certificate problem: unable to get local issuer certificate。
这个问题通常是因为本地 CA 证书链不完整。最简单的临时解决办法是:
git config --global http.sslVerify false但我必须提醒你:这个操作会关闭所有远程仓库的 SSL 验证,有安全隐患,一般只建议在紧急情况下临时用。更稳妥的做法是更新系统的根证书,或者在 Git 安装目录里更新 ca-bundle.crt 文件。
我的一位朋友就因为这个报错卡了大半天,最后发现是公司内网的防火墙做了 HTTPS 拦截,他关了 SSL 验证也解决不了,最后改用 SSH 协议克隆远程仓库才真正绕过去了。所以如果你的场景也涉及公司网络代理,优先检查这个方向。
6.5 误提交敏感文件后的处理
如果你不小心把.env文件或者带密码的配置提交到了 Git,并推送到远程了。这里有一个残酷的事实:就算你立刻删除并重新提交,远程历史里依然存在这条记录,因为别人 clone 时会把全部历史拉下来。
正确且简单的流程是:
- 在本地的
.gitignore里加入该文件; - 用
git rm --cached 文件名把它从 Git 追踪中移除(保留本地文件); - 提交并推送;
- 立即去远程平台(如 GitHub)重置或删除相关密钥、密码,换新的;
- 如果必须彻底清除历史,考虑用
git filter-repo重写历史,但注意这会改变所有提交哈希,协调成本很高。
这条经验值得你花时间记住,因为很多人第一次撞上敏感文件泄漏时,都会天真地以为删除提交就算完了。
6.6 其他几个值得记住的小问题
Git Bash 打开后提示warning: templates not found,一般是 Git 安装被移动过导致检测不到模板目录,重装一次即可解决。这个提示通常不影响正常使用,可以忽略。
忽略文件无效时,先检查你的规则是否写对了。规则后面加不加斜杠/含义完全不同:build/表示忽略目录,build表示忽略同名文件和目录。再检查.gitignore文件本身是否被纳入了版本管理,以及文件是否已经被 Git 追踪——被追踪的文件即使写入忽略规则也不会生效,需要先git rm --cached。
分支删除失败提示The branch is not fully merged,说明该分支还有未合并的提交。如果你想确认哪些提交未合入当前分支,可以用git log 分支名 --not --oneline查看。
7. 我最后想分享的一个“土办法”
我在教身边的朋友用 Git 时发现,很多人不是命令记不住,而是总在纠结“到底会不会把代码弄丢”。说个我的真实体会:Git 在 Windows 上的学习,最忌“只读不敲”。你读十篇教程不如自己建一个测试项目,把所有命令挨个敲一遍,尤其是 reset、revert、stash 这些听起来吓人的操作。
我自己的学习方法很简单:用一个专门拿来“搞坏”的文件夹,里面放几个测试文本文件,然后在该执行的命令全部执行一遍,看仓库状态怎么变、.git文件夹体积怎么变、日志怎么长。这样折腾几次之后,你对 Git 的信心会完全不一样。这个“土办法”我用到现在教新人,仍然是我觉得最有效的路径。
另外一个细节是,Windows 上做 Git 操作时尽量统一使用 Git Bash。CMD 和 PowerShell 虽然能用,但有些命令的行为会有细微差异(比如文件路径斜杠、环境变量语法),Git Bash 在 Windows 上是最接近 Linux 风格的环境,也更符合 Git 的设计预期。
Git 不难,难的是你迟迟不肯动手敲那第一行命令。把这条只读不敲的死循环破掉,Git 的世界很快就会向你敞开大门。希望你读完这些内容后,已经打开 Git Bash 开始敲第一条命令了。