Upgrade to Pro — share decks privately, control downloads, hide ads and more …

動かして理解するGitの内側

 動かして理解するGitの内側

2019.05.18 未来大×企業エンジニア 春のLT大会 発表スライド

Atsuya Sato

May 18, 2019
Tweet

More Decks by Atsuya Sato

Other Decks in Technology

Transcript

  1. 動かして理解する
    Gitの内側
    @natmark / Cookpad Inc.
    2019.05.18 未来大×企業エンジニア 春のLT大会

    View Slide

  2. 始める前に
    「動かして覚える」なので、手元にGitの実
    行環境がある方はスライドを見ながら

    コマンドを叩くと面白いかも?

    (一緒に動かす場合は、gitとzlibを

    インストールしておいてください)

    10分しかないので、LTは割と早口です

    View Slide

  3. 佐藤 敦也
    さとう あつや
    クックパッド株式会社 買物事業部
    エンジニア
    未来大卒業生(2018年度) / 松原克弥研究室
    [email protected]
    !OBUNBSL

    View Slide

  4. Git使ったことありますか?"

    View Slide

  5. Gitとは
    • 一言で言うと

    「分散型バージョン管理システム」
    (使ったことない人が多かった時用の説明資料)
    分散型の説明は省きます

    View Slide

  6. バージョン管理とは
    (使ったことない人が多かった時用の説明資料)

    View Slide

  7. バージョン管理とは
    (使ったことない人が多かった時用の説明資料)
    どれが最新なの…

    View Slide

  8. Gitを使うと
    (使ったことない人が多かった時用の説明資料)
    フォルダには最新
    のファイルだけ

    View Slide

  9. Gitを使うと
    (使ったことない人が多かった時用の説明資料)
    変更の履歴を
    確認できる

    View Slide

  10. Gitを使うと
    (使ったことない人が多かった時用の説明資料)
    変更差分が見れる

    View Slide

  11. Gitは差分情報を保存しておいて、
    差分情報からバージョン管理が
    できる便利なやつ!!!

    View Slide

  12. View Slide

  13. 果たして、これは本当にそうなのだろうか?

    View Slide

  14. 動かして理解する
    Gitの内側
    (ここから本番)

    View Slide

  15. (ちなみに) .git の中を
    覗いたことがある人"

    View Slide

  16. Gitのリポジトリを作る
    $ mkdir git-inside-workshop
    $ cd git-inside-workshop
    $ git init
    Initialized empty Git repository in /Users/atsuya-sato/
    Desktop/git-inside-workshop/.git/
    $ ls -a
    . .. .git

    View Slide

  17. .gitを覗いてみる
    $ cd .git
    $ ls -a
    . .. HEAD config description
    hooks info objects refs

    View Slide

  18. .gitを覗いてみる
    $ cd .git
    $ ls -a
    . .. HEAD config description
    hooks info objects refs
    いろいろでてきた
    わからん!

    View Slide

  19. .gitをGit管理する
    $ pwd
    /Users/atsuya-sato/Desktop/git-inside-workshop/.git
    $ git init
    Initialized empty Git repository in /Users/atsuya-sato/
    Desktop/git-inside-workshop/.git/.git/

    View Slide

  20. git initの生成物をCommit
    $ git status
    On branch master
    No commits yet
    Untracked files:
    (use "git add <file>..." to include in what will be committed)
    HEAD
    config
    description
    hooks/
    info/
    nothing added to commit but untracked files present (use "git add" to track)

    View Slide

  21. git initの生成物をCommit
    $ git add .
    $ git commit -m “Initial Commit”
    [master (root-commit) 7349f42] Initial Commit
    15 files changed, 655 insertions(+)
    create mode 100644 HEAD
    create mode 100644 config
    create mode 100644 description
    create mode 100755 hooks/applypatch-msg.sample
    create mode 100755 hooks/commit-msg.sample
    create mode 100755 hooks/fsmonitor-watchman.sample
    create mode 100755 hooks/post-update.sample
    create mode 100755 hooks/pre-applypatch.sample
    create mode 100755 hooks/pre-commit.sample
    create mode 100755 hooks/pre-push.sample
    create mode 100755 hooks/pre-rebase.sample
    create mode 100755 hooks/pre-receive.sample
    create mode 100755 hooks/prepare-commit-msg.sample
    create mode 100755 hooks/update.sample
    create mode 100644 info/exclude

    View Slide

  22. 1. git addで
    何が起きているのか

    View Slide

  23. git addで何が起きているのか?
    $ echo “Hello World” > hello.txt
    On branch master
    Untracked files:
    (use "git add <file>..." to include in what will be committed)
    hello.txt
    nothing added to commit but untracked files present (use "git add" to track)
    $ git status
    $ pwd
    /Users/atsuya-sato/Desktop/git-inside-workshop/
    $ cd ../

    View Slide

  24. git addで何が起きているのか?
    $ git add hello.txt
    $ cd .git
    $ git status -uall
    On branch master
    Untracked files:
    (use "git add <file>..." to include in what will be committed)
    index
    objects/55/7db03de997c86a4a028e1ebd3a1ceb225be238
    nothing added to commit but untracked files present (use "git add" to track)

    View Slide

  25. git addで何が起きているのか?
    • hello.txtをgit addしたことによって
    ‣objects/
    55/7db03de997c86a4a028e1ebd3a1ceb22
    5be238
    ‣index
    • の2つのファイルが生成されたことが分かった

    View Slide

  26. objects/
    55/7db03de997c86a4a028e1eb
    d3a1ceb225be238
    とは一体なんなのだろうか

    View Slide

  27. objects/の正体
    • objects/ の正体はGitオブジェクトと呼ばれるもの
    • Gitオブジェクトのヘッダ部とデータ部に対してSHA-1の
    チェックサムを用いたファイル名で格納する(SHA-1ハッ
    シュの初めの2文字がサブディレクトリ・残りの38文字を
    ファイル名とする)
    ‣Gitオブジェクトのチェックサムが
    557db03de997c86a4a028e1ebd3a1ceb225be238 

    の場合
    ‣objects/55/7db03de997c86a4a028e1ebd3a1ceb

    225be238 

    に保存される

    View Slide

  28. objects/の正体
    • objects/ の正体はGitオブジェクトと呼ばれるもの
    • GitはGitオブジェクトとして以下のオブジェクト
    を生成する
    ‣blobオブジェクト
    ‣treeオブジェクト
    ‣commitオブジェクト(tagオブジェクト)

    View Slide

  29. blobオブジェクト
    • ファイルのデータそのもの
    • ファイル名や属性は含まれない

    View Slide

  30. treeオブジェクト
    • フォルダ構造を表す
    • treeオブジェクトは以下のようなものを持つ
    ‣ファイルの属性
    ‣blobオブジェクト(サブフォルダが存在する場
    合はtreeオブジェクト)への参照
    ‣ファイル名

    View Slide

  31. blobとtreeの関係
    .
    ├── new.txt
    ├── test.txt
    └── bak
    └── test.txt

    View Slide

  32. commitオブジェクト
    • git commitした時のCommit情報
    • commitオブジェクトが持つものは
    ‣親commitへの参照
    ‣トップレベルのtreeへの参照
    ‣コミットしたユーザーの情報
    ‣タイムスタンプ
    ‣コミットメッセージ

    View Slide

  33. commitとblobとtreeの関係

    View Slide

  34. objects/55/7db03de997c86a4a0

    28e1ebd3a1ceb225be238
    を詳しく見てみる

    View Slide

  35. objects/
    55/7db03de997c86a4a028e1ebd3a1ceb225be238
    を詳しく見てみる
    $ pwd
    /Users/atsuya-sato/Desktop/git-inside-workshop/.git
    $ cat objects/55/7db03de997c86a4a028e1ebd3

    a1ceb225be238
    xKOR04bH/IAI%

    View Slide

  36. objects/
    55/7db03de997c86a4a028e1ebd3a1ceb225be238
    を詳しく見てみる
    $ pwd
    /Users/atsuya-sato/Desktop/git-inside-workshop/.git
    $ cat objects/55/7db03de997c86a4a028e1ebd3

    a1ceb225be238
    xKOR04bH/IAI%
    なんだこれは…

    View Slide

  37. objects/
    55/7db03de997c86a4a028e1ebd3a1ceb225be238
    を詳しく見てみる
    $ cat objects/55/7db03de997c86a4a028e1ebd3a1

    ceb225be238
    $ zlib -d < objects/55/7db03de997c86a4a028e1eb

    d3a1ceb225be238
    xKOR04bH/IAI%
    blob 12Hello World

    View Slide

  38. objects/
    55/7db03de997c86a4a028e1ebd3a1ceb225be238
    を詳しく見てみる
    $ cat objects/55/7db03de997c86a4a028e1ebd3a1

    ceb225be238
    $ zlib -d < objects/55/7db03de997c86a4a028e1eb

    d3a1ceb225be238
    xKOR04bH/IAI%
    blob 12Hello World
    実はzlibで
    圧縮されている
    中身が出てきた

    View Slide

  39. objects/
    55/7db03de997c86a4a028e1ebd3a1ceb225be238
    をさらに詳しく見てみる
    $ zlib -d < objects/55/7db03de997c86a4a028e1eb

    d3a1ceb225be238 | xxd
    00000000: 626c 6f62 2031 3200 4865 6c6c 6f20 576f
    00000010: 726c 640a
    blob 12.Hello Wo
    rld.

    View Slide

  40. objects/
    55/7db03de997c86a4a028e1ebd3a1ceb225be238
    をさらに詳しく見てみる
    $ zlib -d < objects/55/7db03de997c86a4a028e1eb

    d3a1ceb225be238 | xxd
    00000000: 626c 6f62 2031 3200 4865 6c6c 6f20 576f
    00000010: 726c 640a
    blob 12.Hello Wo
    rld.
    16進ダンプを
    表示する

    View Slide

  41. objects/
    55/7db03de997c86a4a028e1ebd3a1ceb225be238
    をさらに詳しく見てみる
    00000000: 62 6c 6f 62 20 31 32 00 48 65 6c 6c 6f 20 57 6f
    00000010: 72 6c 64 0a
    b b
    l o (Space) 1 2 (NUL) H e l l o W o
    r l d (改行)
    (Space)
    • ASCIIコードと照らし合わせると…
    <オブジェクトタイプ> 0x20 <ファイルバイト数> 0x00 <データバイト>
    • オブジェクトのフォーマットは
    になっている!

    View Slide

  42. ちなみに、Gitオブジェクトは
    git cat-file コマンドでもみることができる
    $ cd ../
    /Users/atsuya-sato/Desktop/git-inside-workshop/.git
    $ git cat-file -t 557db03de997c86a4a028e1ebd3

    a1ceb225be238
    $ pwd
    blob
    $ git cat-file -p 557d
    Hello World
    SHA-1ハッシュの
    先頭4文字だけでも
    名前解決できる
    $ git cat-file -s 557d
    12

    View Slide

  43. git addをするとblobオブジェクト
    が生成されることが分かった!

    View Slide

  44. git addで何が起きているのか?
    • hello.txtをgit addしたことによって
    ‣objects/
    55/7db03de997c86a4a028e1ebd3a1ceb22
    5be238
    ‣index
    • の2つのファイルが生成されたことが分かった

    View Slide

  45. indexとはなんなのか

    View Slide

  46. indexとは何なのか
    • ステージング情報を保持してるバイナリファイ

    • コンフリクトした際の競合の情報などもindex
    が持っている
    • ステージング領域とは「次にコミットしたとき
    にコンテンツとして登録されるもの」

    View Slide

  47. indexを見てみる…?
    $ cat .git/index | xxd
    /Users/atsuya-sato/Desktop/git-inside-workshop
    $ pwd
    00000000: 4449 5243 0000 0002 0000 0001 5cda 3fb1
    00000010: 195f eaed 5cda 3fb1 195f eaed 0100 0004
    00000020: 008c a4c2 0000 81a4 0000 01f6 0000 0014
    00000030: 0000 000c 557d b03d e997 c86a 4a02 8e1e
    00000040: bd3a 1ceb 225b e238 0009 6865 6c6c 6f2e
    00000050: 7478 7400 7990 bb91 d0e6 ff77 8de7 af5b
    00000060: a6ea fb95 c5b9 643a
    DIRC........\.?.
    ._..\.?.._......
    ................
    ....U}.=...jJ...
    .:..”[.8..hello.
    txt......y.w...[
    ......d:

    View Slide

  48. indexを見てみる…?
    00000000: 4449 5243 0000 0002 0000 0001 5cda 3fb1
    00000010: 195f eaed 5cda 3fb1 195f eaed 0100 0004
    00000020: 008c a4c2 0000 81a4 0000 01f6 0000 0014
    00000030: 0000 000c 557d b03d e997 c86a 4a02 8e1e
    00000040: bd3a 1ceb 225b e238 0009 6865 6c6c 6f2e
    00000050: 7478 7400 7990 bb91 d0e6 ff77 8de7 af5b
    00000060: a6ea fb95 c5b9 643a

    View Slide

  49. indexを見てみる…?
    00000000: 4449 5243 0000 0002 0000 0001 5cda 3fb1
    00000010: 195f eaed 5cda 3fb1 195f eaed 0100 0004
    00000020: 008c a4c2 0000 81a4 0000 01f6 0000 0014
    00000030: 0000 000c 557d b03d e997 c86a 4a02 8e1e
    00000040: bd3a 1ceb 225b e238 0009 6865 6c6c 6f2e
    00000050: 7478 7400 7990 bb91 d0e6 ff77 8de7 af5b
    00000060: a6ea fb95 c5b9 643a

    (時間があれば後で読み方を教えます)

    View Slide

  50. indexを見てみる
    $ git ls-files -s
    100644 557db03de997c86a4a028e1ebd3a1ceb225be238 0 hello.txt
    • ls-files -sでステージング領域にキャッシュされているファイル
    の一覧を見ることができる
    • ステージフラグ: 普段は0、マージコンフリクトの解消(3-way
    マージ)の際にステージ1, 2, 3としてインデックスに保存
    • indexファイルは他にもいろいろ情報を持っているが省略(後で
    時間があれば紹介)
    FileMode
    (Permission)
    blobのSHA1ハッシュ ステージフラグ ファイルパス

    View Slide

  51. 2. git commitで
    何が起きているのか

    View Slide

  52. 先にgit addで出来た.git/の

    生成物をコミットしておく
    $ cd .git
    On branch master
    Untracked files:
    (use "git add <file>..." to include in what will be committed)
    index
    objects/55/7db03de997c86a4a028e1ebd3a1ceb225be238
    nothing added to commit but untracked files present (use "git add" to track)
    $ git status -uall
    $ git add .
    $ git commit -m “Exec git add hello.txt”
    /Users/atsuya-sato/Desktop/git-inside-workshop
    $ pwd

    View Slide

  53. git commitで何が起きているのか
    $ cd ../
    /Users/atsuya-sato/Desktop/git-inside-workshop/.git
    $ pwd
    $ git status
    On branch master
    No commits yet
    Changes to be committed:
    (use "git rm --cached <file>..." to unstage)
    new file: hello.txt
    $ git commit -m “Add hello.txt”
    [master (root-commit) 87a9891] Add hello.txt
    1 file changed, 1 insertion(+)
    create mode 100644 hello.txt

    View Slide

  54. git commitで何が起きているのか
    $ cd .git
    $ git status -uall
    On branch master
    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git checkout -- <file>..." to discard changes in working directory)
    modified: index
    Untracked files:
    (use "git add <file>..." to include in what will be committed)
    COMMIT_EDITMSG
    logs/HEAD
    logs/refs/heads/master
    objects/87/a989174c548a6a8b0e78a017d00db3a4e16d12
    objects/97/b49d4c943e3715fe30f141cc6f27a8548cee0e
    refs/heads/master
    no changes added to commit (use "git add" and/or "git commit -a")

    View Slide

  55. git commitで何が起きているのか
    $ cd .git
    $ git status -uall
    On branch master
    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git checkout -- <file>..." to discard changes in working directory)
    modified: index
    Untracked files:
    (use "git add <file>..." to include in what will be committed)
    COMMIT_EDITMSG
    logs/HEAD
    logs/refs/heads/master
    objects/87/a989174c548a6a8b0e78a017d00db3a4e16d12
    objects/97/b49d4c943e3715fe30f141cc6f27a8548cee0e
    refs/heads/master
    no changes added to commit (use "git add" and/or "git commit -a")
    たくさんファイル
    が出てきた!!

    View Slide

  56. git commitで
    何が起きているのか?
    • hello.txtをgit addした後、git commitしたことによって
    ‣index
    • が更新された
    ‣COMMIT_EDITMSGS (説明省略)
    ‣logs/HEAD (説明省略)
    ‣logs/refs/heads/master (説明省略)
    ‣objects/87/a989174c548a6a8b0e78a017d00db3a4e16d12
    ‣objects/97/b49d4c943e3715fe30f141cc6f27a8548cee0e
    ‣refs/heads/master
    • が生成された

    View Slide

  57. git commitで生成された

    Gitオブジェクトを見てみる
    • git commitで追加された
    ‣objects/87/
    a989174c548a6a8b0e78a017d00db
    3a4e16d12
    ‣objects/97/
    b49d4c943e3715fe30f141cc6f27a8
    548cee0e
    • を見てみる

    View Slide

  58. git commitで生成された

    Gitオブジェクトを見てみる
    $ git cat-file -t 87a9
    commit
    $ git cat-file -s 87a9
    tree 97b49d4c943e3715fe30f141cc6f27a8548cee0e
    author atsuya-sato 1557809638 +0900
    committer atsuya-sato 1557809638 +0900
    Add hello.txt
    git commitで追加されたtreeオブジェクト(97b4)を
    ルートに持つcommitオブジェクトが生成されている
    $ cd ../
    $ pwd
    /Users/atsuya-sato/Desktop/git-inside-workshop

    View Slide

  59. git commitで生成された

    Gitオブジェクトを見てみる
    $ git cat-file -t 97b4
    tree
    $ git cat-file -s 97b4
    100644 blob 557db03de997c86a4a028e1ebd3a1ceb225be238 hello.txt
    git addで追加されたhello.txtのblobオブジェクト
    (557d)を持つtreeオブジェクト(97b4)が生成されている

    View Slide

  60. git commitで
    何が起きているのか?
    • hello.txtをgit addした後、git commitしたことによって
    ‣index
    • が更新された
    ‣COMMIT_EDITMSGS (説明省略)
    ‣logs/HEAD (説明省略)
    ‣logs/refs/heads/master (説明省略)
    ‣objects/87/a989174c548a6a8b0e78a017d00db3a4e16d12
    ‣objects/97/b49d4c943e3715fe30f141cc6f27a8548cee0e
    ‣refs/heads/master
    • が生成された

    View Slide

  61. refs/heads/masterをみる
    $ cat .git/refs/heads/master
    87a989174c548a6a8b0e78a017d00db3a4e16d12
    commitオブジェクトのSHA-1ハッシュを持ってい
    ることが分かる
    • refs/heads/masterはmasterブランチのHEAD
    コミットへの参照を持っている

    View Slide

  62. git commitで
    何が起きているのか?
    • hello.txtをgit addした後、git commitしたことによって
    ‣index
    • が更新された
    ‣COMMIT_EDITMSGS (説明省略)
    ‣logs/HEAD (説明省略)
    ‣logs/refs/heads/master (説明省略)
    ‣objects/87/a989174c548a6a8b0e78a017d00db3a4e16d12
    ‣objects/97/b49d4c943e3715fe30f141cc6f27a8548cee0e
    ‣refs/heads/master
    • が生成された

    View Slide

  63. indexを見てみる
    $ cat .git/index | xxd
    00000000: 4449 5243 0000 0002 0000 0001 5cda 3fb1
    00000010: 195f eaed 5cda 3fb1 195f eaed 0100 0004
    00000020: 008c a4c2 0000 81a4 0000 01f6 0000 0014
    00000030: 0000 000c 557d b03d e997 c86a 4a02 8e1e
    00000040: bd3a 1ceb 225b e238 0009 6865 6c6c 6f2e
    00000050: 7478 7400 5452 4545 0000 0019 0031 2030
    00000060: 0a97 b49d 4c94 3e37 15fe 30f1 41cc 6f27
    00000070: a854 8cee 0e94 aef3 b413 ed22 4737 8e4b
    00000080: 95c5 ea68 cafa 4937 f4
    DIRC........\.?.
    ._..\.?.._......
    ................
    ....U}.=...jJ...
    .:.."[.8..hello.
    txt.TREE.....1 0
    ....L.>7..0.A.o'
    .T........."G7.K
    ...h..I7.

    View Slide

  64. indexを見てみる
    00000000: 4449 5243 0000 0002 0000 0001 5cda 3fb1
    00000010: 195f eaed 5cda 3fb1 195f eaed 0100 0004
    00000020: 008c a4c2 0000 81a4 0000 01f6 0000 0014
    00000030: 0000 000c 557d b03d e997 c86a 4a02 8e1e
    00000040: bd3a 1ceb 225b e238 0009 6865 6c6c 6f2e
    00000050: 7478 7400 5452 4545 0000 0019 0031 2030
    00000060: 0a97 b49d 4c94 3e37 15fe 30f1 41cc 6f27
    00000070: a854 8cee 0e94 aef3 b413 ed22 4737 8e4b
    00000080: 95c5 ea68 cafa 4937 f4
    00000000: 4449 5243 0000 0002 0000 0001 5cda 3fb1
    00000010: 195f eaed 5cda 3fb1 195f eaed 0100 0004
    00000020: 008c a4c2 0000 81a4 0000 01f6 0000 0014
    00000030: 0000 000c 557d b03d e997 c86a 4a02 8e1e
    00000040: bd3a 1ceb 225b e238 0009 6865 6c6c 6f2e
    00000050: 7478 7400 7990 bb91 d0e6 ff77 8de7 af5b
    00000060: a6ea fb95 c5b9 643a
    • git add後
    • git commit後
    85バイト目からバイナリ
    が変化していることが分かる

    View Slide

  65. indexをみる
    • git commitによってindexに追加されたのは、
    Cached treeという、Treeの状態を表す情報
    • Cached treeは、現在のGit Workspace内全て
    のtreeの名前・treeのSHA-1ハッシュ・
    subtreeの数・tree内のblobの数を持つ

    View Slide

  66. indexをみる
    • https://github.com/yoichi/git-cat-index
    • というツールを使うと、indexをいい感じ
    に見ることができる
    DIRC (dircache), 1 entries
    557db03de997c86a4a028e1ebd3a1ceb225be238 (stage:0) 100644 hello.txt
    TREE
    97b49d4c943e3715fe30f141cc6f27a8548cee0e (0/1)
    $ git_cat_index.py .git/index
    これがCached tree

    View Slide

  67. 3. gitは本当に差分を保存
    しているのか?

    View Slide

  68. 先にgit commitで出来た.git/の

    生成物をコミットしておく
    $ cd .git
    $ git add .
    $ git commit -m “Exec git commit”
    /Users/atsuya-sato/Desktop/git-inside-workshop
    $ pwd

    View Slide

  69. hello.txtを編集してadd &
    commitする
    $ cd ../
    $ git add hello.txt
    $ echo “Hello FUN” > hello.txt
    $ cat hello.txt
    Hello FUN
    Hello Worldを
    Hello FUNに編集
    $ git commit -m “Update hello.txt”
    [master 0741a4a] Update hello.txt
    1 file changed, 1 insertion(+), 1 deletion(-)
    commitオブジェクト

    (0741)ができた

    View Slide

  70. .gitの変更を見る
    $ cd .git
    $ git status -uall
    On branch master
    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git checkout -- <file>..." to discard changes in working directory)
    modified: COMMIT_EDITMSG
    modified: index
    modified: logs/HEAD
    modified: logs/refs/heads/master
    modified: refs/heads/master
    Untracked files:
    (use "git add <file>..." to include in what will be committed)
    objects/07/41a4a634a5c550e59ed013275ebea2b5bedef6
    objects/2d/ccf803893c8e418bdaa03f0c4af005517f8e88
    objects/70/2e500c6260d7caaf75f266ac27eb8215108f76
    一番上がcommit
    オブジェクト

    View Slide

  71. commitオブジェクト

    の中身を見る
    $ git cat-file -p 0741
    tree 702e500c6260d7caaf75f266ac27eb8215108f76
    parent 87a989174c548a6a8b0e78a017d00db3a4e16d12
    author atsuya-sato 1557813718 +0900
    committer atsuya-sato 1557813718 +0900
    Update hello.txt
    $ cd ../
    (702e)というtreeオブジェクトができているのが分かる

    View Slide

  72. treeオブジェクト

    の中身を見る
    $ git cat-file -p 702e
    100644 blob 2dccf803893c8e418bdaa03f0c4af005517f8e88 hello.txt
    先ほどとblobオブジェクトのSHA-1
    ハッシュが変わっているのが分かる

    View Slide

  73. blobオブジェクト

    の中身を見る
    $ cd .git
    $ zlib -d < objects/55/7db03de997c86a4a028e1eb

    d3a1ceb225be238
    blob 12Hello World
    $ zlib -d < objects/2d/ccf803893c8e418bdaa03f0
    c4af005517f8e88
    blob 10Hello FUN

    View Slide

  74. blobオブジェクト

    の中身を見る
    • 実はGitが保存しているのは差分ではなく、「スナップ
    ショット」
    • blobに関してはファイルデータそのものを保存する
    • オブジェクトファイルに対してSHA-1で生成した
    checksumをファイル名にしているので、ファイルに変
    更がなければ、新たなblobオブジェクトは作成されない
    • treeが持つsubtreeやblobが更新されると、新たなtreeオ
    ブジェクトが作成される

    View Slide

  75. Gitはスナップショットを保存しておいて、commitオブ
    ジェクトとcommitに紐づくtree/blobの生成によって

    バージョン管理をしている

    View Slide

  76. おまけ1: Gitの作り方

    View Slide

  77. Gitの作り方
    • Gitの内側を学ぶ
    • .gitをgit管理して挙動を見る
    • Gitの内側(https://git-scm.com/
    book/ja/v1/
    Git%E3%81%AE%E5%86%85%E
    5%81%B4)を見る

    View Slide

  78. Gitの作り方
    • Write yourself a Git

    (https://wyag.thb.lt/)をやる
    • Gitの作り方がPythonのソースコード付
    きで説明されている(ただし英語)
    • 上の記事を見るとinit, hash-object, cat-
    file, log, ls-tree, show-ref, tag, rev-
    parseが作れる

    View Slide

  79. 自分もSwiftで作ってみた
    https://github.com/natmark/Gift
    Write yourself a Gitのコマンド + add, commit

    まで実装した

    View Slide

  80. おまけ2: 紹介しなかった
    ディレクトリ

    View Slide

  81. 紹介しなかったファイル
    ・description gitwebがリポジトリーの情報を表示するのに使用
    ・config git config —localするときに読み書きされてるのがここ
    ・info/ info/excludeというファイルがあり、コミット対象外にしたいファイルを記述するのに
    使用(.gitignoreと異なり、他人と共有されない)
    ・hooks/ Gitの処理の各フェーズごとに自動的に実行されるスクリプトを設定するのに使用
    (例: pre-push)
    ・refs/ branchやtagが指しているコミットへの参照を保存

    View Slide

  82. おまけ3: indexの読み方

    View Slide

  83. indexを読む
    00000000: 4449 5243 0000 0002 0000 0001 5cda 3fb1
    00000010: 195f eaed 5cda 3fb1 195f eaed 0100 0004
    00000020: 008c a4c2 0000 81a4 0000 01f6 0000 0014
    00000030: 0000 000c 557d b03d e997 c86a 4a02 8e1e
    00000040: bd3a 1ceb 225b e238 0009 6865 6c6c 6f2e
    00000050: 7478 7400 5452 4545 0000 0019 0031 2030
    00000060: 0a97 b49d 4c94 3e37 15fe 30f1 41cc 6f27
    00000070: a854 8cee 0e94 aef3 b413 ed22 4737 8e4b
    00000080: 95c5 ea68 cafa 4937 f4
    DIRC (dircache), 1 entries
    557db03de997c86a4a028e1ebd3a1ceb225be238 (stage:0) 100644 hello.txt
    TREE
    97b49d4c943e3715fe30f141cc6f27a8548cee0e (0/1)

    View Slide

  84. indexを読む
    00000000: 4449 5243 0000 0002 0000 0001 5cda 3fb1
    00000010: 195f eaed 5cda 3fb1 195f eaed 0100 0004
    00000020: 008c a4c2 0000 81a4 0000 01f6 0000 0014
    00000030: 0000 000c 557d b03d e997 c86a 4a02 8e1e
    00000040: bd3a 1ceb 225b e238 0009 6865 6c6c 6f2e
    00000050: 7478 7400 5452 4545 0000 0019 0031 2030
    00000060: 0a97 b49d 4c94 3e37 15fe 30f1 41cc 6f27
    00000070: a854 8cee 0e94 aef3 b413 ed22 4737 8e4b
    00000080: 95c5 ea68 cafa 4937 f4

    View Slide

  85. indexを読む
    • Header
    00000000: 4449 5243 0000 0002 0000 0001
    Signature Format Entries
    D I R C
    (Dircache)
    2
    Indexファイルの

    フォーマット
    1
    Stageされてる
    ファイルの数

    View Slide

  86. • Index entry(1/2)
    indexを読む
    00000000: 5cda 3fb1
    00000010: 195f eaed 5cda 3fb1 195f eaed 0100 0004
    00000020: 008c a4c2 0000 81a4 0000 01f6 0000 0014
    00000030: 0000 000c
    created_at sec
    created_at msec updated_at msec
    updated_at sec deviceID
    inode mode uid gid
    file size
    12 bytes
    9217218 9217218 502 20
    16777220
    1557807025
    425716461 1557807025 425716461

    View Slide

  87. 00000030: 557d b03d e997 c86a 4a02 8e1e
    00000040: bd3a 1ceb 225b e238 0009 6865 6c6c 6f2e
    00000050: 7478 7400
    • Index entry(2/2)
    indexを読む
    SHA-1 Hash
    SHA-1 Hash
    557db03de997c86a4a028e1e
    bd3a1ceb225be238
    Flag File path
    File path zero padding
    hello.
    txt
    Flag: 0009!0000000000001001
    assume valid flag(1bit) | extended flag(1bit) | stageFlag(2bit) | nameLength(12bit)

    View Slide

  88. • Cached tree
    indexを読む
    00000050: 5452 4545 0000 0019 0031 2030
    00000060: 0a97 b49d 4c94 3e37 15fe 30f1 41cc 6f27
    00000070: a854 8cee 0e
    SHA-1 Hash
    SHA-1 Hash
    (LF)
    (Space)
    (NUL)
    Signature
    T R E E
    size
    25 bytes 1 0
    index entries
    count
    subtrees 

    count
    97b49d4c943e3715fe30f141cc6f27
    root tree以外は(LF)の後に
    ディレクトリ名が来る
    a8548cee0e

    View Slide

  89. 00000070: 94 aef3 b413 ed22 4737 8e4b
    00000080: 95c5 ea68 cafa 4937 f4
    • Checksum
    indexを読む
    • 117バイト目までのバイナリデータの
    SHA-1ハッシュ
    SHA-1 Hash
    SHA-1 Hash
    94aef3b413ed2247378e4b
    95c5ea68cafa4937f4

    View Slide

  90. indexの詳しい仕様
    SHA-1 Hash
    https://github.com/git/git/blob/master/
    Documentation/technical/index-format.txt

    View Slide