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

Git再入門

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for fhiyo fhiyo
April 14, 2023

 Git再入門

Avatar for fhiyo

fhiyo

April 14, 2023
Tweet

More Decks by fhiyo

Other Decks in Programming

Transcript

  1. ファイルシステムとしてのGit Git is a content-addressable filesystem. (Git Internals - Git

    Objects) - content-addressable なファイルシステム - 名前やpathを自由につけるのではなく、ファイルの内容に基づいてアドレスを計算し情報を格納す る - ファイルの内容が同一なら必ず同じアドレスになる - 情報を取り出せる - コミットというオブジェクトからある時点でのディレクトリの状態を復元できる - セキュリティ的な利点がある (ファイルの中身を変えるとアドレスも変わる ) 3
  2. 用語 - ワーキングツリー (ワーキングディレクトリ): Gitの管理対象にあるディレクトリ - インデックス (ステージングエリア): 次にコミットする内容を格納したファイル -

    リポジトリ: .gitディレクトリのこと - Gitオブジェクト: 管理対象のファイルやディレクトリなどのGit内部での表現 ※ 正確な定義が分からなかったのであくまで自分の理解 4
  3. ファイルの管理方法 - 以下のGitオブジェクトと呼ばれるオブジェクトで管理される - Blob: ファイルの内容を格納 - Tree: ディレクトリの内容を格納 -

    Commit: ワーキングツリーのルートを表す Treeへの参照 - Tag: Commitへのポインタ - (他にもあるが割愛) - Gitオブジェクトはzlib形式で圧縮→ .git/objects/ 以下にシリアライズしたGitオブ ジェクトをハッシュ化 (デフォルトの関数はSHA-1) した値をパスにして格納 - ハッシュ値がアドレスに対応する - CommitだけでなくBlobやTree, Tagも全部同じ方法で一緒くたに管理している 6
  4. Blob 8 - ファイルをzlib圧縮してヘッダをつけたバイナリファイル - ファイル名は無関係。内容が等しければ別ファイルでも同じ Blobオブジェクトになる - 新しいコミットを追加しても、変更のない Blobはそのまま

    →ストレージの節約になる "blob"<スペース><contentsのサイズ><ヌル文字><contents> ヘッダ (他のGitオブジェクトもほぼ同じ ) ボディ 圧縮前のフォーマット
  5. Tree - 直下にあるファイルのGitオブジェクトの情報を格納する - (パーミッション, 種別, ハッシュ値, ファイル名) の情報を各エントリに対して持つ -

    自身のハッシュ値はヘッダと各エントリの値を連結した文字列をハッシュ化して計算 9 $ git rev-parse HEAD^{tree} f149947b1322f06452ae580b103f7983f0bf6351 $ git cat-file -p f149947b1322f06452ae580b103f7983f0bf6351 040000 tree 556b6843a6a6a41572ad4e7371c09c743ae07a5e .circleci 100644 blob 3c6065443b72fb277382f6b6baad9233ee3b2f86 README.md 040000 tree 6401e939617ea7007eb97a21f170a28e58d5c883 front 040000 tree f3ac12bd3fc42f062bc581b9096349ed11c90908 infra 040000 tree 00eb0847a1bcdaec39901c8f9b80e6d1192188c1 rails ... ファイルパーミッション (的なもの) オブジェクトの種類 ハッシュ値 ファイル名
  6. 変更されたファイルの検出 - 配下にあるファイルのハッシュが変更されたらTreeのハッシュも変わる - ハッシュ値に変化がないノードから下は見なくてよいので楽 10 / /dir2 /dir1/a.txt /dir2/b.txt

    /dir2/c.txt 9e45451 60b70ed 69665dc ae772eb 943a16f /dir1 fe723bb /dir1/a.txt を編集 / /dir2 /dir1/a.txt /dir2/b.txt /dir2/c.txt 4cb9112 69665dc ae772eb 943a16f /dir1 323d00c 5eae772 ←skip! ※ 子のハッシュ値を使って親のハッシュ値を計算する木構造をマークル木という
  7. Commit - ある時点におけるワーキングツリーのスナップショット - ルートツリーを指す (ルートツリーのハッシュ値を含む) - 「親 (一つ前) のコミット」を指すことで変更の履歴を作る

    - バージョン管理システムとしての機能の核となる部分 - 自身のハッシュ値はルート Treeや親コミットのハッシュ値などを連結した文字列をハッシュ化して計 算 11 $ git rev-parse HEAD 4c6bf5c276d3b9e8c61a6254a7ba9fce04c57833 $ git cat-file -p 4c6bf5c276d3b9e8c61a6254a7ba9fce04c57833 tree d8e4cb183020293add52b2d3498c301f1e6d54a5 parent 4cb9112c8ad1d7588cfdd43c0c373d2ceb1e5c87 author fhiyo <[email protected]> 1681263933 +0900 committer fhiyo <[email protected]> 1681263993 +0900 add hogehoge file ルートTreeのハッシュ値 親コミットのハッシュ値 author, コミッタの情報 コミットメッセージ
  8. バージョンの管理 12 / /dir /a.txt /dir/b.txt /dir/c.txt : Commit :

    Tree : Blob ※ / はワーキングツリーのルートを表す 059e454 9e45451 60b70ed 69665dc ae772eb 943a16f main HEAD $ git add a.txt $ git add dir/{b.txt,c.txt} $ git commit -m "first commit"
  9. バージョンの管理 13 / / /dir /a.txt /dir/b.txt /dir/c.txt /dir/c.txt :

    Commit : Tree : Blob /dir ※ / はワーキングツリーのルートを表す 059e454 11db2f9 9e45451 db2f972 60b70ed 69665dc 40d9892 ae772eb 943a16f d27669a main HEAD # dir/c.txt を編集 $ git add dir/c.txt $ git commit -m "update dir/c.txt"
  10. バージョンの管理 14 ︙ … / / /dir /a.txt /dir/b.txt /dir/c.txt

    /dir/c.txt : Commit : Tree : Blob /dir ※ / はワーキングツリーのルートを表す 059e454 11db2f9 aa849b3 9e45451 db2f972 60b70ed 69665dc 40d9892 ae772eb 943a16f d27669a
  11. git cherry-pick は差分を計算して適用している - コミットが差分だと思っていると挙動を勘違いする - コミットをコピーしたわけではなく親との差分が同じになるように調整しているだけ 15 / /

    /a.txt 059e454 11db2f9 9e45451 db2f972 60b70ed /a.txt e320368 aaa aaa bbbbbb / / /a.txt a423b63 /a.txt a aaa a aaa bbbbbb … … a4b5d9a 5922f22 abb130d b75c84c 1cd6e72 git cherry-pick 11db2f9 で左右の差分が全く同じになるよう に新しいコミットができる 親が複数いるときは -m <parent-number> で対象の親 を指定できる HEAD