深入理解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> 一.委托 设想,如果我们写了一个厨师做菜方法用来做菜,里面有 拿菜.切菜.配菜.炒菜 四个环节,但编写此方法代码的人想让 ...
随机推荐
- SoEasyPlatform 代码生成器
介绍 一款轻量级开源的代码生成器,相对较动软代码生成器而言要轻量的多,支持多种数据库,所用到dll组件也都在github有源码,代码非常的简单有点基础的看源码可以把生成的项目改成自已的风格. 特色 该 ...
- SQL server脚本语句积累
1:往现有的表中增加一个字段 IF NOT EXISTS ( SELECT 1 FROM sys.sysobjects so WITH ( NOLOCK ) INNER JOIN sys.syscol ...
- 2.SDL规范文档
01.安全设计Checklist 输入验证 校验跨信任边界传递的不可信数据(策略检查数据合法性,含白名单机制等)格式化字符串时,依然要检验用户输入的合法性,避免可造成系统信息泄露或者拒绝服务 禁止向J ...
- Android远程桌面助手(B1413)
ARDC(B1413) 1.解决Android9显示黑屏问题;2.解决向导菜单显示异常问题;3.解决部分手机无法正常连接的问题;4.切换到WiFi连接时,增加显示NetworkID;5.更新图片压缩的 ...
- 20190415 - iOS11 无法连接到 App Store 的解决办法
问题:更新 iOS 11 后,打开 App Store 提示: 无法连接至 app store 解决: 进入 iOS 系统[设置][iTunes Store 与 App Store],退出当前登录用户 ...
- Java中char,short,int,long占几个字节和多少位
1.字节:byte:用来计量存储容量的一种计量单位:位:bit 2.一个字节等于8位 1byte = 8bit char占用的是2个字节 16位,所以一个char类型的可以存储一个汉字. 整型: b ...
- web服务器,验证码,Xftp使用方法
IIS操作步骤 直接装的wamp 腾讯云主机控制台 安全组里可以配置要开放的端口 关闭防火墙 (C:\wamp\bin\apache\Apache2.4.4) 打开httpd.conf文件 requi ...
- gcc链接,去掉不用的函数和data
编译代码的时候,没有用到的函数经常会被编译,该怎么才能去掉呢? 解决方法: CFLAGS 加上 -ffunction-sections -fdata-sections LDFLAGS 加上 --gc- ...
- 让你用 Chrome 上网快到想哭:Vimium
Chrome 已经成了很多人的主力浏览器,你可能被它的简洁快速所吸引,但它日益丰富的「扩展」,你可能从来都没有接触过,而事实上,很多扩展可以挖掘出 Chrome 的潜能,让它变得前所未有的强大.有哪些 ...
- 用ASP.NET Core 2.1 建立规范的 REST API -- 缓存和并发
本文所需的一些预备知识可以看这里: http://www.cnblogs.com/cgzl/p/9010978.html 和 http://www.cnblogs.com/cgzl/p/9019314 ...