1. 环境准备先把 Git 装好、配好、连上远程仓库我没少见过这样的场景电脑里已经装了一堆 IDE写代码也写了几个月但某天想用 Git 拉个仓库终端敲了个git pull直接弹出一句git 不是内部或外部命令。这时候第一步还真不是学命令而是先把 Git 安装和环境配明白。在 Windows 上装 Git 其实很简单去官网下载安装包一路 next 就行。真正的问题是安装完之后要做的事。装完必须验证一下git --version如果输出了类似git version 2.40.0.windows.1说明安装成功。要是终端提示无法识别十有八九是没加环境变量或者你开着旧的终端窗口重新打开一个就好。这里有个小建议安装时勾选Add to PATH后面省去一堆麻烦。要是环境变量已经坏了手动去系统设置里把 Git 的cmd目录加到 PATH 就行。装完之后别急着 clone先把自己身份信息配上。这一步不做哪怕你 commit 成功提交记录里也是匿名状态推到远端后别人看到的就是一串乱码一样的作者名。git config --global user.name 你的名字 git config --global user.email 你的邮箱现在多数代码托管平台提交邮箱最好和账号绑定的邮箱一致这样提交记录能正确关联到你的头像和账号。配完之后可以用git config --global --list检查一下。然后就是连接远程库。现在几乎都是走 SSH 或 HTTPS 两种方式。个人电脑上我强烈建议用 SSH配好一次之后可以实现长期免密操作之后几乎不用再输账号密码。生成密钥命令ssh-keygen -t rsa -b 4096 -C 你的邮箱一路回车确认默认路径就行。生成完看到个类似Your public key has been saved的提示再把公钥内容复制出来。Windows 下可以直接这么操作cat ~/.ssh/id_rsa.pub把输出的内容整个复制然后去代码托管平台比如 Gitee、GitLab 或者 GitHub的个人设置里找到 SSH 公钥管理入口新建一个 key粘贴进去保存。之后测试一下连接ssh -T gitgitee.com看到欢迎提示就说明配好了。这里很多新手会出问题就是明明公钥贴对了还是提示验证失败。大概率原因是第一次连接时是否信任该主机没有确认有个交互提示输入 yes很多人没注意到就卡在那。多试一次看到确认提示敲 yes 回车就行。这些配置完成后环境才算真正可用。2. 基础工作流一条代码从写出来到合进主干中间到底发生了什么Git 的基本工作流可以用一句非常生活化的话概括在本地仓库里改文件然后给改动拍快照最后把快照推到云端。很多人学了几个月 Git会用 pull 和 push但对中间环节的理解一直模糊导致出了问题完全没法排查。2.1 克隆仓库和创建分支别在主干上直接动刀拿到一个项目后第一步是把它拉到本地git clone gitgitee.com:yourname/yourproject.git也可以带协议换 HTTPS但前面说了推荐 SSH。clone 完成之后你一定不想直接在默认分支上改东西尤其多人协作时主干分支往往有保护机制直接推上去大概率被拒。正确做法是先建自己的分支git checkout -b feature/user-login这条命令等于git branch feature/user-login加git checkout feature/user-login创建并切换一步搞定。分支名建议语义化一眼能看出你要做什么比如手机号登录、修复首页白屏这类不要瞎起个test或者aaa不然过两周你自己都看不懂。2.2 从工作区到暂存区git add 到底是干什么的很多人对git add的理解就是提交之前先执行一下其实它的本质是把文件从工作区放入暂存区。打个最简单的比方工作区是你办公桌上的草稿暂存区是你的待办收纳盒只有放进收纳盒的东西最后才可能被正式归档。日常工作流一般是# 查看当前文件状态 git status # 添加单个文件 git add src/App.js # 添加所有改动文件谨慎使用 git add .git add .很省事但也很危险容易把不该提交的文件也加进去比如临时生成的日志、本地的配置文件、IDE 目录。所以项目里一定得有.gitignore文件把.idea/、node_modules/、*.log这类东西排除掉。实操中我的习惯是先git status看清楚有哪些改动然后逐个 add或者用git add加指定路径尽量避免无脑全部提交。2.3 commit 是在创造项目历史节点add 完之后就要 commit 了。这是给当前暂存区的改动创建一个历史节点。基本命令就一行git commit -m feat: 新增用户登录功能很多人觉得 commit 就是留个记录随便写个更新或者修改就完事。但我得说提交信息是你留给未来同事和未来自己的阅读笔记价值很大。看一眼历史时如果全是update、fix、改bug那你根本不知道哪个提交对应哪个功能。好的提交信息格式大概是提交类型 范围 简述。比如feat(user-login): 完成手机验证码登录接口或者fix(cart): 修复购物车金额精度丢失问题。这套规范属于经验层面不一定有硬性工具约束但对协作效率的提升非常明显。git commit 有个很重要的逻辑要先理解commit 提交的是暂存区的内容不是工作区所有改动。假如你改了三个文件只 add 了两个就 commit那第三个文件不会出现在这次提交里。查漏补缺之前可以通过git status看剩余改动。2.4 push 和 pull一个是寄出去一个是收回来本地 commit 提交完了代码还在本地得推送远端这样别人才看得到你的分支git push origin feature/user-login如果分支第一次推送会提示你设置上游分支。按它提示的敲就行或者直接用git push -u origin feature/user-login-u的作用是把你本地分支和远端分支关联起来之后在同一分支上直接敲git push就能推送不用再指定远端。收代码则用 pullgit pull origin devgit pull 的本质是 fetch 加 merge。fetch 会把远端的新提交下载到本地merge 则将这些提交合并到当前分支。所以有时候网络没问题但 pull 失败往往是 merge 的时候发现了冲突。这个后面专门说。如果把这套流程走完基本的一条代码流转闭环就完成了。但协作项目中往往没那么顺利中间会遇到分支合并、冲突处理、提交信息写错之类的情况这就是下一部分要解决的问题。3. 分支合并与冲突协作开发绕不开的核心环节多人协作用一个仓库时分支合并是每天都要做的事情。你开发完功能要把分支合回主干别人往主干推了新东西你也要把自己的分支更新到最新这个过程必然大量涉及 merge 和 rebase。3.1 merge 和 rebase什么时候用哪个合并分支最常见的方式是 merge# 先把要合入的分支代码拉到本地 git checkout dev git pull origin dev # 切回功能分支把 dev 合并进来 git checkout feature/user-login git merge devmerge 的特点是会生成一个额外的合并提交保存了两条分支的历史轨迹。好处是保留了完整的真实开发记录适合主力分支合入功能分支时用。缺点就是历史里会有很多分叉节点看起来比较乱。如果不想让历史那么多分叉可以改用 rebasegit checkout feature/user-login git rebase devrebase 的理念是把当前分支的基础移动到目标分支最新提交之上让提交历史呈现一条干净的直线。但它有个前提就是你正在 rebase 的分支还没推送到远端或者只有你一个人在维护。如果你已经把分支推到远端别人也拉了这时候 rebase 就会改写远端已有提交的哈希导致别人本地和远端对不上。我个人的习惯是本地分支整理和更新用 rebase 多一点最终并入主干用 merge。这个属于团队风格和倾向的问题没有绝对的对错但原理一定要理解清楚。3.2 冲突到底是怎么产生的又如何解决冲突产生的原因很简单两个分支改了同一个文件的同一片区域Git 无法自动判断谁是对的只能让人类来裁决。比如你在功能分支里把某一行从a 1改成了a 2同时 dev 分支上另一个人也把这一行改成了a 3合并时就必然冲突。遇到冲突时 Git 会给出提示一般会说CONFLICT (content): Merge conflict in src/App.js。同时被冲突的文件里会出现标记 HEAD a 2 a 3 dev上面部分是当前分支的内容下面部分是合并过来的目标分支内容。你要做的就是打开文件把两个版本整合成最终想要的样子然后删掉这些标记。整合完保存接着执行git add src/App.js git commit这里有个很重要的细节merge 时如果冲突解决完不需要再 commitGit 会自动生成合并提交。但如果中间乱了想放弃这次合并回到之前状态可以用git merge --abort我遇到过不少新手被冲突标记吓退本来合并完成后一套操作就行结果直接在编辑器里乱改把代码结构改坏了。记住冲突不可怕它只是 Git 在确认到底以哪方为准解决完用 add 和 commit 收尾即可。只要别在解决冲突时顺手改一堆无关内容就好一次合并只处理合并相关的问题无关功能改动混进来会让 review 的人非常头疼。3.3 合并之后如何验证代码没有引入问题分支合并完成不代表万事大吉最怕的就是改完冲突后代码整体跑不起来了。所以我每次合并之后都会做几件事先跑一遍编译或构建再跑一遍测试用例最后再本地启动一下看主要功能是否正常。这一步虽然不是 Git 命令本身的内容但它是完整工作流的一部分不做的话你推上去一个坏合并整个团队都会受影响。如果有基础检查工具比如 lint、typecheck合并后顺便跑一下能拦截掉大量低级错误。代码形式上保证不了业务正确但至少能保证层面正确。4. 救急与疑难杂症那些一不小心就会踩进去的坑Git 用久了你就会发现翻来覆去就是那么几个问题。我把这些年实操中踩过和见别人踩过的典型问题集中梳理出来基本能覆盖绝大多数人的需求。4.1 提交信息写错了或者少提交了一个文件怎么办有时候提交完才发现信息写错了或者突然想起还有一个文件没 add 进去。有现成的补救工具# 修改最近一次提交的信息 git commit --amend -m 修正后的提交信息 # 把漏掉的文件补进上一次提交且不改变提交信息 git add 漏掉的文件 git commit --amend --no-edit--amend会将当前提交替换掉上一个提交。注意如果你已经push到远端并且这个分支是多人协作的amend改写历史会造成远端同步问题。遇到这种情况要么别 amend新增一个 commit 说明修复要么确认只有你自己在维护这个分支amend 后再git push --force。但这属于有点危险的操作团队里最好先沟通别冷不丁强推一下把别人的记录冲掉。4.2 推错分支或者提交太大想撤销怎么办撤销是 Git 里面最容易搞混的点因为不同场景有不同的命令。如果你想撤销还没有 push 上去的本地 commit可以这样git reset --soft HEAD~1这条命令会把 commit 撤销但保留改动内容到暂存区相当于提交白做了改动还在。极其适合提交信息写错或想把一个大的提交拆成几个小的提交这类场景。如果你不仅想撤销提交连改动内容都想不要用--hardgit reset --hard HEAD~1这一步会彻底丢弃改动执行前一定要确认自己不需要这些文件了否则找不回来。但如果提交已经 push 到远端就不能用 reset 了否则本地和远端不一致下次 push 会被拒。此时用 revert 更安全git revert HEADrevert 的本质是新增一个反向提交把这个提交带来的修改撤销掉历史记录保持完整。多人协作时revert 永远比 reset 稳妥。4.3 SSH 认证失败是一个绕不过去的坎ssh 认证失败是 Git 使用中最常见、也是最容易卡住新人的问题。典型的报错就是Permission denied (publickey)。排查思路按顺序来第一步确认密钥存在执行ls ~/.ssh/看有没有id_rsa和id_rsa.pub两个文件。如果连目录都没有按前面讲过的方式重新生成密钥。第二步确认公钥是否成功添加到远程平台账户。很多平台不叫公钥管理叫SSH keys或者部署公钥路径一般在设置里面的安全相关菜单里。复制公钥内容时注意别多复制了空格。第三步确认你测试的 ssh 地址是哪家的。举个最简单的例子如果你用的是 Gitee 平台测试命令应该是ssh -T gitgitee.com如果你敲的是gitgithub.com它当然不认你的公钥。还有一种常见情况你配置了多个 SSH key 或者 config 文件里写了多条规则导致连接时用了错误的那把钥匙。可以临时用命令指定ssh -i ~/.ssh/id_rsa -T gitgitee.com用它来验证某一个特定密钥是否有效比在配置里翻来覆去改半天快得多。基本上按照这套流程走下来九成以上 ssh 认证问题都能定位到根因。4.4 遇到大文件普通 Git 撑不住LFS 来兜底项目中如果有资源包、模型文件、二进制文件等大文件直接往 Git 里提交会导致仓库体积膨胀clone 越来越慢push 也会越来越卡。现在的通用做法是配合 Git LFSLarge File Storage使用。基本使用流程是git lfs install git lfs track *.psd *.zip *.onnx git add .gitattributes执行之后指定扩展名的文件会被 LFS 接管实际的大文件内容存储到 LFS 服务器上仓库里只保留轻量指针。之后 commit 和 push 的操作和平时完全一样不需要改变日常习惯。常见的坑有两个。一个是忘了 install直接 track 会报错另一个是 LFS 拉取卡住尤其文件比较大的时候看起来像是没响应其实在后台下载。这种情况可以先确认网络状态再决定是否重试。另外在 clone 含 LFS 文件的仓库时如果网络不好可能卡住可以先普通 clone再在仓库里执行git lfs pull单独拉取 LFS 内容这样能把普通文件和 LFS 文件分步处理体验会好一些。4.5 一个仓库想同时维护多个工作目录git worktree 来帮忙很多人不知道 Git 有 worktree 这个功能。它的作用是一个仓库可以同时检出多个工作目录每个目录对应不同的分支适合你同时要改两个分支、又不想频繁切换的场景。举个实际例子我在一个项目里要改功能 A同时突然有个紧急的小需求要修在旧分支上。普通做法是git stash切分支改完再切回来但这样工作区变动容易出问题。用 worktree 可以这样git worktree add ../project-hotfix hotfix/urgent-fix这条命令会在指定路径新创建一个工作目录里面的代码是hotfix/urgent-fix分支的内容。你在原来目录继续开发功能 A在新目录改紧急修复两边互不干扰。等修复完在新目录正常 commit 和 push然后删掉这个 worktreegit worktree remove ../project-hotfix这个功能在有两三个分支并行需求时特别顺手实测下来比反复 stash、checkout 心情舒畅得多。4.6 源码暴露在公网Git 目录泄露这种问题怎么处理这个场景可能偏安全一些但也遇到过不少次。如果你把一个项目的.git目录通过某种方式暴露到了 Web 服务器上比如部署时把整个项目目录直接拷到了站点根目录攻击者就可以通过访问/.git/路径下载仓库里的源代码最终造成源码泄露。判断是否存在这种问题可以尝试访问类似域名/.git/config这样的 URL。如果能看到内容那就说明.git目录确实暴露在公网。修复方式其实不算复杂第一部署时的发布目录里不要包含.git文件夹用构建产物目录作为站点根目录第二配置 Web 服务器的访问规则将.git目录的请求直接拒绝第三如果已经泄露建议检查仓库历史里存放过的敏感信息比如密码、密钥、内部 API 地址等该换的换该撤销的撤销。这个问题有时候被当成 Git 使用教程里的边角料但实际运维中一旦发生影响范围可能相当大值得平时留意。Git 在本质上是一个内容寻址文件系统.git里存的就是完整的版本历史任何人拿到它就等于拥有了你整个项目的所有提交记录所以部署时一定要把它隔绝在发布目录之外。5. 把命令和习惯融进日常我的一些实际体会Git 这东西命令量大但真正高频用到的基础工作流就那十几条。完全没必要死记硬背把核心逻辑想清楚用的时候查一下次数多了自然就记牢了。我个人习惯在电脑上设置一个全局别名让常用命令短一些git config --global alias.st status git config --global alias.co checkout git config --global alias.br branch git config --global alias.cm commit git config --global alias.lg log --oneline --graph --all -10配置完之后git st看状态、git co切分支、git cm提交确实能省不少打字量操作也更顺手。尤其是git lg配合--graph看分支形状一眼就能看出提交历史是线性的还是有分叉的。还有一个细节是.gitignore一定要养成随项目初始化的习惯。很多新项目 clone 下来后第一件事就是看到一堆系统文件被列在 untracked 列表里非常影响判断。写一个覆盖常见开发工具的.gitignore模板一开始就提交进仓库后面会省掉大量的额外工作量。平时还要注意别把本地配置类文件比如带密码的.env、本地路径的配置文件传上去这种问题一旦 push 出去就算后面删掉历史记录里还是会留着收回成本极高。另外提交的频率也值得说一下。写代码按逻辑拆分成小步提交每完成一个独立的小功能就 commit 一次而不是攒了三天的改动一次性提交。小提交的好处是出问题之后能精确到具体的某一步定位和回滚都更轻松。比如你改了 A、B、C 三个功能结果 C 出了 bug如果三个改动在一个提交里排查起来就需要人工分辨如果分开提交直接 revert C 那一条就行。团队协作还有一个不太起眼但非常重要的点pull 之前先看一眼自己的改动区域养成git status的习惯。有时候你本地改了一堆东西远端也更新了一堆直接 pull 有概率产生大量冲突。先看清自己改了什么再决定是 commit 之后再 pull还是先 stash 暂存再更新这样处理冲突会从容得多。最后再多聊一个不算命令的操作习惯提交之前先用git diff看一遍改动内容。我见过太多人提交时把调试代码、console.log、临时注释一起带上去了。提交前扫一眼 diff 是个非常便宜但收益极高的好习惯它能把很多低级问题挡在提交门外。Git 这套基础工作流本质上就是一套反复循环的机制拉代码、建分支、改文件、add、commit、push、合并、解决冲突、再拉代码。你把它跑顺了理解每一次操作背后到底动了什么后面再碰到什么报错都不会慌因为所有的问题本质上都是这套机制某个环节出现了预期外的情况。平时多留一份.git的敬畏心多理解一点底层逻辑工具就只是工具不会反过来成为你的负担。