很多人在公司里用了两三年 Git,其实一直把它当成一个“代码网盘”:改完代码commit一下,push上去,别人pull下来,仅此而已。等到真的碰上麻烦——分支乱成一团、把别人的提交覆盖了、合并冲突不知道怎么处理、误删了分支——才意识到自己对 Git 的理解可能停留在表面。
这篇文章不是简单的命令罗列。我准备把 Git 命令按实际工作流拆成几大类,每一类都讲清楚它解决什么问题、背后的原理是什么、实际使用中会踩哪些坑。内容是从真实项目里最常用的命令和经验整理出来的,适合刚装好 Git 打算系统学习的人,也适合用了很久但总觉得自己处于“知其然不知其所以然”状态的开发者。
1. 为什么搞懂 Git 命令之前,先要理解它的数据模型
我见过太多人卡在"命令记不住"这个死循环里。其实根子不在记忆力,而是不理解 Git 底层的数据模型。你只要想明白 Git 是怎么存东西的,绝大部分命令都能自己推导出来,根本不需要死记硬背。
1.1 三个区域:工作区、暂存区、版本库
Git 本地仓库可以简单理解为三个区域:工作区、暂存区、版本库。
工作区就是你电脑上肉眼可见的目录,里面是真正能编辑的文件。暂存区是一个看不见的中间区域,英文叫 Index,用来存放你准备提交的文件清单。版本库则是 Git 真正保存历史快照的地方,里面存着每次 commit 的完整数据。
这三个区域对应三组核心命令:
git add:把工作区的文件放进暂存区git commit:把暂存区的东西固化成一个快照,存进版本库git status:随时查看三个区域之间的差异状态
用一个生活类比:工作区是你的购物车,暂存区是收银台,版本库是付完款拎回家的袋子。你从货架上拿东西(工作区编辑文件),把东西放到收银台(git add加入暂存区),最后扫码付款装袋(git commit生成快照)。很多人想不通git add为什么不是直接"保存",而是多此一举先放暂存区——这正是 Git 灵活的地方,它允许你把一批改动里挑一部分提交,而不是必须一次性全提交。
1.2 快照与指针:为什么 Git 分支这么轻量
所谓"轻量",是相对 SVN 这类老牌版本控制系统说的。在 Git 里,创建一个分支只是创建一个指向某个 commit 的指针,本质上是创建一个 40 位或 64 位的哈希引用,瞬间就能完成。
很多人下意识会类比:分支就是复制一份代码。这是对 Git 最大的误解。实际上每次 commit 保存的是整个项目的快照,Git 会为每个文件计算校验和,若文件内容没变,就直接复用之前的对象引用,所以哪怕 commit 一万次,仓库里也不会堆一万份重复文件。而分支呢,不过在"当前是哪个 commit"这个位置上多贴了一个便签。
理解了这一点,"分支切换慢不慢""分支多了会不会占空间"这类问题就都消失了。你切分支的时候,本质上只是移动 HEAD 指针,然后 Git 按需更新工作区文件内容而已。这也是为什么团队协作里鼓励多开分支、频繁开分支,成本低到可以忽略不计。
2. 装好与配好:从零开始让 Git 在你的机器上真正可用
先别急着敲命令,安装和初始配置这两个环节藏着不少坑。很多"疑难杂症"其实都是环境没配好导致的。
2.1 Windows、macOS、Linux 下的安装细节
Windows 用户一般直接从 Git 官网下载安装包,一路 next 就行,但有一个选项要注意:在"Adjusting your PATH environment"这一步,推荐选"Git from the command line and also from 3rd-party software",不要选第一项"Use Git from Git Bash only"。如果你选了第一项,以后在 CMD 或 PowerShell 里敲git就是"命令找不到"的报错。
macOS 用户我建议用 Homebrew:
brew install git不建议直接跑git --version然后发现系统自带的老版本。macOS 会预装一个古老的 Git 作为 Xcode 命令行工具的一部分,版本低不说,配置行为也可能和标准版有差异。
Linux 用户按发行版来:
# Ubuntu / Debian sudo apt install git # CentOS / RHEL sudo yum install git装完先确认版本:git --version,至少得是 2.x。低于 2.0 的老版本很多东西行为完全不一样,比如默认分支名可能是 master 而不是 main,遇到这种赶紧升级。
2.2 全局配置里的那些"看不见的坑"
装完 Git 第一件事是配置用户信息,这一步几乎所有人都会做,但大部分人只配了用户名和邮箱就跑了。
git config --global user.name "your name" git config --global user.email "your@email.com"这两条全局配置会写入~/.gitconfig,以后这个机器上所有仓库的提交都默认用这个身份。要注意的是:提交记录里附带的邮箱会被记录在你的 commit 里,如果你提交到 GitHub 这种公开平台,这个邮箱也对所有人可见。GitHub 提供了 noreply 邮箱保护隐私,配置里可以直接用那个。
除了姓名邮箱,我每次装机还会做三件很重要的事:
git config --global init.defaultBranch main git config --global core.autocrlf false git config --global core.editor "code --wait"第一行把默认分支名从 master 改成 main,配合现在主流平台的习惯。第二行关闭自动换行符转换。core.autocrlf在 Windows 上默认可能是 true,它会把 LF 转成 CRLF,这在多人跨平台协作时容易引发"整个文件都被标记为修改"的诡异问题。第三行把编辑器设为 VSCode,你执行git commit不接-m参数时会弹出 VSCode 编辑提交信息,体验比默认的 vim 友好太多。
2.3 SSH 密钥与免密登录:一次配好,半年省心
用 HTTPS 协议连远程仓库也可以,但每次 push 都输用户名密码(现在一般要输 token),体验相当糟糕。我强烈建议把 SSH 配好,一次弄完能安静很久。
生成密钥:
ssh-keygen -t ed25519 -C "your@email.com"一路回车会在~/.ssh/下生成一对密钥:id_ed25519是私钥(锁在自己手里),id_ed25519.pub是公钥(放到 GitHub/Gitee 等平台上)。
然后在平台设置里找到 SSH Keys 入口,把id_ed25519.pub的内容粘贴进去保存。验证是否成功:
ssh -T git@github.com会看到类似"Hi xxx! You've successfully authenticated"的输出,说明密钥已经通了。实测下来,这一步之后就能真正实现免密拉取和推送。要提醒的是:私钥文件建议设置权限 600,特别是多人共用一台机器时。
3. 日常增删改查:高频 Git 命令的分类记忆法
Install 完、configure 配完,真正的大头是日常命令。我按功能把命令分成了四组,每一组记住"它是干什么的、它在哪两个区域之间动作",基本就不容易混。
3.1 查看与对比:status、diff、log 的极简用法
git status:查看工作区、暂存区与版本库的差异概览。改动过的文件会以红色列出,已 add 的文件以绿色列出。git diff:查看工作区里尚未暂存的具体改动内容(逐行显示)。git diff --cached:查看已经暂存、但还没 commit 的内容。git log:查看提交历史。单独用的时候输出太长,我习惯直接加参数:git log --oneline --graph --decorate --all,一屏看到完整的分支拓扑。
这里有个容易混淆点:git diff和git diff --cached到底查的是哪里的差异?我给一个记忆锚点:git diff对比的是"工作区 vs 暂存区",git diff --cached对比的是"暂存区 vs 版本库(HEAD)"。至于git diff HEAD则是对比"工作区 + 暂存区 vs 版本库"。三个命令覆盖了三种对比组合,需要哪个用哪个。
3.2 提交与修改:add、commit、amend 的正确姿势
git add最简单是所有文件直接git add -A,但更推荐的是按需添加,避免把临时文件混进跟业务无关的提交。git add -p这个交互式参数强烈建议学一下,它允许你只提交一个文件里的某几行改动,对"一个文件里既有修复 bug 的改动又有新功能代码"的场景非常有用。
提交:
git commit -m "refactor: extract order validation logic"关于git commit --amend,它可以把新改动追加到最近一次提交里,这个命令在提交信息写错或漏提交了某个文件时很好用。但注意一个红线:amend会改写提交历史(生成新的 commit 哈希),如果这提交已经 push 到公共分支,就不要 amend 了,否则你和同事的本地历史就分叉了。
3.3 文件删除与移动:rm、mv、checkout 的关系
删除用git rm,它等价于rm file && git add file,一步完成两步操作。移动用git mv old new,同理。
还有一个高频操作是"我想丢弃工作区某个文件的修改,回到上次 commit 状态":
git checkout -- file.txt或者新版写法:
git restore file.txt这两者效果一样。restore是 Git 2.23 以后引入的更语义化的命令。注意它只会丢弃工作区未暂存的改动,如果改动已经git add进暂存区了,得先git restore --staged file.txt把文件从暂存区请出来,然后再git restore file.txt恢复工作区。两条 restore 连着用,感觉从"撤销当代"跨到了"撤销清代"。
4. 分支与合并:项目协作的核心战场
分支和合并是 Git 的绝对核心,也是绝大多数新人最没底的部分。我把它单独拆成一整节。
4.1 分支的创建、切换、删除
git branch feature/login # 创建分支 git switch feature/login # 切换分支 git switch -c feature/login # 创建并切换,等价于 checkout -b git branch -d feature/login # 删除分支这里我给一个实测建议:尽量多用git switch而不是老式的git checkout来切换分支。虽然checkout也能切分支,但它同时承担了"恢复文件"的功能,两种语义混在一个命令里容易踩坑。Git 2.23 之后把切换分支的工作拆给了switch,把恢复文件的工作拆给了restore,一命令一职责,更好用。
删除分支时有-d和-D两个选项。-d会先检查分支是否已经合并进当前分支,如果还没合并会拒绝删除;-D是强制删除,管你合没合并。我的习惯是能不用-D就不用,虽然删错了能用reflog找回,但没必要给自己找事。
4.2 merge 与 rebase:两条路线怎么选
合并分支的主流方式有两套:merge和rebase。
merge的执行逻辑是把另一条分支的改动合并进当前分支,自动生成一个新的合并提交。它忠实保留两条分支各自的历史,适合像"主分支"这种公共目标。代价是历史会呈现分叉再汇聚的形状,graph 看多了会有点乱。
rebase的执行逻辑是"把当前分支的提交,重新接到目标分支最新的 commit 上"。它会改写当前分支提交的哈希,历史变得线性整洁。代价是,如果你对已经共享的分支做 rebase,同事的本地历史就全乱了。
我的经验概括成一条原则:公共分支永远用 merge,私有分支随便用 rebase。具体场景来说,你从 main 拉出一个 feature 分支自己开发,开发过程中 main 有新提交了,为了让 feature 跟上进度,可以git rebase main把 feature 的提交整体搬到 main 最新提交之上;但 main 合并 feature 时,应该用git merge feature(或用 GitHub 的 Squash and merge),不要对 main 做 rebase。
4.3 冲突解决:从恐惧到熟练的完整过程
不管 merge 还是 rebase,只要两个人都改了同一文件同一块区域,冲突就是躲不掉的。遇到冲突时,先不要慌,按这个链路处理。
第一步,git status看哪些文件冲突,冲突文件会同时出现在 Changes not staged 和 Unmerged paths 里。第二步,打开冲突文件,找冲突标记:
<<<<<<< HEAD 这里是你当前分支(HEAD)的内容 ======= 这里是另一条分支被合并进来的内容 >>>>>>> feature/login把<<<<<<<到>>>>>>>之间的内容整理成你要的最终版本——要么留左边,要么留右边,要么两边各取一部分手动拼接,删掉所有标记行。
第三步,修改完后git add这个文件,告诉 Git"这个文件的冲突处理完了"。第四步,如果是 merge 冲突,直接git commit完成这次合并;如果是 rebase 冲突,不要commit,而是继续git rebase --continue,让 rebase 过程自己按顺序继续处理后面的提交。
有一个实操心得:解决 rebase 冲突时,如果有很多个提交都冲突,每个提交都可能要处理一遍同样的冲突区域,因为 rebase 是逐个提交重放。这种情况下,如果改动很大、冲突很多,我反而会放弃 rebase,改用git merge,少受几遍折磨。
5. 远程仓库协作:push / pull 背后的完整逻辑
本地毛坯房盖得再漂亮,最终也要跟别人联动。远程协作这一块很多人只知道push、pull,遇到 remote 层面问题就懵了。
5.1 remote 管理:理解 origin 之后一切就顺了
origin不是什么特殊命令,它是你 clone 或添加远程仓库时自动起的默认名字:
git remote -v # 查看当前有哪些远程仓库 git remote add origin <url> # 添加远程仓库 git remote remove origin # 移除远程仓库如果你用git clone拉项目,origin 自动指向你拉取的这个地址。如果你本地git init然后想推到远程,就需要手动git remote add origin加上地址。一个项目可以绑定多个 remote,各自起不同名字,比如上游仓库叫upstream、自己 fork 的叫origin,这在开源协作里很常见。
5.2 fetch、pull、push:三个动作的协作逻辑
git fetch是从远程仓库把最新提交和分支信息拉到本地,但不主动合并。git pull等价于git fetch加git merge(默认配置下)。git push是把本地提交推送到远程。
很多人犯的错误是每天都在git pull,但没有真正理解 pull 是两步动作的复合。如果远程和本地都有各自的提交,git pull可能会自动生成一个 merge commit,这个 commit 有时候并不是你想要的历史。
我建议执行长期项目的协作时,先把 fetch 和 merge 的分离习惯养成:
git fetch origin git diff origin/main # 看看远程比我多哪些东西 git merge origin/main # 确认没问题再合如果想用 rebase 而非 merge 方式同步,可以git pull --rebase,前提是你本地有未 push 的私有提交时这会顺滑很多。
推送时,第一条git push -u origin main里的-u很重要,它把本地 main 与远程 main 建立跟踪关系,之后直接git push就行了,不用再带参数。
5.3 PR / MR 协作流程与代码审查
在团队开发里,主分支一般会设置保护规则,不允许直接push,必须通过 Pull Request(GitHub / Gitee 叫 PR,GitLab 叫 MR)合并。标准流程是:
git switch -c feature/payment # 开发 + 提交 git push -u origin feature/payment # 然后在平台上发起 PR把 feature 分支推到平台后,在网页上发起 PR,指定 reviewer 做 code review,通过后由维护者在平台上点合并。这个流程的好处是主分支始终保持可部署状态,任何改动都要经过审核人眼睛,很多低级错误在 review 阶段就被拦住了。
5.4 Git LFS:大文件仓库的救星
项目里出现 PSD、视频、模型文件这类大文件时,Git 默认的工作方式会让你抓狂——每次改一丁点,Git 都把整个文件的新版本当作一个对象存进仓库,仓库体积飞速膨胀,clone越来越慢。
Git Large File Storage(LFS)的思路是:仓库里只存一个文本指针,指向真正的大文件对象,大文件本体由独立的存储服务托管。使用很简单:
git lfs install git lfs track "*.psd" git add .gitattributes git commit -m "track psd files with lfs".gitattributes文件会被提交到仓库里,团队其他人 clone 后,需要执行git lfs install或依赖 Git LFS 客户端自动下载。这一步容易忽略:如果队友没装 Git LFS 客户端,clone 下来看到的大文件只是一个几 KB 的文本指针文件,容易误以为文件损坏。
6. 撤销与回滚:那些让你从"事故"里安全走出的命令
Git 之所以让人放心,很大程度上是因为"几乎一切误操作都能恢复"。但正因为恢复手段太多,怎么选对命令才是关键。我按"改动所处的状态"来组织这组命令。
6.1 按状态分类的撤销命令对照表
| 你想撤销的状态 | 正确命令 | 影响范围 |
|---|---|---|
| 工作区有改动,还没 add | git restore <file>(或git checkout -- <file>) | 只影响工作区 |
| 已 add 进暂存区,还没 commit | git restore --staged <file> | 把文件从暂存区退回工作区 |
| 已 commit,还没 push | git reset --soft HEAD~1/ 或--mixed | 撤销提交,保留改动 |
| 已 push 到公共分支 | git revert <commit> | 生成反向提交,不改写历史 |
第二行的git restore --staged处理的是"我不想把这个文件提交进去了",它只是把暂存区里的登记取消了,文件改动本身还在工作区躺着,完全不影响内容。
第三行的git reset HEAD~1表示把 HEAD 回退到前一个提交,HEAD~1是"上一个提交"的简写,HEAD~2是"前两个提交"。
6.2 reset 的三种模式:soft、mixed、hard 到底动了什么
git reset带三种模式,这是 Git 新手最晕的地方。拆开看其实就三个维度在变:HEAD 指针位置、暂存区内容、工作区内容。
--soft只移动 HEAD 指针。提交被撤销了,但你的改动还保留在暂存区里,直接git commit就能重新提交。常用于"提交信息写错了,想换个说法重新提交"。--mixed是默认模式。HEAD 指针移动的同时,暂存区也被重置,改动退回到工作区。常用于"提交完发现漏了文件,想重新分组提交"。--hard三个维度全部重置。工作区、暂存区、HEAD 全部回到指定 commit 的状态,未提交的改动直接消失。这是最危险的命令,只在确定要彻底丢弃时用。
一个记忆口诀:soft 只是把"提交"撤回但内容还在台上(暂存区),mixed 是把内容从台上放到购物车(工作区),hard 是所有内容直接扔垃圾桶(不可见)。
6.3 revert:唯一适合公共分支的撤销方式
reset因为会改写提交历史,所以只适合本地或私有分支。公共分支上已经有很多人的提交了,你回退一个 commit,后面的人pull就会看到历史分叉,并且可能把别人的提交也带过去。
git revert <commit>不会删除那个历史提交,而是新生成一个"反向提交",把该 commit 的改动倒过来,历史始终保持线性。
git log --oneline # abc1234 add login feature git revert abc1234执行后 Git 会自动创建一个新提交,内容是这个功能的反向操作。它特别适合线上出问题、需要立即回滚场景:你保留"引入 bug 的提交"和"撤销它的提交"两条记录,审计时能清楚看到当时发生了什么。
6.4 stash:临时切换工作的"内存条"
手上改到一半不想提交,但又要切分支干别的事,这就是stash的用武之地。类似把当前工作区放进一个"临时储物柜",之后随时取回来。
git stash # 保存当前所有改动并清空工作区 git stash push -m "wip login" # 带备注地保存 git switch feature/other # 去处理别的分支 # 处理完回来 git switch feature/login git stash pop # 取回最近的 stash 内容 git stash list # 查看所有 stashstash默认只存储已跟踪文件的改动,新增的未跟踪文件不会进去,需要加-u参数才会连未跟踪文件一起存:
git stash push -u取回时,git stash pop会应用并删除 stash,git stash apply应用但保留 stash 记录——如果想在多个分支上重复应用同一份改动,用apply更合适。
6.5 reflog:找回一切误操作的最后防线
reflog是 Git 的"操作日志",记录了 HEAD 每一次移动的历史。你误删分支、reset --hard回退太多、rebase 出了岔子,只要那个 commit 还留在 reflog 里,就能找回来。
git reflog # 输出类似 # b3f0a12 (HEAD -> main) HEAD@{0}: reset: moving to b3f0a12 # 9c4e891 HEAD@{1}: commit: add payment module假如刚才git reset --hard HEAD~3发现自己后悔了,只需要:
git reset --hard 9c4e891就回到了 reset 之前的提交。reflog 记录默认保留 90 天,这 90 天就是你的后悔药窗口。遇到"误删分支"也可以用它找回:先git reflog找到分支最后一次指向的 commit,然后git branch feature/recover <commit>重新拉回分支。
7. 实际项目中遇到的疑难杂症与排查思路
积累到这一节,都是我真实开发里踩过、也帮同事排查过的典型问题。每个问题我都按照"现象 → 排查链路 → 根因 → 修复方案"的顺序讲。
7.1 SSH 认证失败的完整排查链路
现象:执行git push或ssh -T git@github.com时,提示连接被拒绝或认证失败,而不是正常的欢迎信息。
不要一上来就觉得是密钥问题,先按链路逐层排查:
- 确认能连到服务器:
ping github.com或换个终端再试一次。网络不通是很多 SSH 问题的真正根源。 - 确认本地有密钥:
ls ~/.ssh/看有没有id_ed25519和id_ed25519.pub文件。没有就ssh-keygen -t ed25519 -C "email"生成。 - 确认 ssh-agent 里有密钥:
ssh-add -l列出 agent 里的密钥。如果显示 The agent has no identities,执行ssh-add ~/.ssh/id_ed25519。 - 确认公钥已添加到托管平台:复制
id_ed25519.pub内容,去 GitHub/Gitee 的 SSH Keys 设置页确认粘贴过。这里最容易犯的错是把公钥内容复制成了私钥内容(id_ed25519 而不是 id_ed25519.pub)。 - 用 verbose 模式测试:
ssh -T git@github.com -v,日志里能看到认证过程走到哪一步失败。如果报Permission denied (publickey),基本可以定死在密钥本身;如果报Connection refused,那多半是网络或代理问题。 - 多账号冲突:如果机器上配置了多个平台或账号的密钥,需要在
~/.ssh/config里为不同 Host 绑定不同密钥:
Host github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519_work一个冷知识:ssh -T git@github.com返回的 Exit Code 不是 0 也不代表失败。它如果输出"Hi xxx! You've successfully authenticated",就说明通了,那个"warning: Permanently added"提示也不是错误。
7.2 .gitignore 过滤失效:你加规则为什么没用?
现象:在.gitignore里加了node_modules/或.env,git status却还是显示这些文件被跟踪。
这个 90% 的原因是:.gitignore只对未跟踪文件生效。如果你的文件已经被git add/git commit跟踪过了,之后再加.gitignore规则是拦不住它的。
正确修复办法是从版本控制里移除这些文件,但保留它们在本地磁盘:
git rm -r --cached node_modules git commit -m "stop tracking node_modules"之后.gitignore规则才生效。这个操作只清除暂存/版本库里的跟踪记录,不会动工作区文件。
还有一个常见误区:.gitignore里写*.log能匹配任意层级的 .log 文件,不写斜杠也能匹配根目录;但如果写了/build/,则只匹配仓库根目录下的 build 目录。规则细节比较多,我一般建议先git check-ignore -v <file>查看哪条规则匹配了这个文件,比反复试要高效得多。
7.3 Git LFS clone 卡住:从源头到客户端的处理
现象:clone 一个配置了 LFS 的仓库时,进度条卡在某个大文件半天不动,甚至直接失败。
排查链路:
- 确认 LFS 客户端已安装:
git lfs version。顺手执行git lfs install把 filter 配置写进全局配置,这一步可以提前避免很多 clone 问题。 - 确认远程服务端 LFS 配额:很多平台对单个 LFS 文件大小有明确上限(比如 GitHub 是 2GB,Gitee 可能更低)。如果仓库里有超过上限的文件,clone 时会直接在 LFS 下载阶段失败。检查下
.gitattributes里 track 的模式有没有覆盖到超大文件。 - 降低并发下载数:
git config --global lfs.concurrenttransfers 1,把并发降到 1 可以提升大文件下载稳定性。 - 不下载历史大文件:如果只是想拿当前代码,可以跳过全部 LFS 内容:
GIT_LFS_SKIP_SMUDGE=1 git clone https://...这样仓库克隆会快很多,代码文件都在,大文件变成指针。需要时再手动git lfs pull拉取对应的 LFS 文件。
- Partial clone 过滤 Blob:Git 2.25+ 支持
git clone --filter=blob:none <url>,这会只下载每次 commit 的快照引用而不下载具体文件内容,等到 checkout 或拉取特定文件时再按需获取。对超大仓库非常有效,比 LFS 更深一层地省流量。
7.4 Windows 环境下与 Git 纠缠不清的几个问题
Windows 用户容易踩的坑,集中说几个:
命令行窗口闪退:双击 Git Bash 打开后窗口直接关闭,多半是 PATH 环境变量被改坏,或在启动时加载的配置文件里写了会导致崩溃的命令。排查办法是在 CMD 里跑git --version,CMD 闪退就跑 PowerShell。如果git bash单独正常,就要检查~/.bashrc和~/.bash_profile里的内容。
文件名大小写问题:Windows 文件系统不区分大小写,但 Linux 区分。如果在 Windows 上把Readme.md改成readme.md,Git 默认可能不认为这是改动。全局配置git config core.ignorecase false能强制敏感,但更稳妥的方案是“文件名大小写变更”单独提交一次,不要和正常代码改动混在一起,否则别人 pull 到 Linux 上就是一堆莫名其妙的冲突。
换行符引发的全文件 diff:全公司总有 Windows 和 macOS 用户,只要一个人用 CRLF 提交,别人用 LF 看 diff 就是满屏红色。解决方式是统一配置:
git config --global core.autocrlf false团队仓库里最好再放一个.gitattributes文件,显式声明文本文件的换行符规范,比如* text=auto加*.sh text eol=lf。这样即使有人配错了 autocrlf,仓库内部也能保持统一的换行符。
写在最后
最后再分享一个我自己的习惯吧。
我用了 Git 好几年,从最早把git add、git commit、git push三板斧背得滚瓜烂熟,到后来熟练掌握 rebase、cherry-pick、reflog 这些高级操作,中途最大的转折点其实不是背了多少命令,而是花了一个下午把"commit 是什么、分支是什么、HEAD 是什么"这三个底层概念彻底想通了。从那之后,新命令基本看一眼就能猜到它大概做什么、什么时候该用,遇到没见过的报错也不会慌,因为知道 Git 内部是怎么运作的。
如果你刚学 Git 没多久,我的建议是:先装好环境,把前三章的日常命令用熟,然后在自己的练习仓库里故意制造几次“事故”——比如 reset —hard 删提交、rebase 冲突、误删分支——再用 reflog 和 revert 把现场恢复回来。这个过程比任何教程都管用,因为你会真实感受到 Git 的安全性边界在哪里,也知道哪些操作是真危险、哪些只是表面吓人。等你把这套流程走完一遍,Git 就不再是一个需要背命令的工具了,它就是你手里一个随时可以放心折腾的工作台。