Git入门到实战:版本管理、分支协作与远程仓库全攻略 你电脑里是不是有一堆这样的文件论文终版.doc、论文终版2.doc、论文真的不改了.doc、最终版打死也不改了.docx如果是那你急需 Git。如果你们团队协作还是靠“我改完发你你再改完发我”的微信文件传输模式那你也该认识一下 Git 了。很多人把 Git 当成一个“程序员专用工具”其实它本质上就是一个极其好用的“版本管理神器”你能用它管代码、管文档、管配置甚至可以管你写书的草稿。这篇文章我不打算给你讲太多高深理论我也不会把它写成一本 Git 教科书。我就按照我自己从零折腾 Git 到真正在工作中用明白的路子带你从安装配置、常用命令、分支协作再到 Gitee 远程仓库实战最后把高频问题一网打尽。保证你读完能直接上手在工作里立刻用起来。1. 为什么要用 Git先搞清楚它解决了什么1.1 从“版本管理”这件事说起想象一下你正在写一份年度总结报告改到第三版的时候领导说“还是第一版的感觉对”。如果你没有版本管理工具你可能已经完全找不回第一版了。就算你非常机智地存了第一版.doc、第二版.doc你怎么精确知道第二版和第一版之间到底改了什么第三版又删了哪些关键数据Git 解决的就是这件事。它把你每一次“我要保存一下当前进度”的动作都记录下来生成一个提交commit。每个提交里保存着这一个瞬间所有文件的快照以及这次提交相对于上一次提交改动的地方。这样你随时可以回到过去任何一个保存过的状态也可以随时对比任意两个版本之间的差异。它就像给你的整个工作目录安装了一台时光机想停在哪里就停在哪里。1.2 为什么选 Git 而不是 SVN 这类老牌工具很多老项目还在用 SVN。SVN 是集中式版本控制服务器挂了大家就都歇菜了Git 是分布式版本控制每个开发者本地都有一个完整的仓库历史服务器挂了你的本地照常提交等服务器恢复后再同步就行。这一点在出差、飞机上写代码时优势巨大。再有一个关键差异是分支的成本。在 SVN 里创建分支是个又慢又重的操作通常要复制整个目录所以很多团队干脆不分叉所有人都挤在主线上开发。Git 的分支创建和切换都极其轻量本质只是移动一个指针所以 Git 社区的协作玩法是“人手一个分支随时开叉随时合并”。这个差异直接决定了团队的协作效率和代码仓库的整洁度。1.3 Git 的核心价值观念后悔药自由任何一次误删、误改、误合并只要你有提交记录都能恢复。并行开发你和同事可以同时改同一个项目的不同模块互不干扰最后合并即可。代码审查通过分支和合并请求Pull Request 或 Merge Request别人在合入你代码之前可以清楚地看到你改了什么这比直接往主干上怼代码要安全得多。我自己在实际使用中体会最深的不是那些炫酷的高级命令而是git status和git log这两个“只读”命令。每当我迷茫的时候敲一下这两个命令看一眼当前在哪个分支、工作区有没有改动、历史上的提交是啥样心里就踏实了。Git 对你的要求其实不高——你先学会“查看状态”和“查看历史”这两个动作整个工具就变得不那么可怕了。2. 环境准备把 Git 装好并完成最基础配置2.1 各平台安装方式一览安装 Git 的教程网上满天飞其实核心就是三步下载对应平台的安装包、下一步下一步、打开终端验证。我按平台把关键点列一下。Windows去 Git 官网下载安装包或者用国内的软件管理器安装时注意几个选项开始菜单目录名保持默认即可。默认编辑器建议选 Vim 或 Notepad 都行或者选 VS Code 也可以。你要是完全没接触过 Vim我建议选 VS Code免得提交的时候不小心进了 Vim 不知道怎么退出。调整 PATH 环境变量选 “Git from the command line and also from 3rd-party software” 最保险这样无论你在哪个终端里都能直接敲git命令。行结束符转换选 “Checkout Windows-style, commit Unix-style line endings” 就行这个选项能有效避免大多数跨平台换行符问题。安装完成后打开命令行敲git --version能输出版本号就说明装好了。macOSmacOS 上最简单的方式是用 Homebrewbrew install git如果你没装 Homebrew也可以去官网下载 macOS 安装包。或者你只需要 Xcode Command Line Tools它自带了 Gitxcode-select --installLinuxDebian/Ubuntu 系sudo apt update sudo apt install gitRed Hat/CentOS 系用sudo yum install git2.2 安装后必做的基础配置Git 安装完成后第一件事不是急着建仓库而是告诉它“你是谁”。后续你每一次提交Git 都会把这些信息记录在提交记录里。如果没配提交的时候会弹出提示让你补。git config --global user.name 你的名字 git config --global user.email 你的邮箱这两条命令里的--global表示全局生效也就是在这台机器上所有 Git 仓库默认都会用这个身份。如果你某个特定项目想用不同的身份可以在那个项目目录里去掉--global再设置一次项目级别的配置会覆盖全局配置。顺便说一下很多人忽视了一个配置git config --global core.editor code --wait这个命令把默认编辑器改成 VS Code。我个人实测下来确实比默认的 Vim 对新手友好太多。你要是平时用其他编辑器替换成对应的启动命令就行。最后再推荐一个非常实用的配置git config --global pull.rebase false这是现在 Git 的默认行为你在拉取远程更新时不会意外地把历史改写成一条直线这一点在团队协作中能避免很多心理负担。这个选项用默认值就行不用特意去改。2.3 验证配置是否生效配置完成后可以敲git config --list这个命令会列出当前所有生效的配置项。你只要看到user.name和user.email都正确就说明环境就绪了。实测下来新手最容易栽的跟头反而是在 Windows 上安装了 Git 却找不到命令行入口。记住装完 Git for Windows 后在任意文件夹里右键选择“Git Bash Here”Git 命令就在这个终端里敲。别用系统自带的“命令提示符”去试不是说不行而是 Git Bash 的操作体验更接近 Linux命令兼容性更好。3. 高频命令实战把日常工作跑通3.1 工作区、暂存区、版本库这三个概念必须懂我见过太多人把 Git 命令背得滚瓜烂熟却始终不理解为什么会冒出个“暂存区”。简单打一个比方你在厨房里做菜工作区做好了先端到餐桌上暂存区拍完照发朋友圈生成提交后这顿饭才算正式记录在册版本库。这中间有个很重要的设计意图你可以一次改很多文件但可以分批次地提交比如把“修复 A 问题”相关的文件放到一个提交里把“新增 B 功能”的文件放到另一个提交里这样以后查历史的时候每个提交的目的都清清楚楚别人 code review 也轻松得多。在 Git 中三个区域的关系就是工作区Working Directory你当前能看到的、正在编辑的文件所在的地方。暂存区Staging Area / Index你通过git add把工作区中的改动“挑选”出来放到一个待提交的缓冲区。版本库Repositorygit commit之后暂存区里的内容被固化成一个新的提交永久记录在.git目录中。3.2 创建仓库从零开始假设你新建了一个项目文件夹myproject你想让 Git 接管这里的版本管理cd myproject git init执行完git init后文件夹里会多一个隐藏的.git目录所有版本信息都存在这里。如果你买了新电脑想把云端仓库克隆到本地就不用init而是git clone 远程仓库地址关于init和clone的选择init是你从零新建项目时用clone是拿到一个已存在的项目时用。两者不冲突你的绝大多数工作流程都会涉及这俩。3.3 日常三连add、commit、status现在你在项目里创建了一个文件README.md写了几行内容。当你准备“保存当前进度”时需要执行git add README.md git commit -m 初始化项目添加READMEadd是把改动放到暂存区commit才是真正生成一个版本记录。-m后面的内容是本次提交的说明这个说明非常重要。我看到太多人把提交信息写成“修改”“更新”“dev”这种信息回头看毫无价值。好的提交信息应该回答“这次改动做了什么、为什么”比如“修复用户登录时验证码过期问题”或者“优化首页图片懒加载首屏速度提升20%”。如果你想把所有改动一次性全部暂存包括删除和新建的文件可以用git add .但要注意git add .会把当前目录下所有未暂存的改动全部加进去。如果里面有临时文件、编译产物、密钥文件你就摊上大事了。所以更稳妥的做法是我后面要讲的.gitignore。执行完commit后强烈建议养成一个习惯看一眼git status。git status这个命令会告诉你当前工作区是否干净、哪些文件被修改过、哪些文件还在暂存区没提交。我工作这几年git status是使用频率最高的命令没有之一。3.4 查看历史与差异git log、git diff、git showgit log查看提交历史。默认展示一串提交哈希、作者、日期和提交信息。git diff查看工作区改动和暂存区/版本库之间的差异。git show查看某一次提交时具体改了哪些内容。如果你觉得git log输出的信息太冗长可以试试git log --oneline --graph --all这个组合命令会以一行一条提交的方式展示历史并且用图形化的分支线条展示分支合并关系非常直观。我每次看仓库结构都会用这条命令。git diff在使用时最常见的是两种场景想看看改了但没add的内容直接git diff想看看已经add但还没commit的内容用git diff --cached这些都是“只读”操作不会对仓库产生任何破坏你大可以随便敲。3.5 .gitignore 是保命符项目里总有一些文件是不该进版本库的比如编译输出目录node_modules、dist、build日志文件.log系统文件.DS_Store、Thumbs.db环境配置和密钥.env、*.pem你需要在项目根目录创建一个.gitignore文件把需要忽略的路径规则写进去。一个简单的示例node_modules/ dist/ *.log .env .DS_Store.gitignore的作用是让 Git 自动忽略这些文件和目录这样你执行git add .时就不会不小心把它们提交进去。这个文件本身应该提交到版本库因为它对团队所有人都有用。我踩过最大的坑就是项目早期没写.gitignore直接把包含数据库密码的.env文件提交到了仓库。虽然后来删了但历史记录里还留着最后不得不花一个下午清理 Git 历史还心惊胆战地怕密码泄露。所以新建项目的第一步先建.gitignore永远是值得的。4. 分支协作多人在一个仓库里不打架的玩法4.1 分支的本质平行世界的副本分支这个概念听起来玄乎其实可以理解成平行世界。你在主线通常是main或master上开发到一半突然想尝试一个激进的新功能。你不想把半成品直接往主线上怼免得队友拿到一个跑不起来的代码。这时候你就拉一个分支在分支里随便折腾成功了再合并回主线失败了直接丢弃对主线毫无影响。分支在 Git 里非常轻量创建分支就是创建一个指针指向某个提交对象。这也是 Git 和 SVN 显著的差异点。创建一个新分支并切换过去git branch feature-login git checkout feature-login或者一步到位git checkout -b feature-login现在你已经身处feature-login分支了你在这个分支里的提交不会影响main。等你的开发完成先切回main再合并git checkout main git merge feature-login4.2 合并时遇到冲突怎么办冲突是 Git 新人最害怕的场景但它其实并不可怕。冲突的发生条件很明确两个分支改了同一个文件的同一个位置Git 不知道谁说了算只能让你来决定。我举一个真实的例子。你在feature-login分支里改了README.md加了一句“这是一个登录功能项目”同时同事在main分支也改了README.md改成“这是一个电商项目”。你合并时会看到这样的提示Auto-merging README.md CONFLICT (content): Merge conflict in README.md Automatic merge failed; fix conflicts and then commit the result.打开README.md你会看到类似这样的内容 HEAD 这是一个电商项目 这是一个登录功能项目 feature-loginHEAD表示当前所在分支的内容feature-login表示被合并分支的内容。你需要手动决定保留哪一边或者两边都融合一下。编辑完后删除掉那些、、标记然后git add README.md git commit -m 解决README.md合并冲突重点说一下解决冲突的过程本质上就是你手动编辑文件的过程Git 不会替你智能合并有争议的片段。它的“自动合并”能力仅限于两个分支改动不重叠的部分。我实际工作中的体会尽量减少冲突的最好办法是勤提交、勤合并、小步快跑。一个分支存活的时间越长跟主线的分叉越大合并冲突的概率就越高。4.3 一个够用的分支策略主干-功能分支模式网上关于 Git Flow、GitHub Flow、GitLab Flow 的文章一抓一大把。对于小团队和大多数项目我强烈推荐最简单的模式main始终保持可发布状态代码稳定受保护不允许直接推代码。feature/*每个人从main拉出功能分支开发完合并回去。这样一个功能一个分支一个分支对应一次合并请求审查起来清清楚楚。至于更复杂的环境分支、发布时间线等团队规模上来了再考虑也不迟。4.4 远程分支把分支推到远端你本地创建了分支同事是看不见的。要把分支推到远程仓库git push -u origin feature-login-u的作用是建立本地分支和远程分支的关联。以后你再在这个分支上执行git push或git pull就不用再指定远程分支名了。从远程拉取一个新分支并切换过去git fetch origin git checkout -b feature-login origin/feature-login或者用简写git checkout --track origin/feature-login这里我想特别强调fetch和pull的区别。git pull本质上是git fetch加git merge的组合。fetch只是把远程的更新下载到本地但还没有合并到你的当前分支pull则是直接下载并合并。如果你不确定远程更新会不会对你的当前工作造成冲突可以用fetch先看看情况再决定什么时候合并。5. 进阶操作后悔药、暂存与历史穿梭5.1 git commit --amend 到底怎么用这个命令是热搜词里点名出现的估计不少人卡在这里过。git commit --amend的作用是修改最近的一次提交。它的典型使用场景有三个第一个场景提交信息写错了想重新改一下git commit --amend -m 正确的提交信息执行后最近一次提交的信息就被替换成新内容了提交哈希也会改变。第二个场景提交完发现漏掉了一个文件或者某个文件没保存完全git add 漏掉的文件 git commit --amend --no-edit--no-edit的意思是保持原有提交信息不变只把新暂存的内容并入前一个提交。这样你就不会为了补一个小文件而多出一个毫无意义的“fix typo”提交。第三个场景你想把前一次提交的内容整体重构一下比如发现之前提交的代码有严重 bug改完后又不想保留原来的提交记录那也可以直接修改文件后git add .再执行git commit --amend --no-edit。但是这里有一个极其重要的注意点amend会改写提交历史。如果之前那个提交已经被你推送到了远程仓库并且同事已经基于那个提交做了开发你这时候amend再强推历史就分叉了同事拉取时会遇到一堆冲突。所以我的铁律是只对还没有推送过的本地提交使用amend已经推送到远程的提交永远不要去编写历史。万一你确实需要修改一个已经推送过的提交流程是本地amend后用git push --force-with-lease强制推送。注意这里的--force-with-lease比裸的--force更安全它会在推送前检查远程分支是否被其他人更新过如果有人更新过就会拒绝推送避免覆盖别人的工作。但这仍然只适用于你确认不会有其他人在该分支上工作的情况。5.2 git stash临时放下手里的活你正在开发功能 A改到一半开发还没完成不敢提交因为一提交就是一个半成品。这时候突然来了个紧急 bug需要你在当前分支上切换出去修。怎么办git stash就是为这个场景设计的。它的作用是把当前工作区和暂存区中的改动临时保存起来让工作目录恢复干净。git stash执行后你再git status工作区是干净的。你可以放心切换到别的分支或者做其他事。等那边处理完了回到这个分支恢复你的改动git stash pop如果你存了多个 stash想查看列表用git stash list恢复指定的一条用git stash pop stash{1}。git stash还有一个好用的参数-ugit stash -u这个会把未跟踪的新文件也一起存起来。如果你不放心推荐加上。5.3 git reset回退提交的三种模式git reset可以让你把 HEAD 指向历史中的某个提交。它有三个模式区别很大--soft只移动 HEAD 的指针不改变暂存区和工作区。相当于“软回退”所有的变更都还在而且都处于暂存状态你可以重新组织提交。--mixed默认移动 HEAD 并重置暂存区但不动工作区。改动还在工作区里但暂存状态被清掉了。--hard移动 HEAD并且把暂存区和工作区都重置到目标提交的状态。这是一个破坏性操作所有未提交的改动都会丢失。举个例子你连续提交了三次发现第三次提交的内容根本不要了git reset --hard HEAD~1这条命令会让 HEAD 回到前一次提交的位置第三次提交的内容就没了工作区也同步回到那个状态。特意说一下--hard是非常危险的操作它会把工作区中所有未提交的改动一并抹掉。我在早期对 Git 不熟时用了reset --hard以为自己只是撤销提交结果把一上午写的代码全弄丢了。所以如果你不确定就先git stash或者备份一下当前工作区的文件。5.4 git reflog找到丢失的提交如果你遇到过reset --hard之后后悔的痛点git reflog就是解药。Git 会在本地记录所有分支指针的移动历史包括你用reset、rebase、merge造成的各种变化这些记录就是 reflog。git reflog输出类似这样abc1234 HEAD{0}: reset: moving to HEAD~1 abc5678 HEAD{1}: commit: 完成登录功能如果你reset --hard HEAD~1后反悔了想去回那个被丢掉的提交只需要git reset --hard abc5678这样你就能重新回到那个提交。reflog是本地操作不会推送到远程但它确实是 Git 中“后悔药”的最后一道保险。我的体会是操作reset和rebase之前先看一眼reflog其实深呼吸一下就行了。只要你的提交在本地曾经存在过reflog都能带你回去。5.5 git cherry-pick 与 rebase高级归并手段git cherry-pick的作用是把某个分支上的一次提交“挑”到当前分支来。比如线上分支出了 bug你在feature分支上修复并提交了现在想把这次修复同步到main分支却不想把整个 feature 分支合并过去就可以在main分支上git cherry-pick 提交哈希git rebase的作用是把当前分支的提交重新“搬到”另一个分支的顶端从而让提交历史保持线性。相对地merge会产生一个合并提交历史会有分叉。我不建议新手一上来就用 rebase 去重写历史但你可以先用一种很安全的场景拉取远程更新时用 rebase 而不是 merge这样你的本地提交会被“垫”在远程更新之后历史保持一条直线git pull --rebase如果你已经习惯了这一套再逐步探索交互式变基git rebase -i它可以让你任意合并、修改、重排多个提交。这是 Git 最强大的功能之一但也是最容易制造混乱的地方操作前务必确认这是你的“私人分支”。6. 远程仓库实战以 Gitee 为例配置 SSH 密钥6.1 为什么推荐用 SSH 方式连接远程仓库的平台有很多Gitee 是国内使用非常广泛的代码托管平台对国内网络的访问速度和稳定性都有保证。在你把本地仓库和远程仓库联通的过程中你会遇到两种协议HTTPS 和 SSH。HTTPS 方式的 URL 是https://gitee.com/user/repo.git每次 push 拉取代码时都要输入用户名密码或者个人访问令牌虽然可以靠凭据管理器记住密码但体验一般。SSH 方式是gitgitee.com:user/repo.git只要配置好密钥以后 push 拉取都不需要频繁输密码更安全也更顺滑。所以只要能配 SSH我建议一律用 SSH。6.2 生成 SSH 密钥并添加到 Gitee第一步在本地生成 SSH 密钥。打开 Git BashLinux/macOS 直接打开终端输入ssh-keygen -t ed25519 -C 你的邮箱这里的-t ed25519指定生成 ed25519 类型的密钥这是目前比较推荐的安全算法比传统的 RSA 更短更安全。执行后会出现交互提示询问保存路径和密码短语。路径直接回车用默认的~/.ssh/id_ed25519就行密码短语可空可设如果设了后续每次使用密钥时都要输入不习惯的话可以直接回车留空。生成完成后你会看到两个文件id_ed25519私钥留在本地千万别外传和id_ed25519.pub公钥可以分享给别人。用命令查看公钥内容cat ~/.ssh/id_ed25519.pub把输出的一整行内容复制下来。然后登录 Gitee点击右上角头像选择“设置”在左侧菜单里找到“安全设置”下的“SSH 公钥”把刚才复制的内容粘贴到公钥框内标题随便填一个点击确定保存。6.3 测试 SSH 连接是否成功配置完成后在终端里执行ssh -T gitgitee.com如果是第一次连接会提示你确认主机指纹输入yes回车即可。成功后会看到类似这样的提示Hi 用户名! Youve successfully authenticated, but GITEE.COM does not provide shell access.看到这个提示就说明 SSH 密钥配置成功了。以后你在 Gitee 上新建项目时选择 SSH 协议的地址克隆或关联就不必每天重复录入密码了。6.4 把本地仓库推送到远程仓库在 Gitee 上新建一个空仓库不要勾选“初始化仓库”里的任何选项然后把本地仓库关联到远程git remote add origin gitgitee.com:你的用户名/仓库名.git把本地main分支推送到远程git push -u origin main之后每次推送直接git push就够了。如果你本地仓库还没任何提交第一次推送之前记得先至少 commit 一次否则会提示“Everything up-to-date”或者根本没有可推送的分支。我当年就踩过这个坑建完远程仓库发现 push 不上去排查了半天才发现本地连一次 commit 都没有。6.5 SSH 配置常见报错与处理Permission denied (publickey)大概率是公钥没有正确添加到 Gitee或者ssh-keygen生成密钥时换了文件名导致 Git 找不到默认的私钥。可以先执行ls ~/.ssh看看文件是否存在再确认 Gitee 后台的公钥是否和本地id_ed25519.pub完全一致。Host key verification failed这是因为本机没有信任对方的主机指纹。执行ssh-keyscan -t ed25519 gitee.com ~/.ssh/known_hosts可以解决或者删掉known_hosts里旧的 gitee.com 记录后重连。多个 SSH 密钥共存你公司 Gitee 和个人 GitHub 可能用了不同的密钥文件这时需要在~/.ssh/config里配置不同域名对应不同的私钥文件否则 Git 只会默认找id_ed25519文件。配置~/.ssh/config的大致格式Host gitee.com HostName gitee.com User git IdentityFile ~/.ssh/id_ed25519_gitee Host github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519_github这个文件能给你的多账号 SSH 场景省下不少心推荐早点了解一下。7. 常见问题与排查技巧实录7.1 中文文件名变成转义序列怎么办很多 Windows 用户在 Git 状态或输出里看到中文文件名显示成\346\265\213\350\257\225.txt这种八进制转义序列非常头疼。这是因为 Git 默认会对非 ASCII 文件名进行转义。解决办法是关掉这个转义git config --global core.quotepath false这个配置也是热词“git -c core.quotepathfalse”出现的原因。在命令行里敲git -c core.quotepathfalse status也能临时生效但一次性的参数不能永久改变行为所以我建议直接用git config --global core.quotepath false设置一次一劳永逸。设置完后中文文件名就能正常显示了。7.2 amend 之后远程被拒怎么办我前面说过不建议对已推送的提交做amend。如果你已经犯了推的时候报错! [rejected] main - main (non-fast-forward)这说明远程和本地历史不一致了。如果你确认远程分支只有你自己在用没有人基于旧提交做工作可以强推git push --force-with-lease但要记住这个操作覆盖的是远程的提交历史如果你误操作会严重影响团队成员。所以强推之前一定要和团队确认或者干脆在功能分支上用这个方法永远别在公共主干上轻易改写历史。7.3 执行 git add 后想撤销怎么办你执行了git add把文件加入了暂存区突然发现这不是你想提交的文件。不用慌用git reset HEAD 文件路径这个命令会把文件从暂存区移回到工作区但文件内容不变。在旧版 Git 中常用git reset HEAD来实现新版 Git 更推荐git restore --staged 文件路径这两种方式效果一样选一个你看着顺眼的使用即可。7.4 合并时提示 refusing to merge unrelated histories这个报错通常出现在你本地仓库和远程仓库都有自己的独立提交历史且互不关联时。比如你在 Gitee 上新建了空仓库但本地也先做了 init 和提交这时候去 pull 远程就会报这个错。解决方法是在 pull 或 merge 时加一个参数git pull origin main --allow-unrelated-historiesGit 会把两个不相干的历史强行合并在一起但接着一般会出现冲突你需要手动解决。最简单的方式其实是避免这种情况新建远程仓库时不要初始化任何文件或者本地直接用 clone 方式来获取远程仓库。7.5 换行符警告LF will be replaced by CRLF在 Windows 上使用 Git 时你可能会见到这样的警告warning: LF will be replaced by CRLF这是因为 Windows 系统默认行尾是CRLF而 Linux/macOS 是LF。Git 在提交时会把文件统一成LF存到仓库而在 Windows 检出时再转成CRLF所以提示“LF will be replaced by CRLF”实际上是在告诉你换行符策略正在生效。大多数情况下这个警告可以直接忽略不会对项目造成实质影响。如果你实在不喜欢可以设置git config --global core.autocrlf false但这可能导致跨平台协作时出现大量换行符差异的 diff推荐普通用户还是保持默认配置。7.6 文件删除后怎么恢复误删文件是每个人都会遇到的情况。如果你还没执行git commit可以直接git checkout -- 被删除的文件这个命令会用暂存区或当前 HEAD中的版本恢复文件。如果你已经提交过甚至删除了之后还提交过一次那就需要找到没有删除文件的那个提交然后从那个提交中恢复git restore --source提交哈希 -- 被删除的文件这也是 Git 的威力——只要你的操作留下了提交记录大多数误删误改都能找回。7.7 为什么明明改了文件git status 却提示无变化这种情况一般在大小写改名时出现。Windows 和 macOS 默认文件系统不区分大小写你把readme.md改成README.mdGit 可能完全感知不到变化。解决方法是让 Git 自己识别重命名git mv readme.md README.md如果已经改乱了也可以临时设置git config core.ignorecase false来让 Git 更敏感地追踪大小写但这个配置对已有改动不一定能自动生效最稳妥的方式还是用git mv来执行文件名变更。最后再分享一个实用的小习惯我个人实际工作中Git 用得越久越觉得真正提升效率的未必是最复杂的命令而是一些微小的习惯。比如每次敲完git commit后我都会顺手跑一次git log --oneline -3确认一下刚才的提交信息没写错每次git push前先git fetch看一眼远程有没有新提交能避免不少冲突。还有一个我认为价值极高的习惯提交信息不要只写“update”而是把这个改动的前因后果用一两句话写清楚。三个月后你再回来看历史会深深感谢当时那个认真写提交信息的自己。这些细节看着不起眼积累起来就是你和别人协作时最大的“效率杠杆”。如果你刚开始接触 Git不需要把上面所有内容一次性记下来。先把add、commit、status、log、push、pull这六条命令跑熟再把分支和合并用利索你就已经能覆盖日常 90% 的工作场景了。剩下的都是遇到问题再回来翻的“武器库”随时都能用得上。