资讯动态

Git分支操作详解:查看、创建、合并与冲突处理

发布时间:2026/9/18 8:07:42 来源:尧图企业网站定制
写Git教程往往容易陷入一个误区一上来就铺开讲各种命令讲完大家还是不知道实际开发中怎么用。尤其是分支——这个Git里最核心、也最容易被用乱的功能。这篇是Git系列教程的第五篇我打算把分支的“查看、创建、合并”三条主线串起来结合这些年实际项目里踩过的坑把链路讲透。内容不追求覆盖所有冷门参数而是聚焦日常工作流里最高频的操作怎么看当前在哪个分支、怎么建一个新分支、怎么把分支上的改动合并回主干、冲突了怎么处理。不管你是刚接触Git的应届生还是用了两年Git但一直没理清分支逻辑的“熟练工”这篇都能让你少走几次弯路。先说明一点这篇文章默认你已经装好了Git并且基本了解commit、push、pull这几个基础操作。如果连Git还没有装建议先花十分钟把环境配好再回来看分支操作。分支本身并不难真正容易翻车的往往是把分支与其他概念混在一起的时候——比如“我切换分支怎么代码不见了”“我明明合并了怎么远程没反应”这类问题我会在后面的常见问题章节专门梳理。1. 先搞清楚分支到底是个什么东西很多人用Git分支用了一年可能都没想明白分支本身到底存了什么为什么创建分支那么快为什么切换分支有时候会丢失改动1.1 分支本质上只是一个指针Git里面的分支本质上就是一个指向某个commit对象的可变指针。你可以把Git的提交历史想象成一条由提交节点连成的链每个节点保存了当时项目文件的快照、父节点信息、提交人、提交信息等。分支名就是贴在这条链上某个节点上的“便利贴”。当你执行git commit当前分支这个“便利贴”就会自动挪到新生成的提交节点上。这个设计带来的好处非常明显创建分支几乎是瞬间完成的因为它只是创建一个几字节的指针文件而不是复制一份项目源码。我经常用一句话跟同事解释分支和拷贝的区别“拷贝是把一本书复印一遍分支是在书页上贴个标签书还是那本标签指向哪里哪里就是当前版本。”理解了这一点很多现象就讲得通了为什么你新建的分支能“看到”之前所有提交因为新分支指针默认指向当前HEAD所在的提交从那以后两个分支各自往前走代码才真正分道扬镳。1.2 HEAD你当前到底站在哪里与分支配套的核心概念是HEAD。HEAD也是一个指针但它特殊在它指向的是“当前所在的分支”而不是某个具体的提交。当你执行git checkout或git switch切换分支时Git做的事其实只有两步把HEAD指向新的分支名然后把工作目录里的文件替换成该分支最新提交对应的快照。这里有个极容易踩坑的点HEAD不等于分支名但大多数时候你不需要关心HEAD的内部实现只需要知道“HEAD指向哪个分支我就在哪个分支上”。可以用git symbolic-ref HEAD查看HEAD到底指向什么正常情况下输出类似refs/heads/main。如果你看到的是refs/heads/后面什么都不跟那说明你处于detached HEAD状态也就是直接检出了某个历史提交而不是分支这种状态下做提交会找不到归属新手经常在这里栽跟头。1.3 分支的实际价值隔离与并行明白了分支是指针再来看它的价值就清晰了。分支带来的核心能力是两个隔离和并行。所谓隔离是指不同分支上的提交各自独立互不影响。你可以在dev分支上随便改、随便提交、甚至把代码改坏只要不合并回主分支主干永远是稳定的。所谓并行是指多条开发线可以同时前进——张三在feature/login上做登录模块李四在feature/order上做订单模块互不干扰最后由项目经理或组长统一把功能分支合并回主干。我在团队里经常用一句话强调分支的意义“主干永远是可发布状态。”每个开发者在自己的特性分支上开发合并前经过测试和评审这才是一个成熟团队该有的协作模式。如果你现在还习惯所有人直接往master上提交看完这篇之后建议赶紧改掉这个习惯。2. 查看分支先弄清家底再动手查看分支是分支操作的第一步。很多人一上来就敲git branch然后面对一堆输出懵了到底是本地分支还是远程分支我当前在哪个分支哪些分支合并过了别急逐个来看。2.1 最常用的分支查看命令组合先说最高频的三条git branch列出所有本地分支当前分支前面会有一个*号标记绿色高亮如果你配了颜色。git branch -v在分支名后面显示该分支最新的提交哈希和提交说明方便你快速看出每个分支分别停在哪里。git branch -vv比-v再多一列显示本地分支与远程分支的关联关系也就是upstream信息比如[origin/dev]这样的标记。实际工作中我几乎不用裸的git branch最少也要用git branch -vv。原因很简单光看分支名你不知道这个分支对应远程哪个分支、领先或落后几个提交这些信息对判断下一步操作非常关键。还有两个高频场景查看远程分支用git branch -r查看所有分支本地加远程用git branch -a。-a的输出里远程分支会以remotes/origin/xxx的形式出现注意远程分支你通常不能直接切换上去工作需要先基于它创建本地分支。2.2 怎么看当前在哪个分支这个问题的答案其实不止一种方式。最直观的方式是看命令行提示符。如果你配了git-prompt之类的工具终端会显示类似(main)的前缀。没有配的话执行git branch看哪一行前面带*即可。更进一步执行git status第一行输出On branch xxx一目了然。还有一个被我经常用的方法git log --oneline --graph --all -n 20。这条命令会以图形化的方式展示最近20条提交并且用符号标识各个分支所在的位置。比如你会看到* feature/login、* main这样的标记一眼就能看出当前主线停在哪、功能分支领先了多少个提交。这种“上帝视角”对理解分支关系帮助非常大。平时在IDE里工作的话IDEA的右下角会显示当前分支名VS Code的左下角也有类似标记。不过IDE偶尔会“骗人”——提示信息没自动刷新所以当我拿不准时还是习惯回终端敲一下git branch确认避免判断失误导致误操作。2.3 查看分支之间的差异与状态除了看分支本身开发中更常需要的是对比分支之间的差异。这里列举几个我会用到的高频操作git log main..feature/login查看feature/login上有而main上没有的提交。git diff main feature/login对比两个分支最新提交之间的文件内容差异。git log --oneline --graph --all按图形化方式看整个提交网络这是排查分支结构问题最有效的命令没有之一。其中git log main..feature/login在合并前非常有用。它相当于提前告诉你“如果我执行合并会带进来哪些提交”这些提交是否都是你想要的有没有夹带私人提交提前筛查能减少很多麻烦。另一个很实用的命令是git branch --merged和git branch --no-merged用来列出已经合并进当前分支的以及尚未合并的分支。前者是“可以安全删除的候选名单”后者是“千万别手滑删掉的黑名单”单独记这两个命令不太起眼但在做分支清理的时候简直救命。3. 创建分支建分支原来有这么多讲究说实话创建分支的命令本身非常简单但很多人在“从哪儿建”“建完要不要切”“怎么跟远程关联”这几个问题上反复踩坑。这一节我们把场景拆开讲。3.1 最简单的创建与切换组合创建分支的命令有三兄弟虽然都能完成“创建分支”这件事但细节不同git branch 分支名创建一个新分支但不切换过去。git checkout -b 分支名创建并立即切换过去。git switch -c 分支名Git 2.23推出的更语义化的写法功能与上一条完全一样。我个人的习惯如果只是想生成一个分支供以后使用用git branch如果创建完马上就要开始写代码用git checkout -b或git switch -c。git switch系列命令是Git官方后来刻意推出用来替代checkout的部分功能的因为checkout承担了太多职责切换分支、恢复文件、检出新分支……容易让人混乱。实际场景举例白天上班接到需求“给用户中心加一个找回密码页面”我先git checkout main确保从最新的主干拉分支再执行git checkout -b feature/password-reset然后开始开发。注意一个原则新分支最好从main、develop这类主干分支创建而不是从某个功能分支再拉功能分支。不然功能之间的代码互相纠缠合并的时候会非常痛苦。3.2 从指定提交、标签或远程分支创建git branch的完整用法是git branch 新分支名 起点起点可以是任意提交哈希、已有的本地分支名、远程分支名或标签名。举几个例子git branch fix/hotfix abc1234从提交abc1234位置拉出一个修复分支。git branch dev origin/dev基于远程分支origin/dev创建本地分支dev。git branch demo v1.0.0从标签v1.0.0处拉出demo分支。这个能力在排查线上问题时特别好用。比如线上出了紧急bug但main上已经合了很多新功能不方便直接改这时候可以找到线上版本的tag例如v2.3.1从那个tag拉一个hotfix/xxx分支修复后打补丁发布完全不影响主干上的新功能开发。还有一个非常常见的场景从远程分支创建本地分支。输入git checkout -b dev origin/dev即可。这里有个不那么自动化的点如果本地分支名和远程分支名相同可以直接用git checkout --track origin/devGit会自动创建同名的本地分支并关联远程分支。关联上之后git push和git pull就不用每次指定远程分支名了能省不少事。3.3 分支命名的规范与建议分支名看似随便起但起得不好后面会非常头疼。我见过有人用aaa、test1、new这种名字过一周再回来看根本不知道这个分支是干嘛的。这里给出我在团队里推行的命名风格供参考功能分支feature/功能描述例如feature/user-login修复分支bugfix/问题描述或hotfix/问题描述例如hotfix/login-error发布分支release/版本号例如release/v1.2.0临时实验分支experiment/描述例如experiment/new-cache层级目录式的命名不仅让分支归类清晰还能让很多Git管理工具包括GitLab网页端、SourceTree、IDEA自带的分支面板自动按目录折叠浏览体验好了不止一个档次。另外强烈建议分支名尽量全小写英文加短横线不要用中文、不要用空格、不要用.,这些符号在Shell和工具里多多少少会出幺蛾子。我见过同事用中文建分支结果在Jenkins构建脚本里因为编码问题直接报错白白折腾了一下午。4. 合并分支把成果汇入主干的艺术创建分支容易合并分支才是真正考验功力的时候。很多人怕合并本质上是怕冲突。这里我要先说一句合并本身不可怕只要理解了合并的原理和策略绝大多数冲突你都能从容解决。4.1 两种合并方式快进合并与三方合并Git执行git merge时根据具体情况会选择两种合并方式之一。第一种叫快进合并Fast-forward merge。当目标分支比如main从你拉出feature分支之后没有任何新的提交也就是main的指针还停在feature分支历史的一个祖先节点上这时Git只需要把main指针直接挪到feature当前位置不需要生成新的提交。这种合并最干净历史是一条直线。第二种叫三方合并Three-way merge。当main在拉出分支之后又走了几步而feature也走了几步两个分支产生了分叉Git就需要找出三个快照两个分支的最新提交以及这两个提交的共同祖先merge base然后对比差异把两边都改动的部分合并到一起。如果两遍改的是同一个文件的同一行Git无法自己判断该保留哪边就会产生冲突需要人来做决策。判断合并类型有一个偷懒的办法执行git merge feature时如果输出显示Fast-forward字样就是快进合并如果显示Merge made by the ort strategy较新版本是ort老版本是recursive就是三方合并会额外生成一个合并提交。4.2 合并的主流程从准备到推送一个规范的合并操作我建议按如下步骤走确保工作区干净。执行git status确认没有未提交的改动有的话先提交或暂存git stash。切到目标分支。想合并到main就先git checkout main。拉取最新代码。执行git pull --rebase或git pull确保本地main和远程保持一致。这一步很多人忽略结果合并的时候把远程已经删除的旧文件又带了回来或者在push时收到一堆冲突提示。执行合并。git merge feature/login。冲突了就解决冲突下一节细说没有冲突会直接生成合并提交。推送到远程。git push。这里面我要特别强调第3步。你可以回想一下是不是经常遇到“我明明把分支合并了怎么push上去没有变化”的情况大概率就是你合并之前没有拉取远程最新代码导致你的本地main已经落后合并提交没有包含远程最新的东西。4.3 冲突处理从慌到不慌冲突并不可怕它只是Git在告诉你“这里我搞不定需要你判断。”真正可怕的是冲突之后一顿乱操作把代码搞得更乱。当冲突发生时Git会在冲突文件里插入冲突标记。你会看到类似这样的内容 HEAD 这里的代码是当前分支main的版本 这里的代码是合并进来分支feature的版本 feature/login到之间是当前分支的内容到之间是要合并进来的分支的内容。你需要根据业务逻辑决定保留哪部分、调整哪部分或者两者都要。记得把冲突标记本身删除干净这是新手最常犯的错误——改了半天代码结果把、这些标记留在了文件里编译直接报错。解决完冲突之后对每个冲突过的文件执行git add然后执行git commit注意这里不是git merge --continue也可以但--continue更语义化会自动带上默认的合并提交信息。以IDEA为例解决冲突有图形化界面可以很方便地选择左边、右边还是both强烈推荐用工具解决而不是手动在编辑器里删标记。注意如果你在合并过程中发现自己搞不定想回到合并前的状态执行git merge --abort即可。Git会把你工作区恢复到合并开始之前的样子。这个命令是后悔药心里要始终记得有它。4.4 合并后验证别急着推送合并完成不代表万事大吉。我个人的习惯是在推送之前先做一轮本地验证git log --oneline --graph -n 10确认合并提交生成正确分支网络是否符合预期。git diff main origin/main对比本地与远程main的差异确认没有意外文件被带进来。编译一把并跑相关测试。合并引起的编译失败不是罕见事尤其是两个分支改动同一个接口定义时Git可能不报冲突但编译不通过。推送之前多花两分钟验证比推上去之后再回滚要划算得多。我在团队里见过太多次“推上去才发现少了一个文件”的尴尬场面。5. 常见问题与排查技巧实录这一节的内容全部来源于我实际开发中和带新人时遇到过的真实问题挑高频的整理出来每一条后面都会给出排查思路。5.1 常见问题速查表问题现象原因解决办法切换分支后之前写的代码不见了切换分支前有未提交的改动切到其他分支后改动还留在原工作区切回来继续开发如果你执行了git checkout .或git clean那改动就被丢了只能从git reflog碰运气执行git merge提示“Already up to date”你已经在目标分支上或者两个分支没有分叉确认当前分支名确认是否忘了git fetch拉远程最新信息合并时一堆冲突头都要大了两个分支改了同一批文件的相同区域不要慌逐个文件解决也可以先用git merge --abort退出重新规划合并方式合并完推送远程无变化本地main在合并前没有拉取远程最新代码执行git pull --rebase之后重新合并如果已经推过用git push --force-with-lease覆盖注意force是危险操作确认只有你自己在动这个分支才用误删了还没合并的分支手滑执行了git branch -D xxx立即执行git reflog找到分支最后一个提交的哈希用git branch xxx hash恢复IDEA右下角不显示分支名一般是IDE版本或Git配置问题点击右下角有“Git”字样的位置呼出分支面板如果完全消失检查是否开了“Expose branches from all repos”拉取代码提示“Rebasing”字样卡住git pull默认行为或你在一个rebase进行中如果不想rebase用git pull --no-rebase如果已经在rebase中途用git rebase --abort退出5.2 三个容易忽略的细节习惯第一提交前一定要看清自己在哪个分支。这句话听起来像废话但我在代码评审中见过不止一次有人本该在feature分支开发结果所有提交都打在了main上。原因通常是早上切换到main拉了个最新代码然后忘了切回功能分支就开始写代码了。破解方法很简单写代码前养成执行git branch看一眼的习惯或者把终端提示符配成分支名可见。第二git branch -D是危险操作。大小写区别很大git branch -d只会删除已经合并进当前分支的分支如果分支未合并会拒删git branch -D则不管三七二十一强制删除。我建议日常清理分支优先用-d报错说明分支还有独立提交这时候重新思考是否真要删而不是直接-D暴刀解决。真需要-D的时候先用git log branch_name确认里面没有你需要的提交。第三合并策略不必迷信。Git还提供了git merge --no-ff禁止快进合并和git merge --squash将分支上所有提交压缩成一个提交等策略。很多团队强制要求--no-ff因为这样能保留清晰的“功能合并”历史--squash适合在合并实验性小改动时用能让主干历史整洁。选择哪种策略没有对错团队统一即可但一定要明白合并不仅仅是把代码并过来也是有历史可读性的工程决策。第四配套命令git commit --amend和git stash的使用。你正在分支上开发写完发现提交信息打错了用git commit --amend -m 新的信息就能修正上一次提交。如果你在分支A开发了一半临时要去分支B修个紧急bug又不想把半成品提交上去git stash就是为你准备的——它把你的改动暂存起来切到B分支改完了再切回来git stash pop恢复现场。这两个命令和分支操作经常配合使用用熟了整个开发流会非常顺。5.3 综合实例一次标准的多人协作合并最后用一个完整场景串一下所有操作。假设你在做一个feature/user-center功能分支开发完成后要合入develop分支# 1. 确认当前在feature分支且工作区干净 git branch git status # 2. 切到develop并拉取最新代码 git checkout develop git pull --rebase # 3. 把feature分支合并进来 git merge feature/user-center # 4. 若有冲突逐个文件解决后add和commit # ...解决冲突中... git add . git commit --no-edit # 5. 跑测试、看日志 npm test git log --oneline --graph -n 10 # 6. 推送到远程 git push这就是一个最标准的合并操作闭环。如果中间任何一步出问题翻回上面的速查表对照排查即可。我个人在实际项目中还有一个小习惯合并完develop回到feature分支执行git merge develop把最新的develop反向合并回来。这样做的目的是让功能分支尽早接触主干的新改动减少合并时的大面积冲突。我们团队内部叫它“喂草”——让分支持续吸收主干的养分等真正需要合回主干那天冲突范围会小得多。这个习惯坚持下来你会明显感觉到合并不再是开发流程里的“高危环节”而是一次平常得不能再平常的日常操作。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价