深入理解Git的实现原理
- Git是什么
- Git能够解决哪些问题
- Git的实现原理
请注意,本文的阐述逻辑是:Git是什么——>Git要解决的根本问题是什么——>git是如何解决这些问题的。
另一个个问题,为什么说Git是“分布式”版本控制系统呢?
这里的“分布式”是相对于“集中式”来说的。把数据集中保存在服务器节点,所有的客户节点都从服务节点获取数据的版本控制系统叫做集中式版本控制系统,比如svn就是典型的集中式版本控制系统。
与之相对,Git的数据不止保存在服务器上,同时也完整的保存在本地计算机上,所以我们称Git为分布式版本控制系统。
Git的这种特性带来许多便利,比如你可以在完全离线的情况下使用Git,随时随地提交项目更新,而且你不必为单点故障过分担心,即使服务器宕机或数据损毁,也可以用任何一个节点上的数据恢复项目,因为每一个开发节点都保存着完整的项目文件镜像。
- 我们可以为每一次变更提交版本更新并且备注更新的内容;
- 我们可以在项目的各个历史版本之间自如切换;
- 我们可以一目了然的比较出两个版本之间的差异;
- 我们可以从当前的修改中撤销一些操作;
- 我们可以自如的创建分支、合并分支;
- 我们可以和多人协作开发;
- 我们可以采取自由多样的开发模式。
所以,如果问“Git能够解决哪些问题?”我们可以简单的回答:Git解决了版本控制方面的很多问题,但最核心的是它很好的解决了版本状态存储(即文件变更过程存储)的问题。
- git init 用于创建一个空的git仓库,或重置一个已存在的git仓库
- git hash-object git底层命令,用于向Git数据库中写入数据
- git cat-file git底层命令,用于查看Git数据库中数据
$ git init GitTest Initialized empty Git repository in /home/mp/Workspace/GitTest/.git/ |
$ cd GitTest
$ ls
$ find .git
.git
.git/HEAD .git/config .git/objects .git/objects/info .git/objects/pack .git/refs .git/refs/heads .git/refs/tags .git/hooks .git/hooks/commit-msg.sample .git/hooks/post-update.sample .git/hooks/update.sample .git/hooks/pre-rebase.sample .git/hooks/pre-applypatch.sample .git/hooks/fsmonitor-watchman.sample .git/hooks/applypatch-msg.sample .git/hooks/pre-receive.sample .git/hooks/pre-push.sample .git/hooks/prepare-commit-msg.sample .git/hooks/pre-commit.sample .git/info .git/info/exclude .git/branches .git/description |
$ echo "version 1" | git hash-object -w --stdin 83baae61804e65cc73a7201a7252750c76066a30 $ find .git/objects/ -type f |
$ git cat-file -t 83baa
blob
$ git cat-file -p 83baa
version 1
|
$ echo "version 1" > file.txt
$ git hash-object -w file.txt
83baae61804e65cc73a7201a7252750c76066a30
|
$ find .git/objects -type f .git/objects/83/baae61804e65cc73a7201a7252750c76066a30 |
$ echo "version 2" > file.txt
$ git hash-object -w file.txt
1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
$ find .git/objects -type f
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30 |
我们发现,.git/objects下多出了一个文件,这是我们新保存进数据库的file.txt。接下来,我们执行git cat-file搞清楚这两条数据的内容分别是什么。执行
$git cat-file -p 83baa
version 1
$git cat-file -p 1f7a7a
version 2
|
我们发现,file.txt的变更过程被完整的记录下来了。
$ cat file.txt
version 2 $ git cat-file -p 83baa > file.txt
$ cat file.txt
version 1 |
- 第一,无法记录文件名的变化;
- 第二,无法记录文件夹的变化;
- 第三,记忆每一个版本对应的hash值无聊且乏味且不可能;
- 第四,无法得知文件的变更时序;
- 第五,缺少对每一次版本变化的说明。
- git update-index git底层命令,用于创建暂存区
- git ls-files --stage git底层命令,用于查看暂存区内容
- git write-tree git底层命令,用于将暂存区内容写入一个树对象
$ find .git/index find: ‘.git/index’: No such file or directory $ git update-index --add file.txt $ find .git/index .git/index $ cat .git/index DIRC[���$�;�[���$�;�A���� ���a�Ne�s� rRu vjfile.txt�݀3%A��,I� �` $ find .git/objects/ -type f .git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a .git/objects/83/baae61804e65cc73a7201a7252750c76066a30 $ git ls-files --stage 100644 83baae61804e65cc73a7201a7252750c76066a30 0 file.txt $ git write-tree 391a4e90ba882dbc9ea93855103f6b1fa6791cf6 $ find .git/objects/ -type f .git/objects/39/1a4e90ba882dbc9ea93855103f6b1fa6791cf6 .git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a .git/objects/83/baae61804e65cc73a7201a7252750c76066a30 |
$ git cat-file -t 391a4e tree $ git cat-file -p 391a4e 100644 blob 83baae61804e65cc73a7201a7252750c76066a30 file.txt |
83baae61804e65cc73a7201a7252750c76066a30 |
$ echo "new file" > new $ git ls-files --stage |
- 如果添加git数据库中尚未存储的数据到暂存区,则在执行update-index的时候,会同时把该数据保存到git数据库。
- 添加文件进入暂存区的操作是追加操作,之前已经加入暂存区的文件依然存在——很多人会有误区,认为变更提交之后,暂存区就清空了。
$ git cat-file -p 228e49 100644 blob 83baae61804e65cc73a7201a7252750c76066a30 file.txt 100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new |
$ mkdir new_dir $ git update-index --add new_dir error: new_dir: is a directory - add files inside instead fatal: Unable to process path new_dir |
$ echo "file in new dir" > new_dir/new $ git write-tree $ git cat-file -p 06564b |
$ git write-tree
cb0fbcc484a3376b3e70958a05be0299e57ab495
$ git commit-tree cb0fbcc -m "first commit"
7020a97c0e792f340e00e1bb8edcbafcc4dfb60f
$ git cat-file 7020a97
tree cb0fbcc484a3376b3e70958a05be0299e57ab495
author john <john@163.com> 1537961478 +0800 committer john <john@163.com> 1537961478 +0800 first commit |
$ echo "new version" > file.txt
$ git update-index file.txt
$ git write-tree
848e967643b947124acacc3a2d6c5a13c549231c $ git commit-tree 848e96 -p 7020a97 -m "second commit" e838c8678ef789df84c2666495663060c90975d7 $ git cat-file -p e838c tree 848e967643b947124acacc3a2d6c5a13c549231c parent 7020a97c0e792f340e00e1bb8edcbafcc4dfb60f author john <john@163.com> 1537962442 +0800 committer john <john@163.com> 1537962442 +0800 second commit |
$ echo "another version" > file.txt $ git update-index file.txt $ git write-tree 92867fcc5e0f78c195c43d1de25aa78974fa8103 $ git commit-tree 92867 -p e838c -m "third commit" 491404fa6e6f95eb14683c3c06d10ddc5f8e883f $ git cat-file -p 49140 tree 92867fcc5e0f78c195c43d1de25aa78974fa8103 parent e838c8678ef789df84c2666495663060c90975d7 author john <john@163.com> 1537963274 +0800 committer john <john@163.com> 1537963274 +0800 third commit
|
$ git log 49140 commit 491404fa6e6f95eb14683c3c06d10ddc5f8e883f Author: john <john@163.com> Date: Wed Sep 26 20:01:14 2018 +0800 third commit commit e838c8678ef789df84c2666495663060c90975d7 second commit commit 7020a97c0e792f340e00e1bb8edcbafcc4dfb60f first commit |
git add
和 git commit
命令时, Git 所做的实质工作是将被改写的文件保存为数据对象,更新暂存区,记录树对象,最后创建一个指明了顶层树对象和父提交的提交对象。 这三种主要的 Git 对象——数据对象、树对象、提交对象——最初均以单独文件的形式保存在 .git/objects
目录下。$ echo "491404fa6e6f95eb14683c3c06d10ddc5f8e883f" > .git/refs/heads/master $ cat .git/refs/heads/master 491404fa6e6f95eb14683c3c06d10ddc5f8e883f |
$ git log 491404 commit 491404fa6e6f95eb14683c3c06d10ddc5f8e883f (HEAD -> master) Author: john <john@163.com> Date: Wed Sep 26 20:01:14 2018 +0800 third commit
commit e838c8678ef789df84c2666495663060c90975d7
Author: john <john@163.com> Date: Wed Sep 26 19:47:22 2018 +0800 second commit
commit 7020a97c0e792f340e00e1bb8edcbafcc4dfb60f
Author: john <john@163.com> Date: Wed Sep 26 19:31:18 2018 +0800 first commit
$ git log master commit 491404fa6e6f95eb14683c3c06d10ddc5f8e883f (HEAD -> master) Author: john <john@163.com> Date: Wed Sep 26 20:01:14 2018 +0800 third commit
commit e838c8678ef789df84c2666495663060c90975d7
Author: john <john@163.com> Date: Wed Sep 26 19:47:22 2018 +0800 second commit
commit 7020a97c0e792f340e00e1bb8edcbafcc4dfb60f
Author: john <john@163.com> Date: Wed Sep 26 19:31:18 2018 +0800 first commit
|
$ git update-ref refs/heads/master 49140 |
深入理解Git的实现原理的更多相关文章
- 理解git的分支原理,更好地使用git
文章内容转载于git-scm. 部分内容涉嫌枯燥 一.git分支概念 几乎每一种版本控制系统都以某种形式支持分支.使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作.在很多版本控 ...
- 全面理解Git
前言 人生贵知心,定交无暮早. 原文博客地址:Git命令总结 知乎专栏&&简书专题:前端进击者(知乎) 前端进击者(简书) 正文 1.Git简介 Git的诞生确实是一个有趣的故事,我 ...
- 理解git经常使用命令原理
git不同于类似SVN这样的版本号管理系统,尽管熟悉经常使用的操作就能够满足大部分需求,但为了在遇到麻烦时不至于靠蛮力去尝试,了解git的原理还是非常有必要. 文件 通过git管理的文件版本号信息所有 ...
- 代码管理工具 --- git的学习笔记二《git的工作原理》
通过几个问题来学习代码管理工具之git 一.git是什么?为什么要用它?使用它的好处?它与svn的区别,在Mac上,比较好用的git图形界面客户端有 git 是分布式的代码管理工具,使用它是因为,它便 ...
- Atitit 深入理解耦合Coupling的原理与attilax总结
Atitit 深入理解耦合Coupling的原理与attilax总结 耦合是指两个或两个以上的电路元件或电网络等的输入与输出之间存在紧密配合与相互影响,并通过相互作用从一侧向另一侧传输能量的现 ...
- [diango]理解django视图工作原理
前言:正确理解django视图view,模型model,模板的概念及其之间的关联关系,才能快速学习并上手使用django制作网页 本文主要讲解自己在学习django后对视图view的理解 在进入正文之 ...
- 深入理解git,从研究git目录开始
转发学习的啦. 似乎很少有人在读某个git快速教程的时候会说:“这个关于git的快速教程太酷了!读完了用起git来超级舒服,并且我一点也不怕自己会破坏什么东西.” 对git的初学者来说,刚接触git时 ...
- 真正理解 git fetch, git pull 以及 FETCH_HEAD【转】
转自:http://www.cnblogs.com/ToDoToTry/p/4095626.html 真正理解 git fetch, git pull 要讲清楚git fetch,git pull,必 ...
- ch01.深入理解C#委托及原理(转)
ch01..深入理解C#委托及原理_<没有控件的ASPDONET> 一.委托 设想,如果我们写了一个厨师做菜方法用来做菜,里面有 拿菜.切菜.配菜.炒菜 四个环节,但编写此方法代码的人想让 ...
随机推荐
- 给WEB初学者一些有效率的建议
因为IT互联网发展的非常迅速,而web前端这块很火,目前工资水平给的很高,在市场上也是非常的稀缺人才,现在各个行业转行做web前端的很多,今天给大家一些建议,希望新手少走点弯路吧! 建议一:有一个比较 ...
- canvas实现画板
canvas实现画板 主要用到知识点: 鼠标事件onmousedown() onmousemove() onmouseup() onmouseleave() 事件委托 canvas的一些方法 如:绘制 ...
- 微信小程序计算器Bug版=-=(笔记)
微信小程序计算器BUG版本 无APPID的测试号登录,先在app.json中更改路径,以及修改头部信息. 首先一个输入框字段用{{screenData}} 功能可以退格,清屏,正负号,正常操作加减乘除 ...
- 需求分析&用例编写
一.需求分析? 1.什么是需求 软件产品必须完成的是以及必须具备的品质. 功能性需求:产品必须完成的那些事,要求一定的功能和品质. 例子:淘宝的用户名登录. 非功能性需求:产品必须具备的属性和品质.诸 ...
- Windows10家庭版运行应用提示”管理员已阻止你运行此应用...“的解决办法
win10版本家庭中文版: 运行应用程序报错: 解决办法(亲试): 1.进入”控制面板“--”用户账户“--”用户账户“,选择”更改用户账户控制设置“,选择最后一项,点击”确定“按钮,如下图: 2.按 ...
- 我为什么推荐你使用kindle
我为什么推荐你使用kindle kindle 分 kindle 电子阅读器,pc 版,app 版,下文主要介绍 Amazon 设计和销售的电子书阅读器. 亚马逊官方出的 kindle 使用技巧 使用 ...
- Ambari自定义Service
一.Ambari基本架构 img016.jpg Ambari Server 会读取 Stack 和 Service 的配置文件.当用 Ambari 创建服务的时候,Ambari Server 传送 ...
- IdentityServer4 知多少
1. 引言 现在的应用开发层出不穷,基于浏览器的网页应用,基于微信的公众号.小程序,基于IOS.Android的App,基于Windows系统的桌面应用和UWP应用等等,这么多种类的应用,就给应用的开 ...
- Feign源码解析
1. Feign源码解析 1.1. 启动过程 1.1.1. 流程图 1.1.2. 解释说明 Feign解析过程依赖Spring的初始化,它通过实现ImportBeanDefinitionRegistr ...
- springboot~Money类型在序列化时遇到的问题与解决
在java扩展包里,有这样一个包,它可以描述货币类型,它说币种和金额组成,可以应用在任何复杂的场合里,这个对象结构如下: { "price": { "amount&quo ...