前言

  • 很多版本控制系统都有分支这个概念
  • 使用分支意味着可以将日常工作从主线上脱离,从而避免影响主线
  • Git 鼓励在工作流程中频繁使用分支和合并

Git 是如何保存数据的

  • Git 保存的不是文件的变化或者差异,而是一系列不同时刻的快照
  • 在进行提交操作时,Git 会保存一个提交对象(commit object)
  • 提交对象会包含一个指向暂存内容快照的指针,还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针
  • 首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象, 而由多个分支合并产生的提交对象有多个父对象

实际栗子

  • 假设现在有一个工作目录,里面包含了三个将要被暂存和提交的文件
  • 暂存操作会为每一个文件计算校验和( SHA-1 哈希算法)
  • 然后会把当前版本的文件快照保存到 Git 仓库中 (Git 使用 blob 对象来保存它们)
  • 最终将校验和加入到暂存区域等待提交
git add README test.rb LICENSE
git commit -m 'The initial commit of my project'

执行 git commit 后的步骤

  • Git 会先计算每一个子目录(本例中只有项目根目录)的校验和
  • 然后在 Git 仓库中这些校验和保存为树对象
  • commit 提交对象包含 tree 对象的指针,GIt 就可以在需要的时候重现此次保存的快照
  • Git 仓库中有五个对象
    • 三个 blob 对象:保存着文件快照
    • 一个 tree 对象:记录着目录结构和 blob 对象索引
    • 一个 commit 对象:包含着指向树对象的指针和所有提交信息
 

提交对象和它的树结构

做些修改后再次提交,那么这次产生的提交对象会包含一个指向上次提交对象(父对象)的指针。

多个提交对象和它们的父对象

Git 的分支的本质

  • 仅仅是指向提交对象的可变指针
  • Git 的默认分支名字是 master
  • 每次提交后,master 分支的指针都会指向最新的提交对象
  • master 分支会在每次提交时自动向前移动
  • Git 的 master 分支并不是一个特殊分支,它就跟其它分支完全没有区别
  • 之所以几乎每一个仓库都有 master 分支,是因为 git init 命令默认创建它

分支及其提交历史

创建分支

  • 它只是为你创建了一个可以移动的新的指针
  • 创建一个 testing 分支
git branch testing

这会在当前所在的提交对象上创建一个指针

两个指向相同提交历史的分支

Git 如何知道当前在哪一个分支上呢?

  • 它有一个名为 HEAD 的特殊指针
  • 在 Git 中,它是一个指针,指向当前所在的本地分支
  • 这里本地当前是 master 分支,因为 git branch 命令仅仅创建一个新分支,并不会自动切换到新分支中去

切换分支

两种方式

  • git checkout <分支名>
  • git switch <分支名>
git checkout testing

这样 HEAD 就指向 testing 了

实际栗子

polo@B-J5D1MD6R-2312 watermarker % git checkout newtest2
M test.py
A test1..3.txt
A test1.txt
D test111.txt
A test3.txt
切换到分支 'newtest2'
polo@B-J5D1MD6R-2312 watermarker % git log
commit 6652c6d6c439cb23ef6aaff79eeccbf3213a9a0b (HEAD -> newtest2, tag: 1.2, origin, newtest3)

切换分支后查看提交历史

可以看到指向最新提交对象的分支有三个:origin、newtest2、newtest3,当前 HEAD 指向的分支是 newtest2,因为刚刚切换到 newtest2 了

HEAD 指向当前所在的分支

那么,这样的实现方式会给我们带来什么好处呢?修改后再 提交一次

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

testing 分支会往前移动,但是 master 分支却没有,因为每次 git commit 提交新内容之后,只有 HEAD 指向的分支会自动往前移动,其他分支不会动的

HEAD 分支随着提交操作自动向前移动看看

切换回 master 分支

git checkout master 

做了两件事

  • HEAD 指回 master 分支
  • 将工作目录恢复成 master 分支所指向的快照内容(旧内容)
  • 相当于忽略了 testing 分支所做的修改
  • 重点:切换分支会改变工作目录的文件

当 checkout 时,HEAD 跟着动

再次修改并提交

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

  • 当前项目出现了分支分叉,因为在 master 分支上又提交了一些新内容,所以会产生一个新的提交对象
  • 针对不同的分支,可以在上面工作不同的内容,然后在未来进行合并,合并只需要用到的命令有:branch、checkout、commit

项目分叉历史

git log --oneline --decorate --graph --all 

它会输出你的提交历史、各个分支的指向以及项目的分支分叉情况

git log --oneline --decorate --graph --all
* c2b9e (HEAD, master) Made other changes
| * 87ab2 (testing) Made a change
|/
* f30ab Add feature #32 - ability to add new formats to the central interface
* 34ac2 Fix bug #1328 - stack overflow under certain conditions
* 98ca9 initial commit of my project

Git 的分支操作为何这么快?

  • Git 的分支实质上仅是包含所指对象校验和(长度为 40 的 SHA-1 值字符串)的文件,所以它的创建和销毁都异常高效
  • 创建一个新分支就相当于往一个文件中写入 41 个字节(40 个字符和 1 个换行符),如此的简单能不快吗?
 

Git 系列教程(11)- 分支简介的更多相关文章

  1. [译]Atlassian Git系列教程

    国庆期间把Atlassian的Git系列教程看完了.边看边翻译了相关文章. 原教程: https://www.atlassian.com/git/tutorials/ 我翻译的: git init g ...

  2. Git 系列教程(12)- 分支的新建与合并

    实际工作场景 可能会遇到的工作流 开发某个网站 为实现某个新的用户需求,创建一个分支 在这个分支上开展新工作 正在此时,你突然接到一个电话说有个很严重的问题需要紧急修补,你将按照如下方式来处理: 切换 ...

  3. Git 系列教程(14)- 远程分支

    远程分支 远程引用是对远程仓库的引用(指针),包括分支.标签等等 你可以通过 git ls-remote <remote> 来显式地获得远程引用的完整列表 polo@B-J5D1MD6R- ...

  4. SVG系列教程:SVG简介与嵌入HTML页面的方式

    地址:http://www.w3cplus.com/html5/svg-introduction-and-embedded-html-page.html 随着技术向前的推进,SVG相关的讨论也越渐频繁 ...

  5. Git 系列教程(9)- 打标签

    打标签 一般会给提交历史打个标签,方便后续进行筛选.查看 列出标签 可带上可选的 -l 选项 --list $ git tag v1.0 v2.0 这个命令以字母顺序列出标签 可以按照特定的模式查找标 ...

  6. git 入门教程之分支总览

    分支就是一条独立的时间线,既有分支,必有主干,正如一棵树谈到树枝,必有树干一样的道理.我们先前对git 的全部操作默认都是在主干上进行的,这个主干也是一种特殊的分支,名为 master 分支. 无论是 ...

  7. git 入门教程之分支管理

    背景 什么是分支?简单地说,分支就是两个相对独立的时间线,正常情况下,独立的时间线永远不会有交集,彼此不知道对方的存在,只有特定情况下,两条时间线才会相遇,因为相遇,所以相知,因为相知,所以改变! 正 ...

  8. Git系列五之分支管理

    1.Git分支管理 分支即是平行空间,假设你在为某个手机系统研发拍照功能,代码已经完成了80%,但如果将这不完整的代码直接提交到git仓库中,又有可能影响到其他人的工作,此时我们便可以在该软件的项目之 ...

  9. Git 系列教程(1)- Git 简介

    前言 因为工作中目前要大量使用 Git,虽然之前已经会用了,但没有系统的总结过,现在来重新总结 概念篇会直接搬网上的教程,比如:菜鸟.廖雪峰.老张.中文版Git,就不再花时间自己总结过概念了 Git ...

随机推荐

  1. leetcode最短无序连续子数组

    平民解法: 既然是找最小数组,那就得到一个排序好的数组,然后直接和初试数组比对,用一个left,right分别记录从最初开始不同,到最后不同的小标,最后左右做差再加一,就能得到长度. 其他解法: 双指 ...

  2. anyRTC 6月SDK更新迭代

    anyRTC 6月更新迭代,macOS新增屏幕 ID 进行屏幕共享功能,让共享更高效简单:此外解决了视频的宽高不是16:9导致共享内容缺失的问题,同时对音视频模块,推流组件等多项功能进行了优化改进. ...

  3. AHKManager.ahk AHK管理器 2019年12月15日

    AHKManager.ahk  AHK管理器  2019年12月15日 快捷键   {Alt} + {F1} ///////////////////////////////////////////// ...

  4. (11)MySQL进阶篇SQL优化(InnoDB锁问题排查与解决)

    1.概述 前面章节之所以介绍那么多锁的知识点和示例,其实最终目的就是为了排查与解决死锁的问题,下面我们把之前学过锁知识重温与补充一遍,然后再通过例子演示下如果排查与解决死锁. 2.前期准备 ●数据库事 ...

  5. docker版LAMP(PHP+MYSQL+APACHE)配置

    最近在搭测试环境,一开始就在vagant和docker之间来回折腾.两者其实都非常适合用来搭开发环境:但最终让我决定用Docker的原因是因为Vagant在hyper-v下出现了一些奇怪的问题,所以D ...

  6. ASP.NET Corec初步使用Quartz.NET

    一.什么是Quartz.NET? Quartz.NET 是一个功能齐全的开源作业调度系统,可用于从最小的应用程序到大型企业系统. Quartz.NET是纯净的,它是一个.Net程序集,是非常流行的Ja ...

  7. OOP面向对象程序设计原则

    OOP面向对象程序设计原则 开闭原则(Open Close Principle) 对扩展开放,对修改关闭 里氏代换原则(Liskov Substitution Principle) 继承必须确保超累所 ...

  8. Cookie和Session得使用理解

    Cookie 饼干 什么是Cokkie? 1.Cookie 翻译过来是饼干的意思. 2.Cookie 是服务器通知客户端保存键值对的一种技术. 3.客户端有了 Cookie 后,每次请求都发送给服务器 ...

  9. SortCompare.time的反射版本

    "Algorithms" by Robert Sedgewick, p256, SortCompare.time(): public static double time(Stri ...

  10. Django ORM记录的增删改查结合web端

    模版语法分配变量 在views.py文件中定义一个视图函数show_data: def show_data(request): # 定义一个字典 并将它展示在前端HTML文件 user_dic = { ...