Git笔记

引子

  • 在没有git、svn这些版本管理工具的情况下,如果我们手动管理版本需要做哪些?
    1.复制整个目录。
    2.以日期重命名根目录。

  • 只修改了一小部分怎么办?
    可以将未修改的文件作为引用指向上一个副本的对应文件。

  • 怎么判断文件内容是否有变化?
    整个文件内容做hash,比较hash值。

  • 文件matedata的变化怎么判定?
    不好判断。

  • 副本多了太占空间怎么办?
    每个文件都压缩处理。

  • 版本之间的线性关系怎么记录?
    每个版本加一个文件,记录上一个版本目录的名字,组成链表结构。

  • 新版本的副本如何加入版本线(分支)?
    加在头节点。

  • 多个线性关系(分支)怎么标记?
    每条线取个名字,用文件记录,名字是分支名,内容是对应线条上的某个副本的根目录,一般是链表的头节点。

  • 当前正在开发的版本怎么记录?
    用文件记录,内容为某个副本的目录名,但具体来说一般是指向一个分支,因为不指向分支的提交无意义(detached HEAD,“由于这个提交没有被任何分支跟踪到,因此并不能保证这个提交会永久存在。实际上当reflog中含有该提交的日志过期后,这个提交随时都会从版本库中彻底清除”)。

自动化

以上这些操作全部自动化,即为一个简化版的git。

git对应操作的具体实现

  • 副本:快照
  • 变化的检测:index文件
  • 压缩:zlib
  • 线性关系:{{{blob}tree}commit} 由commit对象为节点,组成的单向链表,提交时,向链表头部添加当前提交对象。
  • 分支、HEAD:指针、二级指针

git内部原理剖析工具

  • git cat-file -t -p, 显示git对象内容
  • git fsck -full, 查看所有垃圾对象
  • SHA-1值,160bit | 20byte | 40个16进制字符表示

要点

  • git 对象的结构
    git 三棵树 working directory、 index(预期的下一次提交的快照)、 HEAD(上一次提交的快照,下一次提交的父结点)
  • 重要命令
    1.git reset
    2.git checkout
    3.git rebase

疑问

  • git commit 后显示相似度如何得来?
    simhash?
  • git stash 如何暂存index信息?

参考样例

  • blob

    • 压缩后的二进制状态(27byte)
      78014BCAC94F523034644836E44A36E24A36E54A360300328F049A
    • 解压后的文本内容(19byte)
      blob 11\x00c1\nc2\nc5\nc6
    • 实际的文件内容
      c1
      c2
      c5
      c6
  • commit

    • 压缩后的二进制内容(149byte)
      78 01 9D 8E 4B 0A C2 30 10 40 5D E7 14 D9 0B 32 99 24 33 1D 10 11 3C C9 E4 47 0B D6 48 4D EF 6F 57 1E C0 DD E3 C1 83 97 FB BA 2E C3 A2 E3 D3 D8 6A B5 B5 49 F4 89 01 1B B2 2A 36 16 5F 24 0B 97 E2 09 28 B5 C2 2D 21 83 98 B7 6E F5 35 AC 62 2C 53 0C E2 38 67 05 DF 82 20 32 4B 0C 09 C1 53 22 74 2A 50 94 8C EE 63 EE 9B 7D 2E FB 73 F9 CC 7B B7 D7 1F 22 38 BE 3B F2 97 DC D7 9B 75 11 23 13 44 0E F6 0C 13 80 39 EC B1 38 EA 5F B1 79 4C E6 0B 09 D0 41 C7
    • 解压后的文本内容(228byte)
      commit 217\x00tree ef953b702f27aa2f793d9c97dd3606bfd7fb2709\nparent a25d854917cca03f492277954b2036b621a90da6\nauthor liulishuo [email protected] 1525760574 +0800\ncommitter liulishuo [email protected] 1525760574 +0800\n\nC8\n
    • 实际文本内容
tree ef953b702f27aa2f793d9c97dd3606bfd7fb2709
parent a25d854917cca03f492277954b2036b621a90da6
author liulishuo  1525760574 +0800
committer liulishuo  1525760574 +0800

C8
  • index文件内容
    • 二进制状态
      44 49 52 43 00 00 00 02 00 00 00 01 5A F1 4B 84 00 91 AA A4 5A F1 4B 84 00 53 D8 44 01 00 00 04 02 DB E8 88 00 00 81 A4 00 00 01 F5 00 00 00 14 00 00 00 17 A2 04 A0 C5 BE 2C F2 48 8C D5 9F D7 3C 8E 95 0E DB D8 B2 68 00 0B 67 69 74 44 65 6D 6F 2E 74 78 74 00 00 00 00 00 00 00 54 52 45 45 00 00 00 19 00 31 20 30 0A E5 13 92 E3 77 AD 81 E5 E9 0F B5 B7 EA 4D 29 D0 F3 D9 BA 33 65 00 4A D8 F1 00 A3 48 66 14 D8 A6 C2 0F EA 57 73 18 77 0E
    • 文本状态
DIRC��ZÒKÑ뙧ZÒKÑSÿD���€Ëàŧ�ı��¢�†≈æ,ÚHå’ü◊<éï�€ÿ≤h�gitDemo.txtTREE�1 0
Â�í„w≠ÅÂÈ�µ∑ÍM)–ÛŸ∫3eJÿÒ£Hf�ÿ¶¬�ÍWs�w�
-  [标志位比对](https://github.com/git/git/blob/master/Documentation/technical/index-format.txt)
Git笔记_第1张图片
Screen Shot 2018-05-17 at 09.04.13.png
  • 终端Ruby交互模式手动查看git对象内容的方法
irb
require 'zlib'
aFile = File.new("", "r")
zlibContent = aFile.sysread()
//解压缩文件
content = Zlib::Inflate.inflate(zlibContent)

//生成SHA-1值
require 'digest/sha1'
sha1 = Digest::SHA1.hexdigest(content)

你可能感兴趣的:(Git笔记)