gitのソースコードを読む
C言語の書き方を調べていて、やはりここは何かのソースを読むべきだと思ってgitを読むことにした。
http://cdn8.atwikiimg.com/git_jp/pub/git-manual-jp/Documentation/chunked/ch10s02.html
ここも参考にしつつ。
https://github.com/git/git ここからソースを取ってきて取りあえず
git checkout e83c5163
を実行する。
zsh % wc -l *.[hc] 93 cache.h 23 cat-file.c 172 commit-tree.c 51 init-db.c 259 read-cache.c 43 read-tree.c 81 show-diff.c 248 update-cache.c 66 write-tree.c 1036 合計
これなら全てのファイルを読める。
最初のバージョンの使い方
zsh % make zsh % ./init-db zsh % ./update-cache README zsh % ./write-tree cdad72b321282004f373339d2700847b96be7de3 zsh % echo "first commit" | ./commit-tree cdad72b321282004f373339d2700847b96be7de3 Committing initial tree cdad72b321282004f373339d2700847b96be7de3 362aabbed1eb2033282d8035837d5f4292572381 zsh % find .dircache/ -type f .dircache/index .dircache/objects/cd/ad72b321282004f373339d2700847b96be7de3 .dircache/objects/36/2aabbed1eb2033282d8035837d5f4292572381 .dircache/objects/66/5025b11ce8fb16fadb7daebf77cb54a2ae39a1
このファイルはzlib圧縮されていて直接読めないので http://www.zlib.net/zpipe.c これを取ってきて読む。
zsh % zpipe -d < .dircache/objects/cd/ad72b321282004f373339d2700847b96be7de3 tree 34100644 READMEfP%�����}��w�T��9�% zsh % zpipe -d < .dircache/objects/36/2aabbed1eb2033282d8035837d5f4292572381 commit 197tree cdad72b321282004f373339d2700847b96be7de3 author nishimura,,, <nishimura@menomosso> Thu Sep 5 19:27:02 2013 committer nishimura,,, <nishimura@menomosso> Thu Sep 5 19:27:02 2013 first commit zsh % zpipe -d < .dircache/objects/66/5025b11ce8fb16fadb7daebf77cb54a2ae39a1 blob 8392^@ GIT - the stupid content tracker "git" can mean anything, depending on your mood. ...
最初のファイルが文字化けしているので16進数表示する。
zsh % zpipe -d < .dircache/objects/cd/ad72b321282004f373339d2700847b96be7de3 | od -t x -c 0000000 65657274 00343320 36303031 52203434 t r e e 3 4 \0 1 0 0 6 4 4 R 0000020 4d444145 50660045 e81cb125 dbfa16fb E A D M E \0 f P % 261 034 350 373 026 372 333 0000040 77bfae7d aea254cb 0000a139 } 256 277 w 313 T 242 256 9 241 0000052
emacsのhexl-modeの方が分かりやすいかも。
形式は
種類(commit, tree, blob) [スペース] サイズ [\0] モード [スペース] ファイル名 [\0] 0x665025b1...
だと分かる。
zsh % ./cat-file cdad72b321282004f373339d2700847b96be7de3 temp_git_file_dIoMiK: tree zsh % ./read-tree cdad72b321282004f373339d2700847b96be7de3 100644 README (665025b11ce8fb16fadb7daebf77cb54a2ae39a1)
cat-file はこの時点ではデータを表示するのではなくて一時ファイルに書き出すようだ。
大体の流れが分かってきたところで、コミットを少し進める。
zsh % make clean zsh % git checkout 7fa6b4e zsh % wc -l *.[hc] 24 blob.c 14 blob.h 128 cache.h 45 cat-file.c 47 check-files.c 183 checkout-cache.c 363 commit-tree.c 85 commit.c 27 commit.h 204 diff-tree.c 171 fsck-cache.c 56 init-db.c 114 ls-tree.c 92 merge-base.c 106 merge-cache.c 96 object.c 29 object.h 259 read-cache.c 260 read-tree.c 145 rev-tree.c 164 revision.h 247 sha1_file.c 212 show-diff.c 193 show-files.c 67 tree.c 17 tree.h 34 unpack-file.c 338 update-cache.c 40 usage.c 130 write-tree.c 3890 合計
55979コミット中の153コミット目なので、まだまだ初期。
zsh % make
エラーが出たのでcommit.cに #include
zsh % ./update-cache COPYING fatal: unable to create new cachefile
ローカルDBディレクトリが.gitになった。
zsh % mv .dircache/ .git zsh % ./update-cache COPYING error: bad signature error: verify header failed fatal: cache corrupted
indexが違ってダメぽい。他にもコマンドが多少変わっている。
作り直す。
zsh % rm -rf .git/ zsh % ./init-db zsh % ./update-cache --add README zsh % echo test1 > test.txt zsh % ./update-cache --add test.txt zsh % ./write-tree 1afff28ca8fdf94d4dd43e4f61391f3ae36c5d95 zsh % echo "first commit" | ./commit-tree 1afff28ca8fdf94d4dd43e4f61391f3ae36c5d95 > .git/HEAD Committing initial tree 1afff28ca8fdf94d4dd43e4f61391f3ae36c5d95 zsh % ./update-cache --add COPYING zsh % echo test2 >> test.txt zsh % ./update-cache test.txt zsh % ./write-tree 8a235d62917e5769dd91a55277a2a0f0d213ce3f zsh % echo "second commit" | ./commit-tree 8a235d62917e5769dd91a55277a2a0f0d213ce3f -p $(cat .git/HEAD) > .git/HEAD zsh % ./cat-file commit $(cat .git/HEAD) tree 8a235d62917e5769dd91a55277a2a0f0d213ce3f parent ef1faf1165edb8de9fda4f948fc73b5e6fea7719 author nishimura <nishimura@menomosso.(none)> 1378378730 +0900 committer nishimura <nishimura@menomosso.(none)> 1378378730 +0900 zsh % find .git/ -type f .git/index .git/HEAD .git/objects/8a/235d62917e5769dd91a55277a2a0f0d213ce3f .git/objects/ef/1faf1165edb8de9fda4f948fc73b5e6fea7719 .git/objects/65/212d3324a089abd0b9ef62f5867ac7c44fc268 .git/objects/1a/fff28ca8fdf94d4dd43e4f61391f3ae36c5d95 .git/objects/fe/2a4177a760fd110e78788734f167bd633be8de .git/objects/0c/8f66a82ac03c86646d8a5538f7ace811d83417 .git/objects/67/9bab7e4796f7e8befb71363bfc53eda778dcb5 .git/objects/b9/ea68dc9f9a51c759b056aaa895ca6176e963e9 .git/objects/f4/3d04b5d74afebc5e8aa2ae2452fbbe034299ac zsh % ./ls-tree 8a235d62917e5769dd91a55277a2a0f0d213ce3f 100644 blob fe2a4177a760fd110e78788734f167bd633be8de COPYING 100644 blob 0c8f66a82ac03c86646d8a5538f7ace811d83417 README 100644 blob 679bab7e4796f7e8befb71363bfc53eda778dcb5 test.txt
gitの一番最初のコミットと現在のバージョンでデータの内部構造がほとんど変わっていないのがすごい。
ソースコードの中身をメモしていこうと思っていたけど、初期gitの使い方メモになってしまった。