Git 这东西,很多人第一次接触是在被代码搞崩之后。改了几天的功能,手一滑删错了文件,Ctrl+Z 救不回来,那种绝望感估计每个开发者都体会过。Git 就是来解决这个问题的——它把你的每一次修改都记录下来,随时可以回到任意一个历史节点。这篇速查表是我从入门到熟练这几年一直在用的操作清单,整理成比较系统的一版,适合两类人:刚接触 Git 的新手,以及用了一阵子但总记不住命令、每次都要现查的老手。配合真实的命令输出和踩坑记录,主打一个能直接照着敲。
1. 开篇:先搞懂 Git 到底在解决什么问题
1.1 版本管理的核心痛点
早期做项目,最常见的"版本管理"就是手动复制文件夹:项目_最终版、项目_最终版2、项目_真最终版、项目_打死也不改了。这种做法的致命问题有三个:一是文件夹一多就分不清哪个才是最新的;二是协同合作时两个人同时改同一份代码,合并起来极其痛苦;三是没有记录,改坏了想找回三天前的版本,只能靠运气。
Git 的出现把这三件事变成了常态操作。它本质上是一个分布式版本控制系统,每次提交都会对整个项目做一个快照,并记录"谁在什么时间改了什么内容"。由于每个开发者本地都有一份完整的仓库,即使没有网络也能正常提交、查历史、回退,这在飞机上、断网时都能干活,是集中式系统做不到的。
还有一个很多人忽略的点:Git 不只是一个备份工具,它是一套协作协议。分支、合并、代码评审这些流程,都是建立在 Git 的对象模型上的。所以学 Git 不能只背命令,要理解它的三个核心区域:工作区(你正在编辑的文件)、暂存区(已标记要提交的内容)、版本库(已提交的历史记录)。后续所有的操作,本质上都是在这三个区域之间搬运内容。
1.2 一张速查表应该怎么用
我的建议是不要试图一次记完所有命令。Git 的命令有几百个,日常真正高频使用的不到二十个。把这张表当成"字典"来用:遇到问题先查对应场景,找到命令后理解它干了什么,再动手执行。用熟了之后,这些命令自然会变成肌肉记忆。
另外提醒一句,网上很多教程把 Git 命令讲得特别玄乎,其实没必要。Git 的设计哲学是"操作不可怕,可怕的是你不知道操作之后会发生什么"。所以我在下面每个部分都会解释命令的执行结果,而不是单纯丢命令。
2. 环境准备:装好工具,配好身份
2.1 安装与命令行环境
不同系统的安装方式差异不小,这里只给最直接的路径:
- Linux(Debian/Ubuntu 系):
sudo apt install git - macOS:
brew install git,或者直接装 Xcode Command Line Tools 也会附带 Git - Windows:去官网下载安装包,一路 Next 就行
装完之后在终端里跑git --version,能输出版本号就说明成功了。我个人强烈建议用命令行而非图形工具,原因很简单:图形工具把操作"包装"掉了,遇到问题你根本不知道它底层执行了什么,排查起来两眼一抹黑。命令行虽然初看枯燥,但输出信息非常明确,学一遍之后收益是长期的。
注意:Windows 上建议直接使用 Git Bash,它模拟了类 Unix 环境,命令行为表现更接近主流场景,避免很多路径和脚本兼容性的坑。
2.2 用户信息与基础配置
安装完第一件事,配置你的"身份"。这一步很多人偷懒跳过,结果提交记录里全是unknown,协作时根本不知道谁改的。
git config --global user.name "你的名字" git config --global user.email "你的邮箱"用git config --global --list可以查看所有全局配置。除了身份信息,还有几个配置我在实际工作中调过,建议一并处理:
# 终端输出彩色显示,看起来舒服很多 git config --global color.ui true # Windows 上处理换行符,防止 CRLF/LF 引发的大规模 diff git config --global core.autocrlf true # 设置默认编辑器为 vim,避免 commit 时卡在 nano 里不会退出 git config --global core.editor "vim"为什么换行符配置重要?Windows 的文件默认以 CRLF 结尾,Linux/macOS 用 LF,Git 如果不做转换,你会看到整个文件都被标记为"修改",而实际上只是换行符变了。core.autocrlf true的含义是:提交到仓库时自动转换为 LF,检出到工作区时转换为 CRLF,这样团队跨平台协作就不会互相污染 diff。
关于换行符配置,我这里多说一句。如果你的团队里大概率只有 Windows 机器,那true就好;如果团队混用系统,我更推荐input,它只在提交时转 LF,检出时不转,保持仓库干净,各平台各用各的。这个配置属于团队级约定,最好写进仓库的.gitattributes里,一劳永逸。
3. 日常操作:从建仓库到第一次提交
3.1 初始化仓库与文件状态
进入项目目录,执行:
git init这时目录里会出现一个隐藏的.git文件夹,它就是 Git 的"数据库",所有版本信息都存在里面。注意,正常情况下你不需要动这个文件夹,也不要把它复制给别人,否则会产生一堆诡异的问题。
然后写一个.gitignore文件,告诉 Git 哪些东西不需要纳入版本管理:依赖目录、编译产物、临时文件、IDE 配置等。这个文件建议在项目一开始就配好,否则后面才发现node_modules被提交了,清理起来相当折腾。简单示例:
node_modules/ dist/ *.log .DS_Store .idea/接下来用git status是检查仓库状态最重要的命令,没有之一。它会告诉你当前处在哪个分支、哪些文件被改过、哪些是新文件没被跟踪。新手最常见的错误就是不看 status 直接 commit,结果把不想提交的文件也提交进去了。
3.2 add、commit、status、log 的正确用法
一次完整的最小提交流程是:
git add README.md # 把文件加入暂存区 git commit -m "添加项目说明文档" # 暂存区内容生成一次提交git add只做一件事:把工作区的改动放入暂存区。它不会保存历史,只相当于"打包待发"的状态。如果一次改了十几个文件,但希望分成两个逻辑提交(比如修复 bug 一个、加功能一个),就可以先git add相关的几个文件,提交,再git add另外几个,再提交,这就是"小步提交"的基本功。
git commit的-m参数直接跟提交信息。提交信息是给人看的,也是给未来的自己看的。我见过太多提交信息写成fix、update、111,过了三个月他自己也看不懂。推荐格式是"动词 + 做了什么",比如修复登录页在移动端无法滚动的问题。
提交之后就是查看历史:
git log --oneline --graph --all--oneline让每条记录只显示一行,--graph用字符画出分支走向,--all显示所有分支。这个组合是我使用频率最高的查看方式,一眼就能看清整个仓库的分叉和合并脉络。
还有两个 diff 命令要掌握:
git diff # 工作区 vs 暂存区的差异 git diff --staged # 暂存区 vs 上次提交的差异记住这个对应关系:git diff看的是"还没 add 的改动",git diff --staged看的是"已经 add 但还没 commit 的改动"。很多新人在这两个命令上栽跟头,核心原因就是对暂存区的概念模糊。
实操心得:每次 commit 之前,一定要先
git diff --staged看一眼即将提交的内容,确认没有误加文件、没有调试代码。这一步花不了十秒,但能避免大量"提交了不该提交的东西"的尴尬。
4. 分支操作:别在主分支上裸奔
4.1 创建、切换、删除分支
分支是 Git 最强大的特性,也是新手最容易绕晕的地方。可以这样理解:分支就是"从某个提交点拉出来的一条平行时间线",你在分支上改代码,不影响主线的其他人。
基础命令:
git branch # 查看本地分支列表,带 * 的是当前分支 git branch feature-login # 创建新分支 git switch feature-login # 切换到该分支(传统写法是 git checkout feature-login) git switch -c hotfix-001 # 创建并切换,一行搞定新版 Git 推荐用git switch和git restore来替代checkout的多重职责,语义更清晰:switch只管切换分支,restore只管恢复文件。旧版命令不是不能用,只是它一个命令干了好几件事,新人容易迷惑。
删除分支:
git branch -d feature-login # 安全删除,未合并的分支会拒绝删除 git branch -D feature-login # 强制删除,危险但有时需要实际项目里,功能分支开发完合并回主分支后,本地分支就可以删掉,保持仓库整洁。但注意:删除本地分支不会影响远程分支,远程的还要单独git push origin --delete。
4.2 合并分支的两种方式
分支开发完了,要汇入主线。合并方式主要有两种:merge和rebase。
git switch main git merge feature-loginmerge会生成一个"合并提交",保留两条分支的历史轨迹,图的走向是分叉再交汇。优点是历史完整、操作无脑,缺点是当开发频率高时,历史图会变得像一团毛线球。
rebase则不同:
git switch feature-login git rebase main它的逻辑是:把 feature 分支上相对于 main 的全部提交"剪下来",重新接到 main 的最新提交后面。结果是一条直线,历史非常清爽。但代价是提交的哈希值全部变了,所以绝不要对已经推送到远程且别人在用的分支做 rebase,否则会把协作伙伴搞崩溃。
选择建议:个人开发或短期功能分支,用 rebase 保持线性;多人长期共用的分支,用 merge 保证安全。没有绝对正确,团队约定一致就行。
合并时最不愿意看到的就是冲突(conflict)。当两个人改了同一文件的同一行,Git 会停下来,把冲突区域标记成:
<<<<<<< HEAD 你的内容 ======= 对方的内容 >>>>>>> feature-login处理方式是直接打开文件,手动修改成最终想要的代码,删掉这些标记符号,然后git add该文件,再git commit完成合并。
遇到冲突别慌,这是正常现象。关键是先看清楚冲突内容再动手改,不要直接挑一边删另一边。如果拿不准,优先和改这部分代码的同事沟通,别自己拍脑袋。
5. 远程仓库:把代码存到远端
5.1 关联远程仓库与推送
本地仓库建好了,把代码推到远程托管平台(比如常见的代码托管服务)上。在托管平台创建一个空仓库后,本地执行:
git remote add origin https://xxx/你的项目.git git push -u origin mainremote add origin的意思是给远程仓库起个名字叫origin,这是约定俗成的默认名。-u参数把本地 main 分支和远程 main 分支的关联关系记下来,之后直接敲git push就能推送,不用每次写全。
第一次向远端推送时可能要输入账号密码。建议用 SSH 方式而不是 HTTPS,配置一次公钥之后就不用每次输入凭证了。做法是:生成本机密钥对,把公钥配置到托管平台账号里,然后 remote 地址用git@xxx:你的项目.git这种格式。
查看远程仓库配置:
git remote -v这个命令列出当前关联的所有远端地址,排查"推错仓库"问题时非常有用。
5.2 拉取更新的两种姿势
团队成员推了新代码,你要同步下来。最常用的是:
git pullgit pull其实是两步的合体:先git fetch把远端的最新内容下载到本地(不动你的工作区),再执行一次合并把远端内容汇入当前分支。明白这一点很重要,因为git pull有可能触发合并冲突。
如果你希望拉取时用 rebase 而不是 merge,可以这样:
git pull --rebase区别和上一节讲的 merge/rebase 完全一致:--rebase会让你的提交依次接到远端最新提交后面,历史更线性。我个人的习惯是团队协作分支上,本地提交没推送时,拉取一律用 rebase,避免产生毫无意义的"merge remote-tracking branch"提交。
还有一个容易踩的坑:远端有更新但你本地也有未提交的修改,这时候git pull可能被拒绝。解决办法是先把本地改动git stash暂存起来,pull 之后再git stash pop恢复。
推送被拒绝的场景也非常常见。原因通常是远端有本地没有的提交,最安全的解法就是:
git pull --rebase git push先用 rebase 把你的提交放到最新代码之上,再推送,一气呵成。不要傻乎乎地去git push --force,强推会把远端提交冲掉,在共用分支上是事故级操作。
6. 撤销与回退:给自己留后悔药
6.1 从容的后悔:还没提交的修改
Git 最让人安心的就是撤销操作。先记住一个前提:不同阶段的撤销,命令完全不同,用错了不但撤销不了,还可能把改动真的丢掉。
情况一:工作区改了文件,但还没 add。想撤销这次修改回到上次提交的状态:
git restore 文件名 # 或者老写法:git checkout -- 文件名这个操作会用版本库里的内容覆盖工作区文件,未提交的改动会永久丢失,执行前想清楚。
情况二:已经 add 了,想从暂存区撤回来:
git restore --staged 文件名 # 或者:git reset HEAD 文件名这个命令只是把文件从暂存区移出来,工作区内容不变,安全。它对应的是"啊我 add 错文件了"的场景。
情况三:想同时撤销暂存和工作区:
git reset --hard HEAD--hard会把工作区、暂存区全部恢复到 HEAD(当前提交点)状态,所有未提交的修改全部丢失。这个命令我使用频率极低,因为风险太大。
6.2 提交错了怎么办
如果已经 commit 了,发现提交信息写错了,或者忘了包含某个文件:
git commit --amend -m "新的提交信息"--amend会修改最近一次提交,包括提交信息、包含的文件列表。它不会新增一条提交记录,而是把原来那条替换掉。注意:这个操作会改写提交哈希,所以只适合尚未推送的提交。
如果需要回退到更早的提交,有三个档位:
git reset --soft 提交哈希 # 只移动 HEAD,暂存区和工作区保留 git reset --mixed 提交哈希 # 移动 HEAD,清空暂存区,工作区保留(默认) git reset --hard 提交哈希 # 全部恢复,工作区也回退,危险怎么选?想"撤销 commit 但保留改动重来",用--soft;想"撤销 add 和 commit,保留文件内容",用--mixed;想"彻底回到过去,文件也变成那个版本",用--hard。
但这里有个大原则:已经推送到远端的分支,不要用 reset 回退。因为 reset 会改变历史,你强推上去会让别人的本地仓库和历史脱节。正确做法是用revert:
git revert 提交哈希revert会生成一条新提交,把目标提交的改动反向应用回去。历史仍然完整,只是多了一条"撤销"记录,所有人都能安全同步。
还有一个救命命令:git reflog。它记录的是本地所有 HEAD 移动的痕迹,包括被 reset 掉的提交。一旦发现--hard回退过头了,可以:
git reflog # 找到回退前的哈希 git reset --hard 那个哈希只要操作过的历史还在 reflog 里,就有机会找回。这是最后一道安全网,但注意 reflog 记录有有效期(默认约 90 天),过期就真的没了。
7. 提升效率的进阶命令
7.1 stash:临时保存现场
写代码写到一半,接到一个紧急需求要切分支处理。直接切分支会提示"本地有未提交的修改,无法切换",这时候就是git stash的用武之地:
git stash # 保存工作区当前状态,工作区变干净 git switch 其他分支 # 放心切换 # 处理完紧急需求后 git switch 原分支 git stash pop # 恢复暂存的改动git stash list可以查看所有暂存记录,git stash apply不删除记录地恢复,git stash drop手动删除某条记录。stash 还可以带信息保存多个现场:
git stash save "登录功能开发到一半"我实际用下来,stash 非常适合"多任务切换"场景。但注意:stash 是本地操作,不会同步到远端,长时间放着有丢失风险,最好当天处理完就pop出来。
7.2 cherry-pick:精准挑选提交
有个分支上只想要其中某一次提交的改动,不想整个合并过来,就用 cherry-pick:
git cherry-pick 提交哈希比如你在测试分支上修了一个 bug,提交哈希是a1b2c3d,主线维护分支也想用这个修复但不想要其他乱七八糟的改动,一条命令就能把这次提交"摘"过来。用法非常场景化,适合临时修复和跨分支同步单个提交。
多个连续提交也可以一次挑选:
git cherry-pick 起始哈希..结束哈希执行过程中如果冲突了,流程和 merge 冲突一样:手动改文件、add、然后git cherry-pick --continue继续。
7.3 别名与小技巧
高频命令手敲确实累,可以在全局配置里加别名:
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"之后输入git st、git lg就能快速执行对应命令。我建议每个人按照自己使用习惯配置一套别名,效率提升非常明显。
再分享一个查看历史命令的技巧。想查某个文件的所有修改历史:
git log --oneline -- 文件名 git log -p -- 文件名 # 连每次改动的 diff 一起看想查某一行代码是谁写的、哪次提交引入的:
git blame 文件名这些命令在排查"这个 bug 是什么时候引入的"时非常有用。
8. 高频问题排查速查表
实际工作里遇到的问题翻来覆去就那么几个,整理成表格方便快速对照。遇到问题先查表,比翻整篇文档有效得多。
| 场景 | 错误示范 | 推荐解法 |
|---|---|---|
| 提交信息写错了 | 重新 commit 一次 | git commit --amend -m "正确信息" |
| 提交后忘了一个文件 | 用--amend或新增提交 | git add 漏掉的文件然后git commit --amend --no-edit |
| 文件误删,还没提交 | 重新手动创建 | git restore 文件名 |
| 不小心 reset 过头了 | 绝望重写 | git reflog找到旧哈希,git reset --hard 旧哈希 |
| 推送被远端拒绝 | 强推--force | git pull --rebase后正常git push |
| 合并冲突不知道怎么处理 | 网上乱搜 | 手动改冲突标记,add 后 commit |
| 不该提交的文件提交了 | 留下痕迹 | git reset --soft HEAD~1,移除文件后重新提交 |
| 分支想删但提示未合并 | 强制删除 | 确认不需要后git branch -D |
| 想放弃所有本地改动 | 逐个删文件 | git reset --hard HEAD(确认后使用) |
| 切分支被未提交修改拦截 | 直接强制切 | git stash保存后切换 |
这几个问题里,我发现最容易出事故的是"推送被拒绝"和"确认不要的本地改动"。前者切忌--force,后者切忌不确认就--hard。多花两秒看 status 和 diff,能省掉几小时恢复时间。
还有一个隐藏很深的坑:文件改名时,Git 有时候会识别成"删了一个旧的、加了一个新的",导致历史关联断裂。处理方法是:
git mv 旧文件名 新文件名用git mv而不是操作系统重命名,Git 就能正确记录重命名行为,保留历史追踪。
9. 写在最后:我的几个实操心得
这张表整理的是我日常使用频率最高的操作,但在真正的工作里,比命令更重要的是一些习惯层面的东西。
第一个心得是提交要小、要频繁。一个功能拆成多个逻辑清晰的提交,每个提交只做一件事,这样回退、排查、代码评审都轻松。别攒一周改动一次性提交,那时候你自己都说不清改了啥。
第二个心得是提交信息是写给未来的人看的。三个月后回来看代码的人——往往是未来的你自己——会感谢你当初多写了几个字。我见过fix bug这种信息,完全无法定位代码意图。好的信息应该像一句话摘要:修复订单金额在小数点两位时四舍五入错误。
第三个心得是别怕 Git,但要敬畏危险命令。--hard、--force、rebase推送这些词,动用之前花十秒钟确认这是不是你想要的。我踩过最狠的坑就是对共享分支用了push --force,看着同事们一脸茫然的表情,那滋味不想来第二次。
这几个心得不是从哪本书上抄来的,是实实在在在项目里摔出来的。Git 学到后面你会发现,命令本身只是工具,真正难的是对版本演进的理解和对协作规范的尊重。把这个速查表存下来,用到哪个查哪个,用十次以上自然就熟了。下一期我会继续整理分支策略和多人协作工作流的实战经验,到时候大家再一起讨论。