
Git 笔记这事我本来是没打算专门更新第二版的。第一版发出去之后照着配的人确实不少但后台和同事这边又陆续冒出一些之前没讲透的问题比如为什么很多图形工具执行 Git 命令时总带一长串-c参数为什么同一个仓库第一次 clone 过免密、换台机器又要反复输密码还有中文文件名在 Git 输出里变成一串\346\265\213...到底是怎么回事。这一版正好赶上我重新搭一台开发机把安装、配置、免密、日常命令再到各种报错完整走了一遍顺手把所有新踩的坑和原来遗漏的点全部补进来希望能当一份能直接照着操作的记录。1. 先把环境重新过一遍Git 安装与版本选择的那些事1.1 版本不是越新越好但也别用古董版本判断 Git 版本时我习惯先跑一句git --version。很多老机器上默认自带的 Git 可能还停在 1.8 或 2.0 时代这类旧版本最大的问题不是命令记不住而是行为差异会让人抓狂默认分支名可能还是master、git pull默认策略不同、对rebase的交互提示也不一样最明显的是很多新特性根本不存在。比如git switch、git restore这种更安全的分支切换与文件恢复命令是 2.23 之后才加入的git init --initial-branchmain则要 2.28 才稳定。在实际协作中如果别人用的命令在你的老版本上直接提示unknown option整个流程都会被卡住。我个人的判断标准是能用发行版官方源里的最新稳定版就用最新稳定版不要追 nightly也尽量别用那种多年没维护的第三方源。选新版本的核心收益不只是新命令更多是文件系统处理、diff 算法和 CRLF 换行处理的修正这些直接影响日常使用的稳定性。尤其多人协作的项目大家 Git 版本差距太大会出现同样的命令行为不一致排查起来非常费劲。1.2 不同环境下我是怎么装 Git 的这次搭的是一台 Linux 开发机系统是 Ubuntu 系的所以我直接用系统包管理器装sudo apt update sudo apt install git -y git --versionRed Hat 系或者 CentOS 流的老机器上命令会换成sudo yum install git或者sudo dnf install git。如果系统源里版本偏老也可以从 Git 官方源码编译安装但我要提醒一句编译安装前记得装好依赖否则后面运行可能出现各种缺失库的报错。常规操作是sudo apt build-dep git把编译期依赖一次性补齐然后再make configure ./configure --prefix/usr/local make sudo make install。这个过程比较耗时非必要我不太推荐。Windows 环境我更建议直接下载官方安装包安装过程中有几个选项需要留意。一个是默认编辑器建议改成 Vim 或者其他你惯用的编辑器一个是 PATH 环境变量建议选 “Git from the command line and also from 3rd-party software”这样后面在 VS Code、JetBrains 系 IDE 里调用 Git 都不会出问题。还有一个容易忽略的是换行符转换选项默认的 “Checkout Windows-style, commit Unix-style line endings” 适合大多数跨平台项目但如果你所在团队已经有统一的.gitattributes规范可以选择 “Checkout as-is, commit as-is”把换行处理完全交给仓库配置文件。macOS 上最省事的是通过 Homebrew 安装git它会自动处理依赖安装完的版本也通常比系统自带的要新。需要注意如果你曾经装过 Xcode Command Line Tools 附带的 Git那只是 Apple 打包的版本路径在/usr/bin/git而 Homebrew 版本通常装在/opt/homebrew/bin/gitApple Silicon或/usr/local/bin/gitIntel。装完建议执行which git看下当前优先用的是哪个避免出现命令行里版本和 IDE 里版本不一致的尴尬。1.3 安装完先别急着写代码检查三件事安装完成之后我会先做三件很小的检查。第一件是确认 Git 可执行文件路径which git。第二件是看版本git --version。第三件是看当前的全局配置都来自哪些文件git config --list --show-origin。这个命令会输出每一行配置项以及它来自哪个文件方便后面排查配置是写在系统级、全局级还是仓库级。很多人配置不生效最后查下来就是三个层级里同名的配置项互相覆盖--show-origin一眼就能看清来源。2. 新机器上手先完成这些基础配置很多奇怪问题都出在这一步2.1 提交者的姓名和邮箱不配置commit 都提不上去我见过不少新手第一次 commit 时被 Git 直接拒绝提示Please tell me who you are这就是因为没配置身份信息。这里要澄清一点Git 的身份信息不等于账号密码它只是写在每次提交记录里的作者标识方便团队成员知道某次改动是谁做的。配置命令是git config --global user.name Your Name git config --global user.email youexample.com--global表示写入用户级配置文件对当前用户的所有仓库生效。如果某个特定项目需要不同的身份比如公司项目和私人项目可以在对应仓库目录下不加--global执行一次写的是仓库级配置优先级会高于全局配置。检查配置是否生效可以用git config user.name和git config user.email。这里有个容易被忽略的细节邮箱最好和你代码托管平台的账号邮箱保持一致。很多平台是根据提交邮箱关联用户头像和贡献度的如果用了一个没验证过的邮箱提交记录虽然能推上去但平台上不会关联到你的账号绿点和头像都会对不上给人感觉提交者是个陌生人。这是我见过很多团队统计贡献排行时出现偏差的主要原因。2.2 几个影响体验的 config 参数quotepath、autocrlf 和编辑器先讲一个很多人天天遇到却不知道原因的现象仓库里的文件名明明是中文git status或者git log里却显示成\346\265\213\350\257\225.txt。这不是文件乱码而是 Git 默认会对非 ASCII 字符做转义显示目的原本是防止终端解析出错。解决方式是在全局配置里关掉这个转义git config --global core.quotepath false配完之后再看中文文件名就是正常可读的状态了。这个配置对带空格的文件名也有影响一旦关闭转义某些需要精确匹配文件名的脚本要注意引号问题但总体收益远大于风险。换行符是另一个跨平台协作的大坑。Windows 上文件换行默认是CRLFLinux 和 macOS 上是LF。如果团队里有人用 Windows、有人用 Linux提交时 Git 会检测到整个文件所有行都变了git diff几乎没法看。Git 提供了core.autocrlf这个选项缓解Windows 上可以设置true表示检出时转成 CRLF、提交时转成 LFLinux/macOS 上建议设置input表示检出时不转、提交时转成 LF。配置命令git config --global core.autocrlf input不过说实话仅靠core.autocrlf在不同 IDE、不同 .gitattributes 规则下还是可能会出现换行反复变更的怪问题。更稳妥的方案是直接在仓库根目录放一个.gitattributes文件把规则固化下来这样所有协作者不管用哪个平台都会按文件里写的规则处理。我常用的最小规则是这样的* textauto *.sh text eollf *.bat text eolcrlftextauto的意思是让 Git 自动检测文本文件并做换行规范化不对二进制文件做处理。对已知明确需要某个换行格式的文件再单独指定eol。这样即使有人没配core.autocrlf仓库内的换行也能保持一致。2.3 用 alias 和默认分支名减少日常击键Git 命令本身已经不算复杂但有些组合命令确实长比如查看日志图、查看某次提交改了什么每次敲一长串很影响效率。我习惯把高频命令设置成 alias例如git config --global alias.co checkout git config --global alias.br branch git config --global alias.ci commit git config --global alias.st status git config --global alias.lg log --oneline --graph --decorate --all git config --global alias.unstage reset HEAD --设置之后git st就等于git statusgit lg直接展示所有分支的提交图比默认的git log直观太多。如果还想让 log 输出带上作者和日期可以再加一个全局配置git config --global format.pretty %h %s (%an, %ad)%h是短哈希%s是提交标题%an是作者名%ad是日期。这样每次git log的输出都会更精炼。新仓库初始化时的默认分支名我也建议统一设成maingit config --global init.defaultBranch main这样git init出来的新仓库不会再出现 master/main 混用的问题和远程仓库平台新建仓库的默认分支也能保持一致。3. 本地与远程仓库的免密配置完整走一遍3.1 为什么推荐用 SSH Key 而不是每次输密码每次git push或git pull都要输入托管平台的账号密码短时间还好一天操作几十次就会非常烦躁。免密一般有三种思路。第一种是 SSH Key 方式本地生成一对公私钥公钥放到远程仓库平台的账户 SSH Key 列表里之后 Git 通过 SSH 协议连接时会自动完成认证。第二种是 HTTPS 凭据缓存或凭据存储把密码交给系统的凭据管理器或 Git 自带的 helper 记下来。第三种是各种 IDE 自带的登录态管理本质上是帮你缓存了凭据。需要说明的是很多代码托管平台现在已经不支持用账号密码直接通过 HTTPS 推送代码了而是要求使用个人访问令牌Personal Access Token。如果你仓库地址是 HTTPS 开头即使本地记住了密码也可能被拒绝此时需要去平台生成 token 然后把它当作密码使用。个人项目里我最推荐 SSH Key配置一次之后基本可以做到一劳永逸还能避免 token 过期后又要重新输入的问题。3.2 生成密钥、添加公钥、测试联通三步完成免密第一步在本地生成密钥对。我推荐使用ed25519算法它的密钥更短、安全性更好而且现代 Git 和托管平台基本都支持ssh-keygen -t ed25519 -C your_emailexample.com命令执行后会提示你选择保存路径默认在~/.ssh/id_ed25519直接回车即可。接着会提示输入 passphrase这是给私钥加的一层口令保护就算私钥文件泄露不知道口令的人也办法直接使用。如果不想每次操作都输入口令可以留空直接回车。要注意的是如果操作系统里有 SSH agent 在运行设置了 passphrase 的私钥可以通过ssh-add加进 agent之后同一次会话内不需要反复输入。第二步把公钥内容复制到远程仓库平台的 SSH Keys 设置页面。公钥文件是~/.ssh/id_ed25519.pub查看命令cat ~/.ssh/id_ed25519.pub复制全部内容后在平台的 SSH Key 设置里粘贴保存。这个公钥相当于你家门锁对应的钥匙私钥留在本地公钥交给平台平台验证时用公钥确认持有私钥的人是你本人。第三步把本地仓库的远程地址改成 SSH 格式。很多人配置完公钥后仍然要输密码原因是当初 clone 时用的是 HTTPS 地址。检查方式git remote -v如果输出是https://xxx/xxx.git可以改成 SSH 格式git remote set-url origin gitgithub.com:user/repo.git地址格式要根据你的托管平台来写大概规律是git平台域名:用户名/仓库名.git。改完之后建议先用 ssh 协议测试一下连接ssh -T git平台域名如果配置成功通常平台会返回一条欢迎信息比如认证成功并显示你的用户名。到这里免密就已经生效后续 clone 和 push 都不需要再输密码。3.3 免密不生效时按这个顺序排查最让我头疼的免密异常通常有四种。第一种是本地存在多个私钥文件而 SSH 客户端默认只会尝试id_rsa或者按 config 文件匹配的私钥导致平台不认识你的密钥。第二种是私钥文件权限太宽松SSH 为了保护密钥会直接拒绝使用权限为644甚至777的私钥这时需要执行chmod 600 ~/.ssh/id_ed25519。第三种是公钥没有添加到平台或者添加时空格、换行被截断。第四种是远程地址仍是 HTTPS 格式即使公钥配置正确也走不到 SSH 认证这一步。如果使用过程中需要切换账号也可以在~/.ssh/config文件里为不同域名指定不同的私钥。比如Host work HostName git.example.com User git IdentityFile ~/.ssh/id_ed25519_work这样执行git clone work:user/repo.git时SSH 会使用id_ed25519_work这把私钥完成认证适合一个人同时维护公司仓库和个人仓库的场景。不过这个属于进阶配置新手如果只有一个账号不需要一上来就写 config 文件。4. 日常高频 Git 命令盘点一套顺手的工作流可以省太多事4.1 从克隆到推送记住这条主线就够了日常开发最常用的场景是从远程仓库拿代码、在本地新建分支、提交改动、推回远程。我第一次带新人的时候给他们画的主线其实只有这几条命令git clone 远程仓库地址 git checkout -b feature/新功能 git add . git commit -m feat: 完成xx功能 git push -u origin feature/新功能git clone会把远程仓库完整复制到本地包括所有历史记录和分支。git checkout -b是基于当前分支新建并切换过去相当于一个安全的“复制当前工作状态开一条新线”。git add .是把当前目录下所有变更加入暂存区这一步叫“暂存”而不是“提交”。git commit则是把暂存区的改动固化成一次本地提交必须写提交信息。git push -u origin 分支名是首次推送新分支到远程并建立跟踪关系之后的推送就可以直接git push。这条主流程看着简单但我观察到新手最常犯的错误是把git add .当成“保存文件”结果把临时文件、IDE 配置文件、甚至包含密码的.env文件全部提交进了历史。规避办法有两个一是提交前执行git status检查二是养成维护.gitignore文件的好习惯把构建产物、依赖目录、IDE 配置、本地环境变量文件全部排除掉。我见过最典型的反面案例是有人把node_modules提交进了仓库单次提交体积直接到几百 MB同事 clone 一次要等半天。4.2 分支与合并merge 和 rebase 应该怎么选分支合并是 Git 里最容易被讨论出争议的话题。git merge和git rebase做的事情最终目标相似都是把另一条分支的改动整合到当前分支但结果差异很大。merge会保留两个分支的完整历史拉出一条合并节点适合公共分支或多人协作分支因为它的历史是真实发生过的、不可篡改。rebase则是把当前分支的提交“摘下来”重新接到目标分支的最新提交后面形成一个线性干净的历史。我在实际项目里的选择逻辑是这样的如果是在自己的功能分支上开发想把主分支最新改动同步过来我会用git rebase origin/main这样功能分支的历史是线性的后续合并回主分支时更清爽。但如果是在一条多人共用的分支上拉取别人最新代码我坚持用merge原因是最小化改写别人提交历史的可能性。简单总结成一张表场景推荐操作理由个人功能分支同步主分支最新git rebase main历史线性后续合并冲突少共用分支拉取同事提交git pull默认 merge不改写历史避免影响他人功能完成后合入主分支git merge 功能分支保留合并点便于回溯4.3 查询三件套status、diff、log 配合使用的姿势很多人遇到 Git 状态混乱就只会盯着git status但status只能告诉你文件处于什么状态没法告诉你具体内容改了什么。要看清改动细节必须搭配git diff。工作区里还没暂存的改动用git diff已经暂存的改动用git diff --cached。如果想要高亮看到某个文件的变化可以指定文件路径git diff 文件名。git log则是查历史提交的眼睛。我平时几乎不会用裸的git log而是固定用配置好的git lg配合--oneline --graph可以快速预览提交图谱。想查某一行代码是谁在什么时候改的可以试试git blame 文件名它会按行标注出每次改动的提交哈希、作者和日期。这个命令排起“这行代码为什么这么写”的锅非常好用。4.4 后悔药reset、revert、reflog 的安全使用边界Git 最让人安心的一点是它几乎不立即销毁数据但前提是得用对恢复命令。git reset用于回退本地提交最常见的三种模式是--soft、--mixed默认和--hard。它们的递进关系非常清晰模式HEAD 指向暂存区工作区适用场景--soft回退不变不变只想撤销 commit重新整理提交信息--mixed回退重置不变撤销 commit 和暂存保留改动待重新处理--hard回退重置重置彻底丢弃本地改动慎用如果提交已经推到了远程分支而其他人可能已经基于它做了开发reset后强推会产生历史分叉影响超出“本地后悔”的边界。更安全的处理是用git revert commit它会新建一条反向提交来冲销目标提交的改动不改变已有历史。由于 revert 是正向追加了一条提交后续推送不会出现历史被重写的问题适合任何分支。git reflog是找回丢失提交的真正王牌。很多人在分支上做了大量提交后误删分支或者reset --hard到了错误位置以为工作全没了。实际上 Git 的引用日志会记录 HEAD 曾经指向的每一次提交执行git reflog能找到丢失前的提交哈希再通过git branch 新分支名 提交哈希把它恢复成一条新分支。虽然没有 100% 保证但多数误删场景都能通过 reflog 救回来这也是我建议新手在--hard前一定要多想一下的直接原因。5. 那些被图形工具藏起来的命令参数一次看懂 -c 和 --no-optional-locks5.1 为什么 IDE 或脚本执行 Git 时要带一堆 -c 参数如果你用过 SourceTree、VS Code 的 Git 集成或者某些自动化脚本可能会在输出面板里看到类似这样的命令git -c diff.mnemonicprefixfalse -c core.quotepathfalse --no-optional-locks status第一反应往往是这几个参数是干嘛的为什么平时手动敲 Git 命令时不需要加其实这是工具在调用 Git 客户端时主动注入的“临时配置”作用范围仅限于这一次调用。-c keyvalue的语义是命令行级覆盖配置项不修改任何配置文件执行完就失效。所以你在终端里手动敲命令时看不到这些参数因为它们本来就不是必须的只是工具为了保证自己的输出结果可预期才加上去。这对我们的启发是如果有人给了你一条带-c的 Git 命令直接执行也没有问题它不会污染你的全局配置。同时如果某条 Git 命令的行为表现和你的全局配置不一致可以先怀疑是不是有 IDE、IDE 插件或者脚本通过-c临时覆盖了相关配置项。5.2 diff.mnemonicprefix、core.quotepath 和 --no-optional-locks 到底管什么diff.mnemonicprefixfalse是控制git diff输出里两个对比文件前缀样式的参数。Git 在 diff 中默认会把旧文件标记为a/、新文件标记为b/这种设计原本是为了让你一眼分清比较的左右来源。当设置为true时Git 会使用更有语义的字母表示比如c/、i/、w/分别代表提交、索引、工作树文件。外部工具把它们关掉的原因通常是希望输出格式更稳定简洁解析起来不出岔子。core.quotepathfalse在前面的基础配置里已经讲过主要是解决非 ASCII 文件名的转义显示问题。图形工具调用 Git 后拿到的结果如果不做解码中文或者其他 Unicode 文件名就会被渲染成一长串八进制字符。所以像 SourceTree 这类工具在把 Git 源码层的原始输出拿给上层界面处理前会显式关闭 quotepath确保界面能正常展示中文文件名。--no-optional-locks是一个全局选项含义是允许 Git 为了性能在上锁可选的情况下跳过某些锁操作。正常情况下git status这类只读命令可能会刷新索引缓存这个过程会拿一个可选锁。但如果脚本、编辑器在后台高频调用git status每次刷新索引都可能引起文件变动甚至和其他 Git 操作抢占锁导致输出出现 unexpected 行为或卡顿。加上--no-optional-locks之后Git 会在这些场景里跳过可选的索引刷新从而降低锁竞争和文件系统写入。手动执行命令时加不加这个参数感受不明显但放到持续监听文件变化的工具链里能够有效减少偶发的index.lock冲突问题。5.3 我们手动敲命令时需要主动使用这些参数吗我的建议是分场景。日常在终端里敲命令绝大多数情况不需要手动带-c diff.mnemonicprefixfalse默认值完全够用。如果你所在仓库里中文文件名特别多、终端又频繁输出乱码式的文件名可以把core.quotepath false写入全局配置一劳永逸。如果你开发环境里同时开着多个终端窗口、IDE 自动刷新又比较频繁日志里偶尔出现Unable to create .../.git/index.lock之类的报错可以尝试在执行只读状态命令时加--no-optional-locks比如git --no-optional-locks status更彻底的办法是排查哪些后台进程在频繁调用 Git。很多代码编辑器的 Git 插件默认会每隔几秒执行一次 status/diff这在大型仓库里既占 CPU 又容易触发锁文件冲突。遇到这种情况与其纠结参数不如把编辑器里的自动刷新间隔调大一些或者直接关掉不必要的文件监听效果立竿见影。6. 实际操作中踩过的坑问题排查与避坑速查表6.1 高频报错的原因和解决方案把这两年我实际遇到过的 Git 问题集中整理成了一张表几乎都对应一个很明确的根因。报错/现象原因解决办法Please tell me who you are未配置 user.name 或 user.email配置身份信息后重新 commit中文文件名显示为八进制转义默认开启 quotepath 转义git config --global core.quotepath false文件没改动却显示所有行 modified换行符 CRLF/LF 不一致统一.gitattributes或 autocrlf 策略refusing to merge unrelated histories两个仓库历史完全不相关确认无误后加--allow-unrelated-histories合并push 被拒绝提示远程有新提交远程分支领先本地先 pull 或 fetch 再 rebase/merge远程分支被删后本地仍能 push本地保留了过期的跟踪分支git remote prune origin清理index.lock文件已存在另一个 Git 进程未正常结束或锁残留确认无进程后删除.git/index.lockcommit 错文件/错了信息提交还不够严谨用git commit --amend修正上一次提交表格里说的都是高频现象解决思路本身不复杂但排查的时候我建议先从运行环境出发。比如index.lock报错如果频繁出现基本可以断定是某个后台工具在持续调用 Git而不是命令本身有问题。6.2 中文文件名乱码与提交信息乱码是两个不同问题很多人把中文文件名显示乱码和中文提交信息乱码混为一谈实际上处理方式有区别。文件名乱码通常是core.quotepathfalse没有设置这个只要配置后立即生效。而提交信息乱码通常发生在 Windows 终端里原因是 Git 默认把日志输出按 UTF-8 编码而终端可能是 GBK 或其他编码集导致 log 里的中文 commit message 显示成问号或乱码。一个常见组合配置是git config --global gui.encoding utf-8 git config --global i18n.commit.encoding utf-8 git config --global i18n.logOutputEncoding utf-8但这些配置只影响新写入和读取的编码声明如果历史提交里已经存在用错误编码写入的中文信息需要手工处理才能恢复比较麻烦。所以我的经验是团队里约定提交信息一律用 UTF-8终端模拟器也统一设成 UTF-8 编码从源头上避开这个坑。6.3 仓库历史被搞乱后怎么安全回退有一次我在实验分支上连续提交了三轮修改最后一轮引入了严重问题想直接放弃最新提交但保留前两轮的成果。正确做法是git reset --hard HEAD~1注意HEAD~1表示当前提交的上一版--hard会让工作区直接回到那个状态。但如果当时最新提交已经推到了远程的公共分支这样操作再 push 会被拒。此时应该改用git revert HEAD它会生成一个反向提交把刚才那轮引入的改动撤销掉然后正常 push 即可。两者的核心区别是reset 会“抹掉”历史revert 会“追加”一段撤销历史。前者适合本地个人分支后者适合远程公共分支。如果已经发生了误删分支或者错误 reset先不要慌更不要重灌代码优先执行git reflog。reflog 默认保留最近一段时间的 HEAD 变化记录找到目标提交哈希后执行git branch 恢复分支名 哈希就能把丢失的分支引回来。我救过不止一次同事误删的本地分支每次都是靠 reflog 一条命令解决的。6.4 特殊文件不让提交.gitignore 的正确书写姿势.gitignore的坑属于“平时不会出问题一出问题就是大问题”。最典型的是写了规则但不生效原因是 Git 会优先检查已经被跟踪的文件如果某个文件之前已经通过git add提交进了版本库那么你后写的.gitignore规则不会自动让它停止被跟踪。解决办法是先把文件从 Git 索引里移除但保留本地文件git rm -r --cached 文件名这个命令执行后Git 会停止跟踪该文件但不会删除工作区里的实际文件。之后再把对应规则写进.gitignore并提交才算真正生效。另外.gitignore支持通配符和取反规则比如忽略所有/build目录但保留/build/release可以写成/build/* !/build/release注意取反规则必须写到忽略规则之后Git 会按顺序依次匹配后写的规则优先级更高。6.5 关于提交信息规范我最后的执念前面聊了各种命令和参数但我想强调的是Git 用久了就会发现提交信息才是整个仓库最值钱的部分。代码功能可能被重构删除注释可能过时但提交历史会一直留下来。第二版记录里我特别想把这条经验写清楚提交信息不要求辞藻华丽但一定要能解释清楚“为什么”。我看到太多人在 commit message 里写update、fix bug三个月后回看历史根本不知道这个提交当时在干嘛。我的习惯是使用约定式提交的简化格式在标题里带上前缀表示类型feat:新功能fix:修复问题refactor:重构不改功能docs:文档变更chore:构建、依赖等杂项正文部分再简单补充为什么要做这个改动。其实不用写很长一两句话把事情说明白就够了。配合前面配置的git config --global format.pretty或自定义 alias每次浏览历史都会非常舒服。另外还有一个小技巧如果刚提交完发现信息写错了或者漏提交了一个文件不需要新增一条“fix typo”的提交直接git add 漏掉的文件 git commit --amend --no-edit--amend会修改最近一次提交--no-edit表示沿用原提交信息。但要注意如果这个提交已经推送到远程并被其他人拉取过尽量不要再用 amend因为它会改写提交哈希容易引发协作混乱。7. 最后分享一下我在实际使用中沉淀下来的几个习惯如果让我从这次重新搭建环境的经历里提炼几条真正有用的建议我会这样排列。第一条是务必区分全局配置和仓库配置能用仓库级.gitattributes和.gitignore固化下来的规则就不要只停留在个人全局配置里团队协作的稳定性全靠文件级规则兜底。第二条是把 reflog 当成保险箱任何高风险操作前先记下当前 HEAD 的哈希或者干脆新建一个备份分支成本几乎为零但能救命。第三条是遇到看不懂的 Git 命令时先拆解它的参数再执行像-c、--no-optional-locks这类附加项都有明确的适用场景理解了之后你不仅会排除 IDE 带来的干扰还能写出更适合自己项目的脚本。Git 本身的学习曲线不算陡峭真正让人头疼的永远是协作过程中那些边界情况。这篇第二版记录没有覆盖所有冷门知识点但如果你能把我提到的安装、配置、免密、高频命令和坑点都过一遍日常开发中至少九成场景都能顺利解决。剩下的那一成保持一个好习惯就好改之前先查状态提交之前看 diff回退之前备份分支然后放心大胆地去操作。