
1. 为什么要整理一份Git自用手册Git这个东西我前后大概用了五六年从最初只会git add、git commit、git push三板斧到现在日常处理分支、解决冲突、恢复误删提交已经变成了肌肉记忆。但有一件事一直没变总有些命令和参数隔几个月不用就忘得一干二净。每次都要翻官方文档或者重新搜一遍效率很低。这份手册就是我在这个背景下整理出来的专门记录那些高频使用、但又容易记混的Git操作。与其说这是一份教程不如说是一份自用手册——里面没有太多教科书式的理论大部分都是从实际项目里踩坑踩出来的经验。Git说到底不是一个需要背完所有命令才能上手的工具你只需要掌握20%的操作就能覆盖日常80%的工作。这份手册的核心目标就是把这些20%的关键操作整理清楚同时把容易踩坑的细节指出来。2. 环境准备Git安装与初始配置2.1 不同平台的Git安装方式不管你是Windows、macOS还是Linux用户安装Git本身都不复杂但不同平台有几个细节值得注意。Windows用户最简单的办法是去Git官网下载安装包一路默认安装就行。官网下载速度如果不太理想也可以考虑国内镜像站。安装时有一个选项会问是否把Git加入系统PATH这个一定要勾选否则后续在命令行里敲git命令会提示找不到。另外建议在安装时选择Checkout as-is, commit as-is的换行符处理方式或者直接使用默认选项问题也不大这个后面单独讲。macOS用户有几种选择如果你装了Homebrew一条brew install git就搞定也可以安装Xcode Command Line Tools系统里会有自带的Git版本。不过需要注意的是bash git --version输出结果里有git版本号就算成功了。我见过不少人在这一步就卡住大概率是PATH没有配好或者终端没有重启。装完后新开一个终端窗口再试基本能解决。 ### 2.2 安装后的三件套配置 Git装完之后第一件事不是急着建仓库而是先配置身份信息。很多人跳过这一步结果提交代码时Git用了一个系统自动生成的默认身份比如 userhostname后面协作时别人根本不知道这个提交是谁做的。更麻烦的是后续想改历史提交的作者信息操作起来非常繁琐。 需要配置的第一个是用户名第二个是邮箱命令如下 bash git config --global user.name 你的名字 git config --global user.email 你的邮箱这里的--global表示全局配置也就是说这台机器上所有仓库默认都会用这个身份。如果你在某个特定项目里想用另一个身份可以在项目目录下不带--global再执行一次那个仓库的配置会覆盖全局配置。这个机制很适合同时有个人项目和公司项目的人。还有一个值得提的配置是命令行颜色。默认情况下Git的输出就是纯文本看着特别费劲。建议开启颜色显示git config --global color.ui true再执行git status和git diff的时候输出会带上红绿颜色哪些文件改了、哪些地方删了增了一目了然。这个配置虽然不起眼但对日常使用的体验提升非常明显。2.3 配置检查与多身份管理配置完之后可以用git config --list查看当前所有配置。这个命令会同时列出系统级、全局级和仓库级的配置如果同一个配置在多个级别都有后面的值会覆盖前面的。提示如果输出结果太长可以直接git config --list | grep user来单独查看用户信息。多身份管理是我实际工作中经常遇到的问题。比如我给公司项目提交时要用公司邮箱给开源项目提交又希望用个人邮箱。这种情况下不要在全局配置里只写一个身份而应该把全局身份设置为最常用的那个然后在特定仓库里用仓库级配置覆盖。具体操作就是在项目根目录下执行git config user.name 公司用户名 git config user.email 公司邮箱不带--global的配置会写进当前仓库的.git/config文件里。这个文件只对当前仓库生效不会影响其他项目。另外如果你同时使用多个代码托管平台比如一个是内部的GitLab一个是GitHub建议直接用SSH配置来处理。因为SSH key可以在不同平台上绑定不同的邮箱和用户名后面会专门讲免密配置部分。3. 高频命令实操覆盖日常80%的操作3.1 先理解Git的三个区域很多人学Git卡住的第一个点就是搞不清楚add、commit这些命令到底在操作什么。这里用一个生活化的类比来解释。Git仓库可以分成三个区域工作区、暂存区、版本库。工作区就是你电脑里实际能看到和编辑的文件目录版本库是Git用来保存提交记录的地方在项目目录下的.git文件夹里暂存区是工作区和版本库中间的一层缓冲区你可以把它理解成去超市购物时的购物车。购物时你会把商品先从货架上拿下来放到购物车里这个动作就相当于git add然后统一去收银台结账相当于git commit。如果只是往购物车里放了东西但没结账那超市版本库里还没有这条记录。这个认知非常重要因为后面所有命令都是围绕这三个区域展开的。比如git status看的就是三个区域之间的差异状态git diff默认看的是工作区和暂存区之间的改动加上--cached参数看的就是暂存区和版本库之间的差异。3.2 最常用的状态与提交命令日常开发的典型流程是改代码 - 查看改动 - 暂存 - 提交 - 推送。下面这几条命令就是整个流程的骨干。首先是git status这个命令在Git所有命令里使用频率几乎是最高的。它会清楚地告诉你当前分支、是否有未跟踪的文件、哪些文件已修改但未暂存、哪些已暂存但未提交。如果不确定下一步该执行什么操作先敲git status基本不会有错。然后是查看具体改了什么用git diff。这个命令按文件对比工作区和暂存区的内容差异。我在提交之前的习惯是必跑一次git diff目的是防止把调试用的临时代码或者不小心改错的地方提交上去。特别是有些编辑器会自动替换行尾或者格式化代码导致diff里出现大量和逻辑无关的改动提前检查能避免很多尴尬。接下来是暂存和提交git add 文件名 # 暂存指定文件 git add . # 暂存当前目录下所有改动 git commit -m 提交说明这里要强调一个习惯尽量别用git add .一把梭。如果项目里混入了生成文件、临时文件或者你根本不清楚哪些文件被改动了git add .会把不该提交的内容也放进来。更稳妥的方式是先git status看清楚再针对性地git add具体文件。如果确实有多次改动、希望分门别类地提交可以先git add一部分文件提交一次再git add另一部分再提交一次。这样每次提交的粒度小、主题明确后面如果需要回滚或者排查问题会轻松很多。git commit的提交说明也值得认真写。我自己采用一个简单的规范第一行用一句话说清楚这次提交做了什么动词开头比如修复登录接口空指针异常、优化列表页首次加载性能。这样在git log里扫一眼就能明白每次提交的意图比写修改bug、更新代码这种没有任何信息量的说明强太多。3.3 后悔药撤销与回滚Git之所以让人安心是因为几乎所有误操作都有补救办法。这一节把最常用的撤销和回滚命令整理成一张速查表。场景命令说明工作区改了但没暂存想放弃修改git checkout -- 文件会丢失工作区的改动不可逆慎用已暂存但没提交想取消暂存git restore --staged 文件从暂存区退回工作区文件内容不变已提交但没推送想撤掉这次提交git reset --soft HEAD~1撤销commit保留改动到暂存区已提交但没推送想彻底撤销git reset --hard HEAD~1丢弃提交及所有改动非常危险已推送想撤销但保留历史git revert 提交ID生成一个反向提交安全可推送git reset有三个模式很多人搞混。--soft只撤销commit把改动放回暂存区--mixed是默认模式撤销commit和暂存把改动放回工作区--hard直接丢弃所有改动。我个人的建议是除非你非常确认那些改动已经不需要了否则不要用--hard。宁可多用一步先把当前状态备份到另一个分支再执行重置操作。git revert和git reset的区别值得单独讲一下。reset是回到过去它会移动分支指针历史记录里那次提交就消失了revert是否定过去它不会删除原提交而是新生成一个反方向的提交来抵消之前的改动。如果是已经推送到远端的提交请一定用revert不要用reset。因为reset会改变提交历史下一次push时远端会拒绝非快进推送除非你强制推送而强制推送在协作分支上可能把队友的历史搞乱。3.4 让日志更清晰的几个技巧git log是所有命令里输出信息最丰富的但默认格式也比较冗长。我常用的几个参数组合如下git log --oneline # 每个提交只显示一行最常用 git log --graph # 显示分支合并图直观看到分之走向 git log --oneline --graph --all # 查看所有分支的提交历史 git log --author名字 # 只看某个人的提交 git log -p # 查看每次提交的具体diff内容我个人最常用的是git log --oneline --graph --all这个组合能在一个页面里看到整个项目的分支走向、合并节点和各个分支的提交位置。在排查某个功能是在哪次合并进来的这类问题时特别好用。另外提一个实用的小命令git log --oneline -10只看最近10条提交。如果项目提交频率很高这个命令能避免日志刷屏快速定位近期改动。4. 分支管理并行开发的基石4.1 分支的本质Git的分支模型是它区别于SVN等旧版本管理工具的核心优势。Git的分支本质上只是一个指向某个提交的指针创建分支的成本极低所以Git鼓励多建分支、多用分支。实际开发中我习惯的做法是主分支保持稳定可用状态所有新功能都从主分支拉出独立的分支来开发功能完成后再合并回去。这样做的最大好处是隔离风险某个功能写了一半、甚至写坏了都不影响主分支上其他人的工作。创建和切换分支的命令git branch feature-login # 创建分支 git checkout feature-login # 切换到分支 # 或者用新版命令一步到位 git switch -c feature-login # 创建并切换git switch是Git 2.23之后引入的替代命令语义更明确git switch只管切换git branch只管增删改查。用checkout也能做同样的事但它的职责太多新手容易混淆。我个人的建议是能记住git switch就多用它而git checkout -- 文件这种撤销用法保留在撤销场景里。4.2 合并与冲突功能开发完需要把分支合并回主分支。标准操作是先切回主分支然后执行合并git checkout main git merge feature-login如果两个分支改动的文件互不重叠Git会自动完成合并生成一个新的合并提交。如果改动了同一个文件的同一块区域Git就会报冲突并在冲突文件里插入类似下面的标记 HEAD 这是当前分支main的代码 这是要合入分支feature-login的代码 feature-login解决冲突的思路不是直接在编辑器里删掉标记而是仔细看两边的代码决定保留哪一边、或者两边都保留并做调整。改完之后执行git add 文件再执行git commit完成合并。这里不要用git merge --abort一遇到冲突就想退出除非你确定这次合并不应该继续。大多数情况下冲突是正常的认真解决就好。如何减少冲突我在团队里推广过几个经验第一主分支和功能分支都尽量小步提交不要攒几百个改动一次性合并第二功能分支开发过程中定期把主分支的最新代码合并进来这样最后合并回去时冲突范围会小很多第三不同成员尽量少改同一文件的同一区域这属于任务拆分的范畴但确实是减少冲突的最有效手段。4.3 merge还是rebase这是永恒的争论关于git merge和git rebase的讨论几乎是每个Git使用者绕不开的话题。简单理解merge会把两个分支的历史合并成一个新的节点保留分叉记录rebase会把当前分支的提交重新放到目标分支的最新提交之后让提交历史变成一条直线。对比维度mergerebase历史形态有分叉有合并节点线性没有合并节点可读性能看出开发并行情况更简洁易于追踪安全性不改变已有历史会重写提交需要谨慎适用场景公共分支整合、保真历史整理本地提交、保持主线干净我的个人建议是在自己的功能分支上可以使用rebase来保持分支整洁但永远不要在公共分支上执行rebase因为rebase会重写提交哈希导致所有基于旧提交的协作者都出现历史不一致的问题。git rebase -i是交互式rebase可以让你压缩提交、修改提交信息、调整提交顺序。我经常在推送之前用它把开发过程中的临时提交、调试提交合并成一个完整的功能提交。操作方式是在当前分支上执行git rebase -i HEAD~3这会打开一个编辑界面列出最近3条提交。每个提交前面是pick你可以把它改成squash压缩到上一个提交、reword修改提交信息等。保存退出后Git会按照新的配置重组提交。这个命令很强大但我建议只在自己本地的、未推送的分支上使用推送到远端之后就不建议再动了。5. 远程仓库协作与免密配置5.1 remote相关命令本地仓库要跟远程仓库对接首先得添加远程地址。一般克隆一个仓库之后远程地址会自动配置好名字叫origin。如果你是从零搭建的项目需要手动关联git remote add origin 远程仓库地址 git remote -v # 查看当前配置了哪些远程地址日常协作最常用的两个命令是push和pull。push把本地提交推送到远程pull把远程更新拉取到本地。git pull实际上等于git fetch加git merge——先获取远程的更新再合并到当前分支。这里有一个很多人初期会犯的错直接在main分支上开发然后git push时发现被拒绝提示远端有你在本地没有的提交。这时千万不要用git push --force强行覆盖正确做法是先git pull把远端更新拉下来解决冲突后再推送。给push设置上游分支也是一个常用操作。首次把本地分支推送到远程git push -u origin feature-login-u的作用是设置上游追踪关系。设置之后后续在这个分支上直接敲git push和git pull就行了不用再指定远程和分支名。5.2 SSH还是HTTPS免密配置的两种思路免密配置是Git使用体验的一大飞跃。我见过太多人在每次push/pull时反复输入账号密码非常影响效率。这里提供两条路SSH方式 和 HTTPS凭据管理方式。SSH方式是大多数开发者的首选。原理是生成一对公钥和私钥把公钥放到代码托管平台上GitHub、GitLab等都支持私钥留在本地。之后Git通过SSH协议连接远程服务器时服务器确认公钥匹配就直接放行不需要再输密码。生成SSH key的命令ssh-keygen -t ed25519 -C 你的邮箱一路回车就行会在~/.ssh/目录下生成id_ed25519.pub公钥文件和id_ed25519私钥文件。然后把公钥内容复制出来cat ~/.ssh/id_ed25519.pub在GitHub的Settings - SSH and GPG keys里新增一个Key把内容粘贴保存。之后本地仓库的远程地址使用SSH格式比如gitgithub.com:用户名/仓库名.gitpush和pull就完全免密了。用SSH还有一个额外的好处如果你的SSH key设置了密码passphrase可以使用ssh-agent来做内存级缓存这样每次会话只需输入一次密码。macOS上还可以让系统钥匙串帮你管理。如果不想折腾SSHHTTPS方式也有对应的免密方案。Git内置了credential helperWindows上安装Git时会自动配置第一次输入用户名密码后凭证会被保存到Windows凭据管理器里之后自动读取。macOS同理会存到钥匙串里。还可以手动开启git config --global credential.helper store这样凭证会明文存在~/.git-credentials文件里。不过这种方式的便捷性是以安全为代价的文件泄露就等于账号泄露。我建议优先使用SSH或者使用系统级的credential helper而不是明文store。另一个常见场景是使用Personal Access Token。现在GitHub要求输入密码的位置必须用token代替密码所以如果你用HTTPS方式连接GitHub需要先去Settings里生成一个token然后把它当密码输入。token本身要妥善保存生成后只显示一次。5.3 远程协作中的典型问题远程协作中最常见的报错是! [rejected] main - main (non-fast-forward)。通俗解释就是你本地的提交历史和远程不一致Git担心你推送会覆盖掉其他人的提交所以拒绝执行。遇到这个情况我的排查顺序是先git status看当前状态确认没有未提交的改动。执行git fetch获取远程最新状态。对比本地和远程的分叉情况git log --oneline --graph --all。执行git pull拉取并合并远程更新解决冲突后再push。在多人协作场景下我强烈建议定一个规矩不要在main分支上直接提交和推送。每个人都在自己的feature分支上开发通过合并请求Pull Request / Merge Request合入主干。这样既能做代码审查又能避免直接推送到主干带来的混乱。团队项目还有一个容易被忽略的点大文件。Git原生不适合存放大文件仓库里有几个上百MB的文件clone速度会变得很慢。如果项目确实需要放大的二进制文件可以考虑Git LFSLarge File Storage方案但这是另一个话题了这里只提醒一句小心大文件进库一旦进了历史想清理干净非常麻烦。6. 常见问题与排查技巧实录6.1 高频问题速查表下面这张表是我这些年实际遇到过的、也帮别人排查过的问题汇总按频率排序整理问题现象原因解决办法git status显示中文文件名乱码Windows下编码问题执行git config --global core.quotepath falsegit commit报Please tell me who you are未配置用户名邮箱按第2.2节配置 user.name/user.email推送时提示non-fast-forward本地历史落后于远端git pull合并后再push不要用强推本来只想提交一个文件结果一堆文件进来了git add .一次暂存了全部用git add 具体文件或git restore --staged 文件取消暂存提交信息写错了还没push提交还停留在本地用git commit --amend -m 新的提交信息修改切分支后找不到自己写的代码可能提交在了另一个分支git log --oneline --all --grep关键词全局搜索提交误删了一个分支后悔了分支被删除用git reflog找到删除前的提交哈希重建分支git clone速度很慢网络或仓库过大检查网络仓库内是否有大文件必要时用浅克隆--depth1终端里输入Git密码一直被拒绝平台要求使用token去平台Settings生成token代替密码输入git reflog是很容易被忽略但极其实用的命令。它记录了HEAD指针的所有历史移动哪怕你执行了git reset --hard或者删除了分支只要reflog里还能找到之前的提交哈希就能恢复。有一次我在一个分支上误操作用git reset --hard丢弃了两个小时的代码改动当时心都凉了。后来用git reflog找到丢失提交的哈希git branch 恢复分支名 提交哈希两分钟的功夫全部找回。这个命令建议每个Git使用者都记住。6.2 保命经验分享最后几条经验是我在多次项目踩坑后总结的频率不高但每次都价值巨大。第一提交之前先看diff。这个习惯可以帮你挡住90%的误提交。代码写完之后先git diff检查一下改了什么确认没有调试语句、没有临时文件、没有遗漏的改动再走add和commit。第二做危险操作前先备份分支。不管是reset、rebase还是force push动手之前先执行git branch backup-当前日期这条命令创建一个当前状态的分支备份万一操作搞砸了随时能切回去。成本极低收益极大。我现在的习惯是每周至少一次给主要分支打个备份标签或者在做任何历史整理操作前必做备份。第三提交信息要让人看得懂。这个前面提过但值得再强调一次。好的提交信息能在半年后帮你快速定位某次改动的意图而不好的提交信息modify、update、fix等于没有。可以在项目里约定一个简单的模板类型简述比如fix: 修复空指针、feat: 新增导出功能。第四不要轻易强制推送。git push --force是一把双刃剑它会让远端分支的历史直接变成你本地的样子队友的提交可能因此丢失。如果确实必须强推先通知团队确保每个人都拉取了最新内容。现在Git提供了--force-with-lease这个更安全的参数它会检查远端是否发生了你本地不知道的更新如果有就拒绝推送没有才允许。我建议把强推的默认选项改成--force-with-lease。第五养成看报错全文的习惯。很多人看到一个英文报错就直接复制到搜索框这没有错但更快的办法是读懂报错。Git的报错信息一般是问题描述解决方案提示比如Please tell me who you are后面就跟着配置user.name和user.email的提示命令。先认真读一遍报错再决定怎么处理这个习惯能让你的排查速度快上一倍。7. 一点个人体会Git这个东西一开始会觉得命令多、概念抽象但只要把工作区、暂存区、版本库这个框架搭起来再把提交、分支、合并、远程协作这几条主线走一遍框架就清晰了。剩下的命令基本都是按需查、按需记用多了自然就熟了。我现在每换一台新电脑第一件事就是装Git、配好用户名邮箱、生成SSH key并绑定到GitHub。这个过程走了很多遍心得就是一次性把这些配置做好后面能省掉无数麻烦。希望这份手册也能帮你把Git的使用体验理顺少踩一些我踩过的坑。