深入 Git:它是如何记录世界的(二)
专栏:Git 进化论
个人主页:手握风云
目录
一、Git 分支基础概念
二、Git 分支基础操作
2.1. 查看本地分支
2.2. 创建分支
2.3. 新建并直接切换分支
2.4. 切换已有分支
2.5. 分支隔离特性
三、分支合并三大模式
3.1. Fast-forward(快进合并)
2.2. 代码冲突合并
2.3. --no-ff 禁用快进合并
四、线上 Bug 临时修复分支
五、废弃分支两种删除方式
5.1. 普通删除
5.2. 强制删除
一、Git 分支基础概念
分支是 Git 体系中极具代表性的核心能力,我们可以借助平行宇宙的生活化类比完整理解它的运行逻辑,当我们在当下的时间线里专注学习 C++ 编程语言时,另一条独立的平行宇宙时间线中,另一个版本的自己正在钻研 Java 语言,两条时间线各自独立推进、互不干扰,不会互相打乱各自的学习进度,而在某个时间节点完成两条时间线的合并操作后,两条线路积累的成果就会整合到一处,最终同时掌握两门编程语言,这一逻辑完全对应 Git 分支的工作模式,不同分支承载独立的开发任务,彼此隔离修改内容,等待开发完成后再执行合并,就能整合所有分支的代码改动。每一次向 Git 仓库提交代码,系统都会将所有提交记录串联成一条连续的时间线,这条从初始化就天然存在的时间线,就是 Git 默认自带的主分支,也就是 master 分支。
很多初学者容易对 HEAD 产生认知偏差,误以为 HEAD 指针直接指向某次代码提交记录,可实际上 HEAD 的真实作用是
标记当前正在使用的分支,它会持续指向 master 分支,而 master 分支内部存储的指针才会精准指向最新的提交节点,每当我们完成一次代码提交,master 分支的指针就会自动向前移动一步,持续锁定最新的提交记录,HEAD 仅维持和 master 分支的绑定关系,以此区分当前所处的工作环境,我们还能直接读取本地仓库内的隐藏目录文件验证这套指针逻辑,打开仓库根目录下的.git 文件夹读取 HEAD 文件,文件内部会记录当前绑定分支的引用路径,继续读取 refs/heads 目录下 master 对应的文件,就能拿到 master 分支指向的提交哈希字符串,以此直观区分 HEAD 与分支指针各自承担的不同作用。
cat .git/HEAD cat .git/refs/heads/master git log二、Git 分支基础操作
2.1. 查看本地分支
git branch # 查看本地所有分支2.2. 创建分支
git branch dev git branch # 带 * 的为当前分支 tree .git2.3. 新建并直接切换分支
git checkout -b dev # 一步完成创建 + 切换2.4. 切换已有分支
git checkout 分支名git checkout dev git branch2.5. 分支隔离特性
不同分支提交完全隔离:在 dev 分支修改并提交后,切回 master 看不到新增代码;只有合并分支后,主分支才能读取其他分支修改。
vim ReadMe # 在 dev 分支上修改 ReadMe 文件 git add ReadMe git commit -m "md ReadMe on dev" git checkout master cat ReadMe # 在 master 分支上查看 ReadMe 文件cat .git/refs/heads/dev cat .git/refs/heads/master最新提交指向了 dev 分支上的最后一次提交。
三、分支合并三大模式
3.1. Fast-forward(快进合并)
Fast-forward 即快进合并,它的触发条件是主分支在创建分支之后没有新增提交,目标分支属于主线顺延提交。它的合并原理是直接移动主分支指针指向目标分支,整个过程不会生成新的 commit。这种合并方式存在一个缺点,在删除对应分支后,版本日志无法看出曾经执行过合并操作,缺少合并记录。
git merge 待合并分支名2.2. 代码冲突合并
冲突产生的条件是两个分支修改同一文件同一行,且各自产生独立提交。
vim ReadMe git add ReadMe git commit -m "md on dev1"git checkout master vim ReadMe git add ReadMe git commit -m "md on master" git merge dev1Git 合并产生冲突时的冲突解决流程为:首先手动修改存在冲突的文件,修改完成后执行 git add 命令进行暂存,再通过 git commit 命令提交合并结果,从而完成冲突处理。
vim ReadMe cat ReadMe git add . git commit -m "merge dev1"我们可以使用 git log --graph --pretty=oneline --abbrev-commit 命令查看分支合并日志,该命令可以可视化展示分支层级结构以及完整的合并轨迹。
git log --graph --pretty=oneline --abbrev-commit2.3. --no-ff 禁用快进合并
git merge --no-ff -m "合并备注" 分支名--no-ff 是团队推荐的禁用快进合并方式,该方式会强制生成一条全新的合并 commit,永久保留这条分支的完整开发历史。它的优势是即使后续删除了原分支,依然可以通过版本日志清晰查看分支合并记录,方便后续版本追溯,适合用于正式版本、线上分支的合并场景。
四、线上 Bug 临时修复分支
使用场景:正在开发分支写一半代码,未完成无法提交,需要紧急切回 master 修复线上 bug。
git checkout -b dev2 vim ReadMe git checkout master cat ReadMe我们没有把 dev2 的修改进行 add 和 commit,切换回 master,会影响到主分支的文件。我们可以通过 git stash 系列命令来储藏还未完成的代码,其中 git stash 命令能够保存当前的工作现场并清空工作区;git stash list 命令可以查看全部储藏记录。
git checkout dev2 git stash git status git checkout master cat ReadMeBug 修复步骤如下:首先储藏当前的开发代码,再切回 master 分支,之后新建临时 fix_bug 分支进行问题修复,修复完成后将该分支合并至 master 分支,推荐使用 --no-ff 方式合并,随后删除临时 bug 分支,最后切回原来的开发分支,恢复储藏的代码继续进行开发。
git checkout -b fix_bug vim ReadMe git add . git commit -m "fix bug in master" git checkout master git merge --no-ff -m "merge fix_bug" fix_bug最佳实践:开发分支先合并 master、本地解决冲突测试,再合并到主分支;避免直接在 master 处理大量冲突,降低线上出错风险。
五、废弃分支两种删除方式
5.1. 普通删除
git branch -d 分支名仅能删除完全合并的分支,未合并分支会直接报错,防止代码丢失。
5.2. 强制删除
git branch -D 分支名直接丢弃分支所有未合并提交,适用于产品叫停、废弃无用功能分支。