Git 操作完全指南:从增量下载到团队协作
写代码基本绕不开 Git。但它真不只是「备份代码」这么件事——往深了说,它管的是你怎么记录每一次改动、怎么把改坏的救回来、怎么跟别人对着同一套代码一起干活。
这篇我从最常用的日常操作讲起,再说说别人改了代码、你只想拉那点增量该怎么办(顺便聊聊第一次克隆超大仓库的坑),最后是团队里怎么合代码、怎么救回误删的东西。都是能直接照抄的命令,平时当手册翻也顺手。
一、先搞懂 Git 的三个区和一个链
很多人被 Git 绕晕,是因为分不清「文件到底在哪」。记住三个区域就清晰了:
1 | 工作区(你正在编辑的文件) |
- 工作区:你电脑上真实能看到的文件。改完不会自动进 Git。
- 暂存区:
git add把「要提交哪些改动」先放进待办清单。 - 本地仓库:
git commit把暂存区的清单正式记成一条历史记录(commit)。 - 远程仓库:
git push把本地的提交同步到服务器,git pull/git fetch把别人推的拉回来。
核心的一个链:每个 commit 都指向前一个 commit,head 指向最新那条。所有分支、合并、回退,本质都是「移动这个链上的指针」,而不是复制文件——这也是 Git 快、省空间的原因。
二、第一次上手
装好 Git 后(Windows 装 Git for Windows,Linux apt install git),先设置身份,否则提交没署名:
1 | git config --global user.name "你的名字" |
把一个目录变成仓库 + 第一次提交:
1 | cd 你的项目目录 |
git init之后目录里会多一个隐藏的.git文件夹——所有版本历史都存在这。想彻底删掉 Git 记录,删掉这个文件夹即可。
三、日常基本操作
这几个命令占了日常 90% 的使用:
1 | git status # 看现在哪些文件改了、哪些在暂存区(最常用的一个) |
git status 会把文件分成三组给你看:
- Changes not staged:改了但没
add - Changes to be committed:已
add等commit - Untracked files:新增的、从没进过 Git 的文件
四、分支:Git 最核心的能力
分支的本质:一个可以移动的指针,指向某条 commit。main(或 master)是默认分支,你新建分支就是「另起一条平行线」,互不干扰。
1 | git branch # 看所有分支,* 是当前所在 |
合并怎么发生:分两种情况——
- Fast-forward(快进):当前分支没新提交,直接让指针往前移动到头,历史是一条直线,干干净净。
- 三方合并:两边各自有提交,Git 把两个分支的改动「嫁接」出一个新的合并提交。如果两边改了同一文件的同一行,就有冲突,需要你手动定夺(见第六节)。
日常推荐流程:在 dev 上干活,git switch -c feature-xxx 开个功能分支,做完 git switch dev && git merge feature-xxx。
五、远程与协作:clone / fetch / pull / push
1 | git clone <仓库地址> # 第一次把远程仓库整个下载到本地 |
fetch 和 pull 的区别:
git fetch:把远程的新提交下载到本地,但不碰你正在改的代码。你想先看看、再决定怎么合,用这个。git pull:下载 + 直接合并到当前分支。图省事用这个,但可能立刻产生冲突。
多人共用同一个分支时,改动前先 git pull 拿到最新,改完再 git push,push 被拒(别人比你高)就先 pull 再 push。
六、冲突怎么解决
git merge 或 git pull 时说 CONFLICT (content),就是两边改了同一处。Git 会在文件里标记:
1 | <<<<<<< HEAD |
解决办法只有一步:手动改这个文件,留下想要的内容,删掉 <<<<<<<、=======、>>>>>>> 这几行标记,然后:
1 | git add 那个文件 # 标记为已解决 |
越早把改动分开到独立分支、越频繁同步,冲突越少、越好解。
七、撤销与回退:救回误操作
这是新手最慌、也最该掌握的部分。分清「想撤销哪种改动」。
① 文件改了还没 add,想丢弃:
1 | git restore <文件> # 回到上一次提交的状态(新命令) |
② 已经 add 了,想移出暂存区(不想提交了):
1 | git restore --staged <文件> |
③ 已经 commit 了,想撤销这次提交但保留改动:
1 | git reset --soft HEAD~1 # 撤销最近1次提交,改动留在暂存区 |
④ 提交错了想彻底抹掉(此后的历史重写):
1 | git reset --hard HEAD~1 # 撤销最近1次提交,改动也没了(慎用!) |
⑤ 已经 push 到远程了,想回退——reset 会强制改历史、影响别人,别用。用 revert:新增一个反向提交把那次改动抵消掉:
1 | git revert <commit的hash> |
⑥ 临时藏起手上做了一半的改动:
1 | git stash # 把未提交的改动暂存起来,工作区清空 |
⚠️ 一条救命常识:
git reflog能看到你最近所有「指针移动」的记录,即使reset --hard删掉的分支/提交,也能从 reflog 里找回。几乎所有「误删」都能用git reflog+git reset --hard <hash>救回来,别慌。
八、增量与部分克隆:别人改了代码,我只拿改过的部分
这是很多人问的「能不能只下载别人改的部分」。答案是:Git 本身就是增量传输的,而且是自动的。
8.1 有本地仓库时:pull 天然只下增量
你 git clone 过一次后,本地有一个完整对象库。之后别人改了并 push,你再 git pull / git fetch,Git 只传输你本地缺的那几个 commit 和文件对象,绝不会重新下载整个仓库。所以:
只要你已经 clone 过,
git pull就自动只拿别人改过的部分,不用任何特殊配置。
Git 的传输是按「对象」打包的,缺什么传什么,跟「全量/增量」无关——它天生就是增量的。
8.2 第一次克隆超大仓库:用参数少下载点
真正的痛点是不想「第一次就全量 clone」一个几个 GB 的 monorepo。三个参数按需省流量:
| 参数 | 作用 | 代价 |
|---|---|---|
--depth 1 |
只下载最新一次提交的快照 | 没有历史,git log 只剩一条 |
--filter=blob:none |
下载全部提交和目录结构,但文件内容按需下载 | 用到哪个文件才下哪个,历史完整 |
--sparse |
只检出指定目录 | 仓库其余部分不进本地 |
最省组合(只要最新代码 + 只挑某个目录):
1 | git clone --depth 1 --filter=blob:none --sparse <仓库地址> |
注意:--filter(partial clone)和稀疏检出需要服务器支持才行(GitHub / GitLab 都支持)。如果你用的是本地镜像代理(比如某些加速镜像),很可能不支持 filter,那部分参数会失效甚至报错——这种情况退回到 --depth 1(纯客户端行为,服务器无要求,一定有效)。
8.3 只想看别人改了哪些文件(不想下载)
1 | git fetch # 拉远程提交,但不合并 |
想精确看某个文件改了什么,再针对性查看,按需取用。
九、忽略不想进 Git 的东西:.gitignore
有些文件不该进版本库(依赖、密钥、本地配置、构建产物)。在项目根目录建一个 .gitignore:
1 | node_modules/ |
这样 git add . 会自动跳过这些,不会误提交大文件或密钥。⚠️ 密钥千万别传——一旦推到公开仓库就等于泄露,历史里也删不干净。
十、团队协作的标准流程(分支 + PR)
现在协作基本都走「功能分支 + Pull Request」:
1 | # 1. 同步最新 |
- 别人 review 后合并,分支可删。
- 你的分支落后于 dev?在分支上
git merge dev或git rebase dev同步。 - rebase vs merge:merge 保留众人历史(会有合并分叉),rebase 把分支「垫」到 dev 顶端(历史更线性),各有取舍。团队有约定就按约定来。
十一、速查表
| 需求 | 命令 |
|---|---|
| 看状态 | git status |
| 暂存改动 | git add . |
| 提交 | git commit -m "..." |
| 看历史 | git log --oneline |
| 开分支并切换 | git switch -c 分支名 |
| 合并分支 | git merge 分支名 |
| 拉 + 合并 | git pull |
| 只拉不合并 | git fetch |
| 推送 | git push |
| 丢弃工作区改动 | git restore <文件> |
| 撤销最近提交(留改动) | git reset --soft HEAD~1 |
| 撤销并抹掉最近提交 | git reset --hard HEAD~1(慎用) |
| 远程回退(补反向提交) | git revert <hash> |
| 暂存手头改动 | git stash |
| 找回误删 | git reflog |
| 只看改了哪些文件 | git diff --stat HEAD..origin/分支 |
结语
Git 的核心不是你记多少命令,而是理解那个 「工作区 → 暂存区 → 提交 → 远程」的链和 「分支就是可移动指针」。懂了这两点,其余命令都是围绕它们转的便捷工具。
日常用熟:status、add、commit、log、switch、merge、pull、push 这八个就够绝大多数场景;reset、revert、stash、reflog 是用来救命的,记住它们的存在,关键时刻不慌。
