GIT原理 GIT如何管理你的代码 commit tree blob

[toc]

引用

抄自 https://www.bilibili.com/video/BV11z4y1X79p?spm_id_from=333.337.search-card.all.click 该链接

并且结合 PRO_GIT 一书总结

git 不关注差异,只关注当前快照

git和svn的一大区别是,svn关注的是修改,git关注当前现状

比方说,一个空房间里有两个箱子。每次这两个箱子移动,svn都会记录他们的移动路线,但是git不在乎,它只会在你commit的时候,拿着相机进屋拍个照,箱子在哪就是哪里,爱咋咋地。


image.png

Git 不按照以上方式对待或保存数据。反之,Git 更像是把数据看作是对小型文件系统的一系列快照。 在 Git
中,每当你提交更新或保存项目状态时,它基本上就会对当时的全部文件创建一个快照并保存这个快照的索引。为了效率,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 Git 对待数据更像是一个 快照流。

image.png

git commit tree blob 结构图

现在,Git 仓库中有五个对象:三个 blob 对象(保存着文件快照)、一个 树 对象 (记录着目录结构和 blob 对象索引)以及一个 提交 对象(包含着指向前述树对象的指针和所有提交信息)。


image.png

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


image.png

./git 中的对象 commit tree blob

blob自行百度,总之这里你理解成个存储数据的格式就行了

仿照视频里面的步骤,我们也用个窗口,来观察当你执行 add commit操作的时候, ./git 里面发生了什么。同样我们也删除 hooks

git init后

.git
├── branches
├── config
├── description
├── HEAD
├── info
│   └── exclude
├── objects
│   ├── info
│   └── pack
└── refs
    ├── heads
    └── tags

8 directories, 4 files

变换一:新建test1.c, 之后add --生成blob

vi test1.c
写一行 The Master Chief,然后 wq
这个时候没有任何变化

git add test1.c
我们发现多了下面的object

.git
├── branches
├── config
├── description
├── HEAD
├── index
├── info
│   └── exclude
├── objects
│   ├── c2
│   │   └── 673408f719c6224ae85b27c9d4245ad96e55d6
│   ├── info
│   └── pack
└── refs
    ├── heads
    └── tags

9 directories, 6 files

git cat-file -t c267
发现是 blob 类型

git cat-file -p c267
会显示 The Master Chief

变化二:第一次 commit --生成tree和commit

git commit -m "first commit"
该操作会生成两个新的 objects 作为 tree 和 commit

.git 
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── index
├── info
│   └── exclude
├── logs
│   ├── HEAD
│   └── refs
│       └── heads
│           └── master
├── objects
│   ├── 12
│   │   └── 6dbd7bfa165928164e2807e0e6a42b4d85ac37
│   ├── 55
│   │   └── d9df99408ea612721fbe8ba7e18be1b7a3c594
│   ├── c2
│   │   └── 673408f719c6224ae85b27c9d4245ad96e55d6
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   └── master
    └── tags

14 directories, 12 files

这里我们分别的 git cat-file -t git cat-file -p 看下

git cat-file -t 126d
显示 commit

git cat-file -p 126d
显示四行,分别是 tree/author/committer 和 和最后的commit信息

git cat-file -t 55d9
显示 tree

git cat-file -p 55d9
显示 100644 blob c2673408f719c6224ae85b27c9d4245ad96e55d6 test1.c
这里面的blob 刚好就是我们之前 add 的blob 对应的文件

完全相同的文件,将会使用同一个blob

创建一个test2.c,内容完全和 test1.c 一致,观察

vi test2.c
写一行 The Master Chief,然后 wq
这个时候没有任何变化

git add test2.c
结果.git文件夹里面的内容毫无变化

.git 
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── index
├── info
│   └── exclude
├── logs
│   ├── HEAD
│   └── refs
│       └── heads
│           └── master
├── objects
│   ├── 12
│   │   └── 6dbd7bfa165928164e2807e0e6a42b4d85ac37
│   ├── 55
│   │   └── d9df99408ea612721fbe8ba7e18be1b7a3c594
│   ├── c2
│   │   └── 673408f719c6224ae85b27c9d4245ad96e55d6
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   └── master
    └── tags

14 directories, 12 files

第二次commit

git commit -m "second commit"
该操作会再生成两个新的 objects 作为 tree 和 commit

.git 
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── index
├── info
│   └── exclude
├── logs
│   ├── HEAD
│   └── refs
│       └── heads
│           └── master
├── objects
│   ├── 12
│   │   └── 6dbd7bfa165928164e2807e0e6a42b4d85ac37
│   ├── 55
│   │   └── d9df99408ea612721fbe8ba7e18be1b7a3c594
│   ├── 8f
│   │   └── ddf9dedce34df33de41c544e7bf6213494e9e4
│   ├── b9
│   │   └── be6a158220da6aa0cd39e64402d7909a217773
│   ├── c2
│   │   └── 673408f719c6224ae85b27c9d4245ad96e55d6
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   └── master
    └── tags

16 directories, 14 files

这里我们分别的 git cat-file -t git cat-file -p 看下

git cat-file -t 8fdd
显示 commit

git cat-file -p 8fdd
显示五行,分别是 tree/parent/author/committer 和 和 second commit

git cat-file -t b9be
显示 tree

git cat-file -p b9be
显示

100644 blob c2673408f719c6224ae85b27c9d4245ad96e55d6    test1.c
100644 blob c2673408f719c6224ae85b27c9d4245ad96e55d6    test2.c

可以看到tree里面引用了 一模一样的blob

修改同一个文件,将生成额外的blob

修改 test1.c,然后add

现在我们修改 vi test1.c,另起一行加入一句 Spartan 117,然后 wq

git add test1.c
多了一条object ``38a1```

.git 
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── index
├── info
│   └── exclude
├── logs
│   ├── HEAD
│   └── refs
│       └── heads
│           └── master
├── objects
│   ├── 12
│   │   └── 6dbd7bfa165928164e2807e0e6a42b4d85ac37
│   ├── 38
│   │   └── a13225d42cba196f7f183ce0b17e0ec31b7cd9
│   ├── 55
│   │   └── d9df99408ea612721fbe8ba7e18be1b7a3c594
│   ├── 8f
│   │   └── ddf9dedce34df33de41c544e7bf6213494e9e4
│   ├── b9
│   │   └── be6a158220da6aa0cd39e64402d7909a217773
│   ├── c2
│   │   └── 673408f719c6224ae85b27c9d4245ad96e55d6
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   └── master
    └── tags

17 directories, 15 files

检查一下这个 38a1

git cat-file -t 38a1
显示 blob

git cat-file -p 38a1
显示

The Master Chief
Spartan 117

第三次 commit,生成新的 tree 和 commit

git commit -m "third commit"
该操作会再生成两个新的 objects 作为 tree 和 commit

4d65 5385

.git 
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── index
├── info
│   └── exclude
├── logs
│   ├── HEAD
│   └── refs
│       └── heads
│           └── master
├── objects
│   ├── 12
│   │   └── 6dbd7bfa165928164e2807e0e6a42b4d85ac37
│   ├── 38
│   │   └── a13225d42cba196f7f183ce0b17e0ec31b7cd9
│   ├── 4d
│   │   └── 65a099692964508d4cab2dc6f4764e2e8bfeae
│   ├── 53
│   │   └── 854de4bae0ad5aaeb7f841da470fbec0008a78
│   ├── 55
│   │   └── d9df99408ea612721fbe8ba7e18be1b7a3c594
│   ├── 8f
│   │   └── ddf9dedce34df33de41c544e7bf6213494e9e4
│   ├── b9
│   │   └── be6a158220da6aa0cd39e64402d7909a217773
│   ├── c2
│   │   └── 673408f719c6224ae85b27c9d4245ad96e55d6
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   └── master
    └── tags

19 directories, 17 files

git cat-file -t 4d65
显示 commit

git cat-file -p 4d65
显示五行,分别是 tree/parent/author/committer 和 third commit

git cat-file -t 5385
显示 tree

git cat-file -p 5385
显示

100644 blob 38a13225d42cba196f7f183ce0b17e0ec31b7cd9    test1.c
100644 blob c2673408f719c6224ae85b27c9d4245ad96e55d6    test2.c

当前的tree引用了 test1.c的新blob 38a1,但是原先的 test1.c blob并没有消失,依然保存在 ./git

这也就是为什么 git reset 的时候你能很快的回到当前commit点,因为直接通过指针,找到了对应的tree和blob

test1.c 又改回到第一次commit的状态,新commit一次,tree会怎么变

tree会回到第一次的状态,虽然他们上面的commit点哈希值不一样,tree本身的哈希值也不一样,但是tree的内容会一样

reset --hard 对 .git 内 objects 的影响

事实上是没有影响,所有已经存在的 objects 都会被保留。所以reset --hard 并不是不能恢复的,但是如果你删除掉本地的库,又没有远程库保存,那么就彻底不能恢复了,因为你的 objects 都被干掉了

刚才有三次commit,我reset --hard 到第一次,再cherry之前的commit点哈希,发现是可以cherry-pick的。

所以,如果不小心 reset --hard,远端也没有保存,
千万不要随便删除本地库的文件夹,没有这个.git你就彻底恢复不了了

git分支原理 && 为什么 git 分支切换速度快

svn如果你创建一个分支,它会将自己的所有的代码全部复制一份,然后建立一个新分支。

git的分支不同,它只是一个指针,指向了你的某个commit点,相当于你创建一个新分支的时候,只不过是创建了一个指针而已。

之前提过,或者结合下图,我们打印commit点的时候,会生成5行内容
分别是 tree/parent/author/committer

其中parent就是指向父commit点的指针

image.png

首次提交产生的提交对象没有父对象,普通提交操
作产生的提交对象有一个父对象, 而由多个分支合并产生的提交对象有多个父对象

git在管理代码时,如果出现reset rebase pull merge等等改变当前commit点的操作时,会根据最终的commit点指针,找到它下面连着的tree,再找到tree对应的blob文件,瞬间恢复到该commit点应该有的状态。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,997评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,603评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,359评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,309评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,346评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,258评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,122评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,970评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,403评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,596评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,769评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,464评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,075评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,705评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,848评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,831评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,678评论 2 354

推荐阅读更多精彩内容