Git篇(二):Git 分支:代码的平行宇宙,看完再也不怕合并冲突
你是否遇到过这些崩溃瞬间多人共用 main 分支写代码改动互相覆盖线上突然爆出紧急 Bug正在开发的半成品代码没法直接上线写一半的功能想临时改需求又不想把脏提交留在主分支这些问题Git 最核心的杀器 ——分支就能完美解决。 不同于 SVN 笨重的复制式分支Git 的分支是轻量到近乎无成本的指针它相当于给项目开辟多条互不干扰的平行开发线开发新功能、修复线上缺陷、做实验性重构全部可以单独拉一条分支隔离操作完全不会污染稳定主代码。本文会抛开晦涩底层术语先讲清分支本质再手把手带你走完创建、切换、合并、冲突处理、清理分支全流程最后分享主流团队分支管理策略看完你会发现开分支本该像写代码一样日常。目录一.分支和HEAD的关系二.分支操作1.查看分支2.创建分支3.切换分支一键创建加切换4.合并分支5.删除分支1.普通删除2.强制删除三.合并冲突四.分支管理策略1.分支合并策略1.快进模式Fast forward1.触发条件2.合并过程合并前合并后2.非快进模式1.触发条件2.合并后结构五.分支策略的应用1.bug分支1.储藏工作区信息2.恢复工作区信息2.解决分支合并冲突一.分支和HEAD的关系在版本回退里你已经知道每次提交Git都把它们串成一条时间线这条时间线就可以理解为是一个分支。截止到目前只有一条时间线在Git里这个分支叫主分支即master分支。再来理解一下HEADHEAD严格来说不是指向提交而是指向mastermaster才是指向提交的所以HEAD指向的就是当前分支。每次提交master分支都会向前移动一步这样随着你不断提交master分支的线也越来越长而HEAD只要一直指向master分支即可指向当前分支。cat .git/HEAD cat .git/refs/heads/master二.分支操作1.查看分支git branch2.创建分支git branch 分支名 //创建分支* 表示当前 HEAD 指向的分支是 master 分支。新创建的分支和原来的分支指向同一个修改3.切换分支git checkout 分支名一键创建加切换git checkout -b 分支名尝试在新分支进行提交此时分支状态4.合并分支此时分支状态分支合并完之后新的分支已经没有用了可以删除了5.删除分支1.普通删除git branch -d 分支名此时分支状态2.强制删除当本地分支存在未合并提交、废弃无用、普通删除命令无法清理时使用 git branch -D 强制删除该本地分支。git branch -D 分支名三.合并冲突两个分支修改了同一个文件的同一处代码再执行 merge/rebase 合并时Git 分不清该保留哪一份修改就会报合并冲突。可以发现上面不同分支的文件内容是有差异的下面进行合并会有什么效果核心说明两个分支master、dev同时修改了 ReadMe 文件的同一处内容Git 无法自动判断保留哪一份代码因此触发合并冲突合并流程中断。发现 ReadMe 文件有冲突后可以直接查看文件内容要说的是Git 会用 来标记出不同分支的冲突内容如下所示此时我们必须要手动调整冲突代码并需要再次提交修正后的结果再次提交很重要切勿忘记直接将dev分支的冲突内容删除再次执行add commit 最后再进行分支合并操作即可git log --graph --abbrev-commit //查看合并情况 或者 git log --graph --prettyoneline --abbrev-commit四.分支管理策略1.分支合并策略1.快进模式Fast forward操作命令# 默认就是快进模式 git checkout main git merge 分支名1.触发条件被合并分支dev的提交链完全在目标分支main前方两条分支没有分叉main 没有新增提交。也就是main的最新 commitC是dev的祖先。2.合并过程Git不创建新合并提交只把main指针直接移动到dev最新 commitE像“快进播放”一样滑动指针。3.合并前后结构合并前A--B--C (main) \ D--E (dev)合并后A--B--C--D--E (main, dev)优点干净无多余提交缺点丢失分支合并痕迹后期看不出这里曾经单独开了 dev 分支。2.非快进模式1.触发条件操作命令git merge --no-ff -m merge with no-ff 分支名 //引号内容为合并说明两个分支分叉目标分支main在分支创建后有新提交两条分支各自前进历史出现岔路。示例A--B--C--F (main) \ D--E (dev)此时执行git merge dev无法直接移动指针必须生成一个全新的合并 commit同时指向两条分支末端F、E把两条历史线融合。2.合并后结构A--B--C--F-----G (main) \ / D--E五.分支策略的应用在实际开发中我们应该按照几个基本原则进行分支管理首先master分支应该是非常稳定的也就是仅用来发布新版本平时不能在上面干活那在哪开发呢日常开发在dev分支上也就是说dev分支是不稳定的到某个时候比如1.0版本发布时再把dev分支合并到master上在master分支发布1.0版本你和你的小伙伴们每个人都在dev分支上干活每个人都有自己的分支时不时地往dev分支上合并就可以了。所以团队合作的分支看起来就像这样1.bug分支假如我们现在正在dev2分支上进行开发开发到一半突然发现master分支上面有 bug需要解决。在Git中每个 bug 都可以通过一个新的临时分支来修复修复后合并分支然后将临时分支删除。可现在 dev2 的代码在工作区中开发了一半还无法提交怎么办例如1.储藏工作区信息Git提供了 git stash 命令可以将当前的工作区信息进行储藏被储藏的内容可以在将来某个时间恢复出来。git stash在bug分支上修改完bug后就该合并到master分支上了这里有一个小技巧先将master分支合并到bug分支进行检验如果没问题之后再将bug分支合并到master分支bug已经修复完了接下来回到dev2分支继续进行开发2.恢复工作区信息git stash pop查看储藏信息git stash list除以上命令外还有一下命令供参考# git stash 恢复储藏两种方式总结 ## 方式1git stash pop一步恢复自动删除储藏 1. 恢复最新储藏自动删除储藏记录 git stash pop 2. 恢复指定编号储藏并自动删除 git stash pop stash{0} ## 方式2git stash apply推荐测试不删除储藏 1. 恢复最新储藏储藏记录保留 git stash apply 2. 恢复指定编号储藏例stash{0} git stash apply stash{0} 3. 确认无需后手动删除该储藏 git stash drop stash{0} //关键注意本地存在未提交修改时pop会直接报错终止apply容错性更高2.解决分支合并冲突但我们注意到了修复bug的内容并没有在 dev2 上显示。此时的状态图为master分支目前最新的提交是要领先于新建dev2时基于的master分支的提交的所以我们在dev2中当然看不见修复bug的相关代码。我们的最终目的是要让master合并dev2分支的那么正常情况下我们切回master分支直接合并即可但这样其实是有一定风险的。是因为在合并分支时可能会有冲突而代码冲突需要我们手动解决在master上解决。我们无法保证对于冲突问题可以正确地一次性解决掉因为在实际的项目中代码冲突不只一两行那么简单有可能几十上百行甚至更多解决的过程中难免手误出错导致错误的代码被合并到master上。此时的状态为解决方案最好在自己的分支上合并下 master再让 master 去合并 dev这样做的目的是有冲突可以在本地分支解决并进行测试而不影响 master。此时的状态为