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

Git 研修 Basic【MIXI 25新卒技術研修】

Git 研修 Basic【MIXI 25新卒技術研修】

本スライドは、MIXIの2025年度新卒向け技術研修で使用された資料です。
 
MIXI 2025新卒技術研修
『Git 研修 Basic』
  
▼リポジトリ
https://github.com/mixigroup/2025BeginnerTrainingGit
▼動画
https://youtu.be/DTY3RBkXQBA
 
───────────────────────────────
※皆様へのお願い※ 資料・動画・リポジトリのご利用について
───────────────────────────────
公開している資料や動画は、是非、勉強会や社内の研修などにご自由にお使いいただければと思いますが、以下のような場でのご利用はご遠慮ください。
- 受講者から参加費や授業料など金銭を集めるような場での利用
(会場費や飲食費など勉強会の運営に必要な実費を集める場合は問題ありません)
- 出典を削除または改変しての利用

Avatar for MIXI ENGINEERS

MIXI ENGINEERS PRO

April 15, 2025
Tweet

Video

More Decks by MIXI ENGINEERS

Other Decks in Technology

Transcript

  1. 22 ©MIXI 講師紹介 太⽥ 理⽃ おおた りと 2024年度新卒⼊社 デジタルエンターテインメントオペレーションズ本部 モンスト開発部

    クライアント2グループ 業務: C++、Unity、アウトゲーム開発 など 趣味: 最近ダーツ始めました 好きなGitコマンド: git commit --amend 得意なこと: 漫画のセリフクイズ、ご飯沢⼭⾷べる 苦⼿なこと: ⾷欲の我慢
  2. 33 ©MIXI 講師紹介 久⽥ 将成 ひさだ まさなり 2022年度新卒⼊社 ライブエクスペリエンス事業本部 ファンコミュニケーション部

    Fansta開発グループ 業務: Ruby on Rails 、Next.js 、Flutter など 趣味: Rust など 好きなGitコマンド: git rebase 得意なこと: コンフリクトを起こすこと、夜更かし 苦⼿なこと: コンフリクトの解消、早起き
  3. 4 ©MIXI タイムテーブル(予定) 10:30 - 12:00 Git(基礎 / 内部構造) 12:00

    - 13:00 お昼休憩 13:00 - 14:00 Git(内部構造続き/チーム開発について) 14:20 - 18:00 Git Challenge
  4. 5 ©MIXI ⽬次 1. Gitとは 2. Gitの基本的な使い⽅ 3. ブランチの使⽤ 4.

    歴史の改変 5. その他便利機能 基礎編 1. Gitオブジェクト 2. コミットの仕組み 3. resetの仕組み 内部構造編
  5. 10 ©MIXI Gitとは Gitを使⽤したバージョン管理 書類.pdf 04/02 15:00 書類.pdf 04/03 10:00

    書類.pdf 04/01 12:00 書類.pdf 04/02 13:00 最新版 初稿 差分が出せたり 好きな版に戻れたり この他にもチーム開発に便利な機能がたくさん!
  6. 13 ©MIXI Gitの基本的な使い⽅ はじめにリポジトリ(repository)を作る Gitでバージョン管理したいディレクトリに移動してから $ git init 以下のように表⽰されたら成功! Initialized

    empty Git repository in ディレクトリパス このディレクトリ内がGitが管理する範囲になり、これをリポジトリと呼ぶ ちなみに 既存のリポジトリで作業を始める場合はクローン(clone)する $ git clone リポジトリURL 参照: git-init Documentation git-clone Documentation もっとちなみに リポジトリ直下には .git というディレクトリが作られる 詳しくは内部構造編で!
  7. 14 ©MIXI Gitの基本的な使い⽅ Gitでは「コミット(commit)」という単位で変更を保存する 書類.pdf 04/01 12:00 コミット 書類.pdf 04/02

    13:00 コミット 書類.pdf 04/02 15:00 コミット 変更をコミット対象にする(ステージング) ステージングした変更でコミットする $ git add ファイル名 $ git commit 書類.pdf 04/03 10:00 コミット 全部なら -A オプション 参照: git-add Documentation git-commit Documentation
  8. 16 ©MIXI Gitの基本的な使い⽅ コミットログを⾒てみる $ git log --oneline --graph bca877d40

    最初のコミット 6aa4aa7ae 2番⽬のコミット 4e62a7326 3番⽬のコミット コミットID コミットメッセージ コミットIDはコミットを⼀意に識別するID コマンド内でコミットを指定する場合に使ったりする 例えばコミットの詳細を⾒るには $ git show コミットID 他にもコミット間の差分を⾒るには $ git diff コミットID1 コミットID2 ちなみに 最後に ^ をつけるとその1つ前のコミット、 HEAD を指定すると今いるコミットを⽰す [HEAD] もっとちなみに 参照: git-log Documentation git-show Documentation git-diff Documentation コミットID部分は正確には参照(refs)も可 後述するブランチとかタグとか
  9. 18 ©MIXI Gitの基本的な使い⽅ 別のコミットに戻りたいときはチェックアウト(checkout) $ git checkout コミットID $ git

    switch コミットID --detach もしくは EXPERIMENTAL ファイルを別のコミット時点に戻したいときもチェックアウト $ git checkout コミットID ファイル名 $ git restore ファイル名 -s コミットID EXPERIMENTAL もしくは 参照: git-checkout Documentation git-switch Documentation Git - git-restore Documentation
  10. 19 ©MIXI Gitの基本的な使い⽅ コミットを打ち消したいときはリバート(revert) 指定したコミットと逆のコミットを追加する 1 Hello, World! 2 1

    Hello, World! 2 Hello, MIXI! 3 MIXIを追加 1 Hello, World! 2 Hello, MIXI! 3 revert Revert <MIXIを追加> コミットをリバートする $ git revert コミットID 参照: git-revert Documentation
  11. 20 ©MIXI Gitの基本的な使い⽅ タグ(tag)機能を使うと特定のコミットに⽬印を付けられる $ git tag タグ名 コミットID version1.2

    version1.1 version1.0 リリースしたらバージョン名のタグを作る運⽤も多い印象 タグ名はコミットIDと同じように使える $ git switch タグ名 --detach $ git show タグ名 タグのついたコミットに移動するなら タグのついたコミットの詳細を⾒るなら 参照: git-tag Documentation
  12. 23 ©MIXI main develop ブランチの使⽤ まずは develop という名前でブランチを作ってみる $ git

    branch develop bca877d40 Commit 1 最初はmainやmasterという名前のブランチが作られている ブランチの⼀覧を確認してみる $ git branch * main develop 参照: git-branch Documentation
  13. 24 ©MIXI develop ブランチの使⽤ まずは develop という名前でブランチを作ってみる $ git branch

    develop bca877d40 Commit 1 main 最初はmainやmasterという名前のブランチが作られている ブランチの⼀覧を確認してみる $ git branch * main develop develop ブランチに移動してみる $ git checkout develop または $ git switch develop develop 今いるブランチを確認してみる $ git branch main * develop 参照: git-branch Documentation
  14. 26 ©MIXI ブランチの使⽤ コミットを追加してみる $ git commit 2a673e714 Commit 1

    main f20100b9e Commit on develop develop 2f8ff17f6 Commit on main main 仮にmainにコミットが増えるとこうなる
  15. 27 ©MIXI ブランチの使⽤ マージ先ブランチに移動する $ git checkout main 2a673e714 Commit

    1 f20100b9e Commit on develop develop develop main 参照: git-merge Documentation 2f8ff17f6 Commit on main
  16. 28 ©MIXI ブランチの使⽤ マージ先ブランチに移動する $ git checkout main 2a673e714 Commit

    1 f20100b9e Commit on develop develop マージする $ git merge develop develop 95e9ea33b Merge branch ‘develop’ main マージコミット 参照: git-merge Documentation
  17. 29 ©MIXI ブランチの使⽤ マージの際、両ブランチの変更内容は⾃動でいい感じに混ぜられる 1 Hello, World! 2 and 3

    Hello, MIXI! 4 1 Hi, World! 2 and 3 Hello, MIXI! 4 1 Hello, World! 2 and 3 Yeah, MIXI! 4 1 Hi, World! 2 and 3 Yeah, MIXI! 4
  18. 31 ©MIXI ブランチの使⽤ マージしてみると怒られる Auto-merging hello.txt CONFLICT (content): Merge conflict

    in hello.txt Automatic merge failed; fix conflicts and then commit the result. (以下意訳) hello.txt のマージでコンフリクトが起きたよ。 ⾃動マージが失敗しちゃったからコンフリクトを直してからコミットしてね。 このように⾃動マージに失敗した状況をコンフリクト(conflict: 競合)と呼ぶ コンフリクトが発⽣した場合は⼿動マージが必要
  19. 32 ©MIXI ブランチの使⽤ 直してみる 問題のファイルを開くとこうなっている 1 <<<<<<< HEAD 2 Hello,

    e-Mercury! 3 4 ======= 5 Hello, MIXI! 6 >>>>>>> mixi コンフリクトーマーカー HEAD(今いるところ)の変更内容 ブランチ mixi の変更内容 これをあるべき姿に直してコミットすればよい
  20. 33 ©MIXI ブランチの使⽤ 例えば Hello, MIXI! を残すならこうする 1 Hello, MIXI!

    2 もしくは両⽅残すならこうする 1 Hello, e-Mercury! 2 Hello, MIXI! 3 忘れずに add してコミットすれば⼿動マージ完了! $ git add hello.txt $ git commit ちなみに $ git status でコンフリクトしているファイルの⼀覧が確認できる たくさんある場合は直したファイルから add していくのがおすすめ
  21. 34 ©MIXI ブランチの使⽤ マージは⾏ごとに処理されるのでこの場合もコンフリクトが起きる 1 Hello, World! 2 1 Hi,

    World! 2 1 Hello, MIXI! 2 1 <<<<<<< HEAD 2 Hi, World! 3 4 ======= 5 Hello, MIXI! 6 >>>>>>> mixi 1 Hi, MIXI! 2
  22. 35 ©MIXI ブランチの使⽤ コンフリクトはできるだけ避けたくはあるものの、起こるときは起こる ⼿動マージは間違いやすいので注意して作業しよう それぞれのブランチで加えられた変更の意図を理解するのが近道 merge-base コマンドで分岐元が調べられる $ git

    merge-base main develop 分岐元からの差分を⾒たり…… 含まれるコミットメッセージやPull requestを読んだり…… ⼤変だけど間違うともっと⼤変なので頑張ろう 参照: git-merge-base Documentation
  23. 36 ©MIXI ブランチの使⽤ ところで fast-forward というマージがある この状態で develop を main

    にマージすると…… 2a673e714 Commit 1 f20100b9e Commit on develop develop main develop $ git merge develop
  24. 37 ©MIXI ブランチの使⽤ ところで fast-forward というマージがある この状態で develop を main

    にマージすると…… こうなる 2a673e714 Commit 1 f20100b9e Commit on develop develop main develop $ git merge develop main
  25. 40 ©MIXI ワークスペースやステージングエリアに変更がある状態ではブランチ移動ができない ⼀旦他ブランチで作業して戻ってきたいときは stash が便利 コミットの退避 $ git stash

    変更を退避 $ git stash list 退避された変更の⼀覧 $ git stash apply stash番号 変更を復元 $ git stash drop stash番号 退避された変更を削除 $ git stash pop を使うとコマンド1つで最新の変更を復元&削除できて便利! 参照: git-stash Documentation
  26. 43 ©MIXI 歴史を改変してみる前にコミットログの構造を少し説明したい 歴史の改変 コミットは1つ前がどのコミットかを知っている(参照を持っている) bca877d40 最初のコミット 6aa4aa7ae 2番⽬のコミット 4e62a7326

    3番⽬のコミット [HEAD] 新 古 つまり…… 参照 参照 新しいコミットから古いコミットは辿れる 古いコミットから新しいコミットは辿れない コミットの削除とはそのコミットが どこからも辿れなくなることを意味する ちなみに 加えて今いるところ(HEAD)や ブランチの先端のコミットを別途保存することで コミットログが描画できる
  27. 44 ©MIXI 歴史の改変 最近のコミットをなかったことにするならリセット(reset) $ git reset コミットID よく使うオプションは以下 HEAD

    HEAD 削除 --soft --mixed(デフォルト) --hard :変更はステージングされた状態で残す :変更はステージングされていない状態で残す :変更は破棄する 変更をステージングしたけどやっぱりやめたいときもresetを使う $ git reset . 参照: git-reset Documentation
  28. 45 ©MIXI 歴史の改変 操作を間違えたら reflog で復旧できる……かも $ git reflog aec805a

    (HEAD -> main) HEAD@{0}: reset: moving to head^^ 561f0de HEAD@{1}: commit: Important commit 2 11dd662 HEAD@{2}: commit: Important commit aec805a (HEAD -> main) HEAD@{3}: commit: Add new file. 74c7044 HEAD@{4}: commit (initial): First commit 操作の結果移動した先のコミット 操作の内容 以下はresetで最新のコミットを2つ消し⾶ばした時のreflog この場合は reset する前にいたコミット 561f0de に再び reset することでもとに戻せる $ git reset 561f0de 参照: git-reflog Documentation
  29. 48 ©MIXI 歴史の改変 よく使うのはコミットをまとめる squash 前のコミットに吸収される w ork1 w ork2

    w ork3 pick 56da94f work1 pick 4a1d066 work2 pick f908cb9 work3 pick 56da94f work1 squash 4a1d066 work2 squash f908cb9 work3 w ork1, 2, 3
  30. 49 ©MIXI 歴史の改変 他にもいろいろできるので⼀部抜粋して紹介 reword edit :コミットをそのまま残す :コミットメッセージを書き直す :コミットを編集する pick(デフォルト)

    fixup exec squash :コミットを前のコミットとまとめる(前述) :squashっぽいけどメッセージはそのコミットのものを採⽤する :任意のコマンドを実⾏する ⾏を並べ替えるとコミットが並べ替えられたり…… ⾏を削除するとコミットが削除できたり…… 開いたエディタにできることが書いてあるので⼀度読んでみるとよい
  31. 52 ©MIXI 歴史の改変 これをプッシュするには強制プッシュが必要 $ git push --force (-f) 削除

    削除 もし他の⼈がコミットをプッシュしていたらそのコミットは消えてしまう
  32. 54 ©MIXI 歴史の改変 多くの⼈で共有している⼤事なブランチは リモートリポジトリ側で強制プッシュを禁⽌する設定をしておくべき(ブランチ保護) とはいえ⾃分のブランチへの操作を誤ってひとりで悲しい思いをするのも切ないので ⽐較的安全な強制プッシュを覚えておこう --force-with-lease: リモートリポジトリ側のコミットログに知らない変更があればプッシュを中⽌する $

    git push --force-with-lease --force-if-includes --force-if-includes: リモートリポジトリ側の最新のコミットに触った形跡がなければプッシュを中⽌する 超ざっくり解説 強制プッシュはいつもこれを使うくらいのつもりで問題ない 正確な説明は公式ドキュメントへ! https://git-scm.com/docs/git-push
  33. 56 ©MIXI commit コマンドの --amend オプション 直前のコミットを上書きしてコミットする 他にも便利な機能があるので紹介しておく その他便利機能 submodule

    参照: Git - Submodules リポジトリ内に別のリポジトリを内包できる cherry-pick 参照: git-cherry-pick Documentation 指定したコミットと同じ内容のコミットを今いるブランチに追加する -(ハイフン) 1つ前にいたブランチを⽰す(例: $ git switch - で1つ前のブランチに戻る) hooks 参照: Git Hooks 指定した操作の前や後に任意の処理を実⾏したりできる
  34. 57 ©MIXI add -A: すべての変更をステージする -p: 変更を部分的にステージする commit -a: すべての変更をステージしてからコミットする

    -m ’メッセージ’: コミットメッセージをオプションで渡せる(エディタが開かない) -n: pre-commit, commit-msg hooks を無視する log --graph: コマンドライン上でグラフィカルに表⽰する --oneline: 1コミット1⾏で表⽰する --all: 今いるブランチ以外のコミットも表⽰する よく使うかもしれない細かいオプションとか(その1) その他便利機能
  35. 58 ©MIXI checkout -b ブランチ名: ブランチを作ってそこに移動する switch -c ブランチ名:ブランチを作ってそこに移動する merge

    --abort: コンフリクトでマージが中断したときに、マージを中⽌する よく使うかもしれない細かいオプションとか(その2) その他便利機能
  36. 61 61 ©MIXI 講師紹介 森⼭ 堅樹 もりやま けんじゅ 2022 年度新卒⼊社

    • 業務:開発本部 たんぽぽ室 映像開発グループ • ARを⽤いた映像合成、その他R &D • C++ Python TypeScript Shader UE5 • 趣味:ゲーム Steamで300くらい持ってます • 好きなGitコマンド:git reflog
  37. 66 ©MIXI Gitの内部構造を知るメリット 1 トラブルにあった際、⾼い精度で情報検索ができる ◦ エラーが起きた原因、妥当性の考察 ◦ 出てきた解決策に対しての評価 2

    Gitの強み/弱みを深く知れる ◦ Gitでやらない⽅がいいことって? ◦ 他のVCSとどこを⽐べればいいの? 3 他のVCSに⾏った時に、周辺知識によって理解がしやすくなる ◦ Gitでは〇〇だったけど、こっちは△△なんだな ◦ この部分はGitと似ているんだな…
  38. 67 ©MIXI Gitについての誤解 Git の内部構造を知る前だと、(僕も含め)各コマンドに対する印象は例えば以下のような イメージになるかもしれない。 1. commit とは、 ◦

    add の操作を確定するもの? ◦ 親 commit との差分を保存しているもの? 2. branch とは、 ◦ 作業を分けるだけのもの? 3. reset とは、 ◦ add や commit を無かったことにできるコマンド? ◦ ファイルの変更を無かったことにできるコマンド?
  39. 68 ©MIXI Gitについての誤解 => 正確ではない Git について、多くの⼈が誤解しているであろうポイントを紹介しました。 これらの実態が分かれば、誤った操作をしてしまった時に焦る必要がないことが分かるよ うになると思います。 ここからは、Git

    がどのようにしてバージョン管理を実現しているかを理解するために、内 部構造を紐解いていきます。具体的には、.gitディレクトリの中⾝について取り扱っていき ます。 git init した時に できるあれ
  40. 69 ©MIXI .git ディレクトリ ⼿元の適当な .gitディレクトリ の中を眺めてみてください もしなければ以下のリポジトリをクローンして使ってください => 2025BeginnerTrainingGit

    $ git clone [email protected]:mixigroup/2025BeginnerTrainingGit.git $ ls .git/objects info pack # packfileを解凍する $ mkdir temp && cd temp $ git init $ git unpack-objects < ../2025BeginnerTrainingGit/.git/objects/pack/pack-xxx.pack $ find .git/objects -not -name 'pack' -a -not -name 'info' -type d -mindepth 1 | xargs -I {} mv {} ../2025BeginnerTrainingGit/.git/objects/ $ cd ../2025BeginnerTrainingGit 最初はPackfileに圧縮 されてしまっている Packfileについて興味 ある⽅はこちら
  41. 70 ©MIXI .git ディレクトリ とりあえず ls して中⾝を⾒てみる まずは objects ディレクトリを⾒ていく

    中にさらにサブディレクトリがあり、その中にファイルがある => Gitオブジェクト $ ls .git COMMIT_EDITMSG HEAD config description hooks index info logs objects packed-refs refs $ ls .git/objects 18 2a 3a 94 ab c7 da info 20 2b 44 a5 c2 d4 df pack $ ls .git/objects/2c/ 108c00a5b976158a0b5ccff04b8261bfe3d7db
  42. 72 ©MIXI Git オブジェクト Git はバージョン管理に必要なデータを主に「オブジェクト」と呼び、 .git/objectsディレクトリで管理しています。 オブジェクトは以下の4種類 • blob

    オブジェクト ◦ ファイルの情報が⼊っているオブジェクト(バックアップ) • tree オブジェクト ◦ ディレクトリ情報が⼊っているオブジェクト • commit オブジェクト ◦ コミットの情報が⼊っているオブジェクト • tag オブジェクト ◦ annotated tag の情報が⼊っているオブジェクト ◦ 重要度が低いので省略 => 興味がある⼈はこちらを参照してください
  43. 73 ©MIXI Git オブジェクト Git はこれらのオブジェクトを Key-Value Store として管理している。 1.

    それぞれのオブジェクト(Value)を作成 2. オブジェクトの中⾝を SHA-1 ハッシュ化した値をKeyとする 3. オブジェクトを zlib 圧縮した上で、.git/objects/以下に Key をファイル名として保存 ◦ 検索効率性のために、Key の先頭2⽂字でサブディレクトリを切る ※SHA-1:https://ja.wikipedia.org/wiki/SHA-1 ※Zlib:https://ja.wikipedia.org/wiki/Zlib $ ls .git/objects 18 2a 3a 94 ab c7 da info 20 2b 44 a5 c2 d4 df pack $ ls .git/objects/ab/ f5c28c73d56830e3e7cc0722be63d4d32b51a4
  44. 74 ©MIXI オブジェクトファイルの基本構成 • オブジェクトの種類:blob or tree or commit or

    tag • オブジェクトのサイズ:数値(単位はbyte) • オブジェクトのコンテンツ:オブジェクトの種類によってさまざま 最初にオブジェクトの種類やサイズなどのメタデータが記録され、そのあとにコンテンツ が続きます。 これからオブジェクトの種類ごとに、順番に中⾝を⾒ていきます。
  45. 75 ©MIXI commit オブジェクト commit オブジェクトは、コミットの情報を記録するオブジェクトです。 実際に、Key=abf5c28c73d56830e3e7cc0722be63d4d32b51a4 の commit オブジェク

    トの中⾝を⾒てみます。 そのままだとファイルは zlib 圧縮されているので意味のない⽂字列が表⽰されます。 $ cat .git/objects/ab/f5c28c73d56830e3e7cc0722be63d4d32b51a4 �a��,jQvt�˶Û���l��ID\Ĕt�5��Y��W/���ۼǗmY�!LJ��A� �u`_��S, �Y��ACN�bcw���)y�2�2�<ri ���q��$�4���|I��#VD'?��Cu/���=���ɶ*�i���o��?�� RS% ���&ˡp�iڞ����Y��u�)?U�15g��; �W�:���{��ï�/5�:�P�%
  46. 76 ©MIXI commit オブジェクト Git オブジェクトの内容を⾒たい場合は、cat-file というサブコマンドを使⽤します。 # tオプションはオブジェクトの種類 $

    git cat-file -t abf5c28c73d56830e3e7cc0722be63d4d32b51a4 commit # sオプションはオブジェクトのサイズ $ git cat-file -s abf5c28c73d56830e3e7cc0722be63d4d32b51a4 253 # pオプションはオブジェクトの中⾝ $ git cat-file -p abf5c28c73d56830e3e7cc0722be63d4d32b51a4 tree 3a2ccd96b192df80437a06ae7ca9bd2d254ef3fb parent 44108c00a5b976158a0b5ccff04b8261bfe3d7db author kenju.moriyama <qujen-caballus> 1744032231 +0900 committer kenju.moriyama <qujen-caballus> 1744032231 +0900 [add]add the second file second-commit.txt 配管コマンド 低レイヤー向けの操作 磁器コマンド 普段打つような操作 参考 Gitの内側 - 配管(Plumbing)と磁器(Porcelain)
  47. 77 ©MIXI commit オブジェクト commit オブジェクトに含まれている情報は以下の通り。 • リポジトリのルートディレクトリの tree オブジェクトのハッシュ値(Key)

    • 親 commit のハッシュ値 • committer と author のタイムスタンプ‧名前‧メールアドレス • コミットメッセージ $ git cat-file -p abf5c28c73d56830e3e7cc0722be63d4d32b51a4 tree 3a2ccd96b192df80437a06ae7ca9bd2d254ef3fb parent 44108c00a5b976158a0b5ccff04b8261bfe3d7db author kenju.moriyama <qujen-caballus> 1744032231 +0900 committer kenju.moriyama <qujen-caballus> 1744032231 +0900 [add]add the second file second-commit.txt 後ほど解説
  48. 78 ©MIXI commit オブジェクト commit オブジェクトに含まれている情報は以下の通り。 • リポジトリのルートディレクトリの tree オブジェクトのハッシュ値(Key)

    • 親 commit のハッシュ値 • committer と author のタイムスタンプ‧名前‧メールアドレス • コミットメッセージ $ git cat-file -p abf5c28c73d56830e3e7cc0722be63d4d32b51a4 tree 3a2ccd96b192df80437a06ae7ca9bd2d254ef3fb parent 44108c00a5b976158a0b5ccff04b8261bfe3d7db author kenju.moriyama <qujen-caballus> 1744032231 +0900 committer kenju.moriyama <qujen-caballus> 1744032231 +0900 [add]add the second file second-commit.txt
  49. 79 ©MIXI commit オブジェクト commit オブジェクトに含まれている情報は以下の通り。 • リポジトリのルートディレクトリの tree オブジェクトのハッシュ値(Key)

    • 親 commit のハッシュ値 • committer と author のタイムスタンプ‧名前‧メールアドレス(アカウント名) • コミットメッセージ $ git cat-file -p abf5c28c73d56830e3e7cc0722be63d4d32b51a4 tree 3a2ccd96b192df80437a06ae7ca9bd2d254ef3fb parent 44108c00a5b976158a0b5ccff04b8261bfe3d7db author kenju.moriyama <qujen-caballus> 1744032231 +0900 committer kenju.moriyama <qujen-caballus> 1744032231 +0900 [add]add the second file second-commit.txt
  50. 80 ©MIXI commit オブジェクト commit オブジェクトに含まれている情報は以下の通り。 • リポジトリのルートディレクトリの tree オブジェクトのハッシュ値(Key)

    • 親 commit のハッシュ値 • committer と author のタイムスタンプ‧名前‧メールアドレス • コミットメッセージ $ git cat-file -p abf5c28c73d56830e3e7cc0722be63d4d32b51a4 tree 3a2ccd96b192df80437a06ae7ca9bd2d254ef3fb parent 44108c00a5b976158a0b5ccff04b8261bfe3d7db author kenju.moriyama <qujen-caballus> 1744032231 +0900 committer kenju.moriyama <qujen-caballus> 1744032231 +0900 [add]add the second file second-commit.txt
  51. 81 ©MIXI commit オブジェクト commit オブジェクトに含まれている情報は以下の通り。 • リポジトリのルートディレクトリの tree オブジェクトのハッシュ値(Key)

    • 親 commit のハッシュ値 • committer と author のタイムスタンプ‧名前‧メールアドレス • コミットメッセージ これらのいずれか1つでも変わると、(SHA-1が衝突しない限り)別の commit ハッシュ になる。=> コミットは⼀意に定まる 親コミットのハッシュも含んでいるため、改ざんにも強い。 次に新出の これを解説
  52. 82 ©MIXI tree オブジェクト treeオブジェクトはディレクトリとしての情報を保持しています。バージョンごとに、Git 管理下の全てのディレクトリに対応する tree オブジェクトが作成されます。 実際に、Key=2bceb6cc10ab98b13ef6b3624bc464d5c020eb57のオブジェクトの中⾝ をみていきます。

    $ git cat-file -t 2bceb6cc10ab98b13ef6b3624bc464d5c020eb57 tree $ git cat-file -s 2bceb6cc10ab98b13ef6b3624bc464d5c020eb57 89 $ git cat-file -p 2bceb6cc10ab98b13ef6b3624bc464d5c020eb57 100644 blob da0d74633ad2023909aea38ce45fcaf1b2fa0e2f first-commit.txt 100644 blob c2f0160862bf1fbc7f338d3a395d9880f5ef7881 second-commit.txt
  53. 83 ©MIXI tree オブジェクト こちらは git-internals ディレクトリのある時点の tree オブジェクトです。左から順に、 パーミッション、種類、Key、ファイル名が記録されています。

    => この tree オブジェクトが作られた時点での、「そのディレクトリに存在したファイ ル」と、「そのバージョンの blobハッシュ値(Key)」 ※(再)blob オブジェクトはファイルの情報が⼊っているオブジェクト $ git cat-file -p 2bceb6cc10ab98b13ef6b3624bc464d5c020eb57 100644 blob da0d74633ad2023909aea38ce45fcaf1b2fa0e2f first-commit.txt 100644 blob c2f0160862bf1fbc7f338d3a395d9880f5ef7881 second-commit.txt
  54. 84 ©MIXI tree オブジェクト 次に、同じバージョンでの、リポジトリのルートディレクトリに対応するtreeオブジェク トも⾒ていきます。 ルートディレクトリにあるファイルの他に、先ほどの git-internals ディレクトリに関する treeオブジェクトへの参照(Key=2bceb6cc10ab98b13ef6b3624bc464d5c020eb57)

    も保持していることが分かると思います。 $ git cat-file -p abf5c28c73d56830e3e7cc0722be63d4d32b51a4 tree 3a2ccd96b192df80437a06ae7ca9bd2d254ef3fb … git cat-file -p 3a2ccd96b192df80437a06ae7ca9bd2d254ef3fb 100644 blob d46017d015af8702f85a62a2eeeb62ca33629e13 README.md 040000 tree 2bceb6cc10ab98b13ef6b3624bc464d5c020eb57 git-internals
  55. 86 ©MIXI 補⾜ (C: commit T: tree B: blob) Readmeが含まれる、GitHubのリポジトリをclone

    C0 └── T0 └── README.md(B0) git-internals/first-commit.txtを作成 add / commit C1 └── T2 ├── README.md(B0) ← 再利⽤ └── git-internals(T1) └── first-commit.txt(B1) git-internals/second-commit.txtを作成 add / commit C2 └── T4 ├── README.md(B0) ← 再利⽤ └── git-internals(T3) ├── first-commit.txt(B1) ← 再利⽤ └── second-commit.txt(B2) 最後に README.mdを編集 / add commit C3 └── T5 ├── README.md(B3) ← 新規 └── git-internals(T3) ← 再利⽤
  56. 87 ©MIXI 補⾜ (C: commit T: tree B: blob) Readmeが含まれる、GitHubのリポジトリをclone

    C0 └── T0 └── README.md(B0) git-internals/first-commit.txtを作成 add / commit C1 └── T2 ├── README.md(B0) ← 再利⽤ └── git-internals(T1) └── first-commit.txt(B1) git-internals/second-commit.txtを作成 add / commit C2 └── T4 ├── README.md(B0) ← 再利⽤ └── git-internals(T3) ├── first-commit.txt(B1) ← 再利⽤ └── second-commit.txt(B2) 最後に README.mdを編集 / add commit C3 └── T5 ├── README.md(B3) ← 新規 └── git-internals(T3) ← 再利⽤ ここを⾒てました
  57. 88 ©MIXI blob オブジェクト blobオブジェクトは、ファイルの実際のバックアップに当たるオブジェクトで、ある時点 (バージョン)でのファイルの情報を記録しています。 $ git rev-list --objects

    --all 20226ccdeaac3afd6030b6c47565aeb2edf88d9d abf5c28c73d56830e3e7cc0722be63d4d32b51a4 44108c00a5b976158a0b5ccff04b8261bfe3d7db c75f1ee6651b241f911e51368998f7c3b3b9ca17 2a1f5aec5669ca3126585393e586c6f7381c0074 182366232745d29b616008e23d5ac365f51df489 README.md 2bceb6cc10ab98b13ef6b3624bc464d5c020eb57 git-internals da0d74633ad2023909aea38ce45fcaf1b2fa0e2f git-internals/first-commit.txt c2f0160862bf1fbc7f338d3a395d9880f5ef7881 git-internals/second-commit.txt 3a2ccd96b192df80437a06ae7ca9bd2d254ef3fb d46017d015af8702f85a62a2eeeb62ca33629e13 README.md 943f712e856b69d55c3422f81f4e979416aa5fea df951d06764371c920ebb2e1b3658fc473042446 git-internals a51f746068d56a49d5bd788f0f042bf100bf1a96
  58. 89 ©MIXI blob オブジェクト blobオブジェクトは、ファイルの実際のバックアップに当たるオブジェクトで、ある時点 (バージョン)でのファイルの情報を記録しています。 この2つはどちらも同⼀ファイル(README.md)の blob オブジェクトで、それぞれ特定 のバージョンに対応する

    blob オブジェクトとなっています。 ここで重要なのは、blob オブジェクトは 「ファイルの差分ではなく、ある時点でのファイルの中⾝そのものを記録している」 ということです。 => Gitの機能を語る上で重要な要素 $ git cat-file -p d46017d015af8702f85a62a2eeeb62ca33629e13 # 2025BeginnerTrainingGit 株式会社MIXI 新卒向けGit研修リポジトリ $ git cat-file -p 182366232745d29b616008e23d5ac365f51df489 # 2025BeginnerTrainingGit 株式会社MIXI 新卒向けGit研修リポジトリ Gitの内部構造の説明に使⽤します。 本リポジトリをcloneした後に、以下のコマンドを実⾏して.... 差分が記録されて いるわけではない
  59. 91 ©MIXI commit の仕組み ここまで紹介した 3つのオブジェクトに関する内容を踏まえて、コミットの仕組みを解説 していきます。 まずここまでの話を整理すると • commit

    オブジェクトは、その時点のリポジトリのルートにあたる tree オブジェクト を参照 • tree オブジェクトは、その時点の ディレクトリ配下の tree オブジェクトと blob オブ ジェクトへの参照を持つ • blob オブジェクトは、その時点のファイルのフルバックアップ => commit オブジェクトを参照し、そこから辿ることで commit 時点のリポジトリの状態 を完全に再現できる => スナップショット
  60. 92 ©MIXI 補⾜ Gitの checkout/switch で、かなり遠い履歴に移る際にも瞬時にリポジトリの状態を復元 できることに驚いた経験はないでしょうか? Gitがファイルを差分で管理しているとしたら、checkout/switch の⾼速な移動は実現で きません。

    コミットの実態がスナップショットになっていることが⾼速な checkout/switch を可能に しています。 Gitではバージョン間を遷移する際にかかる時間は、履歴の遠さには依存せず、変更された ファイル数に依存します。
  61. 93 ©MIXI commit の流れ コミットには⼤きく3つの段階があります。 1. コードを編集する 2. 編集したコードをaddする 3.

    commitする ステップ2で編集したコードを add しています。 この時、Git 内部で⾏われていることを深掘りしていきます。
  62. 94 ©MIXI index について add について、「コミットに含めたいファイルをステージング(index)に登録してい る」という説明を⾒たことはあるかもしれません。 add の説明に⼊る前に、index について解説していきます。

    index の情報は .git/index に記録されているので、オブジェクトと同じように⾒ていきま す。 $ cat .git/index tc:�9�-����_���/git-internals/first-commit.txtg�-��>g�-��>f�����] �b��3�:9]����x�git-internals/second-commit.txtTREE?3 1 *Z�Vi�1&XS����8tgit-internals2 0 +ζ����>�bK�d�� �Wv8l��Y'9� nY*>���%
  63. 95 ©MIXI index について バイナリファイルなので、そのまま cat するだけだと⽂字化けしてしまいます。 index の中⾝を⾒るためのサブコマンドも⽤意されているので、そちらを使います。 左から、ファイルの種類+パーミッション、blob

    ハッシュ、コンフリクトフラグ、ファイ ル名が並んでいます。 index には、現在参照しているバージョン(コミット)で管理対象(ステージングエリア 含め)の全ての blob オブジェクトへの参照をもっています。 $ git ls-files --stage 100644 182366232745d29b616008e23d5ac365f51df489 0 README.md 100644 da0d74633ad2023909aea38ce45fcaf1b2fa0e2f 0git-internals/first-commit.txt 100644 c2f0160862bf1fbc7f338d3a395d9880f5ef7881 0 git-internals/second-commit.txt
  64. 97 ©MIXI add の内部動作 例えば、適当にファイルを作成してaddすると、indexは以下のように更新されています。 temp/hoge.txtがindexに追加されていることがわかります。また、blobハッシュも記録 されており、該当Keyを⾒にいくとblobオブジェクトも⽣成されていることが分かると思 います。 すでにあるファイルを編集した場合も、新しいblobオブジェクトが⽣成され、indexが そのハッシュ値に書き変わります。

    $ mkdir temp $ echo hoge > temp/hoge.txt $ git add temp/hoge.txt $ git ls-files --stage 100644 182366232745d29b616008e23d5ac365f51df489 0 README.md 100644 da0d74633ad2023909aea38ce45fcaf1b2fa0e2f 0git-internals/first-commit.txt 100644 c2f0160862bf1fbc7f338d3a395d9880f5ef7881 0 git-internals/second-commit.txt 100644 2262de0c121f22df8e78f5a37d6e114fd322c0b0 0 temp/hoge.txt
  65. 98 ©MIXI commit の内部挙動 次に、commit した時に起こる内部挙動は、以下の通りです。 • index から tree

    オブジェクトを⽣成 • commit オブジェクトを⽣成 • HEAD を新しい commit ハッシュに書き換え それぞれ詳しく解説していきます。
  66. 99 ©MIXI commit の内部挙動 ~tree オブジェクトの作成~ tree オブジェクトの作成はこの段階で⾏われます。 commit すると、新たに作成されたディレクトリに対する

    tree オブジェクトだけでなく、 リポジトリのルートディレクトリを含むすべてのディレクトリに対する tree オブジェクト の構築処理が動きます。 => index に記録された情報から構築可能 この時、indexに変更があった部分だけが新しい blob および tree オブジェクトに書き換 えられ、それ以外の参照が変わらない部分はそのまま流⽤します。
  67. 100 ©MIXI commit の内部挙動 ~commit オブジェクトの作成~ 新しいルートディレクトリまでの tree オブジェクトが⽣成できたら、次は commit

    オブ ジェクトを作成します。 commit オブジェクトに記録する情報(再掲) • リポジトリのルートディレクトリのtreeオブジェクトのハッシュ値(Key) • 親commitのハッシュ値 • committerとauthorのタイムスタンプ‧名前‧メールアドレス • コミットメッセージ 先述の通り、リポジトリのルートにあたるtreeオブジェクトを参照しているため、そこか らリポジトリ全体をたどることができます。
  68. 101 ©MIXI commit の内部挙動 ~HEAD を新しい commit ハッシュに書き換え~ 最後に、現在参照しているコミットを指す .git/HEAD

    を必要に応じて書き換えます。 .git/HEAD についても中⾝を⾒てみます。 refs/heads/main(mainブランチ)を参照しているとあるのでそちらを辿って⾒ます。 ここに記録されているのが commit ハッシュです。ここを新しいコミットのハッシュ値 (commit オブジェクトのKey)に書き換えることで、コミット操作を完了します。 $ cat .git/HEAD ref: refs/heads/main $ cat .git/refs/heads/main 20226ccdeaac3afd6030b6c47565aeb2edf88d9d $ git cat-file -p 20226ccdeaac3afd6030b6c47565aeb2edf88d9d ……[update]update README to explain Git internal structure
  69. 103 ©MIXI refs について ~light-weight tag~ light-weight tag を作成して確認します。タグは .git/refs/tags/

    に保存されます。 tag を付与した時点のコミットハッシュが記録されていることがわかると思います。 $ git tag test-1 $ git log -n 1 --oneline 20226cc (HEAD -> main, tag: test-1, origin/main, origin/HEAD) [update]update README to explain Git internal structure $ cat .git/refs/tags/test-1 20226ccdeaac3afd6030b6c47565aeb2edf88d9d
  70. 104 ©MIXI refs について ~branch~ 次に branch です。こちらは基本的には light-weight tag

    と同様です。 違いとしては、保存場所が .git/refs/heads 以下になっている点と、branch の場合はその branch でコミットを実⾏すると、branch が指しているコミットハッシュが⾃動で書き変 わっていくことです。 ※「commitの内部挙動 ~HEADを新しい commit ハッシュに書き換え~」で解説した通り branch の実態も、単に特定のコミットへのポインタなので、branch を削除してしまった としても焦る必要はありません。 $ cat .git/refs/heads/main 20226ccdeaac3afd6030b6c47565aeb2edf88d9d
  71. 105 ©MIXI refs について ~HEAD~ 最後に HEAD です。HEAD は先ほども⾔った通り、現在の commit

    を指す refs です。 .git/HEAD に保存されており、commit や checkout/switch などで書き変わります。ま た、branch 名で checkout/switch した時はコミットハッシュではなく branch の場所が 書き込まれるようになっています。
  72. 106 ©MIXI commit の仕組み(再掲) ここまでで、commit に関連する全てのオブジェクトと、仕組みを解説してきました。 commit の流れを再度まとめておきます。 • コードを編集する

    • 編集したコードをaddする ◦ add したファイルの blob オブジェクトの⽣成 ◦ index の更新 • commitする ◦ リポジトリ全体の tree オブジェクトの⽣成 ◦ commit オブジェクトを⽣成 ◦ HEAD の書き換え
  73. 109 ©MIXI reset コマンド reset では、基本的には以下の 3 つを書き換えることでそれらを実現しています。 • ワークツリー(作業ディレクトリ)

    • index • HEAD おおまかには soft, mixed, hard の 3 種類のオプションがあり、指定した commit ハッ シュに向けて、それぞれの内容を書き換える。 
 HEAD
 index
 ワークツリー
 git reset --soft <commit ハッシュ> 書き換える
 
 
 git reset --mixed <commit ハッシュ> 書き換える
 書き換える
 
 git reset --hard <commit ハッシュ> 書き換える
 書き換える
 書き換える

  74. 110 ©MIXI reset コマンド どのオプションでも HEAD の書き換えはある。 なお、checkout/switch と異なり、reset では

    branch の参照先も書き換わる。 checkout/switch の場合 first commit
 main.txt を追加
 README.md に
 「main」と追記
 develop.txt を追加
 main
 README.md に
 「develop」と追記
 develop
 HEAD

  75. 111 ©MIXI reset コマンド どのオプションでも HEAD の書き換えはある。 なお、checkout/switch と異なり、reset では

    branch の参照先も書き換わる。 checkout/switch の場合 first commit
 main.txt を追加
 README.md に
 「main」と追記
 develop.txt を追加
 main
 README.md に
 「develop」と追記
 develop
 HEAD

  76. 112 ©MIXI reset コマンド どのオプションでも HEAD の書き換えはある。 なお、checkout/switch と異なり、reset では

    branch の参照先も書き換わる。 reset の場合 first commit
 main.txt を追加
 README.md に
 「main」と追記
 develop.txt を追加
 main
 README.md に
 「develop」と追記
 develop
 HEAD

  77. 113 ©MIXI reset コマンド どのオプションでも HEAD の書き換えはある。 なお、checkout/switch と異なり、reset では

    branch の参照先も書き換わる。 reset の場合 first commit
 main.txt を追加
 README.md に
 「main」と追記
 develop.txt を追加
 main
 README.md に
 「develop」と追記
 develop
 HEAD

  78. 114 ©MIXI reset コマンド ここまで解説した機能があることで、前述した⽤途を実現できます。 (再掲) • commit の取り消し ◦

    1 つ前の commit ハッシュに branch を向けることで、最新のコミットをなかっ たことにできる(branch の参照先を変えられる機能があるため) • add の取り消し ◦ git reset --mixed HEAD とすると、index を HEAD の状況に戻せるので、add を 取り消すことができる • 作業の取り消し ◦ git reset —hard HEAD とすると、ワークツリーの状況を HEAD に戻せる ◦ ※現在では、restore の⽅が推奨
  79. 115 ©MIXI reset コマンド add, commitの取り消しについて補⾜ あくまで reset で⾏われているのは以下の操作です。 add

    や commit の内部動作で⾏なっていたことを完全に無かったことにできているでしょ うか? 
 HEAD
 index
 ワークツリー
 git reset --soft <commit ハッシュ> 書き換える
 
 
 git reset --mixed <commit ハッシュ> 書き換える
 書き換える
 
 git reset --hard <commit ハッシュ> 書き換える
 書き換える
 書き換える

  80. 116 ©MIXI まとめ 以降はこの後の git challenge で取り組んでください。 ここまでの内容が分かっていれば、講義の最初に挙げた以下の問題が起きた時にも、 焦らず対処できるはずです。 •

    ブランチをマージ前に間違えて消してしまった! • コミットを誤って消してしまった! • コミット前(ステージングエリア)のファイルを消してしまった!