Git从入门到实战:高频命令、分支管理与冲突解决全攻略

发布时间:2026/9/7 18:00:40
Git从入门到实战:高频命令、分支管理与冲突解决全攻略 1. 写在前面为什么你需要一份真正能用的 Git 命令清单Git 这东西我用了十几年从最早 SVN 时代的抵触到后来被强制迁移再到如今团队里带新人时反复讲同一套命令最大的体会是Git 不难难的是没人告诉你每个命令在真实工作流里到底该怎么用、坑在哪里。很多同学背了一堆命令git init 会敲git commit 也会敲但一遇到“改错文件了想撤销”“冲突了不知道怎么处理”“push 被拒绝了”就直接懵了。原因很简单——学校教程和博客喜欢罗列命令却很少讲清楚命令背后的状态模型和适用场景。而日常工作恰恰是场景驱动的你打开终端时想的不是“我要用 git checkout”而是“我刚拉下来的分支怎么切换”“我只想提交其中一个文件的改动”“我 commit 消息写错了要改一下”。这篇博文我打算换个讲法不讲语法字典而是按照大家真正会遇到的场景来组织命令同时把最容易踩坑的细节标出来。内容会覆盖从安装配置、日常提交、分支管理、撤销回滚到免密登录、冲突处理、误操作恢复这些高频场景最后附一张排查速查表方便你在紧急时刻直接抄作业。适合的读者刚入门 Git 想建立完整认知的新人用了几年但始终靠几个死命令打天下的中级开发者以及需要给团队做 Git 培训、想整理一份实用资料的人。看完你会对 Git 的日常操作形成一套完整的心理模型而不是继续在“试出来的命令”里打转。提示本文所有命令在 macOS / Linux / WindowsGit Bash下均验证过项目在 GitLab 和 GitHub 上都一样用。2. 安装、配置与免密登录解决“环境没准备好”的问题2.1 安装 Git不同系统各有一招很多人以为 Git 装完就能用其实装只是第一步装完之后的环境配置才是真正影响效率的地方。先说安装本身。Windows去官网下载安装包一路 Next 就行。唯一需要注意的是在 “Adjusting your PATH environment” 这一步选择 “Git from the command line and also from 3rd-party software”这样以后在 PowerShell 或 CMD 里也能直接用 git 命令。装完打开 Git Bash敲git --version验证。macOS自带一个远古版本建议直接装新版。最简单的方式是brew install git装完会自动覆盖系统自带版本。如果你不想装 Homebrew直接去官网下载 .dmg 安装包也可以。LinuxUbuntu/Debiansudo apt update sudo apt install git -y。CentOS/RHEL 则是sudo yum install git -y。安装本身没有技术含量但版本有讲究。我建议尽量用 2.30 以上版本因为 2021 年之后 Git 把默认分支名从master改成了main很多新特性比如git switch、git restore、稀疏检出也都依赖较新的版本。如果你手里的仓库还在用master也无所谓只是新仓库初始化的默认分支会不同知道这个差异就行不影响后续操作。装完之后做一次全局自检把版本和基本路径确认一下git --version which git这两条命令能确保你敲的git是刚装的那个而不是系统里遗留的旧版本。我之前就遇到过 macOS 上which git指向 Xcode 自带的老版本导致一些新命令不可用。2.2 安装后的三项必做配置身份、编辑器、换行符Git 装完不会自动知道你是谁每次提交commit都需要记录作者信息所以第一件事就是配置全局身份。这一步不做的后果是你提交时 Git 会报一堆错或者提交记录里出现一串不明所以的系统默认用户名。git config --global user.name 你的名字 git config --global user.email 你的邮箱为什么要配邮箱因为这个邮箱会和你的 GitHub/GitLab 账号绑定提交记录会通过邮箱关联到你的头像和主页。建议直接用公司或常用的那个邮箱别随便填一个临时邮箱否则以后改起来还挺麻烦。然后是配置默认编辑器。Git 在合并冲突、交互式变基等场景下需要打开文本编辑器让你写信息默认是 vim。如果你不习惯 vim可以改成 VS Code 或 Notepadgit config --global core.editor code --wait这么一配以后遇到需要编辑的场景Git 会自动打开 VS Code文件保存关闭后 Git 继续执行。这个体验比在终端里啃 vim 舒服太多了。再一个容易忽略的是换行符配置。Windows 和 macOS/Linux 的换行符不一样如果不做处理同一个文件在不同系统间切换会出现整个文件都被标记为改动的情况。建议统一配置git config --global core.autocrlf input # macOS/Linux git config --global core.autocrlf true # Windows配置完成后用git config --list检查所有配置项。如果你发现配置改乱了可以用git config --global --unset 配置项名来删除某一条或者直接改~/.gitconfig文件。注意配置项的作用范围分三层——本地仓库local、全局用户global、系统级system。优先级从高到低是 local global system。同一个配置项在不同层级有不同的值以更具体的层级为准。2.3 免密登录SSH 配置的完整流程日常工作里最烦的事之一就是每次 push/pull 都要输账号密码。虽然 HTTPS 方式在部分 Git 托管平台上配置了凭据管理器后也能记住密码但 SSH 方式依然是最省心、最通用的免密方案一次配置长期有效。先检查你本机有没有现成的 SSH 密钥ls -al ~/.ssh如果看到id_rsa和id_rsa.pub这两个文件说明以前生成过可以复用。如果没有就生成一对新的ssh-keygen -t rsa -b 4096 -C 你的邮箱生成过程中会让你选保存位置和设置 passphrase。保存位置默认即可passphrase 可以留空否则以后每次连接都得输入一遍等于没免密。生成完把公钥内容复制出来cat ~/.ssh/id_rsa.pub登录 GitHub或 GitLab进入 Settings - SSH and GPG keys把公钥粘贴进去保存。然后测试连接ssh -T gitgithub.com看到 “Hi 用户名! Youve successfully authenticated” 就表示成功了。以后克隆仓库时记得用 SSH 地址比如gitgithub.com:user/repo.git而不是https://github.com/user/repo.git这样才能触发免密。如果你不想用 SSH还有一种方案是配置 HTTPS 凭据缓存git config --global credential.helper store执行一次后Git 会把账号密码明文存在~/.git-credentials文件里以后自动使用。虽然方便但明文存密码有安全风险我不建议在共享机器上这么干。更好的做法是用credential.helper cache加超时时间比如缓存一小时git config --global credential.helper cache --timeout36002.4 配置 Git 命令别名把长命令变成短命令配置别名的目的不是“炫技”而是减少高频命令的输入成本。以下是我多年养成的习惯配置覆盖了 status、log、checkout、branch 等最常用命令git config --global alias.st status git config --global alias.co checkout git config --global alias.br branch git config --global alias.cm commit git config --global alias.lg log --oneline --graph --all --decorate git config --global alias.last log -1 HEAD --stat配置完以后git st就是git statusgit lg能以图形化方式查看提交历史。尤其是git lg在代码评审和排查历史时非常好用分支分叉、合并轨迹一眼就能看出来。如果你想更省事还可以把一些组合操作定义成别名比如“提交并推送”git config --global alias.cmp !f() { git add -A git commit -m \$1\ git push; }; f这种写法本质是把一条 shell 函数绑定到 git 子命令上适合你确信操作不会出问题的小改动。不过我的建议是别太依赖这种“一条龙”命令因为git add -A会把所有改动文件都加进来稍有不慎就会把不该提交的文件也提交了。3. 日常开发中最核心的 8 条命令以及它们背后的状态模型3.1 Git 状态模型理解三个“区域”命令就是操作这三个区域要真正掌握 Git 命令不能靠死背要先理解 Git 内部的数据模型。简单来说一个 Git 仓库里有三个关键区域对应你本地文件生命周期的三个阶段工作区Working Directory你电脑上能看到的文件也就是你正在编辑的代码。暂存区Index/Staging Area一次提交前的临时存放区把你想提交的文件“选”到这里来。本地仓库Local Repository已经提交过的历史记录存放在.git目录里。日常操作无非就是在这三个区域之间移动文件而已。git add把文件从工作区放进暂存区git commit把暂存区的内容固化成本地仓库里的一个版本记录git checkout或git restore把文件从暂存区或本地仓库拉回工作区。这三者打通之后你会发现初学阶段的一大堆混乱命令其实只是同一套规则的组合棋步。比如git add为什么会把文件从“未跟踪”变成“已暂存”git commit为什么只提交了一部分文件git status输出里的红色和绿色又分别代表什么——这些都和区域模型相关。写代码时除了这三个区域还有一个常见状态是“未跟踪Untracked”——新文件从未被git add过Git 知道它的存在但不管理它。这就是为什么git status里新文件总是出现在 “Untracked files” 一节里。提示遇到任何不确定的命令先运行git status看当前状态再想下一步要动哪个区域。这比硬猜命令有效得多。3.2 git status 和 git diff提交前必做的两个动作我见过不少同事提交代码前直接git add .然后git commit -m 修改最后发现把调试日志、配置文件、无关文件全提交上去了。要避免这种情况提交前必须花几秒钟检查两个东西改了哪些文件、具体改了什么内容。git status是最基本的检查命令它告诉你工作区和暂存区的当前状态。输出结果中红色的modified:表示文件已修改但还没git add。绿色的new file:或modified:表示文件已暂存。Untracked files:下面的都是新文件Git 还没开始跟踪。如果你想看具体改了什么内容用git diff。不带参数时它比较的是“工作区和暂存区”的差异加上--staged或--cached参数时比较的是“暂存区和本地仓库”的差异。git diff # 工作区 vs 暂存区还没 git add 的那些改动 git diff --staged # 暂存区 vs 本地仓库已经 git add 的改动在实际工作中我提交前通常是这个节奏git status git diff # 浏览未暂存的改动确认没有调试代码 git add file # 按文件添加需要哪些加哪些 git diff --staged # 浏览已暂存的内容确认无误 git commit -m feat: 添加用户登录接口这套流程看起来很繁琐但能避免大量“提交了不该提交的东西”的问题。尤其是git diff这个步骤往往能帮你发现自己在代码里留的临时打印、误改的配置、或者不小心删除的代码。3.3 git add不是只有 git add . 这一种用法git add的核心功能是“把工作区的改动添加到暂存区”但它的用法远比git add .丰富。git add file1 file2只添加指定文件。推荐在改动文件不多、且你想控制提交粒度时用。git add -p交互式分段暂存patch mode。它会把一个文件里的多处改动拆成若干小块让你逐个决定是否暂存。这个命令在“一个文件里既有必须提交的代码又有临时调试代码”的场景下极其有用。git add -A添加所有改动包括删除的文件。相当于git add --all。git add -u只添加已跟踪文件的改动不处理新文件。git add .添加当前目录下的所有改动不包括已删除文件实际是等效于git add -A在当前目录范围内的版本。我个人的习惯是单独文件多用git add file涉及批量文件但想逐个确认时用git add -p。git add .只在确实想把所有改动一起提交时才用因为一旦里面有node_modules、构建产物、本地配置文件等不该提交的东西容易顺手带进仓库。git add -p的实际操作其实很简单命令执行后会进入一个交互界面显示第一个 hunk 开始的行号和 diff 内容然后问你Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]?。常用的就几个键y暂存这一块n不暂存这一块q退出不处理剩余部分a暂存当前 hunk 以及之后所有同文件的 hunkd跳过当前 hunk 以及之后所有同文件的 hunke手动编辑当前 hunk 的内容这个最强大可以精确到行3.4 git commit提交信息怎么写以及 --amend 的正确使用姿势提交信息是一个仓库的“日志”直接影响团队协作时排查问题的效率。好信息应该能回答两个问题改了什么为什么改。我推荐采用目前在业界比较通用的 Conventional Commits 规范格式如下type(scope): subject常见的 type 有feat新功能fix修复 bugdocs文档修改style格式修改不影响逻辑refactor重构test测试相关chore构建配置、工具等比如git commit -m feat(user): 添加用户登录接口 git commit -m fix(cart): 修复购物车删除后总价不刷新的问题git commit --amend是另一个高频命令作用是“修改上一次提交”。它有两种典型用法第一种你刚提交完就发现漏了一个文件或者提交信息写错了。这时候先git add漏掉的文件再执行git commit --amend -m 新的提交信息这会把上一次提交替换成一条新提交不会新增一条“修改提交信息”的垃圾记录。第二种提交后想修改同一提交里的内容。同样先改文件再git add最后git commit --amend --no-edit--no-edit表示沿用原来的提交信息不弹出编辑器。注意--amend会改写提交历史所以只适用于“还没有推送push到远程”的提交。如果已经 push 了--amend之后需要git push --force才能更新远程历史这会导致其他人的本地分支和远程不一致必须谨慎使用。3.5 git log看懂提交历史比会写命令更重要git log是查看提交历史的命令默认输出是“完整提交哈希 作者 日期 提交信息”的列表信息量很大但不直观。日常我几乎只用几个定制格式git log --oneline # 一行一条记录只显示短哈希和提交信息 git log --oneline --graph # 显示分支合并图谱 git log --oneline --graph --all # 所有分支的历史常用于排查分叉情况 git log -5 # 只看最近 5 条 git log --oneline --author名字 # 按作者过滤 git log --oneline --since2 weeks ago # 按时间过滤 git log -p file # 查看某个文件的完整修改记录如果你想快速知道某行代码是哪个提交引入的推荐一条比git log更精准的命令git blame file它会把文件每一行的内容、行号、最后修改的 commit、提交者和时间都列出来。排查“这行代码是谁在什么时候写的、出于什么原因”时git blame能直接给出答案比在日志里翻半天高效得多。3.6 git branch、git checkout/switch分支管理的核心动作开发新需求时最忌讳直接在主干上改代码。每个需求都应该有一个独立分支开发完再合并回主干。这是 Git Flow 和 GitHub Flow 都遵循的基本纪律能防止别人的临时提交影响你的代码也方便后续代码评审和灰度发布。git branch # 查看本地分支当前分支前面有 * 号 git branch 新分支名 # 创建新分支不切换过去 git checkout 分支名 # 切换分支 git switch 分支名 # Git 2.23 推荐的分支切换命令 git switch -c 新分支名 # 创建并切换等价于 git checkout -b 新分支名 git branch -d 分支名 # 删除分支已合并的分支才能删 git branch -D 分支名 # 强制删除分支未合并的分支也能删会丢失提交在切换分支前一个很重要的习惯是先确认工作区是干净的否则未提交的改动可能跟着你“跑”到其他分支里。Git 在切换分支时会尝试把工作区的改动带过去如果冲突就会拒绝切换。所以建议的流程是git status # 确认当前改动是否已提交 git stash # 如果有未提交的改动又必须切换先暂存起来 git checkout main # 切换分支 # 处理完事情再切回来 git stash pop # 恢复暂存的改动git switch是我非常推荐的替代git checkout的命令因为它的职责边界更清晰。git checkout既负责“切换分支”又负责“恢复文件”两个语义混在一起容易误操作。而git switch只管分支切换git restore只管文件恢复分开理解更安全。4. 与远程仓库协作clone、push、pull、fetch 的完整细节4.1 从零到一git clone 的几种形态git clone是把远程仓库完整复制到本地的命令有两个细节容易忽视。第一默认克隆下来的仓库只包含远程的主分支比如main或master的本地跟踪分支但git clone会把整份 Git 历史都拉下来所以你可以在本地看到所有分支的历史。如果你需要本地操作某个远程分支需要手动检出git clone 远程地址 git branch -r # 查看远程分支列表 git checkout -b 本地分支 origin/远程分支第二如果仓库很大、历史很长可以考虑浅克隆只拉取最近几条提交git clone --depth1 远程地址浅克隆能极大加速克隆过程代价是看不到完整历史后续某些操作比如git log查看老历史、合并较老分支会受限。正式项目开发建议全量克隆临时实验可以用浅克隆。4.2 git push推送的三种方式和上游分支git push用于把本地提交推送到远程仓库。最基本的用法是git push origin 本地分支名如果本地分支和远程分支同名或者已经建立了上游关系upstream可以简写为git push新建立的分支第一次推送时Git 通常会提示你设置上游分支。推荐用这个带参数的写法git push -u origin 本地分支名-u是--set-upstream的简写它会建立“本地分支 - 远程同名分支”的跟踪关系。以后在这个分支上直接git push和git pull就能工作不用再带分支名。我的习惯是每次新建分支后第一次推送必带-u。有时推送会被拒绝提示non-fast-forward这通常是因为远程分支已经有人推送了新提交你本地分支落后了。解决办法是先拉取远程最新代码再推送git pull origin 分支名 git push origin 分支名4.3 git pull 和 git fetch一字之差影响很大git pull和git fetch的关系一句话就能说清git fetch只把远程的最新提交拉取到本地但不会自动合并或改动你当前的工作区git pull则是git fetch 自动合并merge一步到位。理论上如果团队协作频繁或者你对合并方式有特定要求更安全的做法是先 fetch 再手动 mergegit fetch origin git diff local_branch origin/local_branch # 先看差异 git merge origin/local_branch # 无异常再合并git pull的默认合并方式是 merge这会在历史里产生一条“Merge branch ...”记录。如果你希望历史更线性可以用git pull --rebase它的行为是先把本地未推送的提交暂存起来然后把本地分支的基底更新到远程最新提交之上再按顺序重放你的提交。效果就是没有多余的 merge 节点历史干净。不过--rebase也有代价如果本地提交和远程提交修改了同一个位置最后一步重放时会遇到冲突需要逐个文件解决。merge 遇到冲突则是在合并时解决两者解决冲突的方式大体一样只是重放顺序不同。我的建议是单人小团队怎么拉都行多人协作、分支并行多时--rebase能保持历史干净但前提是每个人都熟悉冲突解决的基本流程。4.4 远程分支同步与删除清理远程分支远程分支列表用git branch -r查看。如果一个远程分支已经合并并被删除本地可能还存有缓存的远程分支引用需要清理git fetch --prune它会删除本地保存的、远程已经不存在的分支引用。团队里经常删分支的情况下建议养成定期执行git fetch --prune的习惯否则git branch -r的列表会越来越脏。删除远程分支的命令是git push origin --delete 分支名这个操作会直接删除远程分支只删分支不删代码。如果分支上还有未合并的提交Git 会拒绝删除并给出提示你需要确认是否真的要放弃这些内容。5. 撤销与回滚reset、restore、revert、stash 的适用场景5.1 后悔药分级从“改错了文件”到“提交坏了”撤销操作是 Git 新手最头疼的部分因为“撤销”这个词太笼统。真实的场景千差万别对应着完全不同的命令。我把它按严重程度分四层第一层文件在工作区改乱了还没git add。想放弃修改恢复成暂存区或本地仓库里的样子。第二层文件已经git add进暂存区了想取消暂存。第三层已经git commit了但提交内容有问题想撤销这次提交。第四层已经git push了远程仓库里也有问题提交想在不影响其他人的前提下修复。分清楚这四层再看命令就不会乱。5.2 第一层git restore 与 git checkout如果你在工作区乱改了一通想放弃修改有两种做法git restore file # 推荐Git 2.23 git checkout -- file # 老写法git restore本质是把文件恢复到“暂存区”的内容。因为此时你还没git add暂存区里的内容就是上一次git add后的样子或者空文件所以恢复后的文件会回到最近一次提交状态。如果你连暂存区的内容也想一起覆盖可以用git restore --sourceHEAD --worktree file这会直接把文件恢复到最近一次提交HEAD的内容并覆盖工作区。5.3 第二层取消 git add文件已经暂存了但你想把它从暂存区撤出来不动工作区的文件内容git restore --staged file等价的老写法是git reset HEAD file。执行后文件会变回“已修改但未暂存”的状态内容还在工作区里。这个操作在“我git add多了文件想从中挑几个出来”的场景下极其常用。5.4 第三层git reset 的三种模式git reset是用来移动当前分支指针HEAD的命令有三种模式git reset --soft commit git reset --mixed commit # 默认模式 git reset --hard commit区别在于撤销后文件的状态保留情况--soft保留暂存区和工作区的内容只移动 HEAD 指针。效果是“撤销了 commit但文件的改动还在暂存区里可以重新提交”。--mixed重置暂存区但保留工作区内容。这是默认模式效果是“撤销 commit 且取消暂存但文件内容保留在工作区”。--hard重置暂存区和工作区彻底丢弃内容回到指定 commit 时的状态。这是最危险的一个模式一旦执行工作区里的未提交改动会永久丢失。一个典型的--soft场景你连续提交了多个 commit发现它们其实应该合并成一个更清晰的提交或者中间某个 commit 提交了不该提交的文件。你可以git reset --soft HEAD~3 git commit -m 把三次提交合并成一次HEAD~3表示往回移动 3 个提交--soft保证所有改动还保留在暂存区然后一次性重新提交。--hard的使用要极其谨慎它会把工作区恢复到指定 commit 的状态当前工作区里的未提交改动会直接被丢弃。所以执行前务必确认自己不需要这些改动或者先git stash备份一下。注意git reset --hard只会影响工作区和暂存区已经 push 到远程的提交不会因为本地 reset 而消失。要影响远程历史必须git push --force这会带来更大的风险除非你明确知道自己在做什么否则不建议在共享分支上使用。5.5 第四层git revert —— 用一次新提交来撤销旧提交如果你的错误提交已经推送到了远程共享分支正确的撤销方式是git revert而不是git reset。git revert会创建一个新提交这个新提交的内容是“撤销某个提交的改动”但它不修改历史只是往历史里追加一条记录。git revert commit哈希 git revert HEAD # 撤销最近一次提交这样做的好处是远程分支的历史仍然是线性、向前走的其他同事在 pull 时不会遇到强制更新的问题。代价是历史里会多出两条提交记录一条原提交一条撤销提交阅读历史时需要稍作区分。如果只想撤销某个文件在某个提交里的改动而不是整个提交可以使用git revert -n commit哈希 # -n 表示不自动创建提交 git restore --staged . # 把 revert 后的改动从暂存区撤出来 git checkout -- file # 按文件决定保留哪些这个过程比较细致适合“大提交里只有一部分改动是坏的”场景。5.6 git stash做到一半的改动先存起来开发新需求到一半突然要切分支修个紧急 bug此时你还没来得及提交也不想提交半成品——git stash就是干这个的。git stash # 把所有未提交的改动暂存到一个栈里工作区恢复干净 git stash list # 查看暂存列表 git stash pop # 恢复最近一次 stash并从列表中删除 git stash apply # 恢复最近一次 stash但保留列表记录 git stash drop stash{0} # 删除指定的 stashgit stash pop和git stash apply的区别在于pop恢复后自动把该 stash 从栈里移除apply会保留。如果你担心恢复后出问题可以先apply确认无误后再手动drop。git stash默认只暂存已跟踪文件的改动新建的未跟踪文件不在里面。如果想连同新文件一起暂存git stash -u # 或 --include-untracked恢复时如果有冲突Git 会提示你手动解决过程和 merge 冲突一样。5.7 误删分支、误丢提交和 reflog 做朋友前面一提到git reset --hard很危险因为会丢失提交。但 Git 其实留了一个“后悔药”——git reflog。它记录了所有分支指针和 HEAD 的每一次移动历史包括 reset、checkout、commit 等操作。举一个我真实经历过的情况某同事在 dev 分支上提交了很多代码然后误操作git reset --hard回到了更早的提交所有刚写的代码“消失”了。这时只要执行git reflog就能看到一连串的 HEAD 移动记录找到那个丢失提交的哈希比如abc1234然后git checkout abc1234 git branch 新分支名 # 把这个提交拉回成一个新分支这样一来丢失的提交就找回来了。这里的关键是只要提交后的对象没有被 Git 的 GC 机制清理reflog 里都能找到。默认情况下Git 会保存 reflog 记录 90 天所以“后悔”的时间窗口还是挺宽的。6. 合并与冲突merge、rebase 和冲突解决的正确姿势6.1 merge 与 rebase两条路线各自取舍合并分支的命令有两个git merge和git rebase。它们在大多数情况下都能把分支改动集成到一起但方式和效果完全不同。git merge的机制是创建一个新的合并提交这个提交有两个父提交。它的历史是非线性的能看到“哪些分支在什么时候汇入过主干”适合多人并行开发的场景。git rebase的机制是把当前分支的提交“搬到”目标分支的最新提交后面相当于把分支的基底换了一下。它的历史是线性的看起来像一条从头到尾的流水线代码评审时更易读懂适合频繁更新自己的功能分支、想让历史干净的场景。用一个生活化的类比merge 有点像两条河流交汇汇合点之后继续前进rebase 则像把一条支流的水先切到新的河道里再顺着主河道流。想象一下瀑布的中游和下游merge 在汇合处会留下一个明显的“汇流点”rebase 则不会。日常建议功能分支合并到主干用git merge --no-ff 分支名保留分支历史方便后续追溯。从主干更新功能分支推荐git rebase main让功能分支历史跟随主干滚动减少最终合并时的冲突。多人协作且冲突频繁如果 rebase 解决问题耗时太久可以退回用 merge优先保证代码能快速集成。6.2 冲突是什么、怎么产生的以及解决冲突的标准流程冲突产生的本质是两个分支修改了同一个文件的同一段代码Git 无法自动判断应该保留哪个版本。冲突提示会直观地告诉你哪些文件冲突了Auto-merging index.js CONFLICT (content): Merge conflict in index.js Automatic merge failed; fix conflicts and then commit the result.打开冲突文件会看到类似这样的标记 HEAD const title 新功能开发中; const title 修复紧急bug; feature/fix-bug HEAD和之间是当前分支HEAD的内容和 feature/fix-bug之间是正在合并进来的分支的内容。你需要手动决定保留哪一版或者合并两者然后删掉三行标记。解决冲突的标准流程是用编辑器打开冲突文件逐个处理冲突标记。保存文件后执行git add file标记为已解决。重复git status确认没有其他冲突文件。执行git commitmerge 模式会自动生成合并提交信息。如果在 rebase 过程中冲突流程略有差别每个冲突解决后你需要git add file然后git rebase --continue让 rebase 继续重放后续的提交。如果你想放弃整个 rebase可以用git rebase --abort回到 rebase 之前的状态。冲突处理过程中的几个实用技巧git status会列出所有冲突文件按它们当前的状态分组。git diff可以查看冲突的具体差异内容。合并冲突时git diff显示的其实就是当前合并状态的差异。如果冲突文件很多可以先解决简单的再统一git add不用一个个提交。6.3 永远不要怕冲突冲突处理的三个实战技巧技巧一善用 IDE 的可视化冲突编辑器。VS Code、IntelliJ IDEA、WebStorm 都内置了“接受当前更改 / 接受传入更改 / 同时保留两者”的按钮三选一即可。处理完再手动检查一遍代码逻辑。技巧二如果冲突涉及大范围改动建议使用git mergetool配合 Beyond Compare、Meld 等专业对比工具。配置一次后每次git mergetool会逐文件打开对比界面左右两侧分别是两个分支的版本下方是合并结果比手改标记直观得多。技巧三把握“先更新、再开发”的节奏。冲突高峰往往发生在“你的分支落后主干很久却攒了一堆改动一次性合并”的时候。如果你定期从主干 rebase 更新自己的功能分支每次冲突的规模都会被限制在小范围内解决起来会很轻松。我见过太多人习惯开发完再同步结果冲突文件成堆处理过程痛苦且容易引入 bug。7. 新项目实战演练用一个完整流程串联所有命令说了这么多理论我用一个“新需求从零到上线”的完整流程把命令串起来你可以照着走一遍加深理解。假设公司代码托管在 GitLab 上项目已经存在你负责开发一个新功能“用户中心”。第一步克隆仓库git clone gitgitlab.com:company/user-center.git cd user-center第二步创建功能分支git switch -c feature/user-center第三步开发、暂存、提交git status # 查看改动 git diff # 确认具体改动 git add src/ # 添加相关文件 git commit -m feat(user): 添加用户中心基础页面第四步定期同步主干更新git fetch origin git rebase origin/main # 把主干最新提交合入功能分支第五步推送并设置上游git push -u origin feature/user-center第六步代码评审修改反馈评审人提出修改意见你在本地改完继续提交然后再次推送git add . git commit -m fix(user): 根据评审意见调整表单校验 git push第七步合并到主干在 GitLab 上发起 Merge Request合并后本地同步git checkout main git pull origin main git branch -d feature/user-center # 删除已合并的功能分支第八步清理远程分支远程通过 MR 合并后GitLab 默认会自动删除源分支。如果没删手动删git push origin --delete feature/user-center这套流程看起来平铺直叙但每一步背后都有设计逻辑功能分支隔离开开发中的不稳定性定期 rebase 降低最终合并的冲突风险提交信息用规范前缀方便追溯push 带-u建立上游关系省去后续参数。照着这个节奏练上一周你就能形成肌肉记忆。8. 高频问题速查表与避坑经验最后整理一份我在实际工作中反复遇到的高频问题速查表按场景检索对应命令和注意事项。场景推荐命令注意事项修改了文件想放弃git restore file只影响工作区未暂存和已提交的内容不会变已 git add想取消暂存git restore --staged file工作区内容不变提交信息写错了git commit --amend -m 新信息仅限未 push 时使用提交漏了文件git add file然后git commit --amend --no-edit会替换原来的提交未 push 才能改丢弃最近一次提交保留改动git reset --soft HEAD~1改动保留在暂存区丢弃最近一次提交不保留改动git reset --hard HEAD~1极其危险无法恢复未提交改动撤销已 push 的提交git revert commit创建反向提交不修改历史想切分支但工作区很脏git stash→ 切分支 →git stash pop注意 untracked 文件用-u推送被拒git pull --rebase再git push看具体错误确认是落后导致的非快进冲突标记无法定位git status或git diff --name-only --diff-filterU后者只列出冲突文件误删分支git reflog找哈希 →git branch 名 哈希分支删除前 commit 还在 reflog 里远程分支看不到git fetch --prune清理本地缓存引用想合并多次提交git reset --soft HEAD~n再git commit适合整理本地未 push 的提交查看文件每行是谁改的git blame file排查历史必备查看图形化提交历史git log --oneline --graph --all配合--decorate显示分支名8.1 避坑经验我踩过的几个大雷第一永远不要在主分支上直接提交。哪怕是很小的改动也在单独的临时分支上做完再合并。因为主分支是所有人的基线任何一个错误提交都会扩散到所有人。我在团队里立过一个规矩主分支上不允许git push直接提交只能通过 Merge Request 合并。第二git pull --rebase并不是银弹。如果您的分支已经有多个本地未推送的提交rebase 时遇到冲突需要逐个提交解决过程反而比 merge 更痛苦。经验是分支里提交数少时优先 rebase提交数多且冲突可能性大时就老实 merge。第三注意.gitignore和文件提交时机。很多人在项目初始化时没有配置.gitignore导致本地的.env、node_modules、编译产物全被提交到仓库。这个问题在团队协作中很致命——配置文件一旦被提交之后每次本地修改都会产生 diff还会引发权限问题。建议项目创建时就配好.gitignore常见的 Node.js/Python/Java 模板可以从 GitHub 的 gitignore 仓库直接抄。第四提交信息不要写“改了一下”“修复 bug”这种废话。你当下知道改了什么但半年后回来看历史这种信息毫无价值。每条提交都应该能让未来的你或同事一眼看懂这次改动的范围和原因。第五多用git status少用猜。我在终端里最常敲的命令就是git status每执行完一条可能有副作用的命令都会看一眼状态确保自己没走偏。它就像一个仪表盘时刻告诉你当前在哪个分支、哪些文件被改了、是否落后于远程。很多人报错的第一反应是“查命令”我建议先git status。8.2 一个提高效率的终极大招给别人写清楚你的提交也给自己留好后路最后分享一个我坚持了很久的小习惯每次提交前快速跑一遍git diff --staged --stat。这条命令会列出“即将提交的文件列表和改动行数统计”比git status更精确能确认没有误加文件、没有漏加文件。适合养成习惯几秒钟的成本能省下后续几十倍排查时间。另外抽时间把常用命令做成一张小抄贴在终端旁边。不需要死记硬背Git 的美妙之处在于它的状态模型是有限且统一的。理解了工作区、暂存区、本地仓库、远程仓库四者的关系绝大多数命令都是自然推导出来的。遇到不熟悉的操作时git help 命令永远是值得一试的选项。9. 一些实际操作中的体会用了这么多年 Git我的一个核心感受是命令本身从来不是瓶颈真正拉开开发效率差距的是“能不能快速把自己从失误中捞出来”。Git 提供了几乎是所有版本控制工具里最强大的后悔机制——不管是 reset、revert 还是 reflog你总能找到一种方式把局面扳回来只要你没有被恐惧支配得手足无措。所以我特别建议你在本地拿一个不重要的仓库把今天提到的这些命令全部练一遍。故意制造一次冲突故意 reset 一下故意误删一次分支再用 reflog 找回来。只有亲手经历过这些“事故现场”你才能在真实工作中保持沉着而不是慌慌张张去网上搜命令、复制粘贴一个不知道后果的--force操作。另外第一次使用这些命令时尽量读一读完整输出。Git 的报错提示越来越友好它会直接告诉你下一步该怎么办比如“git pull 去同步”“git merge --abort 撤销合并”。很多人不看输出就急着上网搜索反而错过了 Git 已经给出的正确答案。希望这份清单能让你在下次遇到 Git 问题时先冷静看一眼自己的仓库状态再挑一把合适的“手术刀”下手。用熟了之后你会发现Git 不是敌人它是你写代码时最可靠的后盾之一。