Git 从安装到原理:一文掌握版本控制与分支管理

发布时间:2026/9/14 0:08:59
Git 从安装到原理:一文掌握版本控制与分支管理 干这行越久越发现一个扎心的事实很多写了几年代码的同事Git 用得依然是“三板斧”——clone、add、commit、push遇到冲突要么乱改一通要么喊人帮忙。Git 不是背命令的考试它是你每天吃饭的筷子。用不好 Git浪费的不是时间是你的耐心和信任。我打算用一整篇的篇幅把 Git 从安装、配置到原理、进阶、排错完完整整捋一遍。这不是官方文档的翻译是我自己这些年踩坑踩出来的实战总结。不管你是刚入门的新手还是用了一段时间但总觉得“差点意思”的开发者这篇内容都值得你花半小时看完。看完你会发现Git 原来没那么玄乎理解了它的设计逻辑之后很多命令根本不用死记硬背。1. Git 到底是什么以及它凭什么能“救你的命”先聊一个最根本的问题Git 解决的是什么痛点想象一下没有版本管理的日子——你写了一个文件改了几版之后文件名变成了论文_最终版_v3_不要再改了.docx。过两天你又改了一版发现改坏了想回退结果发现最终版_v3已经是改坏之后的版本了你再也找不到之前那个能跑通的状态。程序员的版本管理要是也这么干那项目部早就炸了。Git 就是干这个的它把你每次的改动记录成一个“快照”你可以在任意时间点穿梭、对比、回退、合并。它不是简单地存几个备份文件而是通过一套精密的存储模型让你能够像操作时间线一样操作代码。1.1 分布式和集中式到底差在哪你肯定听说过 Git 是“分布式版本控制系统”跟 SVN 这种“集中式”不一样。这话听着专业但很多人其实没真正理解。集中式比如 SVN所有代码存在中央服务器上每个人从服务器拉最新代码改完再提交上去所有人都围绕一个中心点转。这有个致命问题服务器挂了或者网络不通你没法提交代码历史记录也查不了。分布式比如 Git每个人的本地都是一个完整的仓库包含所有历史记录、所有分支。你可以离线提交、离线查看历史、离线创建分支一切操作都在本地完成。之后你选择什么时候把本地的提交推送到远程什么时候从远程拉取别人新增的提交。这就是“分布式”三个字的真正分量——你的电脑不只是个工作副本它本身就是仓库。这也带来了一个直接的体验差异Git 的操作速度飞快。因为大部分操作提交、查看历史、切分支都在本地完成不用经过网络git log这种命令基本上是毫秒级响应。用惯了 Git 再用回 SVN你会觉得每一步都在等服务器响应极其难受。1.2 Git 是 Linus 的“三天之作”但设计极精妙Git 的诞生背景也值得一提知道这段历史能帮你理解它为什么长这样。Linux 内核是世界上最庞大的开源项目之一维护者 Linus Torvalds 当年用的 BitKeeper 因为许可问题不让他们用了Linus 一怒之下自己写了一个版本控制系统据说两天还是三天就写出了第一个可用版本。这套系统设计的核心诉求就是高性能、分布式、能支撑 Linux 内核这种超大型项目的日常协作。所以你如果觉得 Git 的命令设计得反直觉、缩写诡异、概念抽象别怀疑自己——它本来就是个“天才给自己写的趁手工具”后来才被推广成全民工具。这也解释了为什么网上有大量 Git 疑难杂症的帖子因为它的学习曲线确实有一定高度。但一旦你理解了它背后的对象模型和数据流一切都豁然开朗。2. 从零开始安装、配置与“小乌龟”实战别嫌这步简单我见过太多人卡在“装不上”“配不好”的阶段。这节我把 Windows、macOS、Linux 三种系统的安装和初始化配置都过一遍顺便聊聊 Git 自带 GUI 和 TortoiseGit小乌龟的选择问题。2.1 Windows 安装下载、选项、环境变量一次说清Windows 下安装 Git 最标准的做法是去 Git 官网下载 Git for Windows。如果官网访问慢国内也有不少镜像站提供同版本安装包具体版本号以你下载时为准。下载下来是.exe文件双击运行。安装过程中的选项目比较关键我逐个说Select Components如果你以后可能要在 Bash 里写 Linux 风格脚本建议勾选“Git Bash Here”和“Git GUI Here”这样右键菜单会多出入口按钮使用非常方便。Default editor默认是 Vim劝新手别硬刚 Vim建议选 Notepad 或者 VS Code不然你第一次写 commit message 时会被困在 Vim 里不知道怎么退出按:wq可以保存退出但新手真不一定知道。Adjusting your PATH强烈建议选第一项 “Git from the command line and also from 3rd-party software”。如果这里选错了你之后在 PowerShell、CMD 里敲git会直接报错比如最常见的那个报错——git : 无法将“git”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。如果你已经装完发现命令行里git用不了多半就是 PATH 没有配置好。解决办法手动把 Git 的安装目录下的cmd文件夹路径常见的是C:\Program Files\Git\cmd加到系统环境变量的Path里然后重开一个终端窗口。Line Ending Conversions这步是很多新手困惑的重灾区。Windows 用 CRLF 换行Linux/macOS 用 LF 换行。如果团队有人用 Windows、有人用 macOS换行符不一致就会导致明明只改了一行Git 却显示整文件都被改了。我推荐选 “Checkout as-is, commit as-is” 或者 “Checkout Windows-style, commit Unix-style”前者是让 Git 保持文件原样后者是 checkout 时转成 Windows 换行commit 时转成 LF。具体根据团队协作情况定但一定要统一规则否则后面全是坑。这个我在后面“常见问题”里还会专门展开。安装完成后打开 Git Bash 或者 CMD输入git --version看到版本号输出就说明装好了。2.2 macOS 和 Linux 安装macOS 上装 Xcode Command Line Tools 的时候会带上 Git。但你如果想要更新的版本建议通过 Homebrew 安装brew install gitLinux 直接用系统包管理器# Debian/Ubuntu sudo apt update sudo apt install git # CentOS/RHEL sudo yum install git不管哪个系统装完之后都建议先看一眼版本确保装的是新版旧版本部分命令行为会有差异。2.3 必做的全局配置身份、换行符、别名装好 Git 之后第一件要紧事是配置你的身份信息。没有它你根本没法提交——提交时 Git 会强制要求知道“谁”在提交git config --global user.name 你的名字 git config --global user.email 你的邮箱这里有个细节这个邮箱不要求一定是真实邮箱但建议用你注册 GitHub/Gitee 的邮箱这样提交记录能正确关联到你的账号上。不少人随手填了个123456qq.com后面统计贡献度时发现全是“无名氏”追悔莫及。然后是换行符的全局配置Windows 下可以执行git config --global core.autocrlf truemacOS/Linux 下执行git config --global core.autocrlf inputcore.autocrlf true表示提交时自动把 CRLF 转成 LF检出时把 LF 转成 CRLF。input表示提交时转 LF检出时不转。这组配置能极大减少跨平台协作时换行符带来的 diff 噪音。再配两个别名能省不少事git config --global alias.st status git config --global alias.lg log --graph --prettyformat:%h -%d %s (%cr) %an --abbrev-commit以后你就可以用git st看状态用git lg看漂亮的提交记录图。2.4 配置 SSH 密钥Gitee 和 GitHub 的免密通行证每次 push 都输账号密码表面上是安全实际是浪费生命。我建议配置 SSH 密钥一劳永逸。生成密钥的命令ssh-keygen -t rsa -b 4096 -C 你的邮箱一路回车就行默认会生成在~/.ssh/id_rsa.pub。然后查看公钥内容cat ~/.ssh/id_rsa.pub复制输出的内容到 Gitee 的“设置—SSH公钥”或者 GitHub 的“Settings—SSH and GPG keys”里粘贴保存。之后克隆仓库时用 SSH 地址gitgithub.com:用户名/仓库名.git或gitgitee.com:用户名/仓库名.git就不再需要输密码了。我遇到过一种情况密钥配置好了但连接时提示Permission denied (publickey)。排查思路一般是先确认ssh-agent是否运行密钥是否加载eval $(ssh-agent -s) ssh-add ~/.ssh/id_rsa如果还是不行检查你是不是用了自定义文件名的密钥。如果密钥文件名不是默认的id_rsa还需要在~/.ssh/config里配置IdentityFile路径。这些都是细节第一次配好后面能省心很多年。2.5 TortoiseGit小乌龟到底要不要装“小乌龟”是 Windows 上最经典的 Git 图形客户端它的标志性优势是集成到资源管理器右键菜单里你无需打开命令行在文件夹里右键就能完成提交、更新、查看日志等操作。安装小乌龟略繁琐先装 TortoiseGit 本体再装一个语言包还得在设置里改成中文。安装时它会自动探测你电脑上的 Git 安装路径如果找不到就得手动指定。日常用法图标叠加文件有修改时显示红色感叹号、右键提交、右键更新pull、右键显示日志show log——对不习惯命令行的朋友确实很友好。我的建议分场景如果你只是偶尔提交代码、改改文件小乌龟够用了如果你每天大量操作 Git跟分支、改冲突、处理复杂情况命令行依然是效率最高的方式图形界面反而会限制你理解 Git 真正发生了什么。3. 核心原理三个区域、对象模型以及 Git “快”的秘密从这节开始你学到的将不是“怎么敲命令”而是“命令为什么是这样设计的”。理解了原理之后你会发现自己对 Git 的恐惧感消失了很多问题不再需要百度。3.1 工作区、暂存区、版本库和远程仓库的关系用一张图在脑子里构建 Git 的存储模型。理解以下四个概念就掌握了 60% 的 Git工作区Working Directory就是你在电脑里能看到的那些文件和文件夹你天天编辑的就是这里。暂存区Index / Staging Area一个隐藏的区域你运行git add后文件的“准备提交”版本会被放到这里。它是工作区与版本库之间的缓冲区。本地版本库Local Repository在你项目根目录的.git文件夹里保存着你所有的提交历史和对象数据。远程仓库Remote Repository就是 GitHub、Gitee 或者你自己服务器上的那份仓库用于多人协作和备份。它们之间的关系可以用一句话概括你在工作区修改文件挑选一部分改动用git add放上暂存区然后通过git commit把暂存区的内容打包成一个提交存入本地版本库最后通过git push推送到远程仓库。为什么要设计暂存区这么一层因为现实中你经常会同时改多个文件但有些改动是一个功能有些改动是另一个功能。没有暂存区你只能一个接一个提交每次提交都带上所有未提交的改动。有了暂存区你可以精确挑选哪几个文件进入下一次提交让每次提交的语义更清晰。这就是 Git 被称为“优秀的提交管理工具”的原因之一。3.2 Git 对象模型blob、tree、commit 和 tagGit 内部本质上是一个存储对象的数据库。理解这几个对象类型你就看透了 Git 的底层逻辑blob文件内容的快照。Git 不管文件名只管内容内容相同就复用同一个 blob。tree目录结构的快照它记录了目录里有哪些文件、每个文件对应哪个 blob、以及子目录对应的 tree。commit一次提交它包含指向某个 tree 的引用、父提交的引用、作者信息、提交信息等。tag一个固定的引用通常指向某个 commit用作里程碑标记。当你运行git commit时Git 实际上做了这样的事把暂存区里的文件内容写入对象库生成 blob把这些 blob 按目录结构组织成 tree再生成一个 commit 对象指向这个 tree最后把当前分支的指针更新到新的 commit。这解释了 Git 一个很多人会觉得“玄乎”的地方为什么 Git 存储的不是差异diff而是快照snapshot因为每次提交Git 都完整地记录了当时所有文件的内容。空间占用看起来会很大但 Git 内部有压缩和去重机制相同内容的 blob 不重复存储实际空间开销远比你想象的小。而快照模型带来的是极致的读取速度——切换分支、对比历史都不需要去“算”出某个版本的文件内容直接拿出来用就行。3.3 分支为什么“轻”得惊人——指针的艺术理解了对象模型分支就不难了。在 Git 里分支本质上只是一个指向某个 commit 对象的可移动指针。当你创建一个新分支时Git 并不是复制文件而是创建了一个 41 字节的指针文件。所以 Git 创建分支、切换分支才那么快——它只是把 HEAD 指针从一个 commit 挪到另一个 commit然后更新工作区文件。如果你切到历史很旧的分支看起来好像“代码变了”其实不是 Git 帮你改了代码只是工作区的文件被替换成了目标 commit 对应的快照。这个指针模型还能解释很多“怪现象”为什么git branch能秒建几十个分支因为只是新建指针。为什么git checkout能迅速在不同分支间跳转因为本质是移动指针。为什么 Git 鼓励多建分支因为分支的创建和销毁成本极低这是分布式开发模型的最大红利。理解指针模型还有一个好处未来你把git reset、git merge、git rebase理解了它们本质上都是在移动指针或创建新的提交而不是“魔法”。4. 日常实战克隆、提交、分支、合并一次打通原理讲完了说点能直接上手的。这一节我从最常用的操作讲起带你走一遍日常开发的主流程。4.1 克隆仓库与完整提交流程得到一个新项目的第一个动作通常是克隆git clone 远程仓库地址这会在你当前目录下创建一个跟仓库同名的文件夹并把默认分支通常叫 main 或 master的最新代码拉下来。克隆下来后你就可以开始改了。日常开发主循环是这几个命令# 1. 查看当前状态红色标识未跟踪或已修改文件 git status # 2. 把文件加入暂存区可以用 . 表示所有改动 git add . # 3. 查看暂存区与前一个提交的差异绿色显示 git diff --cached # 4. 提交写清改动说明 git commit -m feat: 新增登录功能 # 5. 推送到远程仓库 git push我每次提交前几乎都会执行git diff --cached看一眼自己到底改了什么东西防止把调试代码、临时输出、敏感信息误提交上去。这一步看着多余实际上能救你无数次。4.2 提交规范怎么写 commit message 才不招人烦提交信息不是随便写几个字就完事的。一个团队如果提交习惯差一个月后看提交历史根本不知道每个 commit 改了些什么。推荐 Angular 提交规范这也是目前开源社区最通行的一套结构是type(scope): subjectTypes 常见取值feat新功能featurefix修复 bugdocs文档变更style格式调整不影响逻辑refactor重构既有功能不变perf性能优化test增加或修改测试chore构建过程或辅助工具的变动举个例子git commit -m fix(login): 修复密码错误时无提示的问题这样写的意思一目了然这次提交修复了登录模块的一个 bug具体问题是密码错误时没有提示。看历史的人不用打开代码就能知道每次提交的意图配合git blame定位问题也会有价值得多。如果你觉得命令行写多行 commit message 太麻烦可以用git commit不带-mGit 会打开你配置的编辑器在那里可以写标题和正文推荐正文部分写清楚“为什么改了这些”。4.3 reset、revert、restore三个撤销命令一招分清“我想撤销刚才的提交”“我想把工作区恢复原状”“我想放弃某个文件的修改”——这些需求分别对应不同命令很多人搞混了。我按“目标”来梳理git restore file丢弃工作区的改动把文件恢复到最近一次提交或暂存的状态。适合“我改坏了还没 add”的场景。git reset移动当前分支的 HEAD 指针。用于撤销提交有三种模式参数作用区域变化--soft只移动 HEAD不动暂存区和工作区改动保留在暂存区--mixed默认移动 HEAD重置暂存区不动工作区改动保留在工作区--hard移动 HEAD重置暂存区和工作区改动彻底丢失--hard是一个非常危险的操作它会把工作区文件直接重置掉未提交的改动会彻底消失。用之前务必确认。git revert commit通过创建一个新的反向提交来抵消指定提交的改动。这是“安全回滚”的首选尤其是修改已经 push 到远程的情况下因为 git revert 不会改写公共历史不会造成别人 pull 时的冲突。一句话改坏了还没提交用restore提交了但没推送想重写历史用reset提交了且已推送想安全回滚用revert。4.4 分支管理feature、merge、rebase 的正确姿势日常开发中主分支main/master通常要保持稳定。每次开发新功能时从主分支拉一个新的功能分支# 基于当前分支创建并切换到新分支 git checkout -b feature/login开发完、测试通过、把改动合并回主分支# 先切回主分支拉取最新远程代码 git checkout main git pull # 合并功能分支 git merge feature/login合并之后常用的清理动作git branch -d feature/login git push origin --delete feature/login-d只能删除已合并的分支如果分支还有未合并的提交Git 会拒绝需要换成-D强制删除。这个保护机制很有用防止你误删掉还有价值的工作。关于git merge和git rebase的选择合并会产生一个真实的合并提交保留分支聚合的轨迹变基会把你当前分支的提交“重新放”到目标分支的顶端让提交历史变成一条直线更整洁。我的建议是公共分支、几个人协同的分支上用 merge 更安全自己一个人开发的功能分支想保持历史干净可以用 rebase。4.5 冲突处理别慌一步一步来冲突是 Git 入门者的噩梦。但说白了冲突只不过是 Git 在问你同一块地方两个人做了不同的修改我该听谁的比如你和同事同时改了login.js的第 10 行他先提交了你再 pull 时就会冲突。出现冲突后Git 会在冲突文件里标记 HEAD 这是你当前分支的内容 这是别人分支的内容 feature/login处理步骤用编辑器打开冲突文件你会看到上面这种标记。手动选择保留哪部分代码、删除哪部分或者两边合并。删除所有、、标记。保存文件然后git add该文件再git commit完成合并提交。避免冲突最有效的手段是频繁 pull 最新代码每次 pull 之后立刻测试。冲突发生得越晚上下文差异越大解决成本越高。经常跟远程同步可以最大程度减少同时间同区域修改的概率。5. 进阶玩法Git 服务器搭建、忽略文件与安全加固如果你只是个人开发用 GitHub 或 Gitee 就够了。但公司内部代码一般不建议放公网你需要自己搭一个 Git 服务器。这也是从“会用 Git”走向“懂 Git”的一个重要台阶。5.1 自己搭建 Git 服务器Gitea 与 GitLab 的选型搭建 Git 服务器的方案有好几种从轻量到重量排个序纯 Git 裸仓库最轻量在 Linux 服务器上创建一个裸仓库通过 SSH 协议共享。适合个人或极小团队但缺少权限管理、代码审查、Web 界面。Gitea一个非常轻量的 Git 服务程序内存占用小部署快自带 Web 界面、账户体系和简单的代码审查。对大多数中小团队来说Gitea 完全够用了。GitLab功能非常全CI/CD、代码审查、权限模型、安全扫描等都内置了但资源占用大官方建议至少 4GB 内存适合对功能和集成有高要求的团队。我个人给团队搭建时默认方案是 Gitea。它的安装太友好了下载对应平台的二进制文件或者用 Dockerdocker run -d --namegitea -p 3000:3000 -p 22:22 -v /var/lib/gitea:/data gitea/gitea:latest启动后浏览器访问 3000 端口按提示做初始化配置就能在网页上创建仓库、添加 SSH 密钥了。整个过程不到十分钟。之后成员使用跟 GitHub 的体验基本一致克隆、推送、拉取都一样。5.2 Git 目录泄露风险与应对聊一个偏安全的话题。git目录泄露是指网站的.git目录被错误地暴露在公网上导致任何人都能通过浏览器直接访问.git目录里的对象文件进而用工具恢复出整个源代码仓库。这是很常见的错误部署方式——很多人在发布网站时直接把整个开发目录上传忘了排除.git文件夹。作为开发者你要注意两件事自己不要踩这个坑。部署时用.gitignore不影响.git目录的排除部署前务必确认.git不会被上传到服务器。静态站点部署尤其注意建议在服务器配置层禁止访问.开头的目录。发现泄露后的处理。如果真的不小心把.git目录暴露了第一时间收紧目录访问权限、移除公网访问路径并且加固服务器配置。如果是别人部署的系统泄露了应及时联系提醒处理。生产环境服务器上如果存在.git目录建议做一次排查。Git 目录泄露反映出的核心问题是对 Git 机制理解不足——.git目录是整个仓库的“内核”里面装着全部历史记录和对象数据暴露它就等于把源码和历史全部交了出去。5.3 忽略文件 .gitignore 的正确姿势.gitignore是项目里必须有的文件用来告诉 Git 哪些文件不要纳入版本管理。常见的需要忽略的临时文件、日志、编译产物、依赖目录如node_modules/、本地配置、IDE 配置、密钥文件等。一个典型的 Node.js 项目 .gitignore 长这样node_modules/ dist/ *.log .env .DS_Store .idea/ .vscode/这里强调几个经验密钥、环境变量文件.env、config.local.js必须忽略否则一旦提交到 Git 历史里即使后面删掉历史记录里依然存在这是泄露的高危区。.gitignore只影响尚未跟踪的文件。如果你之前已经把某个本应忽略的文件 add 过那么忽略规则不会生效需要先把它从版本库移除git rm --cached filename再添加到.gitignore里。尽量在项目创建的第一时间就把.gitignore建好避免后面处理“已经入库的垃圾文件”这种尴尬局面。5.4 Git 大文件存储LFS 能解决什么问题仓库里如果放了很多图片、视频、二进制安装包仓库体积会迅速膨胀克隆和拉取都会变得很慢。Git LFSLarge File Storage就是为这个场景设计的。LFS 的原理是把大文件替换成一个文本指针文件真正的文件内容存到 LFS 服务器上。克隆仓库时只下载指针文件只有真正 checkout 到大文件的版本时才去下载内容。这样历史仓库不会因为频繁修改大文件而无限膨胀。使用方式# 安装 LFS git lfs install # 跟踪指定类型的大文件 git lfs track *.psd *.zip # 提交 .gitattributes git add .gitattributes git commit -m chore: 配置 Git LFS要注意的是LFS 只是把大文件的存储方式改了并不是万能药。如果可以不往仓库里放大文件尽量别放。如果是超大单体文件考虑构建产物走专门的制品库源码仓库保持精简。6. 高频报错速查我把这些年踩过的坑都贴在这最后这部分我把使用 Git 过程中遇到频率最高的报错和排查思路整理成表格。每个问题的描述、原因、解决办法都写清楚建议收藏遇到直接查。报错/现象常见原因解决办法git 无法识别为 cmdlet、函数、脚本文件或可运行程序的名称Git 未安装或未加入 PATH重新运行安装包勾选“Git from the command line”或手动将Git/cmd加入系统 PATHPlease tell me who you are未配置 user.name / user.email执行git config --global user.name 名字和git config --global user.email 邮箱Permission denied (publickey)SSH 密钥未配置或未加载检查~/.ssh/id_rsa.pub是否已添加到 Gitee/GitHub用ssh -T gitgitee.com测试连通性LF will be replaced by CRLF换行符配置不统一统一core.autocrlf配置Windows 用truemacOS/Linux 用input中文文件名显示为\346\265\213...未正确配置core.quotepath执行git config --global core.quotepath falsefatal: refusing to merge unrelated histories两个仓库没有共同历史如果确认要合并使用git pull origin main --allow-unrelated-historieserror: failed to push some refs to ...远程有新提交本地落后先git pull或git fetchgit rebase解决冲突后再 pushYour local changes would be overwritten by merge工作区有未提交修改和合并冲突先用git stash暂存改动合并完再git stash popUpdates were rejected because the tip of your current branch is behind远程分支领先于本地git pull --rebase后重新 push6.1 命令行没反应先看这五个地方有时候命令敲下去并没有报错但也没效果。这类“诡异”问题我通常按以下顺序排查看当前分支git branch确认你没在 detached HEAD 状态即 HEAD 没有指向任何分支。看远程分支同步情况git remote -v确认 remote URL 指向正确没配置错仓库。看 .gitignore是不是新文件被忽略了所以git add .没效果。看 index.lock如果.git/index.lock文件存在且进程已死会导致 Git 命令被阻塞。删除这个文件可以解决但前提是确认没有 Git 进程正在运行。看代理设置某些 Git 命令如 Clone 走 HTTPS会读取系统代理代理配置异常会导致超时或 fallback 失败。检查git config --global --list里是否有残留的 proxy 配置。6.2 小乌龟登录失败问题排查有同学用 TortoiseGit 配合 GitLab/Gitee 时遇到过这样的提示login failed. check api token or gitlab version. log in via git if the version...。这种情况主要发生在小乌龟的某种“Git 远端”集成场景下通常和 API Token 有关。遇到这类问题我的处理思路是检查远端地址是否使用了正确的带 token 的 URL 格式。检查 token 权限是否足够比如只给了 read 权限却想 push。最省事的做法不要依赖小乌龟的远端集成认证改用 SSH 方式连接仓库密钥配好了就不用管理 token 过期的问题。另外小乌龟的某些“远端”用了应用的 API 能力如果服务端版本比较老、接口不兼容也会报这个错。升级 TortoiseGit 到最新版往往能解决这类兼容性问题。6.3 一个实用技巧 stash把临时改动存起来场景你正在功能分支上改代码改了一半突然需要紧急修一个线上的 bug。你不能把没写完的代码提交上去但切分支又会因为工作区有未提交改动而被拒绝。这时候git stash是你的救星git stash git checkout main git pull # 紧急修复... git checkout feature/login git stash popgit stash会把工作区的未提交改动暂时存到一个栈里让工作区恢复干净。git stash pop再把之前存起来的改动弹回来。这个命令我几乎每周都会用到是非常高频的实用技巧。如果你想看到 stash 列表用git stash list如果弹回来后冲突了处理冲突的方式跟普通合并一样解决后git add即可。最后再分享一点我的个人体会Git 学了很久之后我才想明白一件事很多人觉得 Git 难难的不是命令而是心智模型。一旦你搞懂工作区、暂存区、版本库、远程仓库四个概念明白分支是指针、提交是快照那些看起来“乱糟糟”的命令其实自然而然就有了归属感。所以我的建议是别急着背命令表先把原理啃下来然后在实操中不断加深理解。每遇到一个报错都是一次加深理解的机会。真要在面试或者同事面前“露一手”你不一定要背出所有命令但你能讲清楚git pull实际上做了 fetch 和 merge 两件事、git reset --hard为什么会丢代码、为什么 Git 切分支这么迅速——这些远比默写命令列表更有说服力。工具永远服务于人。Git 不是用来折磨你的它是用来保护你的时间和心血的。希望你把它真正变成自己的武器而不仅是几行指令。