
上个月有个同事跑过来问我说能不能给他整理一份“Git资料”最好是一份拿来就能看懂的。我说网上教程一堆为什么不直接搜。他说搜到的不是太零碎就是讲得太绕看完等于没看。我想了想确实Git这玩意儿对老手来说就是日常操作但对刚开始接触的人来说第一次配置、第一次提交、第一次因为合并冲突而满头问号每一步都可能是坑。这份“Git资料”不是某个超级工程而是把Git从安装、配置到日常命令、团队协作、问题排查串起来的一套笔记今天把它整理出来希望对每个正在用Git或准备用Git的人有点帮助。这套资料能解决什么问题往小了说是让你别再因为git pull和git push的顺序搞出冲突往大了说是帮你理解版本控制到底在干嘛为什么团队里十个人同时写一个项目代码还能不乱。适合谁看刚入行的开发者、从SVN或直接复制粘贴文件管理版本转过来的同学、以及用了Git但一直靠两三条命令“走天下”的人。如果你已经对Git很熟可以重点看看第4节和第5节那部分是关于协作和避坑的经验。1. 装Git之前先弄明白版本管理到底在解决什么问题1.1 没有版本管理的时候项目有多痛我一直觉得理解一个工具的“为什么存在”比记住命令本身重要得多。你没用过没有版本管理的项目可能不知道那种痛苦一个项目文件夹里堆着项目最终版.py、项目最终版2.py、项目真最终版_改.py、打死不改版.py这还算好的更怕的是改完代码发现思路走错了想退回昨天的状态结果昨天的代码在U盘里U盘又落在工位上。这就是经典的“文件复制粘贴管理法”它最大的问题是文件多了以后你根本分不清哪份是最新的、哪份是能跑的、哪份中间夹着同事改到一半的半成品。Git解决的就是这件事。它把你的项目变成一个仓库repository每次你有意识地保存一个“版本”Git就帮你记一次快照。这个快照不是把整个目录复制一遍那么笨它只记录变化的部分所以仓库越用越大也不会立刻爆炸。因为你随时可以回到任何一个快照点所以再改代码的时候心态完全不一样。以前改代码是“这版改坏就完蛋了”现在改代码是“改坏了大不了回到昨天那个能跑的版本”。这个心态变化对开发效率的影响是很大的。1.2 不同操作系统选哪个安装方式Git的安装在Windows、macOS和Linux上不太一样很多新手在这里就卡住了觉得是不是装错了。先说Windows最主流的方式是去Git官网下载安装包双击一路Next。但这里有个高频问题有些教程会让你在安装过程中选“Use Git from the Windows Command Prompt”有些又建议选“Use Git and optional Unix tools from the Command Prompt”到底选哪个我自己实践下来的建议是如果你平时主要用CMD或者Windows Terminal选“Use Git from the Windows Command Prompt”就够了因为这样你在CMD里敲git命令系统能找到它而且不会覆盖系统自带的find、sort等命令。选项里那些“Checkout as-is, commit Unix-style line endings”之类的暂时不用管后面配置里我再说现在保持默认即可。macOS用户则分两种一种是装了Homebrew的直接brew install git方便以后升级另一种是不想装额外工具链的去官网下载macOS安装包也行但在“允许从任意来源下载”这一步可能要多点一下右键打开。Linux用户更简单发行版软件源里基本都有Git比如Debian/Ubuntu系的apt install gitFedora系的dnf install git。装完以后正式使用前先验证一下版本终端输入git --version能输出版本号就算基础安装成功了。1.3 安装这事最常见的坑不是“装不上”很多新手以为装Git最麻烦的是网络下载慢、安装包找不到。实际真正恼火的是装完了之后在终端里敲git提示command not found。这种情况在macOS和Linux上出现概率较高尤其是用官网安装包装macOS版本的时候因为默认路径可能不在PATH里。排查方法其实很简单先确认安装路径再手动加个环境变量。比如在macOS上如果Git装在/usr/local/git/bin你就往shell配置文件的末尾加一行export PATH/usr/local/git/bin:$PATH再执行source ~/.zshrc或者source ~/.bash_profile让它生效。Windows上如果出现command not found多半是安装时没勾选加入PATH的选项或者安装完了没重启终端。我建议装完后新开一个终端窗口而不是在旧窗口里继续敲命令这个细节能省下十分钟的怀疑人生时间。提示安装完成不等于配置完成。第一次用Git的人最容易忽略的是还没有设置用户名和邮箱就开始提交然后Git会默认生成一个“本机用户”的配置提交记录乱成一锅粥后期想改又得额外学命令。所以安装完的第一步不是急着git init而是先把自己的“身份”告诉Git。2. 初始化与全局配置第一次提交前先把这些做好2.1 三个必须做的基础配置当你在一个项目目录里执行git init之后Git只是把目录变成了一个仓库它并不知道你是谁。所以在开始提交之前必须先设置用户名和邮箱。这两条命令是我在任何一台新电脑上首先执行的git config --global user.name 你的名字 git config --global user.email 你的邮箱这里有个细节--global表示全局生效意思是这台电脑上所有Git仓库都会默认使用这个身份。如果你在公司电脑上有个人项目不想让公司的提交记录顶着自己的私人邮箱那就要学会用局部配置。某个仓库单独设置身份的方法是进入该仓库目录后去掉--global执行相同命令。我见过不少同事因为一开始用了全局配置往公司代码库提交了一堆私人邮箱的记录最后只能找管理员后台改非常麻烦。第三个必做配置是默认编辑器。当Git需要你输入提交信息而你用了git commit却没有带-m的时候它会弹出一个文本编辑器。默认可能是Vim很多新人进去之后怎么都退不出来只能直接关终端。提前设置成自己熟悉的编辑器会舒服很多git config --global core.editor code --wait上面这条是把VSCode当默认编辑器执行后代码提交时会自动打开VSCode新建的待写入信息文件保存关闭后Git才会继续。如果你用的编辑器不是VSCode换成相同思路即可。核心是让Git能唤醒一个你用着顺手、且支持“等文件保存后退出”的编辑器。2.2 换行符和编码这两个看不见的坑Windows和Linux/macOS的文本换行符不一样Windows用CRLF回车加换行Unix内核系统用LF换行。Git默认会对换行符做一些自动转换于是你经常会在提交时看到那种警告LF will be replaced by CRLF。这个警告本身不会让你代码坏掉但它背后是一个经典的多平台协作问题——同一个文件在Windows上提交、在Linux上部署时可能会因为换行符不同而产生诡异差异。我现在常用的做法是在Windows上设置git config --global core.autocrlf true让Git在提交时把CRLF转成LF存进仓库检出代码时再转回CRLF。在macOS/Linux上设置core.autocrlf input提交时转成LF检出不额外转换。如果团队里全是macOS和Linux直接提交时统一成LF是最省心的。编码问题同样容易炸。团队协作时如果项目里有老旧的GBK编码文件而Git默认把文本内容当作UTF-8那么在diff差异比较时看到的可能是一堆乱码。我建议新项目统一用UTF-8编码历史项目如果没办法改编码至少添加一个.gitattributes文件去指定某些文件类型的编码处理方式。不过说实话这种存量问题优先靠沟通解决别指望用一条配置命令就洗白所有历史文件。2.3 .gitignore到底该写什么不该写什么每次初始化仓库后我建议第一件事不是提交代码而是先把.gitignore写好。它的作用是把某些文件或目录排除在Git管理之外比如依赖目录、编译产物、本地环境配置文件。很多人最头疼的是不知道怎么写得合适我的经验是先根据项目类型去找一份对应的模板GitHub的gitignore仓库里很全然后结合自己的项目再改。比如Node.js项目里node_modules是一定要排除的几千个第三方包没必要、也不应该提交到仓库里Python项目里__pycache__、.venv这些也要排除Java项目里target目录肯定不能进仓库。关键原则是凡是能从代码重新生成的东西尽量不要进仓库。这里有个反例我见过有项目把node_modules直接塞进仓库导致克隆一个项目要下载几百兆甚至几个G的东西既费流量又拖慢速度而且容易出现平台相关的二进制差异。不过.gitignore也有个容易坑人的地方如果某个文件已经被Git跟踪了再把它写进.gitignore是没用的。你必须在.gitignore生效前先把文件从Git缓存里移除git rm -r --cached node_modules然后再把node_modules写进.gitignore提交这一次变更后续才不会继续跟踪。很多新人在这块卡住以为是.gitignore写错了其实是没有“解绑”历史跟踪。3. 最常用的Git命令整理成一条能跑通的工作流3.1 拉代码、看一眼状态、提交这个闭环每天重复十次我不打算把Git的所有命令都列出来那不现实也没必要。日常中最实用的其实是几个基础命令的组合。首先是克隆项目git clone gitgithub.com:用户名/仓库名.git克隆后在目录下创建或修改文件然后我要先看一眼当前仓库的状态git statusgit status的输出会有三块内容已暂存Staged也就是即将进入下次提交的变更、已修改但未暂存Modified not staged、未跟踪文件Untracked。新人常犯的错误是以为git status显示的就是“所有文件”其实它更像是一块仪表盘提示你当前有哪些文件被改动以及这些改动处于哪个阶段。提交的流程是这样的git add 文件名 # 把某个文件放进暂存区 git add . # 把所有改动放进暂存区慎用容易把不该提交的也带进去 git commit -m 提交说明 git push origin 分支名 # 把本地提交推送到远程这套流程看起来简单但我必须强调git add .的隐患。它会把当前目录下所有未被忽略的改动全部加入暂存区如果你同时改了代码和某个本地配置文件就会把不该提交的配置一起推送出去。所以我更推荐用git add 具体文件或git add src/这种按目录区分的方式。看到这里如果你觉得麻烦那我告诉你很多老手在审查提交时最关注的就是“有没有混进不该提交的文件”从第一步养成好习惯后面会少很多尴尬事。3.2 分支操作别再把主线搞得一团糟分支是Git里一个核心概念我用一句话解释分支相当于从当前代码状态复制出一条平行线你在自己的平行线上改动不会影响原来的主线等改完了再把平行线“合并”回主线。这个设计让多人同时开发不同需求成为可能。最常用的操作是新建分支并切换过去git checkout -b feature/login这条命令等价于两条命令的合并git branch feature/login新建分支git checkout feature/login切换分支。现在新版Git也提供了git switch -c feature/login语义更明确但大部分教程和老机器上还是以checkout居多两种都认识比较好。切分支之前最重要的一句话先把当前分支的工作区清理干净。如果你手上改到一半的文件没提交带着脏状态切换分支Git会自动尝试把这些改动带到目标分支。如果目标分支里同一份文件内容不同Git就会直接不让你切要求你先提交或暂存。这时候可以用git stashgit stash会把当前未提交的改动先存到一个临时区让工作区变干净然后再切分支。等下次切回来时执行git stash pop恢复改动。这个命令是很多人解决“手头工作没做完又必须切个分支改紧急bug”的法宝。3.3 撤销与回滚出错了别慌先看清楚再动手Git最让人心生好感的地方是它给了你“后悔药”但这个药也分版本用错了可能让你更崩溃。我把最常见的几个场景梳理一下。场景一git add加错了文件但不改文件本身只想移出暂存区git reset HEAD 文件名这条命令把文件从暂存区退回工作区改动还在只是不再暂存。场景二本地提交信息写错了或者把几次细小改动打成了一次提交想修改最近一次提交git commit --amend这条命令会把当前暂存区的改动合并进上一次提交并且重新编辑提交信息。注意--amend会改变提交的哈希值所以只适合处理“还没有推送到远程”的提交。如果已经push了再amend推送时大概率会要求强推强行覆盖远程历史对团队协作来说这是危险操作。场景三想彻底回退到某个历史提交但本地有一些已经提交但不想保留的版本git reset --hard 目标提交哈希值--hard会丢弃所有改动包括工作区和暂存区的。这条命令很暴力用之前一定要确认确实不要这些改动了。更温柔一点的做法是git revert 哈希值它会反向生成一个新提交把指定提交的改动抵消掉适合已经推送到远程的提交回滚。我的习惯是本地未推送的版本用reset远程已经存在的提交用revert。这条规则能避免绝大多数团队协作翻车事故。4. 团队协作里的Git细节很多老手也在这里栽跟头4.1 合并冲突到底怎么解决当你执行git pull或者git merge时如果当前分支和要合并进来的分支改动了同一个文件的同一段代码Git会告诉你发生了冲突。很多人看到“CONFLICT”就心里一紧其实冲突不是出了事故而是Git在请人做决定两边的改动它不会自动选需要你来定夺哪个才是要的。出现冲突后打开那个被标记的文件你会看到类似这样的内容 HEAD 这是当前分支的代码 这是要合并过来的代码 feature/login处理方式就是自己手动把、、这些标记删除掉保留正确的代码。然后git add这个文件再继续提交合并且冲突解决就算完成了。听上去简单但有两点经验很重要第一处理冲突时建议打开整份文件看一眼上下文别只看冲突标注的地方有时候两个分支在相邻区域的改动也会互相影响。第二不是所有冲突都是文本层的比如两个分支各自改了package.json里的同一行冲突很容易看到但如果一个是基于旧版本的依赖调整一个是新加了依赖即使Git没报冲突合出来的结果也可能是依赖丢失。遇到这种“无冲突但逻辑冲突”的情况只能靠测试和代码审查兜底。4.2 提交信息规范是你的另一个门面我觉得提交信息这件事常被新手当作“随便写写”但真到出问题的时候才知道它多值钱。比如线上出了bug一根线上排查线索就是git log的提交历史。如果提交信息写的是“update”“fix”那基本没有排查价值如果写的是“修复登录页在iOS 16下点击按钮无响应的问题”那排查效率直接翻倍。我现在工作的团队约定了一套简单的提交规范格式是类型: 简述。类型一般有feat新功能、fix修bug、docs文档、refactor重构、chore杂项等。例如fix: 修复移动端登录按钮在iOS 16下无法触发点击事件 feat: 新增用户头像上传功能 docs: 更新README中的部署步骤这套规范最直接的好处是Git log一目了然哪天想回滚某个发布可以在提交历史里快速筛出相关提交。配合分支名和PR/MR的标题一起看基本能还原整个需求的开发脉络。4.3 push之前先pull这个顺序能救你的命很多新手把git push当成“上传”觉得本地提交完成就完事了一推却被远端拒绝。原因通常是远程分支上有其他人先推了新提交而本地分支的基线落后了。此时Git出于安全机制会拒绝你“非快进式”的推送要求你先git pull把远程变更同步到本地。正确的习惯是在push之前先pull但不是无脑git pull。如果你本地有未提交的改动直接git pull可能会出来一堆组合问题。我自己的标准流程是# 1. 查看状态 git status # 2. 如果有本地的未提交改动先提交或暂存 git commit -m 提交说明 # 3. 拉取远程变更并尽量用变基的方式合入 git pull --rebase # 4. 推送远程 git push--rebase的意思是把本地已经在基线之上产生的提交先“暂时摘下”等拉取到远程最新代码后再重新放到最顶层。这样提交历史会是一条直线比较干净。如果不加--rebaseGit会用merge的方式合并本地可能会出现一个Merge branch xxx into xxx的合并提交看历史时会多一些“噪音”。不过rebase也要知道它改写了本地提交的哈希所以绝不应对已经推送到远程的公共提交执行rebase。5. Git配置与命令的实用技巧能省不少事5.1 用别名给高频命令“改个短名”Git命令本身不短敲起来效率不高。Git支持配置别名也就是给命令重新起一个简短的别名。我电脑上常年使用的别名配置如下git config --global alias.st status git config --global alias.co checkout git config --global alias.br branch git config --global alias.ci commit git config --global alias.last log -1 HEAD --stat配置之后git st等于git statusgit co等于git checkout。这些别名不会影响你写完整命令但会让日常操作省下不少按键。在给团队分享知识时我也会告诉大家别名配置放在~/.gitconfig里整体上很容易迁移到新电脑。5.2 用日志筛选提交别再翻聊天记录git log是查看提交历史的命令但它有很多变体。比如想看最近三条提交的简洁列表git log --oneline -3想按作者筛选git log --author你的名字想搜某个提交信息里含有关键字的改变git log --grep登录这些命令在排查问题时极其好用。另外看某一次提交动了哪些文件、每处改动是什么可以用git show 提交哈希值这个命令会同时展示这次提交的元信息、改动文件名和具体增删行是代码审查时最常用的命令之一。5.3 暂存与清理工作区有讲究前面提到过git stash可以暂时藏起未提交的改动这个工具在“紧急切换任务”场景下非常香。但它的使用也有细节git stash默认不会把新增的未跟踪文件Untracked files藏进来如果你新创建了一个文件但还没git add执行git stash之后它依然躺在工作区里可能导致切换分支后这个问题还在。想要把未跟踪文件一并藏起来要用git stash -u恢复的时候我习惯用git stash pop而不是git stash apply区别在于pop会把藏起来的改动弹出并清除掉这次stash记录而apply会保留记录适合你想在多个分支上应用同一份改动的情况。当你有一堆stash记录时用git stash list查看恢复指定某条记录用git stash pop stash{2}。6. 常见问题排查与避坑技巧实录6.1 推送/拉取时报错先看提示再问人很多Git使用中的报错英文提示本身就写得很清楚了但新手常常被一长串英文吓到下意识跳过提示去搜“万能的答案”。其实排查思路很固定。比如最常见的一类报错fatal: unable to access https://xxx.git/: Failed to connect to github.com port 443这是网络层面的问题要么是DNS解析不了要么是远程地址访问不通。如果是国内网络环境可以在克隆或配置远程地址时使用镜像或加速前缀来处理这不是魔法就是把远程地址换成可达的地址而已。另一类高频报错是Permission denied (publickey)意思是远程服务端没有认可你的SSH密钥。解决思路是先在本地生成密钥ssh-keygen -t ed25519 -C 你的邮箱然后把~/.ssh/id_ed25519.pub里的内容配置到代码托管平台后台的SSH Keys列表里。配置完用ssh -T gitgithub.com测试连通性能看到欢迎信息就说明生效了。6.2 detached HEAD是什么怎么理解有些新手发现git checkout 某个提交哈希值之后提交了新代码却感觉“丢”了而且Git提示你处于detached HEAD状态。这其实是Git在告诉你你现在没站在任何分支上而是直接站在某个历史提交点上。在这个状态下提交的内容没有分支引用它一旦切走就可能找不回来。正确的逃跑方式是如果要基于这个历史提交做更改先基于它创建一个分支git checkout -b feature/from-history 目标提交哈希值这样HEAD就重新指向了新分支后续提交也不会“丢”。这个错误我在新人身上见得太多了核心原因是不理解分支和HEAD的关系建议看到这段文字的读者自己对git switch和git checkout建立一套清晰记忆日常切分支用switch文件维度还原用checkout。6.3 文件后缀不重要但文件类型很重要有些项目会把设计稿、二进制包、大体积样例数据放进Git仓库导致仓库越来越臃肿、克隆越来越慢。这时候git rm --cached只是删除了“跟踪关系”历史里依然保留着这些大文件的快照仓库体积不会变小。想真正瘦身可以借助git filter-repo这类工具重写历史但这会改变所有历史提交的哈希只适合在团队统一协调下操作。如果项目确实需要在仓库里管理二进制大文件更推荐使用Git LFSLarge File Storage把大文件替换成轻量指针内容存储在独立空间克隆时按需下载。日常建议是设计稿、视频、模型文件、密钥证书等要么走独立的制品库要么用LFS别暴力塞进普通Git仓库。7. 一套适合小团队的Git协作流程参考7.1 从主干拉分支别直接在主线上改一个人的项目随便怎么搞都行但到了两个以上的人协作时就需要一点流程约束。小团队最简单的策略是主干分支main/master保持可发布状态其他人develop临时分支功能开发从main拉出自己的功能分支开发完合并回main。功能分支的命名可以用feat/下单流程、fix/修复支付回调这种格式一看就懂改的是什么。我遇到过最头疼的情况是团队里有人图省事直接在main分支上改代码也没人知道。等要发布时发现线上版本和别人本地代码差了十万八千里合并冲突一个接一个。后来我们定了规矩任何改动哪怕只改一行都要走分支、提交、合并的流程。一开始会觉得多了一步但三个月后你看看稳定的主线和清晰的历史就知道这一步有多值。7.2 Code Review和CI怎么配合Git用代码合入主分支前最好有一个自动化的检查流程这就是CI持续集成。你推了代码之后CI自动跑测试跑过了才能合并。Git本身不负责这件事但它提供了“保护分支”的配置在代码托管平台上可以设置main分支不允许直接推送只能通过合并请求合入而且必须通过CI检查和指定人数Review。这些小配置不会增加太多管理成本但对团队代码质量提升非常明显。一方面它强制了“先审后合”的协作流程另一方面也减少了“谁都能往主干塞代码”的恐惧。虽然有些人觉得这样很繁琐但我个人体验下来这恰恰是小团队逐渐正规化过程中成本最低的一步。7.3 版本发布与Tag线上版本要能一眼定位每次正式发布我非常建议给对应的提交打上一个标签Tag。打标签的命令git tag v1.0.0 git push origin v1.0.0以后线上有任何问题直接在仓库里找对应版本的标签git checkout v1.0.0就能定位到当时的代码状态配合git log看那个时间窗口里改了哪些提交排查效率会高很多。很多人觉得Tag是发布流程后面的事但在小团队里它就是一条“线”把线上版本和代码历史挂钩没有这条线版本回溯就是空话。8. 最后再分享一些我的个人习惯Git的语法不算难但它的概念模型一开始确实有点反直觉。刚开始用的时候我建议不要上来就背命令先把 “工作区、暂存区、本地仓库、远程仓库” 这四个概念搞清楚后面所有的命令都是在这些区域之间搬运内容。工作区就是你电脑上能看到的文件暂存区是准备打包的临时区域本地仓库是提交形成的版本历史远程仓库是大家共享的中央存储。我的一个小习惯是每天开工前先git pull一次收工前再git push一次并确保工作区没有未提交的东西。这个习惯让我的分支始终跟得上团队进度也避免了下班前发现一堆改动没提交的焦虑。另一个习惯是每隔一段时间用git log --oneline --graph看一下整个分支脉络能直观感受到团队协作的“轨迹”也容易发现自己是不是在某个分支上闷头写太久了。最后想说的是这份“Git资料”不是拿来背的是拿来用的。你在项目里遇到问题翻一翻、照着敲踩过两次坑基本就记住了。希望这份整理能帮你少走点弯路把精力花在真正要解决的代码问题上而不是被版本管理本身绊住脚。