Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
たぶんもう怖くないGit ~Git内部の仕組み~
Slide 2
Slide 2 text
自己紹介 - 名前: 阿部 真之 - 仕事: 主にAndroidエンジニア - 最近はサーバサイド Kotlinの仕事も始めました - 趣味 - コーヒー、ビール、アニメ、ゲーム、読書、 etc… - Twitter: @marchin_1989
Slide 3
Slide 3 text
本日はqiitaで書いた記事の内容です
Slide 4
Slide 4 text
アジェンダ - バージョン管理システム(VCS)について - Gitオブジェクトとリファレンス - Gitオブジェクトとリファレンスの視点でgit操作をみる
Slide 5
Slide 5 text
ここで話さないこと - コミット間の差分の検出方法 - gitの設定
Slide 6
Slide 6 text
ここで話さないこと - コミット間の差分の検出方法 - gitの設定 => gitコマンドを打って、gitプログラムの処理が終わった後の、 gitのデータの最終結果にフォーカスする
Slide 7
Slide 7 text
そもそもバージョン管理システム(VCS) - 集中型 - CVS, Subversion, SVN - みんなで1つのリポジトリにネットワーク接続。 - 最新のソースコードを手元に持ってきて編集。 - 各自が中央のリポジトリに変更を直接反映する。 - 変更履歴を見たい場合は、中央リポジトリにアクセスする必要がある。 - 分散型(DVCS) - Git - 各自がリポジトリを持つ。 - リモートリポジトリにネットワーク接続不要 で、 各自のリポジトリで変更、履歴の確認ができる。 - 他の人に影響を与えず、各自のリポジトリで変更を反映できる。 - 例: 各自のローカルマシン内にリポジトリがある。 - リモートリポジトリに、後からまとめて変更を反映。 自分で送りたいものだけ共有できる。 集中型 分散型
Slide 8
Slide 8 text
Git - オープンソースの分散型バージョン管理システム。 - リーナス・トーバルズによって開発。 - Linuxカーネルの効率的な開発のために作られた。 - gitのソースコードもgitで管理されてる。 - 2005年12月21日リリース。
Slide 9
Slide 9 text
よくある疑問 - どうやってGitは履歴を管理してるんだ? - よくブランチみたいな複雑そうなものうまく動いてんな。 - ブランチ is 何?枝なの? - HEAD is 何? - detached headみたいなログが出たけど、これなに?
Slide 10
Slide 10 text
よくある疑問 - どうやってGitは履歴を管理してるんだ? - よくブランチみたいな複雑そうなものうまく動いてんな。 - ブランチ is 何?枝なの? - HEAD is 何? - detached headみたいなログが出たけど、これなに? => 毎日Git使ってるのに、よくわかってない。。。
Slide 11
Slide 11 text
git内部の仕組みを知っていると役立つこと - gitのコマンドを間違って実行してしまった時の対処 - 例 - 作業していたブランチを消してしまった。。 - revert、reset、rebaseなど使ったけど、期待した状態にならなかった。。
Slide 12
Slide 12 text
git内部の仕組みを知っていると役立つこと - gitのコマンドを間違って実行してしまった時の対処 - 例 - 作業していたブランチを消してしまった。。 - revert、reset、rebaseなど使ったけど、期待した状態にならなかった。。 => 戻したいけど、毎回なんとなくググってやってる。 合ってるのかよくわからないけど、okにしてませんか?
Slide 13
Slide 13 text
git内部の仕組みを知っていると役立つこと - gitのコマンドを間違って実行してしまった時の対処 - 例 - 作業していたブランチを消してしまった。。 - revert、reset、rebaseなど使ったけど、期待した状態にならなかった。。 => 戻したいけど、毎回なんとなくググってやってる。 合ってるのかよくわからないけど、okにしてませんか? => git内部の仕組みを知ることで、gitコマンドが何をやっているのか理解しやすい
Slide 14
Slide 14 text
gitのデータ保存の仕組み(いきなり結論) - gitは、オブジェクトモデルでデータを保存している。 - gitオブジェクトの集まりで、単なるDAG(有向非巡回グラフ)とポストイットで履歴を管理 している。 - DAG: Directed Acyclic Graph(有向非巡回グラフ) - https://ja.wikipedia.org/wiki/%E6%9C%89%E5%90%91%E9%9D%9E%E5%B7%A1%E5%9B %9E%E3%82%B0%E3%83%A9%E3%83%95 - コミットは差分ではなく、スナップショット。 - gitの数あるコマンドは、DAGのオブジェクトの追加、ポストイットの移動を行ってい るだけ。
Slide 15
Slide 15 text
キーワード - Gitオブジェクト - blob, tree, commit, tag - リファレンス - branch, HEAD, tag
Slide 16
Slide 16 text
キーワード - Gitオブジェクト - blob, tree, commit, tag - リファレンス - branch, HEAD, tag => Gitオブジェクト と リファレンスの存在を強く意識すると理解しやすいです。
Slide 17
Slide 17 text
ここからの説明の順番 1. Gitオブジェクトとリファレンスの説明 2. DAG(非巡回有向グラフ)全体を眺めて、gitコマンドでDAGがどうなるかまずざっくり 説明 3. さらにより詳しく、gitコマンドによって、Gitオブジェクトが作成される様子や、リファレ ンスが作成されたり、移動する様子をみる
Slide 18
Slide 18 text
gitオブジェクト
Slide 19
Slide 19 text
gitオブジェクト(objects) - すべてzlibライブラリで可逆圧縮されたもの。 - SHA-1ハッシュによって識別子がついている。 - オブジェクトは4種類。 - 「.git/objects」ディレクトリを見ると確認できる。 - イミュータブル。一度作られたらなかなか消えない。 ※アノテーションタグ hash: e732... hash: 4g35... hash: k35g... hash: 245f...
Slide 20
Slide 20 text
gitオブジェクト(objects) - すべてzlibライブラリで可逆圧縮されたもの。 - SHA-1ハッシュによって識別子がついている。 - オブジェクトは4種類。 - 「.git/objects」ディレクトリを見ると確認できる。 - イミュータブル。一度作られたらなかなか消えない。 ※アノテーションタグ hash: e732... hash: 4g35... hash: k35g... hash: 245f... リファレンスにも「tag」があ る。ややこしいので、リファレ ンスの時に一緒に見る。
Slide 21
Slide 21 text
gitオブジェクトは「.git/objects」以下にある
Slide 22
Slide 22 text
blobオブジェクト - ファイルデータ(テキストデータ、画像etc)の中身そのもの。 - ファイル名などの情報は含まれていない。
Slide 23
Slide 23 text
blobオブジェクト - ファイルデータ(テキストデータ、画像etc)の中身そのもの。 - ファイル名などの情報は含まれていない。 gitオブジェクトは、可逆圧縮されているので、普通 にファイルを開いても意味がない。 gitのコマンドで、gitオブジェクトの内容を表示するも のがある。 git cat-file -p
Slide 24
Slide 24 text
blobオブジェクト - ファイルデータ(テキストデータ、画像etc)の中身そのもの。 - ファイル名などの情報は含まれていない。 この出力が、blobオブジェクトの内容。 docker-compose.ymlの中身そのもの。 この出力に「docker-compose.yml」のファ イル名の情報はどこにもない。
Slide 25
Slide 25 text
treeオブジェクト - ディレクトリを表す。 - ファイル名、blobオブジェクト or 別のtreeオブジェクトへの参照を持っている。
Slide 26
Slide 26 text
treeオブジェクト - ディレクトリを表す。 - ファイル名、blobオブジェクト or 別のtreeオブジェクトへの参照を持っている。 5r8d20 また、git cat-fileコマンドで、 内容を見てみる。
Slide 27
Slide 27 text
treeオブジェクト - ディレクトリを表す。 - ファイル名、blobオブジェクト or 別のtreeオブジェクトへの参照を持っている。 5r8d20 これがtreeオブジェクトの内 容。
Slide 28
Slide 28 text
treeオブジェクト - ディレクトリを表す。 - ファイル名、blobオブジェクト or 別のtreeオブジェクトへの参照を持っている。 この一行に注目してみる。 5r8d20
Slide 29
Slide 29 text
treeオブジェクト - ディレクトリを表す。 - ファイル名、blobオブジェクト or 別のtreeオブジェクトへの参照を持っている。 gitオブジェクトのタイプ blobもしくは、tree。 5r8d20
Slide 30
Slide 30 text
treeオブジェクト - ディレクトリを表す。 - ファイル名、blobオブジェクト or 別のtreeオブジェクトへの参照を持っている。 ディレクトリ内のgitオブジェクトのハッシュ 値。 5r8d20
Slide 31
Slide 31 text
treeオブジェクト - ディレクトリを表す。 - ファイル名、blobオブジェクト or 別のtreeオブジェクトへの参照を持っている。 ファイル名やディレクトリ名。 5r8d20
Slide 32
Slide 32 text
treeオブジェクト - ディレクトリを表す。 - ファイル名、blobオブジェクト or 別のtreeオブジェクトへの参照を持っている。 5r8d20 0be9e3 c5ac20 93db38 Procfile README.md app この3つを、図に当てはめてみると ...
Slide 33
Slide 33 text
treeオブジェクト - ディレクトリを表す。 - ファイル名、blobオブジェクト or 別のtreeオブジェクトへの参照を持っている。 5r8d20 0be9e3 c5ac20 93db38 Procfile README.md app 参照先のgitオブジェクトと、タイプ、それぞ れのファイル名(ディレクトリ名)を保持して いることわかる。
Slide 34
Slide 34 text
treeオブジェクト - ディレクトリを表す。 - ファイル名、blobオブジェクト or 別のtreeオブジェクトへの参照を持っている。 以降出てくる「矢印」は参 照の方向です。
Slide 35
Slide 35 text
- 以下の情報を持つ。 - トップレベルのtreeオブジェクトへの参照 - コミットしたユーザの情報 - タイムスタンプ - コミットメッセージ - 親コミットへの参照 commitオブジェクト
Slide 36
Slide 36 text
- 以下の情報を持つ。 - トップレベルのtreeオブジェクトへの参照 - コミットしたユーザの情報 - タイムスタンプ - コミットメッセージ - 親コミットへの参照 commitオブジェクト 1aaa また、git cat-fileコマンドで、 内容を見てみる。
Slide 37
Slide 37 text
- 以下の情報を持つ。 - トップレベルのtreeオブジェクトへの参照 - コミットしたユーザの情報 - タイムスタンプ - コミットメッセージ - 親コミットへの参照 commitオブジェクト 1aaa これがcommitオブジェクトの 内容。
Slide 38
Slide 38 text
- 以下の情報を持つ。 - トップレベルのtreeオブジェクトへの参照 - コミットしたユーザの情報 - タイムスタンプ - コミットメッセージ - 親コミットへの参照 commitオブジェクト 1aaa トップレベルのtreeオブジェク トを指している。 5f8d20
Slide 39
Slide 39 text
- 以下の情報を持つ。 - トップレベルのtreeオブジェクトへの参照 - コミットしたユーザの情報 - タイムスタンプ - コミットメッセージ - 親コミットへの参照 commitオブジェクト 1aaa 親commitオブジェクトのハッ シュ値を指している。 e6c06e
Slide 40
Slide 40 text
- 以下の情報を持つ。 - トップレベルのtreeオブジェクトへの参照 - コミットしたユーザの情報 - タイムスタンプ - コミットメッセージ - 親コミットへの参照 commitオブジェクト 1aaa 親がないcommitは、initial commit。 親が2つあるのは?(問題) e6c06e
Slide 41
Slide 41 text
- 以下の情報を持つ。 - トップレベルのtreeオブジェクトへの参照 - コミットしたユーザの情報 - タイムスタンプ - コミットメッセージ - 親コミットへの参照 commitオブジェクト 1aaa 親がないcommitは、initial commit。 親が2つあるのは?(問題) e6c06e マージコミット(正解)
Slide 42
Slide 42 text
- 以下の情報を持つ。 - トップレベルのtreeオブジェクトへの参照 - コミットしたユーザの情報 - タイムスタンプ - コミットメッセージ - 親コミットへの参照 commitオブジェクト 1aaa コミットしたユーザの情報。
Slide 43
Slide 43 text
- 以下の情報を持つ。 - トップレベルのtreeオブジェクトへの参照 - コミットしたユーザの情報 - タイムスタンプ - コミットメッセージ - 親コミットへの参照 commitオブジェクト 1aaa コミットメッセージ
Slide 44
Slide 44 text
- 以下の情報を持つ。 - トップレベルのtreeオブジェクトへの参照 - コミットしたユーザの情報 - タイムスタンプ - コミットメッセージ - 親コミットへの参照 commitオブジェクト 1aaa コミットから辿れば、 この時点の プロジェクトを再構成できる。
Slide 45
Slide 45 text
つまりこういう有向非巡回グラフ
Slide 46
Slide 46 text
つまりこういう有向非巡回グラフ 矢印は依存の方向。 サイクルがない、向きを持ったグ ラフ。
Slide 47
Slide 47 text
gitオブジェクトの作り方 - ハッシュ値 - ヘッダー: オブジェクトのタイプ (blob, tree, commit) + スペース + コンテンツのサイズ + ヌルバイト - 「ヘッダー」と「コンテンツ」を連結、 sha1 hashをとったもの。 - gitオブジェクト - 「ヘッダー」と「コンテンツ」を連結、 zlibで可逆圧縮したもの。
Slide 48
Slide 48 text
gitオブジェクトの作り方 - ハッシュ値 - ヘッダー: オブジェクトのタイプ (blob, tree, commit) + スペース + コンテンツのサイズ + ヌルバイト - 「ヘッダー」と「コンテンツ」を連結、 sha1 hashをとったもの。 - gitオブジェクト - 「ヘッダー」と「コンテンツ」を連結、 zlibで可逆圧縮したもの。 出典: git documentation https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-Git%E 3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88 ハッシュ値、gitオブジェ クトを作ってみる。
Slide 49
Slide 49 text
gitオブジェクトの作り方 - ハッシュ値 - ヘッダー: オブジェクトのタイプ (blob, tree, commit) + スペース + コンテンツのサイズ + ヌルバイト - 「ヘッダー」と「コンテンツ」を連結、 sha1 hashをとったもの。 - gitオブジェクト - 「ヘッダー」と「コンテンツ」を連結、 zlibで可逆圧縮したもの。 出典: git documentation https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-Git%E 3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88 コンテンツ
Slide 50
Slide 50 text
gitオブジェクトの作り方 - ハッシュ値 - ヘッダー: オブジェクトのタイプ (blob, tree, commit) + スペース + コンテンツのサイズ + ヌルバイト - 「ヘッダー」と「コンテンツ」を連結、 sha1 hashをとったもの。 - gitオブジェクト - 「ヘッダー」と「コンテンツ」を連結、 zlibで可逆圧縮したもの。 出典: git documentation https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-Git%E 3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88 コンテンツ ヘッダー
Slide 51
Slide 51 text
gitオブジェクトの作り方 - ハッシュ値 - ヘッダー: オブジェクトのタイプ (blob, tree, commit) + スペース + コンテンツのサイズ + ヌルバイト - 「ヘッダー」と「コンテンツ」を連結、 sha1 hashをとったもの。 - gitオブジェクト - 「ヘッダー」と「コンテンツ」を連結、 zlibで可逆圧縮したもの。 出典: git documentation https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-Git%E 3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88 ヘッダー コンテンツ ヘッダー+コンテンツ
Slide 52
Slide 52 text
gitオブジェクトの作り方 - ハッシュ値 - ヘッダー: オブジェクトのタイプ (blob, tree, commit) + スペース + コンテンツのサイズ + ヌルバイト - 「ヘッダー」と「コンテンツ」を連結、 sha1 hashをとったもの。 - gitオブジェクト - 「ヘッダー」と「コンテンツ」を連結、 zlibで可逆圧縮したもの。 出典: git documentation https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-Git%E 3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88 ヘッダー コンテンツ ヘッダー+コンテンツ ハッシュ値
Slide 53
Slide 53 text
gitオブジェクトの作り方 - ハッシュ値 - ヘッダー: オブジェクトのタイプ (blob, tree, commit) + スペース + コンテンツのサイズ + ヌルバイト - 「ヘッダー」と「コンテンツ」を連結、 sha1 hashをとったもの。 - gitオブジェクト - 「ヘッダー」と「コンテンツ」を連結、 zlibで可逆圧縮したもの。 出典: git documentation https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-Git%E 3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88 ヘッダー コンテンツ ヘッダー+コンテンツ ハッシュ値 gitオブジェクト
Slide 54
Slide 54 text
gitオブジェクトの作り方 - ハッシュ値 - ヘッダー: オブジェクトのタイプ (blob, tree, commit) + スペース + コンテンツのサイズ + ヌルバイト - 「ヘッダー」と「コンテンツ」を連結、 sha1 hashをとったもの。 - gitオブジェクト - 「ヘッダー」と「コンテンツ」を連結、 zlibで可逆圧縮したもの。 出典: git documentation https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-Git%E 3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88 ヘッダー コンテンツ ヘッダー+コンテンツ ハッシュ値 gitオブジェクト 【重要】 「ヘッダー」と「コンテンツ」が同じ内容なら、 同じgitオブジェクト、同じハッシュ値になる。
Slide 55
Slide 55 text
gitオブジェクト ※アノテーションタグ hash: e732... hash: 4g35... hash: k35g... hash: 245f... 以上、gitオブジェクトでした。 タグはリファレンスで説明します。
Slide 56
Slide 56 text
リファレンス
Slide 57
Slide 57 text
リファレンス(refs) - commitオブジェクトのポインタ - commitオブジェクトのハッシュ値を指している - 簡単に指し示す先を変更できる(ポストイットみたいに) - 注意: tagはできない - 「.git/refs」や、「.git/HEAD」で確認できる。 - 3種類
Slide 58
Slide 58 text
これも 「.git」以下で確認できる。 リファレンス(refs)
Slide 59
Slide 59 text
これも 「.git」以下で確認できる。 リファレンス(refs) branch
Slide 60
Slide 60 text
これも 「.git」以下で確認できる。 リファレンス(refs) HEAD
Slide 61
Slide 61 text
これも 「.git」以下で確認できる。 リファレンス(refs) tag
Slide 62
Slide 62 text
branch - コミットを指す単純なポインタ。 - remoteのブランチも一緒。
Slide 63
Slide 63 text
branch - コミットを指す単純なポインタ。 - remoteのブランチも一緒。 「.git/refs/」以下にある。
Slide 64
Slide 64 text
branch - コミットを指す単純なポインタ。 - remoteのブランチも一緒。 ローカルのブランチ
Slide 65
Slide 65 text
branch - コミットを指す単純なポインタ。 - remoteのブランチも一緒。 remoteのブランチ
Slide 66
Slide 66 text
branch - コミットを指す単純なポインタ。 - remoteのブランチも一緒。 .git/refs/heads/main ブランチの 内容を見てみる。 ※gitオブジェクトと違い、リファレ ンスは圧縮されてない。
Slide 67
Slide 67 text
branch - コミットを指す単純なポインタ。 - remoteのブランチも一緒。 「main」ブランチは、commitの ハッシュを指している。 1aaa
Slide 68
Slide 68 text
HEAD - 現在チェックアウトしている、リファレンスを指す。 - つまり、リファレンスのリファレンス。
Slide 69
Slide 69 text
HEAD - 現在チェックアウトしている、リファレンスを指す。 - つまり、リファレンスのリファレンス。 HEADは、 「refs/heads/main」ファイ ルを指している。
Slide 70
Slide 70 text
HEAD - 現在チェックアウトしている、リファレンスを指す。 - つまり、リファレンスのリファレンス。 - 直接commitオブジェクトを参照する時もある。detached HEAD 。 リファレンスではなく、 commitオブ ジェクトを直接指せる。これが detached HEAD
Slide 71
Slide 71 text
tag - 軽量タグ - コミットを参照するリファレンス。 2種類あるが、まず1つ目。
Slide 72
Slide 72 text
tag - 軽量タグ - コミットを参照するリファレンス。 「.git/refs/tags」以下にある。 commitオブジェクトのハッシュ値を 指している。 これは軽量タグ。 aee092
Slide 73
Slide 73 text
tag - 軽量タグ - コミットを参照するリファレンス。 - アノテートタグ - tagオブジェクト(gitオブジェクト)へのリファレンス。 アノテートタグ(リファレンス)
Slide 74
Slide 74 text
tag - 軽量タグ - コミットを参照するリファレンス。 - アノテートタグ - tagオブジェクト(gitオブジェクト)へのリファレンス。 - tagオブジェクトは、commitオブジェクトへの参照を持つ。 アノテートタグ(リファレンス) tagオブジェクト(gitオブジェクト)
Slide 75
Slide 75 text
tag - 軽量タグ - コミットを参照するリファレンス。 - アノテートタグ - tagオブジェクト(gitオブジェクト)へのリファレンス。 - tagオブジェクトは、commitオブジェクトへの参照を持つ。 - 軽量タグは、コミットのハッシュしか指せないが、 tagオブジェクトでアノテート(注釈)情報を保持できる アノテートタグ(リファレンス) tagオブジェクト(gitオブジェクト)
Slide 76
Slide 76 text
tag - 軽量タグ - コミットを参照するリファレンス。 - アノテートタグ - tagオブジェクト(gitオブジェクト)へのリファレンス。 - tagオブジェクトは、commitオブジェクトへの参照を持つ。 - 軽量タグは、コミットのハッシュしか指せないが、 tagオブジェクトでアノテート(注釈)情報を保持できる アノテートタグ(リファレンス) tagオブジェクト(gitオブジェクト) a3da72 tagオブジェクトの内容(コンテンツ) 1aaa21
Slide 77
Slide 77 text
Gitオブジェクトとリファレンス - ここまでで、Gitオブジェクトとリファレンスの説明をしました
Slide 78
Slide 78 text
Gitオブジェクトとリファレンス - ここまでで、Gitオブジェクトとリファレンスの説明をしました - DAG(非巡回有向グラフ)全体を眺めて、gitコマンドでDAGがどうなるかまずざっくり 説明します
Slide 79
Slide 79 text
Gitオブジェクトとリファレンス - ここまでで、Gitオブジェクトとリファレンスの説明をしました - DAG(非巡回有向グラフ)全体を眺めて、gitコマンドでDAGがどうなるかまずざっくり 説明します - 後で、さらにより詳しく、gitコマンドによって、Gitオブジェクトが作成される様子や、リ ファレンスが作成されたり、移動する様子をみる
Slide 80
Slide 80 text
左の図の状況を考える。 いくつかコミットされ、ブランチなど のリファレンスがある。
Slide 81
Slide 81 text
HEADの現在地
Slide 82
Slide 82 text
別のブランチにチェック アウトしてみる
Slide 83
Slide 83 text
No content
Slide 84
Slide 84 text
HEADの指すブランチが 変わる。
Slide 85
Slide 85 text
HEADが指すコミットの状態(スナッ プショット)に、ワーキングディレクトリ が変更される。
Slide 86
Slide 86 text
ヘッドを元の場所に戻した。 次に、新しくコミットしてみる。
Slide 87
Slide 87 text
No content
Slide 88
Slide 88 text
新しいcommit(Gitオブジェクト) ができた。 また、mainブランチ(リファレン ス)が移動する。
Slide 89
Slide 89 text
HEADは元からmainブランチを 参照していたので、間接的に新 しいcommitを指すことになる。
Slide 90
Slide 90 text
以上、gitの内部の仕組みでした - GitオブジェクトでDAGを作り、リファレンスで参照しているだけ。 - 意外とシンプル。
Slide 91
Slide 91 text
gitオブジェクトとリファレンスの視点でgit操作を見る - gitコマンドによって、Gitオブジェクトが作成される様子や、リファレンスが作成され たり、移動する様子をみる。 - 確認するgitコマンド - git init - git add - git commit - git log - git branch - git checkout - git clone - git fetch - git merge(fast forward, non fast forward) - git rebase ※コンフリクトは起きない前提です
Slide 92
Slide 92 text
新しいまっさらなディレクトリ gitdemoを用意。 git initする。
Slide 93
Slide 93 text
git管理開始
Slide 94
Slide 94 text
.git/objects/ 以下を確認 してみる。
Slide 95
Slide 95 text
初期化した直後は、 info, packディレクトリのみ
Slide 96
Slide 96 text
hello1.txtを作成
Slide 97
Slide 97 text
中身を確認。 「hello1」1行の内容。
Slide 98
Slide 98 text
addしてステージングす る
Slide 99
Slide 99 text
再度、.git/objects/ 以下を確 認。
Slide 100
Slide 100 text
Gitオブジェクトができる。 注: ハッシュ値は先頭2文字 がディレクトリ名になる
Slide 101
Slide 101 text
git cat-fileコマンドでGitオブ ジェクトの中身を確認。 これがblobオブジェクト。 hello1.txtのコンテンツの中 身だけ持っている。
Slide 102
Slide 102 text
DAGでは、blobのみできてい る状態。
Slide 103
Slide 103 text
commitしてみる。
Slide 104
Slide 104 text
Gitオブジェクトが増 える
Slide 105
Slide 105 text
b321cd のハッシュの中身を確 認。 これはcommitオブジェクト。
Slide 106
Slide 106 text
DAGでは、このオブジェクト。
Slide 107
Slide 107 text
f97e7a のハッシュの中身を確認。 これはtreeオブジェクト。
Slide 108
Slide 108 text
DAGでは、このオブジェクト。
Slide 109
Slide 109 text
commitすると、この2つのGitオブ ジェクトできた。
Slide 110
Slide 110 text
リファレンスは、masterとHEAD ができる。 HEADはmasterを指していて、 masterはcommitオブジェクト (b321cd)を指している。
Slide 111
Slide 111 text
ディレクトリを作成。
Slide 112
Slide 112 text
dir配下に、hello2.txtと hello3.txt を作成。
Slide 113
Slide 113 text
ワーキングディレクトリ の状態。
Slide 114
Slide 114 text
両方ともaddする。
Slide 115
Slide 115 text
中身を確認。 2つblobができる。
Slide 116
Slide 116 text
DAGはここができてい る。
Slide 117
Slide 117 text
コミットしてみる。
Slide 118
Slide 118 text
この3つのGitオブジェク トができた。
Slide 119
Slide 119 text
Commitオブジェクトが作成される。 masterブランチが移動し、HEADはmasterを 指しているので、同じコミットを指す。
Slide 120
Slide 120 text
新しくできたCommitオブ ジェクトの中身を確認。
Slide 121
Slide 121 text
トップレベルのtreeを参照 している。
Slide 122
Slide 122 text
トップレベルのtreeの中身 を確認。
Slide 123
Slide 123 text
子に持つtreeとblobの参照と、 ファイル名(ディレクトリ名)を 持っている。
Slide 124
Slide 124 text
ここで注意。 ハッシュ値が同じ。実はこの2つは同じもの で、別のtreeから参照されている。 ※図(DAG)がわかりづらくなるので、あえて 分けて書いている。 変更がないgitオブジェクトは、commitの度に コピーされるわけではない。 新しいcommitでも、同じgitオブジェクトを参 照している。 =
Slide 125
Slide 125 text
ここで注意。 ハッシュ値が同じ。実はこの2つは同じもの で、別のtreeから参照されている。 ※図(DAG)がわかりづらくなるので、あえて 分けて書いている。 変更がないgitオブジェクトは、commitの度に コピーされるわけではない。 新しいcommitでも、同じgitオブジェクトを参 照している。 = gitオブジェクトは、圧縮されて いるし、中身が同じ別の gitオ ブジェクトは作成されないの で、データ量の削減にもなって いる。
Slide 126
Slide 126 text
git logで確認してみる。 右下のDAGの図とHEAD、masterブ ランチが一致している。
Slide 127
Slide 127 text
ブランチを作成する。
Slide 128
Slide 128 text
またgit logを実行してみると、「 foo」ブ ランチが作成されていて、 3498e2の ハッシュ値のcommitを指している。
Slide 129
Slide 129 text
hello1.txtを修正してみる。
Slide 130
Slide 130 text
もう1行hello1が追加された。
Slide 131
Slide 131 text
addして、commitする。
Slide 132
Slide 132 text
Commitオブジェクトが作成される。 masterブランチが移動。(HEADも追 従)
Slide 133
Slide 133 text
前のhello1.txtのコンテンツの中身を 表していたblobとは別に、新しいblob ができる。
Slide 134
Slide 134 text
このblobが編集されるわけではない。 (Gitオブジェクトはイミュータブル) 前のhello1.txtのコンテンツの中身を 表していたblobとは別に、新しいblob ができる。
Slide 135
Slide 135 text
参照していた子のblobが変更されるので、 topレベルのtreeも別に、新しいtreeオブジェ クトができる。 参照する子供のgitオブジェクトが変わると、 芋づる式に新しいgitオブジェクトができる。
Slide 136
Slide 136 text
ただし、子のtreeである、77ffd0のtree以 下は変更がないため同じものが参照され る。
Slide 137
Slide 137 text
fooブランチにチェックアウトしてみる。
Slide 138
Slide 138 text
HEADがfooブランチを指すようにな る。
Slide 139
Slide 139 text
ワーキングディレクトリは前の Commitオ ブジェクトの状態になるので、 hello1.txt が1行になっている。
Slide 140
Slide 140 text
以降のgitコマンドはDAGだけみていきます
Slide 141
Slide 141 text
git clone リモートリポジトリがある状態。
Slide 142
Slide 142 text
git clone 自分のローカルマシン。リモートリポジトリを cloneす る。
Slide 143
Slide 143 text
git clone リモートリポジトリの gitオブジェクト、 リファレンスが取得された。
Slide 144
Slide 144 text
git clone HEADが指すブランチのコミットの状態に、 作業ツリーが展開される
Slide 145
Slide 145 text
git fetch xxx xxx yyy yyy zzz リモートリポジトリの方が、 commitオブジェクトが作成さ れていて、mainブランチが進 んでいる状態。 さらにdevelopブランチが作 成されている。 git fetchしてみる。
Slide 146
Slide 146 text
git fetch xxx xxx yyy yyy zzz git fetchを行うと、リモートリ ポジトリのgitオブジェクトやリ ファレンスがローカルリポジ トリに反映される。 ただし、ローカルのbranchや HEADのリファレンスは動か ない。 zzz
Slide 147
Slide 147 text
git merge(fast-forward) HEADはmainを指している状 態。 「git merge develop」 を実行 してみる。
Slide 148
Slide 148 text
git merge(fast-forward) branchリファレンス(main)が移動 するだけ。 commitオブジェクトは作成され ない。
Slide 149
Slide 149 text
git merge(non-fast-forward) ローカルでcommitオブジェクトを作っ たとする。 リモートにはまだプッシュしておらず、 origin/mainは一つ前のコミットを指し ている。 この状態でfetchする。(まだ状況説明 が続く)
Slide 150
Slide 150 text
git merge(non-fast-forward) リモートリポジトリでコミットが作られて おり、origin/mainがそのコミットを参照 している状態になった。
Slide 151
Slide 151 text
git merge(non-fast-forward) リモートリポジトリの新しい変更 (commitオブジェクト) を、ローカルのbranchに取り込みたい。 gitオブジェクトはイミュータブルなため、我々にできる ことは、gitオブジェクトの追加か、 リファレンスの移動しかできない。 リファレンスの移動を試そうにも、つけて貼るしかでき ないため、両方の変更を取り込めない。
Slide 152
Slide 152 text
git merge(non-fast-forward) リモートリポジトリの新しい変更 (commitオブジェクト) を、ローカルのbranchに取り込みたい。 gitオブジェクトはイミュータブルなため、我々にできる ことは、gitオブジェクトの追加か、 リファレンスの移動しかできない。 リファレンスの移動を試そうにも、つけて貼るしかでき ないため、両方の変更を取り込めない。 新しいcommitオブジェクトを作 成するしかない。
Slide 153
Slide 153 text
git merge(non-fast-forward) 「git merge origin/master」を実行する。
Slide 154
Slide 154 text
git merge(non-fast-forward) 新しいcommitオブジェクトが作成される。 親commitを2つ参照しているという情報が 残る。 さらに、branch(main)が移動する。 これがnon-fast-forward merge。
Slide 155
Slide 155 text
git rebase HEADはmainにあり、mainはこの commitオブジェクトを指している。
Slide 156
Slide 156 text
git rebase origin/mainは下のcommitオブジェクトを指 している。
Slide 157
Slide 157 text
git rebase non fast forward mergeすれば変更は取り 込める。 しかし、ステッチ(縫い目)の様な状態になっ てしまうため、やりたくない。
Slide 158
Slide 158 text
git rebase 「git rebase origin/main」を実行する。
Slide 159
Slide 159 text
git rebase 新しいcommitオブジェクトができる。 branch(main)が移動する。 gitオブジェクトはイミュータブルなので、前 のcommitオブジェクトが修正されるわけで はない。
Slide 160
Slide 160 text
git rebase rebaseしても前のcommitオブジェクトは 残っている。branchを移動すれば、元の状 態に戻せる。 ※gitオブジェクトは、どこからも参照されな いと、適切なタイミングで、 gitのガベージコ レクションで消される。
Slide 161
Slide 161 text
まとめ - gitのデータストアはgitオブジェクトの集まり。 - 単なるDAGとポストイットで履歴を管理している。 - コミットは差分ではなく、スナップショット。 - commitオブジェクトから、tree, blobと参照を辿ることで、その時点の履歴を復元し ている。 - gitの数あるコマンドは、DAGのオブジェクトの追加、ポストイットの移動を行ってい るだけ。
Slide 162
Slide 162 text
参考文献 - Git for Computer Scientists - https://eagain.net/articles/git-for-computer-scientists/ - Gitの内側 - gitオブジェクト - https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-Git%E3%82%AA%E3%83%96%E3 %82%B8%E3%82%A7%E3%82%AF%E3%83%88 - Gitの参照 - https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-Git%E3%81%AE%E5%8F%82%E7 %85%A7 - コミットはスナップショットであり差分ではない - https://github.blog/jp/2021-01-06-commits-are-snapshots-not-diffs/
Slide 163
Slide 163 text
ご清聴ありがとうございました!