Git Internal #1:内容管理

来源:互联网 发布:马克思资本论 知乎 编辑:程序博客网 时间:2024/06/05 02:10

在公司里面几次用了git,始终感觉还是把git当作svn在用,于是决定深究一下,看看git到底是个啥,跟svn的本质区别在哪。

这篇文章用来记录git在内容管理上的一些实现细节。主要是.git目录下的objectsrefs这两个子目录下所存储的东东。

objects

objects目录下存储了三种类型的对象。深入之前有必要先看下我所使用的git版本,

E:\Projects\kisimple.github.io>git versiongit version 1.9.0.msysgit.0

commit

先用git log来看下提交的历史记录,

commit 418a8e76dd148da5b0b54e64cdd4e989b028b1ffAuthor: tongyuan.zbs <tongyuan.zbs@taobao.com>Date:   Sat Apr 9 16:26:24 2016 +0800    update idp-2016.txtcommit 627ff95e2557546b5001eb7c7003d0e147534f49Author: kisimple <blues.dev@gmail.com>Date:   Wed Apr 6 09:52:30 2016 +0800    Update idp-2016.txt

commit后面所跟的那个ID对应的就是接下来我们要讲的第一种类型,也就是commit类型的对象。git cat-file命令可以用来查看这个commit对象,

E:\Projects\kisimple.github.io>git cat-file -p 418a8e76dd148da5b0b54e64cdd4e989b028b1fftree b21c057571416cedf38457cf58482321e7bdedd6parent 627ff95e2557546b5001eb7c7003d0e147534f49author tongyuan.zbs <tongyuan.zbs@taobao.com> 1460190384 +0800committer tongyuan.zbs <tongyuan.zbs@taobao.com> 1460190384 +0800update idp-2016.txt

我们也可以使用下面这个python脚本来查看更原始的commit对象的内容,实际上就是对.git/objects/41/8a8e76dd148da5b0b54e64cdd4e989b028b1ff这个文件进行解压缩,

E:\Projects\kisimple.github.io>python -c "import zlib,sys;print repr(zlib.decompress(sys.stdin.read()))" < .git/objects/41/8a8e76dd148da5b0b54e64cdd4e989b028b1ff'commit 244\x00tree b21c057571416cedf38457cf58482321e7bdedd6\nparent 627ff95e2557546b5001eb7c7003d0e147534f49\nauthor tongyuan.zbs <tongyuan.zbs@taobao.com> 1460190384 +0800\ncommitter tongyuan.zbs <tongyuan.zbs@taobao.com> 1460190384 +0800\n\nupdate idp-2016.txt\n'

其中我们可以看到主要存储的是我们要讲的第二种对象类型,也就是tree类型的对象。

tree

同样的,使用git cat-file来看下tree类型的对象存储的是啥东东,

E:\Projects\kisimple.github.io>git cat-file -p b21c057571416cedf38457cf58482321e7bdedd6100644 blob 33c0adbab2d9f5f50ddd156c6d5da5de04838276    .gitignore100644 blob 4bf3f7d8fca35a944e38e273e6ff3da2e292d81b    404.html100644 blob c175fc5ba723f6efafbe0037f8fcf9b2096435e1    CNAME100644 blob 4c2bcdb51506b42a08359825b9e1427ce5f4da6b    README.md100644 blob daf27d4490a30e0a8b9952741f92e8301e0b7283    _config.yml040000 tree d04459efd2a8fe1dc6c434e230bdb55f2bba376c    _includes040000 tree 5babdc6a6f795f70d2672febc8901ebeda7e49ee    _layouts040000 tree cac8aaf06079797ea308eff21dce8e61734cc19d    _plugins040000 tree 81ddcb0d61dfb5d8496f636be229f7becceb9824    _posts040000 tree 8c8a68965a7d0cfc066f763d0a4ea9e53d6c4e15    _sass100644 blob 9f7c3fa92ace0d72fd21d312e5b709fdbebef96c    about.html100644 blob bafc806e0a33e7db2b8a53896f8fb0b04983b1fb    atom.xml100644 blob 87726bea35eab5b28ebe0fe3c576e3f683e83ad9    index.html040000 tree cdb2e20c1fcac083db3c6c8f064c9ff5089d6e6c    public040000 tree 211e829111a9d017c6de284fb92dd7bbef50ebd0    r100644 blob cc9fb545290d7c4b18436186fa5ca8e331126156    road.txt040000 tree ccd25eaa073b0a2f84a146edae9695d734cf8942    s100644 blob 0825f63aea0cf1f7b43d9073dc6d8ba1bdf9dcdf    styles.scss100644 blob e597fc78c5756e592bbcba2c1e9af6b9f45428f4    tags.html

可以看到,主要就是tree对象和第三种,也就是blob类型的对象,blob是Binary Large OBject,这里就是我们的文件对象了,存储的就是文件的内容。

blob

我们使用下面的脚本来模拟git对文件的压缩(压缩算法见参考链接),

E:\Projects\kisimple.github.io>pythonPython 2.7.6 (default, Nov 10 2013, 19:24:18) [MSC v.1500 32 bit (Intel)] on win32Type "help", "copyright", "credits" or "license" for more information.>>> from hashlib import sha1>>> f = open('r/idp-2016.txt')>>> h = sha1()>>> data = f.read()>>> h.update("blob %u\0" % len(data))>>> h.update(data)>>> h.hexdigest()'2cc4c9a0cc4cb0f72af498fdb074c53f5f9fea3e'

然后使用git cat-file来验证我们上面的脚本的正确性,

E:\Projects\kisimple.github.io>git cat-file -p 2cc4c9a0cc4cb0f72af498fdb074c53f5f9fea3e

可以看到输出的内容确实就是我们上面脚本所压缩的r/idp-2016.txt文件的内容,这里就不贴出来了。

简单看完objects目录下的东东,下面来看看refs目录。

refs

先看下这个目录下都有啥,

E:\Projects\kisimple.github.io\.git>tree refsE:\PROJECTS\KISIMPLE.GITHUB.IO\.GIT\REFS├─heads├─remotes│  └─origin└─tags

.git目录下有个HEAD文件用来记录当前HEAD是在哪个分支上,

E:\Projects\kisimple.github.io\.git>cat HEADref: refs/heads/master

看下refs/heads/master文件,

E:\Projects\kisimple.github.io\.git>cat refs/heads/master418a8e76dd148da5b0b54e64cdd4e989b028b1ff

所以存储了当前HEAD是在哪个commit对象上面。
refs/remotes/origin/HEAD这个文件则存储了远程仓库现在的HEAD是在哪个分支上,

E:\Projects\kisimple.github.io\.git>cat refs/remotes/origin/HEADref: refs/remotes/origin/masterE:\Projects\kisimple.github.io\.git>cat refs/remotes/origin/master627ff95e2557546b5001eb7c7003d0e147534f49

所以远程的HEAD是落后于本地的HEAD的,这意味着本地还有代码尚未push到远程仓库。

最后,贴一张git的object model

参考资料

  • http://www.slideshare.net/chacon/getting-git
  • http://slidetocode.com/2013/08/25/how-git-works/
  • https://gist.github.com/msabramo/763200
0 0