导航
导航
文章目录
  1. 一、Git 分支本质
    1. 1.1、首次提交后,各对象间关系
    2. 1.2、多次提交后,提交对象间关系
    3. 1.3、本地master主分支
    4. 1.4、创建新分支
    5. 1.5、当前分支
    6. 1.6、切换分支
  2. 二、分支工作流程
    1. 2.1、开发某个项目(master分支)
    2. 2.2、为该项目增加某个新需求 (iss53分支)
    3. 2.3、修补上线项目Bug(hotfix分支)
    4. 2.4、合并补丁(hotfix分支)到master分支
    5. 2.5、继续开发新需求,并纳入已发布的补丁
  3. 三、远程分支
    1. 3.1、克隆远程分支
    2. 3.2、更新本地分支
    3. 3.3、跟踪分支
    4. 3.4、推送本地分支
  4. 四、衍合
    1. 4.1、合并与衍合区别
    2. 4.2、衍合(rebase)风险
  5. 五、小结
    1. 5.1、新建本地分支
    2. 5.2、合并本地分支
    3. 5.3、解决合并冲突
    4. 5.4、合并远程分支
    5. 5.5、删除远程分支
    6. 5.6、创建跟踪分支
    7. 5.7、查看分支
    8. 5.8、衍合所在分支

图解Git的分支管理

Git 分支模型被称为“必杀技特性”,与其他版本控制系统相比可谓是难以置信的轻量级,本文是 《Git 使用指南》 后续:图解Git的分支管理。

本文是 《Pro Git》 阅读笔记整理,文中不详细之处,可阅读原著补充。

一、Git 分支本质

1.1、首次提交后,各对象间关系

  • 生成blob类型对象,它存储着当前文件状态的快照。(暂存操作)
  • 生成tree对象,该对象中的每个文件,包含着指向blob对象的索引。(提交)
  • 创建commit对象,它包含指向tree对象的索引和其他元数据。(提交操作)

https://img.cdn.wangyan.org/g/git-1-1.jpg

图1-1:Git仓库各对象间关系

1.2、多次提交后,提交对象间关系

修改后再次提交,那么这次的提交对象会包含一个指向上次提交对象的指针。

https://img.cdn.wangyan.org/g/git-1-2.jpg

图1-2:多次提交后,提交对象间的关系

1.3、本地master主分支

Git分支本质:是一个指向commit 对象的可变指针,例如master为默认分支名称。

https://img.cdn.wangyan.org/g/git-1-3.jpg

图1-3:指向提交历史的master分支

1.4、创建新分支

创建新分支本质:是创建一个指向当前commit对象的指针。

git branch testing #创建testing分支

https://img.cdn.wangyan.org/g/git-1-4.jpg

图1-4:指向同一提交历史的多个分支(master、testing)

1.5、当前分支

HEAD 指针指向当前分支,默认指向 master 分支。

https://img.cdn.wangyan.org/g/git-1-5.jpg

图1-5:HEAD 指向当前所在的分支

1.6、切换分支

checkout 切换至 testing 分支,于是 HEAD 指针也指向了testing分支。(图1-6-1)

git checkout testing #切换至testing分支

https://img.cdn.wangyan.org/g/git-1-6-1.jpg

图1-6-1:HEAD 指向了testing分支

修改后再提交,HEAD 依然随着testing分支一起向前移动(图1-6-2)

vim test.rb
git commit -a -m 'made a change'

https://img.cdn.wangyan.org/g/git-1-6-2.jpg

图1-6-2:每次提交后HEAD 随着分支一起向前移动

返回原来的master主分支继续工作。(图1-6-3)

git checkout master

https://img.cdn.wangyan.org/g/git-1-6-3.jpg

图1-6-3:返回原来的master主分支

当在主分支中修改提交后,分叉出”87ab2”的提交对象,但不会干扰到testing分支。(图1-6-4)

vim test.rb
git commit -a -m 'made other changes'

https://img.cdn.wangyan.org/g/git-1-6-4.jpg

图1-6-4:分叉了的分支历史

二、分支工作流程

  1. 开发某个项目 (master主分支,生产服务器)
  2. 为该项目增加某个新需求 (iss53分支)
  3. 已上线项目需要修补,于是为本次修补建立新分支(hotfix分支)
  4. 合并补丁(hotfix分支)到master分支,完成已上线项目Bug修补
  5. 继续开发新需求(iss53分支),并且纳入已发布的补丁

2.1、开发某个项目(master分支)

首先,我们正在开发某个项目,并推送到了生产服务器。

https://img.cdn.wangyan.org/g/git-2-1.jpg

图2-1:一个简单的提交历史

2.2、为该项目增加某个新需求 (iss53分支)

创建并切换至iss53分支,注意要加”-b”参数。

git checkout -b iss53

https://img.cdn.wangyan.org/g/git-2-2-1.jpg

图2-2-1:创建一个新的分支(iss53)

修改后再次提交。

vim index.html 
git commit -a-m 'addedanewfooter [issue53]' 

https://img.cdn.wangyan.org/g/git-2-2-2.jpg

图2-2-2:iss53 分支随工作进展向前推进

2.3、修补上线项目Bug(hotfix分支)

已上线项目需要修补,于是为本次修补建立新分支(hotfix分支)

git checkout master #首先切换到主分支
git checkout -b 'hotfix' #然后创建hotfix分支

https://img.cdn.wangyan.org/g/git-2-3.jpg

图2-3:hotfix分支是从master(c2位置)分出

2.4、合并补丁(hotfix分支)到master分支

补丁(hotfix分支)测试完毕,于是合并到master分支,完成Bug修补。

git checkout master  #首先切换到主分支
git merge hotfix #测试完毕后,合并hotfix分支
git branch -d hotfix #删除已合并的hotfix分支

合并时会出现“Fast forward”(快进)提示,表示无分歧需要解决,直接向前移动指针。

https://img.cdn.wangyan.org/g/git-2-4.jpg

图2-4:合并hotfix分支后指针位置

2.5、继续开发新需求,并纳入已发布的补丁

git checkout master #切换至master 
git merge iss53 #合并iss53到master

注意:这次与之前hotfix合并不同,由于当前master分支直接祖先是C2,iss53分支直接祖先是C3,所以Git需要和它们的共同祖先C2进行一次简单的三方合并计算。

https://img.cdn.wangyan.org/g/git-2-5-1.jpg

图2-5-1:合并iss53分支后指针位置

解决合并冲突

git status #合并失败的文件以"unmerged"标出
git add . #标记冲突已解决,并暂存文件
#git mergetool Git默认图形化冲突解决工具

https://img.cdn.wangyan.org/g/git-2-5-2.jpg

图2-5-2:Git 自动创建了包含合并结果的对象(C6)

三、远程分支

远程分支(remote branch)是对远程仓库状态的索引,格式如下:

格式:远程仓库名/分支名
默认:origin/master

3.1、克隆远程分支

Git clone 会克隆远程origin/master分支,并建立一个相同位置的本地master分支。

https://img.cdn.wangyan.org/g/git-3-1-1.jpg

图3-1-1:Git clone 建立本地master和远程origin/master分支

正在本地master分支工作,与此同时,其他人向远程仓库推送了内容,从f42c5更新到了190a3,但是本地origin/master指针依然会停留在f42c5位置。

https://img.cdn.wangyan.org/g/git-3-1-2.jpg

图3-1-2:远程仓库更新,但本地origin/master指针不改变

3.2、更新本地分支

git fetch 从远程仓库更新你本地还没有的数据。(新增了31b8e,190a3)

https://img.cdn.wangyan.org/g/git-3-1-3.jpg

图3-1-3:运行 git fetch origin 同步远程仓库至本地

注意:在fetch操作抓来新远程分支XX之后,本地不会新增XX分支,有的只是一个你无法移动的origin/XX指针。

如果要把远程分支合并到当前分支,可以运行:

git merge [远程仓库名]/[分支名]
git merge origin/serverfix。

3.3、跟踪分支

从远程分支检出的本地分支,称为跟踪分支(tracking branch)。在跟踪分支里git push可推送本地分支到相应的远程仓库,反过来可直接运行git pull,可获取远程分支所有更新,并且合并到当前本地分支。

注:克隆操作会自动创建一个master分支来跟踪origin/master。

如果想要在远程分支的基础上分化出一个新分支,可以运行:

方法一:

git checkout -b [分支名] [远程名]/[分支名]
git checkout -b serverfix origin/serverfix

方法二:(适用1.6.2以上版本Git)

git checkout --track [远程名]/[分支名] 
git checkout --track origin/serverfix

3.4、推送本地分支

方法一:

语法:git push (远程仓库名) (本地分支名)
实例:git push origin serverfix

方法二:(可自定义远程分支名)

语法:git push (远程仓库名) (本地分支名):(远程分支名)
实例:git push origin serverfix:serferfix

四、衍合

把一个分支整合到另一个分支的办法有两种:merge(合并) 和rebase(衍合),两者得到的结果一样,但衍合能产生一个更为整洁的提交历史。

4.1、合并与衍合区别

合并(merge):通过C2-C3-C4三方合并计算生成C5。

https://img.cdn.wangyan.org/g/git-4-1-1.jpg

图4-1-1:合并(merge)分支后的提交历史

衍合(rebase):把在C3 里产生的变化补丁重新在C4 的基础上打一遍。

衍合原理:从两个分支共同祖先(C2)开始,提取你所在分支(experiment)每次提交时产生的差异(diff),然后回到需要衍合入的分支(master),按顺序施用每一个差异补丁文件。

git checkout experiment
git rebase master

https://img.cdn.wangyan.org/g/git-4-1-2.jpg

图4-1-2:把C3 里产生的改变衍合到C4 中

最后回到master分支进行一次快进合并,结果同三方合并例子中的C5内容一模一样,但衍合能产生一个更为整洁的提交历。

https://img.cdn.wangyan.org/g/git-4-1-3.jpg

图4-1-3:master 分支的快进。

4.2、衍合(rebase)风险

注释事项:永远不要衍合那些已经推送到公共仓库的更新。

常见用法:一般把衍合当成一种在推送之前清理提交历史的手段,而且仅仅衍合那些永远不会公开的commit

五、小结

5.1、新建本地分支

git branch testing #创建testing分支
git checkout testing #切换至testing分支
git checkout -b iss53 #创建并切换至iss53分支。

5.2、合并本地分支

git checkout master  #首先切换到主分支
git merge hotfix #测试完毕后,合并hotfix分支
git branch -d hotfix #删除已合并的hotfix分支

5.3、解决合并冲突

git status #合并失败的文件以"unmerged"标出
git add . #标记冲突已解决,并暂存文件
git mergetool #Git默认图形化冲突解决工具

5.4、合并远程分支

origin/master #格式:远程仓库/分支名
git merge origin/serverfix #合并远程分支serverfix到当前分支

5.5、删除远程分支

#git push [远程仓库名] :[远程分支]
#注意区别:git push [远程名] [本地分支]:[远程分支]
git push origin :serverfix #删除远程分支

5.6、创建跟踪分支

方法一:

git checkout -b [分支名] [远程名]/[分支名]
git checkout -b serverfix origin/serverfix

方法二:(适用1.6.2以上版本Git)

git checkout --track [远程名]/[分支名] 
git checkout --track origin/serverfix

5.7、查看分支

git branch #列出所有分支,星号"*"表示当前所在分支。
git branch -v #查看各分支最后一次提交信息

#查看已和当前分支合并的分支
#可用git branch -d 删掉未标星号的分支,因为已经合并了。
git branch --merged 

#查看未和当前分支合并的分支
#强制删除未合并的分支git branch -D
git branch --no-merged 

5.8、衍合所在分支

git checkout experiment #切换到需要衍合的分支
git rebase master #衍合experiment分支到主分支
支持一下
扫一扫,支持一下