Git 实战指南:从安装配置到团队协作的完整命令速查

发布时间:2026/9/19 4:15:10
Git 实战指南:从安装配置到团队协作的完整命令速查 只要写代码就绕不开 Git。这句话我说了无数回每次带新人的第一件事就是先发一份 Git 命令速查表过去省得在 add、commit、push 这三个词之间来回折腾。其实 Git 本身的概念并不复杂它就是一个文件版本管理工具但命令体系确实比较庞大新手经常被各种参数吓退老手偶尔也会被一些偏门报错卡住。这篇文章我打算把自己这几年用 Git 的常用命令、踩过的坑、以及文档里不会明说的经验一次性整理出来。内容从 Windows、macOS、Linux 的安装配置到本地仓库的日常操作、分支管理、远程协作、撤销与误删恢复最后还会送上一张常见报错速查表。不管你是刚入行的学生还是从 SVN 转过来的老开发甚至只是需要管理自己脚本文件的人只要电脑里装过 Git这套内容你都能直接对照着用。我们不聊那些一年用不到一次的花活就讲工作日里每天都在用的东西。1. 环境准备与安装配置1.1 各平台安装教程Windows、macOS、Linux 全覆盖先说 Windows。绝大多数人用的是 Git for Windows它自带了 Git Bash、Git CMD 和 Git GUI 三个工具。安装时去官网下载 exe一路 Next 能装完但有几个选项需要手动确认。第一是默认编辑器新版安装器会让你选如果选 Vim后面每次写提交信息都会卡在 Vim 奇奇怪怪的交互里建议直接选 Visual Studio Code 或者 Notepad。第二是 PATH 环境变量那一步务必选择“Git from the command line and also from 3rd-party software”这样 VS Code、IDEA、小乌龟这些第三方软件才能直接在终端里找到 git 命令。如果官网下载速度太慢可以找国内开源镜像站下载 Git for Windows文件名一般是类似Git-x.x.x-64-bit.exe这种格式认准官方版本号即可。macOS 上最简单的办法是先尝试直接执行git --version系统会弹出安装命令行开发者工具的提示装完自带 Git。想自己控制版本的话用 Homebrew 安装更干净命令就一条brew install gitLinux 上根据发行版选包管理器Debian/Ubuntu 用apt install gitCentOS/RHEL 用yum install git或dnf install git。我是建议 Linux 用户优先走系统包管理除非你要用的是最新特性否则系统源里的 Git 版本完全够用。装完之后统一执行git --version能看到版本号就说明安装成功。1.2 环境变量与基础配置解决“git 无法识别”和首次设置Windows 上经常遇到一种情况安装完成后打开 cmd 或 PowerShell输入git --version却提示“无法将‘git’项识别为 cmdlet、函数、脚本文件或可运行程序的名称”。这基本就是环境变量没配置好。打开系统环境变量设置找到 Path把 Git 的Gits\cmd目录加进去默认路径通常是C:\Program Files\Git\cmd手动添加后重新打开终端即可生效。这里提醒一句改完环境变量一定要记得关闭并重开终端不然系统读不到新的变量值。Git 装好后第一件事是配置用户名和邮箱这一步不能偷懒因为每次提交都会把这两条信息记录到历史里。配置文件分三级--system针对整台机器--global针对当前用户--local只对当前仓库生效优先级从高到低是 local global system。日常开发配置全局用户名和邮箱就够了git config --global user.name 你的名字 git config --global user.email youexample.com配置完可以用git config --list检查所有生效的配置项。还有两个配置我强烈建议顺手加上。一个是 Windows 下处理换行符Git 默认会有 CRLF 的警告执行git config --global core.autocrlf true可以让 Git 帮你把换行符自动转换团队协作时能少一票莫名其妙的 diff 问题。另一个是git config --global core.quotepath false这个配置解决的是中文文件名和中文路径在git status里显示成八进制乱码的问题很多人在国内仓库里被这玩意儿坑过配置之后显示就正常了。2. 本地仓库的日常操作命令2.1 仓库初始化与文件生命周期理解 Git 的三层状态Git 的文件管理核心是三棵树的概念工作区、暂存区Index、本地仓库。打个比方工作区是你的工位暂存区是打包台本地仓库是货架。文件先放在工位上你挑出要发走的放在打包台最后统一搬到货架上存放。日常命令基本就在这三个区域之间搬运文件。初始化仓库有两种方式。第一种是从零开始在项目根目录执行git init这条命令会在目录下生成一个.git文件夹里面装着所有版本历史。第二种是从远程拿项目git clone会把远端仓库完整复制到本地。很多新手容易把git init当成所有项目的起点但如果你的项目已经在一个远程仓库里了直接用git clone就行不要先 clone 再git init那会破坏仓库结构。日常编辑文件的流程是这样的先用git status查看当前状态它会明确告诉你哪些文件被修改了、哪些还没被跟踪。文件从工作区挪到暂存区用git add file全部添加用git add .只添加部分文件或部分改动可以用git add -p这个交互式命令会询问每一块改动是否暂存适合代码里混了调试日志时精准提交。暂存完毕用git commit -m 提交信息生成一次提交。这里想多说一句提交信息理想情况下应该写清楚“为什么改”而不是“改了啥”比如“修复登录接口空指针异常”就比“update”好得多。2.2 查看历史与差异对比git log 和 git diff 的常用组合提交记录查少了会找不到代码是谁改的查多了又费眼关键是掌握几个常用参数。git log --oneline把每次提交压成一行显示干净利落git log --graph --all会把分支的合并图谱画出来适合观察整体结构git log -5只看最近 5 条。我个人每天最常用的命令是git log --oneline --graph --all在公司代码里查分支合并情况一眼就能看出哪个功能是从哪个分支合进来的。差异对比要看场景分四种命令git diff比较工作区与暂存区的差异也就是你改了但还没 add 的内容git diff --cached比较暂存区与本地仓库的差异也就是已经 add 但还没 commit 的内容git diff commit1 commit2比较两个提交之间的差异git show commit_id查看某一次提交具体改了什么文件、哪些行增删。带着这个对照关系去用基本不用再背参数了。2.3 .gitignore 配置让 Git 自动忽略不该提交的文件几乎每个仓库里都有一些不该进版本库的文件比如 IDE 配置、依赖目录、日志文件、本地环境变量。这些文件的共同点是每个人都不同、自动生成、更新频繁。Git 提供了.gitignore文件来过滤它们。.gitignore的规则不复杂但有几个关键点容易踩坑。以/开头的路径表示仓库根目录/结尾的表示目录*匹配零个或多个字符!表示取反。给一个实际例子node_modules/ target/ dist/ *.log .env .idea/ .vscode/每一行表示一种忽略规则。如果某些文件已经被跟踪了再往.gitignore里加规则是无效的需要先git rm -r --cached file把它们从暂存区移除再提交一次之后的改动才会被忽略。新手最容易在这里困惑明明加了规则git status 还在显示某个文件八成就是因为它之前已经被 add 过了。3. 分支管理并行开发的“平行宇宙”3.1 分支的创建、切换与合并分支是 Git 最让人上头的设计本质上就是一个指向某次提交的可移动指针。创建分支用git branch branch_name创建并切换用git checkout -b branch_name。从 Git 2.23 开始官方更推荐用git switch系列命令git switch -c创建并切换git switch切换已有分支语义更清晰不容易和还原文件的checkout混淆。合并分支用git merge branch_name。合并有两种常见形态fast-forward 和 三方合并。如果当前分支的 HEAD 是被合并分支的上游Git 会直接把指针往前移不产生新的合并提交如果两个分支在分开后都有新提交Git 就必须做三方合并生成一个 merge commit。很多团队为保证主干历史清晰会习惯用git merge --no-ff branch_name强制保留一个合并节点这样主分支上的功能合并点一目了然回滚时也方便定位。3.2 解决冲突的正确姿势冲突是合并时最让人头疼的事但处理过一次之后就会发现其实逻辑很机械。Git 在冲突发生时会在冲突文件里插入、、三行标记分别表示当前分支的内容、分隔线、被合并分支的内容。你需要做的就是打开文件手动逐段选择保留哪边删掉这三行标记然后git add file再git commit。我的经验是遇到冲突千万别在终端里硬凭记忆改尤其当冲突文件比较大时用 VS Code 或者 IDEA 自带的冲突解决工具效率会高很多这两个工具都提供“接受当前/接受传入/同时保留”的按钮可视化操作不容易出错。改完之后重点检查一遍整个文件确认没有遗留的标记再提交。提交信息里不用专门写“解决冲突”默认的 merge 提交信息就行。3.3 stash 临时保存工作现场开发中最尴尬的事情莫过于当前分支代码改了一半还没写完不能提交这时候突然要切到另一个分支改个紧急 bug。硬切分支会被 Git 拦住因为工作区和目标分支有冲突。这时候git stash就派上用场了它能把当前工作区的修改保存到一个临时堆栈里让工作区恢复干净。git stash git stash list git stash popgit stash默认只保存已跟踪文件的修改如果你在工作区新建了一个还没git add的文件需要加-u参数即git stash -u才会一并保存。恢复时用git stash pop会把最新一次 stash 弹出并应用如果你同时在多个 stash 之间切换用git stash apply stash{1}可以恢复指定的那次。如果 stash 了多个任务建议压栈时带个备注git stash push -m 登录模块的临时修改不然时间一长自己都分不清哪条是哪条。4. 远程仓库协作4.1 SSH 配置与免密推送以 Gitee 为例使用 HTTPS 协议拉代码虽然简单但每次 push 都要输账号密码相当影响心情。SSH 协议通过密钥对免密认证而且更安全是很多开发者的首选。生成密钥的方法很简单在 Git Bash 里执行ssh-keygen -t rsa -b 4096 -C youexample.com一路回车生成的密钥默认在~/.ssh/id_rsa私钥和~/.ssh/id_rsa.pub公钥。然后把公钥内容复制到代码托管平台的设置页面Gitee 的地址是“设置 - SSH 公钥”粘贴保存即可。验证是否配置成功用ssh -T gitgitee.com如果显示成功欢迎信息说明密钥已经生效。我遇到过不少情况是公钥复制不全少几个字符导致认证失败还有人是把私钥内容贴上去了这里尤其要注意粘贴的一定是.pub结尾的公钥文件内容。4.2 clone、pull、fetch、push 的区别与使用场景很多初学者分不清这四个命令其实它们承担完全不同的职责。git clone是把远程仓库整个拿下来只在新机器或新目录上执行一次。git fetch会把远程的新提交拉取到本地但不会自动合并到你的工作分支适合想先看看别人改了什么再决定怎么处理的情况。git pull等于fetch merge一条命令直接把远程更新合并进当前分支。git push则是把本地提交推送到远程。这里有一个值得反复强调的习惯在多人协作的分支上做git push之前先执行一次git pull或git pull --rebase把远程的更新合并到本地再推上去。直接推很容易被服务器拒绝报出failed to push some refs那基本就是远程有本地还没有的提交。如果本地和远程各自都有新提交用git pull --rebase可以把本地的提交“垫”到远程提交之后提交历史是一条直线比自动产生的 merge 提交更清爽。4.3 团队协作的完整工作流与 PR/MR 流程现在稍微正规一点的团队都会走 pull request 或 merge request 流程。完整的命令序列大概是这样先 clone 主仓库为每个功能创建独立分支在分支上完成开发并推送到远程然后在代码托管平台上发起合并请求等有权限的人评审通过后合并。本地操作对应的完整命令链是git clone gitgitee.com:yourname/project.git git checkout -b feature-login # 写代码... git add . git commit -m feat: 完成登录功能 git push -u origin feature-login-u参数全称--set-upstream的作用是让本地分支和远程分支建立跟踪关系第一次推送之后就可以直接git push而不用再写远程分支名。整个工作流的精髓在于主干分支保持稳定所有变更都经过分支和评审这样即使某个功能写崩了也不会直接影响线上代码。5. 撤销操作与历史改写5.1 撤回暂存区和工作区的修改git restore 的正确用法撤销操作是最容易把仓库搞乱的地方因为 Git 有好几种“反悔”方式应用场景完全不同。最简单的情况是你改了一个文件但还没git add想恢复到上次提交的状态用git restore file或旧式写法git checkout -- file。如果已经git add进入了暂存区想撤销暂存用git restore --staged file这样文件会变回“已修改未暂存”的状态但工作区内容不会变。再多走一步想把文件彻底恢复到上次提交的样子先git restore --staged file再git restore file两步组合拳打好就行。这里需要特别提醒git checkout -- file和git restore file都是不可恢复的操作如果这个文件有重要的、未提交的修改一旦覆盖就找不回来了。执行前最好先git diff看一眼确实要丢弃这些改动。5.2 commit --amend 修改最后一次提交提交完之后发现漏了个文件、提交信息写错、或者想多带一个文件进去这种情况几乎每周都会遇到。git commit --amend就是为它准备的。最简单用法git add . git commit --amend -m 新的提交信息如果只是想把新文件并进上一次提交不改提交信息用git commit --amend --no-edit。这个命令的本质是生成一个新的提交对象来替换原来的提交。用起来很顺手但有一个大忌只能 amend 还没推送到远程的提交。如果已经git push了再 amend 会导致本地与远程历史不一致之后推送会被强制要求git push --force而 force push 会把远程历史覆盖掉团队里其他人可能因此直接乱套。所以我的习惯是没推送随便改推送了宁可新开一条提交也不要 amend。5.3 用 revert 安全回滚已推送的提交已推送提交出了问题想要安全回滚首选不是reset而是git revert。git revert commit_id会生成一个新的提交内容正好是那次提交的逆操作相当于“用新提交撤销旧提交”。这种方式的好处是不改变已有历史远程仓库的历史一直是线性增长的团队其他成员 pull 下来不会有任何冲突。对比一下git reset和git revert的区别reset是把 HEAD 指针回退到过去的某个提交适用于本地还没有推送、想彻底抹掉一段历史的情况revert是在当前历史后面追加一个反向提交适用于线上分支、公共分支因为历史不会被改写。说人话就是自己家里怎么折腾都行公共区域还是用revert这种留痕的方式更稳妥。5.4 reflog 找回误删的分支和提交git reflog是真正意义上的后悔药。它记录了 HEAD 指针每一次移动的历史包括 reset、revert、merge、branch 删除等操作。就算你误删了一个分支只要你知道分支最后指向的提交 ID就能用git checkout -b branch_name commit_id把它原封不动找回来。操作步骤是git reflog输出里能看到一串操作记录比如HEAD{2}: checkout: moving from feature to main找到对应的提交 ID然后基于它重建分支即可。我自己的经历是曾在一个项目里误删了特性分支以为一个星期的代码全没了后来在 reflog 里翻出来恢复那一刻真的长出一口气。这个命令在日常工作中用得不多但一旦用上就是救命级的操作。6. 进阶技巧与工作流6.1 worktree 一库多目录并行开发git worktree是我近两年用得越来越顺手的功能。它允许一个仓库同时 checkout 出多个工作目录每个目录可以停留在不同的分支上。最典型的场景你正在 feature 分支改一个比较复杂的功能代码一半没写完线上突然出现一个紧急 bug 必须马上修复。常规做法是 stash 或 commit切回主干分支修复修完再切回来来回折腾很痛苦。用 worktree 就不一样git worktree add ../hotfix -b hotfix-urgent这个命令会在上层目录新建一个hotfix目录并自动 checkout 一个新的hotfix-urgent分支。你可以在这个新目录里修复 bug、提交、推送完全不影响原目录里没写完的功能。等 bug 修好回到原目录继续干活就行。常用操作还包括git worktree list查看所有关联目录git worktree remove path删除某个工作目录。我用完的感受就是早该装了省掉大量 stash 和切换分支的中断成本。6.2 cherry-pick 摘取指定提交有些时候你并不想把一个分支整个合并过来只需要其中某一个提交。比如某个修复 bug 的提交在 develop 分支上但线上用的还是 release 分支只想把那个 fix 拿过来。git cherry-pick commit_id就能精准摘取git switch release git cherry-pick a1b2c3da1b2c3d是 fix 提交的 ID。cherry-pick 会把这次提交的改动应用到你当前的分支上并生成一个新的提交。它和 merge 的关系可以这么理解merge 是整条分支嫁接到一起cherry-pick 是单独取一两个提交搬到别的分支。如果过程中有冲突解决方式跟 merge 冲突一样处理完记得git cherry-pick --continue收尾不要中途退出否则 Git 会一直处于一个未完成的 cherry-pick 状态。6.3 submodule 子模块把仓库嵌进仓库当一个项目需要引用另一个独立开发的仓库时可以用git submodule。典型场景你的主系统依赖一个内部公共库这个公共库有自己的仓库和版本演进你不想把它的代码直接复制进来而是希望锁定到某个版本主仓库和子模块各自独立演进。git submodule add https://github.com/example/common-lib.git libs/common git clone 主仓库地址 git submodule update --init --recursive第一行命令添加子模块之后别人 clone 主仓库时子模块目录是空的需要执行第三条命令初始化并拉取。这里最常见的坑是子模块的 URL 写在.gitmodules文件里如果这个文件用了团队的内部地址外面的人 clone 时会因为没权限而失败。在实际工作中除非确有强依赖否则我不太建议轻易使用 submodule因为它让仓库复杂度上了一整个台阶。简单的依赖关系用包管理器它不香吗只有当共享代码必须跟随独立版本发布时submodule 才是正确答案。7. 常见问题与排查技巧实录7.1 常见报错速查表把工作里高频出现的 Git 报错整理成一张表每个错误都是我或者同事实际踩过的照着排查能省下大量搜索时间。报错信息出现原因解决办法fatal: not a git repository (or any of the parent directories): .git当前目录不是 Git 仓库或者命令执行错了位置先cd进仓库目录必要时用git init初始化仓库无法将“git”项识别为 cmdlet、函数、脚本文件或可运行程序的名称Windows 环境下 Git 没有安装或没配环境变量检查是否安装了 Git然后在系统环境变量 Path 中加入Git\cmdfatal: refusing to merge unrelated histories两个分支仓库没有共同的历史基点确认没问题后用git merge --allow-unrelated-histories branchfailed to push some refs to ...远程分支有本地没有的提交先git pull --rebase再重新推送Permission denied (publickey)SSH 公钥未配置、配置错误或密钥不匹配检查ssh -T gitgitee.com确认公钥已完整添加warning: LF will be replaced by CRLF换行符不统一引起的警告执行git config --global core.autocrlf trueLogin failed. Check API token or GitLab versionIDE 插件连不上 GitLab通常是 token 过期或版本兼容问题在 IDE 设置里重新生成并填入 Access Token并确认 GitLab 版本中文文件名显示成\346\265\213...core.quotepath 默认转义了非 ASCII 字符执行git config --global core.quotepath falseerror: Your local changes would be overwritten by checkout当前工作区有未提交修改且目标分支也改过这些文件先git stash保存现场切换分支后再git stash pop7.2 一个完整的日常协作战术演练把上面的命令串起来模拟一个典型的开发日。早上到公司先拉取最新代码git pull。然后基于最新主干创建功能分支git switch -c feature-optimize-query。开始写代码写了一部分后想看一眼自己改了什么git diff。确认无误后提交git add . git commit -m perf: 优化查询接口的数据库访问。下午发现功能分支写了一半线上出了紧急 bug。用git stash -u保存当前未完成改动切回主干创建修复分支修完提交推送到远程发起合并请求。线上问题处理完后切回功能分支git stash pop恢复现场。下班前把功能分支推送到远程git push -u origin feature-optimize-query然后在代码托管平台发起 MR 让同事评审。整套流程熟练之后其实每天会输入的命令就那十几条不用背敲多了自然就形成了肌肉记忆。7.3 少有人提的实用经验别名、quotepath 和 optional locks有一部分高频命令我建议配置别名能显著提升日常操作效率。Git 的别名配置非常简单git config --global alias.st status git config --global alias.co checkout git config --global alias.lg log --oneline --graph --all配完之后git st等于git statusgit lg可以快速浏览分支图谱。这些别名存的位置在用户目录下的~/.gitconfig文件里想删想改直接编辑文本文件也行。关于 IDE 集成的-c core.quotepathfalse参数它的作用和前面配置 core.quotepath 一样只是 IDE 启动 Git 命令时通过-c keyvalue的方式临时注入配置不需要全局修改。--no-optional-locks则是告诉 Git 在运行只读命令比如 status、diff时不要创建可选锁文件避免多个 Git 进程并发时互相影响。这个参数在脚本里调用 Git 命令时尤其有用很多 CI 工具调用 Git 都会默认加上它。另外提醒一句如果你负责部署项目务必确认 Web 服务器不会把仓库的.git目录暴露到可访问路径下。这虽然不是 Git 命令本身的问题但一旦.git目录能被外部下载整个代码历史和配置信息就全部泄露了这是部署配置层面的硬性教训。7.4 安全操作提醒git push --force是能直接改写远程历史的命令风险极高不建议在公共分支上使用。如果确实需要 force push先确认没有其他同事正在使用该分支操作后主动通知团队。更温和的做法是用git push --force-with-lease它会在推送前检查远程分支是否与你上次拉取时一致如果期间有别人推了新提交就会自动拒绝安全性高得多。Git 命令的报错信息有时候看起来吓人但绝大多数都只是语法或状态问题。我的经验是先看第一行提示它通常直接告诉你错误类型再确认当前在哪个分支、工作区状态如何用git status打开局面最后才搜索或者查文档。盲目执行网络上搜来的命令尤其是和管理历史相关的命令往往是搞坏仓库的根源。最后分享一个我自己的习惯吧。每天收工前我都会执行一遍git status确认工作区是干净的再看一眼git log --oneline -5确认今天的提交都在。这个习惯坚持了很多年让我几乎很少遇到“代码到底提交到哪去了”的情况。Git 这门工具命令确实多但每天真正高频用到的就那一小部分把这部分练扎实再配合 reflog 和 worktree 这类进阶兜底能力日常开发已经绰绰有余。希望这篇整理能替你省下一点摸石头过河的时间。