Git实战指南:从版本控制到分支合并与团队协作
发布时间:2026/10/6 8:25:39 作者:尧图编辑部 阅读量:1,286

扯个真实经历开场吧。我在刚入行那年有一次合并同事代码手一抖把对方刚写好的一整版接口逻辑覆盖掉了。那时候公司用的还是“文件夹备份大法”什么v2_final_3_改、项目备份_0921_最终版这种命名满天飞等到想找回被覆盖的那版翻遍共享目录愣是没找到。就是从那天起我下决心把Git从头到尾系统啃了一遍也在后续几年的团队协作里把常见的坑基本踩了个遍。这篇笔记不是Git官方文档的翻译也不是命令大全的罗列而是我结合日常开发、团队协作、代码托管平台使用整理出来的核心实战学习路径。适合刚接触Git的新手建立整体认知也适合已经用了很久但总在分支合并、认证报错、版本回退上犯迷糊的同学。1. 从一个真实翻车现场说起Git到底帮我解决了什么1.1 没有版本管理的日子有多痛先认真说一句在没有版本管理工具的时候多人协作写代码这件事本质上是在赌运气。我见过太多团队用共享文件夹或网盘同步代码。每个人本地都是“最新版”改完往共享目录一扔第二个同事再覆盖上去。看起来大家都在更新实际上谁先保存谁就赢后保存的人会把前面的改动无声无息地冲掉。你说不对啊覆盖前不是会提示吗问题是提示只会告诉你“文件已存在”不会告诉你“这里面的内容和你本地有什么差异”。等真正出了问题再想追溯你能拿出来的证据只有文件名上的最终版、最终版2、最新版_改这类毫无规则的后缀。更麻烦的是你根本不知道某一行代码是什么时候被谁改成了现在这样也没办法安全地回到三天前那个“还能跑”的状态。Git这类分布式版本控制工具解决的就是这些事每次提交都是一次完整快照可以随时回溯每一行改动都能追踪到提交人和提交时间分支机制让多人并行开发互不干扰远程仓库让协作有了一个大家都认可的同步基准。1.2 理解Git的三个区域比背一百条命令都管用很多人学Git卡在命令记不住本质是没有建立底层模型。我后来发现只需要把Git想象成三个区域几乎所有命令都能对号入座。工作区Working Directory你电脑上正在编辑的文件夹写代码、改文件都发生在这里。暂存区Staging Area / Index一个中间状态用来挑出“本次提交要包含哪些改动”。相当于你去超市购物时手里的购物车——买了什么先放进车里最后统一结账。本地仓库Repository / .gitGit真正保存历史快照的地方。每次git commit就是一次结账生成一个不可变的版本节点。再补充两个容易混淆的概念HEAD是指向你当前所在提交的指针branch本质上也是一个指向提交的指针。理解了“分支是指针”这件事后面讲分支合并、版本回退就顺畅多了。另外Git和SVN那种集中式版本控制还有个本质区别Git的每个仓库都包含完整历史本地离线状态下也能正常提交、查看历史、切换分支。只有push和pull需要连接远程。1.3 什么人需要认真学Git什么情况不必硬上如果你是独立开发者做的是不需要协作的个人项目那Git对你来说最重要的价值就是“后悔药”和历史追溯。哪怕不用远程仓库本地git init之后勤快地提交也能获得版本回退的能力。如果是团队协作哪怕只有两个人Git都几乎是必需品。分支策略、合并规范、冲突解决、代码评审——这些都不是确有更好用的替代工具而是在你理解了Git的基本操作之后才能自然谈起的进阶话题。不过我也要说句实话如果你的项目只是几个零散文档参与者也完全没有协作概念那强行引入Git反而会变成负担。工具是服务人的没必要为了用而用。2. 安装与全局配置别跳过这三步否则后面全是坑2.1 各平台安装Git和验证安装结果安装这件事看似简单但“下载了但没装进命令行”的情况我见过太多了。先说说最常见的平台Windows去Git官网下载安装包默认点下一步就行。有一个选项值得留意安装时建议选择“Git from the command line and also from 3rd-party software”这样第三方软件也能调用git命令。装完以后打开CMD或者PowerShell输入git --version能看到git version 2.x.x.windows.x就说明OK了。如果提示找不到命令检查一下Path环境变量里有没有Git的cmd目录。macOS装了Homebrew的话直接brew install git或者直接git --version系统会弹出提示引导安装Xcode Command Line Tools。装完同样验证版本号。LinuxUbuntu/Debian系sudo apt update sudo apt install git然后同样验证。这里单独提一点很多Windows用户以为下载了GitHub Desktop就等于装了Git其实这俩不是一回事。GitHub Desktop是一个图形化客户端它确实会自带Git核心但如果你还要在命令行里用git最好还是单独安装Git for Windows。后面讲IDE集成时也会碰到这个区分。2.2 全局配置用户名、邮箱、换行符一个都不能少第一次装完Git第一件事不是急着建仓库而是配置身份信息。这一步不做后面每次提交都报错或者提交记录里显示一个随机用户名追责的时候特别尴尬。git config --global user.name 你的名字或花名 git config --global user.email 你的邮箱注意这个邮箱最好和你在代码托管平台GitHub、GitLab、Gitee等上绑定的邮箱一致这样提交记录才能正确关联到你账号的头像和主页。很多平台还会在首页展示你的提交贡献图如果不一致就会出现“提交了但绿点不亮、贡献图一片空”的情况。查看配置用git config --global --list想改直接重跑上面的命令覆盖即可。另一条容易踩坑的全局配置是换行符git config --global core.autocrlf true # Windows推荐 git config --global core.autocrlf input # macOS/Linux推荐不同操作系统对一行文本结尾的标记不一样Windows用CRLFUnix系用LF。如果这个配置不统一同一个文件在不同人电脑上会被Git认为“全部改动”diff时满屏飘红非常头疼。在Windows上设true提交时会自动转成LF在macOS/Linux上设input只在提交时转换。团队协作时这个配置最好在仓库里用.gitattributes统一约束后面会专门讲。2.3 第一个仓库初始化必写的.gitignore配置好身份信息就可以开始第一个仓库了。mkdir demo-project cd demo-project git init这时候Git会在当前目录生成一个隐藏的.git文件夹这就是本地仓库的实体。注意git init只是初始化还没有任何版本历史。在第一次提交之前强烈建议先创建.gitignore文件。它的作用是告诉Git“哪些文件和目录不需要纳入版本管理”。别小看这一步我见过有人稀里糊涂把node_modules、target、.idea、.vscode这类目录提交进仓库轻则仓库体积迅速膨胀重则别人的本地配置互相污染。一个默认模板大概是这样的# 依赖目录 node_modules/ target/ vendor/ # IDE 配置 .idea/ .vscode/ *.iml # 构建产物 dist/ build/ *.class *.log # 环境变量 .env创建好.gitignore后第一次提交就来了git add . git commit -m chore: 初始化项目添加gitignore以后每次写完功能先git add再git commit就是一个完整循环。至于怎么高效地用add和commit下一节展开。3. 核心命令的底层逻辑commit、branch、reset各自在操作什么3.1 高频命令和它们背后对应的数据对象从零开始学Git我建议不要按字母顺序背命令而是先理解Git的四个底层对象Blob文件内容也就是某个文件在某时刻的完整快照。Tree目录结构记录了目录里有哪些文件、每个文件对应哪个Blob。Commit一次提交包含作者、提交时间、提交信息、指向的Tree以及父提交的引用。Reference引用branch、tag、HEAD都属于引用本质是给某个Commit起的一个可变或不可变的名字。那日常命令对应到这些对象就很清晰了git add把工作区的文件内容写入Blob并更新暂存区的索引。git commit把暂存区的内容打包成Tree再生成一个Commit对象然后把当前分支指针移动到新Commit。git branch name创建一个新引用指向当前HEAD所在的Commit。分支就是一个可移动的指针。git checkout branch或git switch把HEAD指向目标分支并把工作区内容恢复到该分支所指的Commit。理解这一点之后你就不会再问“分支和提交到底是什么关系”了。分支不是一整套代码的副本它只是一个轻量级的指针创建分支的开销几乎为零。这也是Git鼓励多用分支的原因。3.2 提交信息的书写习惯给未来的自己留线索提交信息这事说小了是习惯说大了是团队资产。git log里翻三个月前的提交如果全是一堆update、fix、111你根本不知道该不该回退、回退到哪个版本。我一般建议提交信息按照“类型: 简要描述”的格式来写这是社区比较通用的约定feat: 新增用户注册接口 fix: 修复登录页面验证码不刷新问题 docs: 更新README中的部署说明 refactor: 重构订单状态机逻辑不影响对外行为 style: 调整代码缩进和命名格式 test: 补充登录模块的单元测试 chore: 更新依赖版本这样git log --oneline扫一眼整个项目演进的脉络就清楚了。提交粒度也很重要一次提交只做一件事不要把“改了三个页面的样式修复一个接口bug加了一个工具函数”全部塞进一个提交。粒度太粗后续想单独回退某个功能时就只能靠手改代码了。3.3 reset、checkout、restore三种撤销方式的适用场景撤销操作是Git里最容易把人绕晕的地方核心原因是“你想撤销的东西在不同阶段”。我按三个场景来拆。第一文件改了但还没git add我想放弃工作区的改动git checkout -- 文件名 # 老写法 git restore 文件名 # 新写法语义更清晰这个操作是把工作区文件恢复到暂存区/HEAD里的内容本质上是用旧内容覆盖当前文件。改动没有提交之前才适合这么做如果已经提交过又被你改坏了这就成了“回退到某个历史提交”的问题。第二文件已经git add了我想把它移出暂存区但不改变工作区文件git restore --staged 文件名对应以前常用git reset HEAD 文件名。这个操作不清空文件内容只是把它从“待提交”状态放回“已修改”状态非常安全。第三已经git commit了想撤销整个提交。这时要区分两个子场景提交还没push到远程可以用git reset --soft HEAD~1保留改动在暂存区或git reset --mixed HEAD~1保留改动在工作区也可以git reset --hard HEAD~1彻底丢弃改动危险。提交已经push到远程不要直接reset --hard后再强推因为强推会重写远程历史影响其他人。正确做法是用git revert HEAD它会新增一个提交把上一次提交的改动反向应用让历史保持线性且完整。再说一下HEAD~1和HEAD^的区别两者在大多数场景下都表示“当前提交的父提交”但合并产生的提交有多个父提交时HEAD^指的是第一个父提交HEAD^2可以指第二个父提交。我在实际工作中更习惯用HEAD~1这种写法含义明确。3.4 让log和diff说人话追溯一行代码是谁写的刚开始用Git很多人只会git log加回车翻页页面长一点就懵了。我常用的两个参数组合值得记下来git log --oneline --graph --decorate --all--oneline把每个提交压缩成一行--graph显示分支合并的关系图--decorate显示每个分支指向哪个提交--all把本地和远程的所有分支都显示出来。配合起来一个仓库的完整演进图基本一目了然。看改动内容用git diffgit diff # 查看工作区与暂存区的差异 git diff --staged # 查看暂存区与上次提交的差异等于git diff --cached git diff commit1 commit2 # 对比两个提交如果想查某一行代码是什么时候被谁改的用git blamegit blame src/controller/user.js它会显示该文件每一行的提交哈希、作者、提交时间。追查线上bug定位到某个字段时这个命令比在聊天记录里翻有用得多。4. 分支合并实战merge、rebase与冲突解决完整记录4.1 团队协作的分支约定从main到feature现在的团队基本都采用主干分支功能分支的协作模式。主干分支main或master保持稳定功能开发在独立分支上进行合并前经过评审和测试。分支命名最好有规则可循比如feature/user-login # 新功能 bugfix/issue-1234 # 修复问题带上issue编号 hotfix/critical-payment # 紧急修复 release/2.3.0 # 发版分支创建一个新分支并切换过去我推荐使用git switch -c feature/user-login这等于git branch feature/user-login加git switch feature/user-login的合体。新切换到功能分支后正常开发、提交就行和主干隔离、互不干扰这就是并行开发的根基。4.2 merge与rebase两种合并思路两种取舍功能开发完要把改动合回主干最常见的有两条路merge和rebase。**Merge合并**的表现形式是产生一个“合并提交”它有两个父提交历史会保留分叉的痕迹。举个例子你在feature分支开发时主干上同事也提交了两次合并后提交记录会像一张并列再汇聚的网。好处是真实保留了所有并行开发的过程坏处是历史看起来不够线性对某些需要严格回溯的场景比如二分查找定位bug不太友好。git switch main git merge feature/user-login**Rebase变基**的表现形式是把当前分支的提交“搬”到另一个分支的最新提交之上重新播放一遍。比如你在feature分支上基于旧主干做了3个提交主干上同事又提交了2个git switch feature git rebase main后你那3个提交会被放到主干最新提交的后面历史变成一条完全线性的线。# Rebase 前 main: A--B--C feature: A--B--D--E # Rebase 后 main: A--B--C feature: A--B--C--D--E注意D和E的哈希会变化因为提交的父提交变了。这也引出一条铁律不要对已经推送到共享远程分支的提交做rebase因为那会重写远程别人可能基于的历史合作者的本地分支一旦落后就会出一堆难解的冲突。rebase只适合在个人功能分支上做。那实际工作中怎么选我的经验是个人功能分支在合并回主干前想让它保持干净、迅速跟上主干的最新变更用git pull --rebase或git rebase main。最终把一个完成的功能合进主干、保留合并记录时用git merge --no-ff feature/xxx。--no-ff会强制生成一个合并提交方便后面知道这是一次功能合入。4.3 冲突解决一次完整的实战记录冲突是很多人对Git望而生畏的原因。但我想说冲突的本质不是“出错了”而是Git发现两个分支对同一处内容做了不同的修改它不知道怎么替你决定只能把问题交给人。我构造一个简单的冲突场景假设main分支上文件README.md有一行是version: 1.0feature/style分支也基于这一行做了修改。两边同时改了这行合并时就会冲突。git switch main git merge feature/styleGit的输出会类似Auto-merging README.md CONFLICT (content): Merge conflict in README.md Automatic merge failed; fix conflicts and then commit the result.打开README.md会看到冲突标记 HEAD version: 2.0 version: 2.1 feature/style HEAD到之间是当前分支的内容到之间是待合并分支的内容。你需要手动判断这两行应该保留谁、怎么合并。比如最终决定升级为2.0那就把version: 2.0留下来删掉其他所有标记行version: 2.0然后git add README.md git commit -m merge: 合并feature/style分支解决README版本号冲突冲突解决本身不难难的是对代码逻辑的判断。我强烈建议在IDE里可视化解决冲突比纯命令行看标记要直观得多。IntelliJ IDEA、VS Code都提供左右对比和三方合并界面能直接看到“哪个版本改了哪一行”。4.4 stash切换分支前的救命技能开发到一半突然需要切到另一个分支处理紧急问题但手头还有未提交的改动。直接git switch可能会被拒绝因为工作区有冲突的未提交内容。这时候用git stash把当前改动暂存起来切换分支办完事再切回来恢复git stash # 保存当前未提交的改动 git switch main # 干别的事 git switch feature/xxx # 回来 git stash pop # 恢复之前暂存的改动git stash list可以查看暂存列表git stash pop会弹出最近一个并应用。如果多个stash堆在一起可以用git stash apply stash{1}来指定。这个命令在开发节奏比较快的时候特别实用算是切换分支前的一道保险。5. 远程协作与SSH认证失败从clone到push的完整链路排查5.1 远程仓库的本质origin只是个默认别名本地仓库和远程仓库之间的关系通过git remote来管理。添加一个远程地址git remote add origin gitgithub.com:yourname/your-repo.git git remote -v # 查看当前所有远程地址这里的origin只是一个默认别名可以随意改。一个本地仓库可以配置多个远程比如origin指向GitHub、internal指向公司内部GitLab需要推送时指定不同remotegit push origin main git push internal release/2.0远程地址有两种协议HTTPS和SSH。HTTPS首次操作会提示输入账号密码或Personal Access TokenSSH则基于一对本地私钥和远程公钥完成认证不需要每次输密码。对于频繁操作的开发者SSH是更顺手的方案。后面会遇到的各种报错大半都集中在SSH认证上。5.2 从零配置SSH Key并验证是否可用先在本地生成密钥对。现在的版本都推荐RSA 4096或Ed25519算法我一般直接用Ed25519ssh-keygen -t ed25519 -C 你的邮箱或备注一路回车可以它会默认生成在~/.ssh/id_ed25519和~/.ssh/id_ed25519.pub。其中.pub是公钥可以公开没有后缀的私钥文件绝不能泄露。然后把公钥内容复制出来cat ~/.ssh/id_ed25519.pub复制整行打开代码托管平台GitHub/GitLab/Gitee的SSH Keys设置页粘贴保存。这一步是让远程平台“认识”你的电脑。验证是否成功ssh -T gitgithub.com如果配置正确会看到一句带有你用户名的欢迎信息。看到它说明私钥公钥的匹配链路已经通了。5.3 认证失败的三种高频场景与完整排查链路SSH认证失败的报错通常长这样gitgithub.com: Permission denied (publickey). fatal: Could not read from remote repository.这种问题在网络或者团队里经常出现。我总结出三种高频原因按排查顺序排列。**场景一根本没生成密钥或公钥没加到平台。**这是最常见的情况。排查步骤看~/.ssh下有没有id_ed25519和id_ed25519.pub文件没有就重新生成。把.pub文件的内容粘贴到平台SSH Keys设置页。再用ssh -T gitgithub.com验证。**场景二生成了密钥但ssh-agent没加载或者加载了错误的密钥。**确认本地ssh-agent在运行并加载了私钥eval $(ssh-agent -s) ssh-add ~/.ssh/id_ed25519 ssh-add -l # 查看已加载的密钥列表有些系统重开后agent需要重新加载这个步骤容易被忽略。**场景三本机有多对密钥用错了私钥。**这个在个人电脑上尤其常见办公电脑既连公司GitLab又连个人GitHub默认的私钥可能只对其中一个平台有效。解决办法是在~/.ssh/config里配置主机别名指定不同域名使用不同的私钥文件Host github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519_github Host gitlab.company.com HostName gitlab.company.com User git IdentityFile ~/.ssh/id_ed25519_work配置好后用ssh -T gitgithub.com验证立即生效。另外提一个机率不高但真实存在的情况~/.ssh目录或私钥文件的权限过于宽松OpenSSH会拒绝信任。Linux/macOS下把目录权限设为700、私钥设为600chmod 700 ~/.ssh chmod 600 ~/.ssh/id_ed25519排查这类问题可以用详细日志模式逐步查看认证过程卡在哪一步ssh -vT gitgithub.com日志里如果看到Offering public key说明在尝试你的私钥如果远程一直No more authentication methods to try基本就是公钥没配对或私钥不被接受。5.4 push之前的习惯先pull再push少睡几个安稳觉远程分支在团队协作中时刻在变化。如果你改完代码直接git push但本地分支已经相对远程落后Git会拒绝推送并提示你先拉取更新。这其实是保护不是报错。git pull # 等价于 git fetch git merge git pull --rebase # 更推荐把本地的提交放到远程最新提交之后如果本地和远程都改动了同一处pull时同样会触发冲突解决流程和前面合并冲突一样。养成push前先pull --rebase的习惯能减少大量不必要的合并节点历史也干净。6. 从命令行回到IDE用IDEA拉取Git项目的完整实操6.1 用IDE从远程仓库拉取新项目很多初学者觉得Git是纯命令行的东西其实主流IDE的集成已经做得很成熟。以IntelliJ IDEA为例Studio开发场景里最常见的操作就是“从Git拉取项目到本地”。打开IDEA的欢迎页点击Get from VCS在弹窗里选择Repository URL粘贴远程仓库的SSH或HTTPS地址选择存放目录点Clone即可。这对应的命令行操作其实就是一个git clone gitgithub.com:yourname/your-repo.git如果认证链路通Clone过程几乎是无声完成的。拉下来的项目IDEA会自动识别Git根目录并提供完整的Git集成面板。拉完如果提示无法连接或认证失败要回到上一节讲的SSH排查链路去查IDE只是个客户端底层认证逻辑是一样的。6.2 提交、推送和分支操作在IDE里的映射日常开发流程在IDEA里可以全程用快捷键完成右键项目或修改的文件选择Git Commit Directory...对应的命令是git commit。提交面板左侧能看到本次改动的差异对照勾选要提交的文件填好提交信息再提交。提交面板里有一个Commit and Push...按钮点它等于git commit加git push一气呵成。右下角的分支菜单显示当前分支可以New Branch创建、Checkout切换、Merge Into Current合并。IDE最值钱的其实是冲突解决工具。命令行里只能看到标记IDE则把双方版本并排展示还能选择“左右合并的某一部分”。团队合作中复杂冲突基本都靠它处理。6.3 拉取新项目后的三件套检查用IDE拉下项目别急着开始写代码先花一分钟检查三件事检查.gitignore是否把.idea目录忽略了。IDE的目录里存着个人配置和项目级本地配置一旦提交进仓库每个成员的本地路径、编码设置、插件状态会互相干扰。没忽略就第一时间补上并提交。检查项目根目录是否识别正确。有时IDE识别到的Git根目录和项目实际根目录不一致导致提交时只包含子目录。打开Git Git Repositories面板看根目录位置即可。检查git remote -v是否指向预期地址。从旧电脑迁移开发环境时最容易把远程地址指向旧的、已废弃的仓库。还有个小提醒IDEA首选项里有一个Git Repository Ignore files and folders的全局忽略列表如果在IDE里看不到某些文件但他们确实存在看看是不是被这个全局规则过滤了。团队协作规范里通常推荐IDE相关的文件放进项目.gitignore而不是依赖个人工具的全局忽略否则换个机器或者换个同事的IDE环境配置就各不一致了。7. 高频翻车点补遗detached HEAD、误删分支、换行符陷阱7.1 detached HEAD游离头指针是怎么发生的有些开发者在排查问题时喜欢直接git checkout某个提交哈希比如git checkout 7a4e2f9Git会提示你“HEAD is now at 7a4e2f9...”这时就进入了detached HEAD状态。意思是你当前不在任何分支上HEAD直接指向了那个提交。在这个状态下做新提交提交会挂在一个不被任何分支引用的位置之后你切回其他分支这些提交就“游离”了很容易丢掉。解决办法也很简单觉得这些提交有价值就当场创建一个分支把它保住git switch -c temp-branch从日常使用的角度更稳妥的做法是用git switch 分支名 --detach明确自己是在游离状态或者用git log先看清结构再决定要不要临时切过去。养成“只在明确目的下检查历史提交”的习惯就不会频繁触发detached HEAD。7.2 误删分支与误丢提交的恢复git branch -D feature/xxx删掉一个分支后如果发现还需要里面的提交第一反应别慌。Git的reflog会记录你本机所有HEAD指针的移动历史包括被删分支的提交位置git reflog输出里能找到类似8c6d4a2 HEAD{3}: branch: Created from...这样的记录记下那个哈希然后用它重建分支git branch feature/xxx 8c6d4a2reflog同样能救回被git reset --hard丢弃的提交。只要提交还在本地对象库里reflog就有它的线索。这也是我一直强调的误操作后先查reflog再做决定。但注意reflog有有效期默认90天内可恢复过期后就真的找不回来了。7.3 换行符、大小写和误提交大文件三种诡异现象的根源先说说换行符。前面配置里提过core.autocrlf如果团队成员配置不一致会出现“根本没改代码diff却显示整个文件全红”的现象。治本的办法是在仓库根目录添加.gitattributes文件强制统一规则* textauto *.sh text eollf *.bat text eolcrlf这样不管各人电脑是什么系统Git都会按仓库规则自动转换。再说文件大小写。在默认配置下Git对文件名是大小写敏感的但文件系统尤其在Windows/macOS上不敏感。把一个文件从User.java改名为user.java你改了文件名后Git可能毫无感知提交后远程还是旧名字。需要显式操作git mv User.java user.java或者改完名后git add -A处理。团队规范里最好直接约定文件名一律统一命名风格避免无谓的大小写切换。最后说误提交大文件。项目里有人不小心把几百MB的安装包或数据库备份提交进了仓库Git会把整个对象永久保存在历史里即使后续删除仓库体积也不会变小。遇到这种情况轻则克隆慢重则撑爆服务器的仓库配额。实用的处理方式是立即停止继续提交新增提交移除该文件再重写历史剔除误提交的大文件对象。如果历史不复杂也可以直接用filter-repo这类工具清洗。不过更省心的办法是在源头就杜绝时刻维护.gitignore并约定“超过几十MB的文件一律不放版本库”。这些年我最大的感受是Git的报错大多不是坏事它是在帮你把危险操作拦在门外。真正要修炼的不是背下所有命令而是理解“快照、指针、引用”这套模型并固化成小步提交、清晰分支、勤pull、善用reflog的工作习惯。还有一个开头提到的习惯可以再强调一次每次git commit之前先看一眼git diff确认你提交的真是你想提交的东西。这个小动作让我少了很多“提交了个寂寞”的尴尬瞬间。