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

Gitを内部構造で完全理解する

Avatar for Umehara Umehara
September 23, 2025

 Gitを内部構造で完全理解する

本資料はオンライン勉強会の資料です。

https://supporterz-seminar.connpass.com/event/365286/

新卒1年目、初めてrebaseを触ったとき何が起きているのか分からず、ただ怖かった――そんな経験から、Gitの“中身”を理解したいと思うようになりました。
仕事では巨大なコードベースに向き合い、過去コミットを読み解く必要も多く、Gitは「なんとなく使うツール」では済まされないと感じています。
本勉強会では、Gitの内部構造を1から紐解き、addやcommitの正体からrebaseの仕組みまで、図解と構造で完全に理解することを目指します。

Avatar for Umehara

Umehara

September 23, 2025

More Decks by Umehara

Other Decks in Programming

Transcript

  1. 名前 : 梅原 隆一 仕事: 自動運転系のソフトウェア開発、副業ではWeb開発(フロ ント: TypeScript, React、バックエンド: Python,

    NodeJS, Go、 インフラ: Terraform, aws cdk) 趣味: バスケットボール、野球観戦(阪神🐅)、ゴルフ⛳
  2. 本日の目標 1. Commitは差分ではなく、スナップショットであることを 理解する 2. 3-WAYマージを理解する 3. git init から

    git rebaseの動作を理解する ⚠本発表では本質をわかりやすく伝えるために一部処理順序が異なったり、簡略 化して伝えている部分が存在します🙏

  3. アジェンダ 1. git init で作成されるもの 2. 履歴を積み重ねる git add /

    commit 3. 履歴を分岐させる git checkout 4. 履歴をマージさせる git merge 5. 履歴を操作する git rebase / cherry-pick
  4. アジェンダ 1. git init で作成されるもの 2. 履歴を積み重ねる git add /

    commit 3. 履歴を分岐させる git checkout 4. 履歴をマージさせる git merge 5. 履歴を操作する git rebase / cherry-pick
  5. commit / tree / blob の関係性
 gachit
 C
 D
 src


    README.md
 4368f3
 ccfd88 e0kl4d gachit
 23d9fb7 README.md
 e70524 WorkTree
 tree
 blob
 commit

  6. commit objectの中身を見てみよう
 • tree -> リポジトリルートのtreeオブジェクトのsha
 • parent -> 一つ前のcommit


    • author / commiter -> 作成者とcommitした人物(と時刻)
 • comment
 C
 D
 gachit
 23d9fb7 tree
 parent

  7. commit / tree / blob の関係性
 gachit
 C
 D
 src


    README.md
 4368f3
 ccfd88 e0kl4d gachit
 23d9fb7 README.md
 e70524 WorkTree
 tree
 blob
 commit

  8. アジェンダ 1. git init で作成されるもの 2. 履歴を積み重ねる git add /

    commit 3. 履歴を分岐させる git checkout 4. 履歴をマージさせる git merge 5. 履歴を操作する git rebase / cherry-pick
  9. git add / commit
 gachit
 C
 D
 src
 README.md 


    23d9fb7
 ccfd88 e70524 gachit
 as3fc66
 README.md 
 bm59o4 82f9275 .gitignore e70524 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py WorkTree
 Stagingエリア
 feat
 git add
 git commit
 Tree
 Blob
 git object

  10. git add <ファイルpath> の内部動作
 1. README.mdを修正 2. $ git add

    READMD.md 3. READMD.mdをblobとして.git/objects以下に保存
 4. Indexファイルを更新 (変更がステージングエリアに移動)
 
 82f9275 .gitignore e70524 README.md bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py WorkTree
 Stagingエリア
 git add
 README.md
 bm59o4
  11. git commit の内部動作
 1. IndexファイルからTreeオブジェクトファイルを作る
 2. TreeオブジェクトファイルからCommitオブジェクトファイルを作る
 3. <HEAD /

    branch>の更新
 82f9275 .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py Stagingエリア
 git commit
 gachit
 HEAD
 C
 src
 README.md
 23d9fb7
 ccfd88 e70524 feat
 Tree
 Blob

  12. git commit の内部動作
 1. IndexファイルからTreeオブジェクトファイルを作る 
 2. TreeオブジェクトファイルからCommitオブジェクトファイルを作る
 3. <HEAD

    / branch>の更新
 gachit
 HEAD
 C
 src
 README.md
 23d9fb7
 ccfd88 e70524 82f9275 .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py Stagingエリア
 feat
 Tree
 Blob
 git commit
 gachit
 as3fc66
 README.md
 bm59o4
  13. Indexファイルからtree objectを作成
 treeのハッシュ値はその下のtreeやblobのハッシュ値によって変わる!
 bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py ef7ba989

    src/tests/add_test.py e331b1c src/tests/checkout_test.py Stagingエリア
 src
 gachit
 README.md
 e70524 gachit
 tests
 __init__.py
 ca3839 __main__.py
 5d5c0c add_test.py
 ef7ba9 checkout_test.py 
 e331b1
  14. Indexファイルからtree objectを作成
 treeのハッシュ値はその下のtreeやblobのハッシュ値によって変わる!
 Stagingエリア
 src
 gachit
 README.md
 e70524 gachit
 tests


    ccfd88 __init__.py
 ca3839 __main__.py
 5d5c0c add_test.py
 ef7ba9 checkout_test.py 
 e331b1 bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py ef7ba989 src/tests/add_test.py e331b1c src/tests/checkout_test.py
  15. Indexファイルからtree objectを作成
 treeのハッシュ値はその下のtreeやblobのハッシュ値によって変わる!
 Stagingエリア
 src
 gachit
 README.md
 e70524 gachit
 ccfd88

    tests
 ccfd88 __init__.py
 ca3839 __main__.py
 5d5c0c add_test.py
 ef7ba9 checkout_test.py 
 e331b1 bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py ef7ba989 src/tests/add_test.py e331b1c src/tests/checkout_test.py
  16. Indexファイルからtree objectを作成
 treeのハッシュ値はその下のtreeやblobのハッシュ値によって変わる!
 Stagingエリア
 src
 gachit
 README.md
 ccfd88 e70524 gachit


    ccfd88 tests
 ccfd88 __init__.py
 ca3839 __main__.py
 5d5c0c add_test.py
 ef7ba9 checkout_test.py 
 e331b1 bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py ef7ba989 src/tests/add_test.py e331b1c src/tests/checkout_test.py
  17. Indexファイルからtree objectを作成
 treeのハッシュ値はその下のtreeやblobのハッシュ値によって変わる!
 Stagingエリア
 src
 gachit
 README.md
 ccfd88 23d9fb7
 e70524

    gachit
 ccfd88 tests
 ccfd88 __init__.py
 ca3839 __main__.py
 5d5c0c add_test.py
 ef7ba9 checkout_test.py 
 e331b1 bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py ef7ba989 src/tests/add_test.py e331b1c src/tests/checkout_test.py
  18. git commit の内部動作
 1. IndexファイルからTreeオブジェクトファイルを作る 
 2. TreeオブジェクトファイルからCommitオブジェクトファイルを作る
 3. <HEAD

    / branch>の更新
 gachit
 HEAD
 C
 src
 README.md
 23d9fb7
 ccfd88 e70524 82f9275 .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py Stagingエリア
 feat
 Tree
 Blob
 git commit
 gachit
 as3fc66
 README.md
 bm59o4 commit間で変更がなければtreeは 
 同じtreeが共有される 

  19. git commit の内部動作
 1. IndexファイルからTreeオブジェクトファイルを作る
 2. TreeオブジェクトファイルからCommitオブジェクトファイルを作る 
 3. <HEAD

    / branch>の更新
 gachit
 HEAD
 C
 D
 src
 README.md
 23d9fb7
 ccfd88 e70524 gachit
 as3fc66
 README.md
 bm59o4 82f9275 .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py Stagingエリア
 feat
 Tree
 Blob
 git commit

  20. git commit の内部動作
 1. IndexファイルからTreeオブジェクトファイルを作る
 2. TreeオブジェクトファイルからCommitオブジェクトファイルを作る
 3. <HEAD /

    branch>の更新 
 gachit
 HEAD
 C
 D
 src
 README.md
 23d9fb7
 ccfd88 e70524 gachit
 as3fc66
 README.md
 bm59o4 82f9275 .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py Stagingエリア
 feat
 Tree
 Blob
 git commit

  21. 疑問: なんでtree?
 • ディレクトリを表現するだけならINDEXファイルだけで十分
 なのにtreeというややこしい構造を持ち出すのはなぜか
 ◦ ファイル数も多くなる。 
 ◦ ディレクトリ全てのファイルを見るには複数ファイルを跨がないといけない

    
 
 
 
 この疑問を意識して
 後半の発表を聞いてね!
 gachit
 C
 D
 src
 README.md
 23d9fb7
 ccfd88 e70524 gachit
 as3fc66
 README.md
 bm59o4 82f9275 .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py Stagingエリア
 Tree
 Blob

  22. アジェンダ 1. git init で作成されるもの 2. 履歴を積み重ねる git add /

    commit 3. 履歴を分岐させる git checkout 4. 履歴をマージさせる git merge 5. 履歴を操作する git rebase / cherry-pick
  23. GitのRefについて
 • commitのハッシュは直感的に理解不能 
 • gitにはcommitに参照=ref (つまりは名札📛みたいなもの)をつけられる。
 • Refは3種類
 a.

    branch: branchの先頭のcommitを指す 
 b. HEAD: 今見てるbranch(or commit)を指す 
 c. tag: リリースバージョンなど特定のcommitを指す 
 • ファイルとしては
 .git
 └ refs
 └ <branch名のtextファイル>
 にCommitのshaを記載して保存されている。
 
 A
 main
 HEAD
 v1.1
 B
 C
 D
 feat
 main
 v1.1

  24. branch作成 ( branch / checkout )
 1. refの作成
 2. (HEADの切り替え)


    A
 main
 HEAD
 feat
 A
 main
 HEAD
 A
 main
 HEAD
 git branch
 git checkout -b
 feat
 A
 main
 HEAD

  25. branchを切り替える git checkout
 A
 main
 HEAD
 B
 C
 D
 82f9275

    .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py WorkTree
 Stagingエリア
 feat
 1. HEADをtarget branchに移動
 2. target branchとHEADの差分を計算
 a. Worktreeを修正
 b. INDEXファイルの修正

  26. branchを切り替える git checkout
 A
 main
 HEAD
 B
 C
 D
 82f9275

    .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py WorkTree
 Stagingエリア
 feat
 1. HEADをtarget branchに移動 
 2. target branchとHEADの差分を計算
 a. Worktreeを修正
 b. INDEXファイルの修正

  27. branchを切り替える git checkout
 A
 main
 B
 C
 D
 82f9275 .gitignore

    bm59o4 README.md e70524 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py WorkTree
 Stagingエリア
 feat
 1. HEADをtarget branchに移動
 2. target branchとHEADの差分を計算
 a. Worktreeを修正 
 b. INDEXファイルの修正 
 HEAD

  28. branchを切り替える git checkout
 A
 main
 B
 C
 D
 82f9275 .gitignore

    bm59o4 README.md e70524 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py WorkTree
 Stagingエリア
 feat
 1. HEADをtarget branchに移動
 2. target branchとHEADの差分を計算 
 a. Worktreeを修正
 b. INDEXファイルの修正
 HEAD

  29. branchを切り替える git checkout
 A
 main
 HEAD
 B
 C
 D
 82f9275

    .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py WorkTree
 Stagingエリア
 feat
 1. HEADをtarget branchに移動
 2. target branchとHEADの差分を計算
 a. Worktreeを修正
 b. INDEXファイルの修正

  30. 余談: 1つ前のブランチ、N個前のブランチ
 feat/hogeで開発中にmainブランチが更新された....
 1. <on feat/hoge> $ git checkout main

    # mainブランチに移動
 2. <on main> $ git pull # 最新の変更を取ってきて、mainブランチを更新
 3. (さぁfeatブランチに戻ってrebaseしよう...あれ、前居たブランチ忘れた...)

  31. git reset
 git reset = refの付け替え
 C
 D
 feat
 HEAD


    C
 D
 feat
 HEAD
 git reset <commitC>
 commitDのハッシュ値を知らないと resetは取り消せない

  32. git reset
 git reset = refの付け替え
 C
 D
 feat
 HEAD


    C
 D
 feat
 HEAD
 HEADがbranchから離れる
 = detached HEAD状態
 git checkout <commitC>
 C
 D
 feat
 HEAD
 git reset <commitC>
 commitDのハッシュ値を知らないと resetは取り消せない

  33. 3種類のgit reset
 • --soft
 ◦ ref(branchとHEAD)のみを修正 
 • --mixed
 ◦

    ref + Indexファイルを修正 
 • --hard
 ◦ ref + Indexファイル + WorkTreeを修正 
 A
 main
 HEAD
 B
 C
 D
 82f9275 .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py WorkTree
 Stagingエリア
 feat

  34. git reset --soft <commitC>
 • --soft
 ◦ ref(branchとHEAD)のみを修正 
 •

    --mixed
 ◦ ref + Indexファイルを修正 
 • --hard
 ◦ ref + Indexファイル + WorkTreeを修正 
 A
 main
 HEAD
 B
 C
 D
 82f9275 .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py WorkTree
 Stagingエリア
 feat
 commitDのまま
 差分

  35. git reset --mixed <commitC>
 • --soft
 ◦ ref(branchとHEAD)のみを修正 
 •

    --mixed
 ◦ ref + Indexファイルを修正 
 • --hard
 ◦ ref + Indexファイル + WorkTreeを修正 
 A
 main
 HEAD
 B
 C
 D
 82f9275 .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py WorkTree
 Stagingエリア
 feat
 commitDのまま
 差分
 commitC

  36. 余談: git resetの使い道
 commitの分割、結合に便利
 • 分割したい場合
 ◦ git reset --mixed

    → git add <一部分> → git commit → git add <残り> → git commit 
 A
 main
 HEAD
 B
 C
 D
 82f9275 .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py WorkTree
 Stagingエリア
 feat
 commitDのまま
 差分
 commitC

  37. 余談: git resetの使い道
 commitの分割、結合に便利
 • 結合したい場合
 ◦ git reset --soft

    <commit C> → git commit
 82f9275 .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py Stagingエリア
 A
 main
 HEAD
 B
 C
 D
 feat
 E
 F

  38. 余談: git resetの使い道
 commitの分割、結合に便利
 • 結合したい場合
 ◦ git reset --soft

    <commit C> → git commit
 82f9275 .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py Stagingエリア
 差分
 commitFのまま
 A
 main
 HEAD
 B
 C
 feat

  39. 余談: git resetの使い道
 commitの分割、結合に便利
 • 結合したい場合
 ◦ git reset --soft

    <commit C> → git commit
 82f9275 .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py Stagingエリア
 A
 main
 B
 C
 HEAD
 DE F
 feat

  40. git reset --hard <commitC>
 • --soft
 ◦ ref(branchとHEAD)のみを修正 
 •

    --mixed
 ◦ ref + Indexファイルを修正 
 • --hard
 ◦ ref + Indexファイル + WorkTreeを修正 
 A
 main
 HEAD
 B
 C
 D
 82f9275 .gitignore bm59o4 README.md ca383925 src/gachit/__init__.py 5d5c0cb src/gachit/__main__.py WorkTree
 Stagingエリア
 feat
 commitC

  41. 余談: git reflog
 • reset --hardしても大丈夫!
 • git reflogでgitの操作 +

    その時のcommitが記録されてる
 • 元々のcommitを見つけてもう一度reset --hardすればいい。
 C
 D
 feat
 HEAD
 C
 D
 feat
 HEAD
 git reset --hard

  42. アジェンダ 1. git init で作成されるもの 2. 履歴を積み重ねる git add /

    commit 3. 履歴を分岐させる git checkout 4. 履歴をマージさせる git merge 5. 履歴を操作する git rebase / cherry-pick
  43. 2-wayマージ
 例: AちゃんとDくんは授業で同じ班となり共同でプログラムを作ります。
 2人が作業した内容をマージしたいです。
 def greet(): hi = "hello" name

    = "jinan" return f”{hi} {name}” 
 def say_hello(): hi = "hello" name = "aanya" return f”{hi} {name}” ❓
 どちらを採用すればいいかわからない。。。

  44. 3-wayマージ
 例: AちゃんとDくんは授業で同じ班となり共同でプログラムを作ります。
 2人が作業した内容をマージしたいです。
 def greet(): hi = "hello" name

    = "jinan" return f”{hi} {name}” 
 def say_hello(): hi = "hello" name = "aanya" return f”{hi} {name}” def say_hello(): hi = "hello" name = "jinan" return f”{hi} {name}” ベースプログラム
 関数名を変更
 nameを変更
 2つの変更をマージ! 

  45. 3-wayマージ
 例: AちゃんとDくんは授業で同じ班となり共同でプログラムを作ります。
 2人が作業した内容をマージしたいです。
 def greet(): hi = "hello" name

    = "jinan" return f”{hi} {name}” 
 def say_hello(): hi = "hello" name = "aanya" return f”{hi} {name}” def say_hello(): hi = "hello" name = "jinan" return f”{hi} {name}” ベースプログラム
 def greet(): hi = "hello" name = "aanya" return f”{hi} {name}”
  46. 3-wayマージ
 例: AちゃんとDくんは授業で同じ班となり共同でプログラムを作ります。
 2人が作業した内容をマージしたいです。
 def greet(): hi = "hello" name

    = "jinan" return f”{hi} {name}” 
 def say_hello(): hi = "hello" name = "aanya" return f”{hi} {name}” def say_hello(): hi = "hello" name = "jinan" return f”{hi} {name}” ベースプログラム
 3点でマージ
 →3wayマージ

  47. 3-wayマージ
 例: AちゃんとDくんは授業で同じ班となり共同でプログラムを作ります。
 2人が作業した内容をマージしたいです。
 def greet(): hi = "hello" name

    = "jinan" return f”{hi} {name}” 
 def say_hello(): hi = "hello" name = "aanya" return f”{hi} {name}” def say_hello(): hi = "hello" name = "jinan" return f”{hi} {name}” ベースプログラム
 def greet(): hi = "hello" name = "aanya" return f”{hi} {name}” merge base
 =

  48. 3wayマージの利点 = 安全なコンフリクト解消
 def greet(): hi = "hello" name =

    "jinan" return f”{hi} {name}” 
 def say_hi(): hi = "hello" name = "jinan" return f”{hi} {name}” def say_hello(): hi = "hello" name = "jinan" return f”{hi} {name}” ベースプログラム
 関数名を変更
 関数名を変更
 ❓
 • コンフリクト = 変更場所が重複すること
 • ユーザーにどちらの変更を採用するか選んでもらえる(コンフリクト解消)
 • ソースコードの意図しない変更を防ぐことができる。

  49. git merge
 • featブランチをmainブランチにマージする時
 ◦ mainで入った変更とfeatで入った変更をマージしたい
 ◦ mainで入った変更 = commitAとcommitBの差分


    ◦ featで入った変更 = commitAとcommitDの差分
 ◦ commitA = best common ancestor (最良共通祖先) 
 ◦ commitM = commitA と commitB と commitD の3wayマージの結果 
 A
 main
 B
 D
 feat
 HEAD
 M
 MERGE_HEAD
 merge base
 HEAD
 C

  50. git merge
 • featブランチをmainブランチにマージする時
 ◦ mainで入った変更とfeatで入った変更をマージしたい
 ◦ mainで入った変更 = commitAとcommitBの差分


    ◦ featで入った変更 = commitAとcommitDの差分
 ◦ commitA = best common ancestor (最良共通祖先) 
 ◦ commitM = commitA と commitB と commitD の3wayマージの結果 
 A
 main
 B
 C
 D
 feat
 HEAD
 T M = T A + |T B - T A | + |T D - T A |
 
 T M =commitMのtree object
 M
 MERGE_HEAD
 merge base
 HEAD

  51. git merge
 • featブランチをmainブランチにマージする時
 ◦ mainで入った変更とfeatで入った変更をマージしたい
 ◦ mainで入った変更 = commitAとcommitBの差分


    ◦ featで入った変更 = commitAとcommitDの差分
 ◦ commitA = best common ancestor (最良共通祖先) 
 ◦ commitM = commitA と commitB と commitD の3wayマージの結果 
 A
 main
 B
 D
 feat
 HEAD
 T M = T A + |T B - T A | + |T D - T A |
 
 T M =commitMのtree object
 
 実はcommitCは全く使われない!
 (commitは差分ではない...!)
 M
 MERGE_HEAD
 merge base
 HEAD
 C

  52. アジェンダ 1. git init で作成されるもの 2. 履歴を積み重ねる git add /

    commit 3. 履歴を分岐させる git checkout 4. 履歴をマージさせる git merge 5. 履歴を操作する rebase / cherry-pick
  53. git cherry-pick
 • 例: mainブランチにcommitDをcherry-pick
 ◦ = commitCとcommitDの差分をcommitBに適用したい
 • T

    D’ = T B + |T D - T C |で良いのでは?
 
 ◦ 本来コンフリクトとして扱うべきなのに、コンフリクトを無視してしまう危険性 
 ◦ = commitBの変更とcommitDの変更が重複していた場合、commit Dが常に優先される
 A
 B
 C
 D
 feat
 main
 D ’
 HEAD

  54. git cherry-pick
 A
 B
 C
 D
 feat
 • 例: mainブランチにcommitDをcherry-pick


    ◦ = commitCとcommitDの差分をcommitBに適用したい
 • T D’ = T B + |T D - T C |で良いのでは?
 
 ◦ 本来コンフリクトとして扱うべきなのに、コンフリクトを無視してしまう危険性 
 ◦ = commitBの変更とcommitDの変更が重複していた場合、commit Dが常に優先される
 • commitCとcommitBとcommitDで3wayマージ!
 main
 D ’
 HEAD

  55. git rebase
 git rebase = reset (--hard) + {cherry-pick} x

    <コミットの数繰り返し>
 例: git rebase mainを実行すると...
 A
 main
 B
 C
 D
 feat
 HEAD
 1. mainにreset —hard

  56. git rebase
 git rebase = reset (--hard) + {cherry-pick} x

    <コミットの数繰り返し>
 例: git rebase mainを実行すると...
 A
 main
 B
 C ’
 feat
 HEAD
 C
 D
 1. mainにreset —hard
 2. cherry-pick C

  57. git rebase
 git rebase = reset (--hard) + {cherry-pick} x

    <コミットの数繰り返し>
 例: git rebase mainを実行すると...
 A
 main
 B
 C ’
 1. mainにreset —hard
 2. cherry-pick C
 3. cherry-pick D
 C
 D
 D ’
 feat
 HEAD

  58. git rebase
 git rebase = reset (--hard) + {cherry-pick} x

    <コミットの数繰り返し>
 例: git rebase mainを実行すると...
 A
 main
 B
 C ’
 D ’
 feat
 HEAD
 1. mainにreset —hard
 2. cherry-pick C
 3. cherry-pick D
 cherry-pickをN回繰り返すので、コンフリクトの解消も最大N回必要

  59. 今日のまとめ
 • rebaseやcherry-pickなどのコマンドも実は3wayマージが基礎
 
 • 3wayマージは3点の差分同士のマージ
 
 • コミットは差分ではなく、スナップショット
 


    • コミットの差分 = treeの差分
 
 • treeというデータ構造とハッシュ値を組み合わせることで、
 gitは差分を効率よく扱っている

  60. • 独習 Git
 ◦ 基礎的な内容からしっかり書かれている 
 ◦ 今回紹介できなかったoriginの話が書かれている 
 ◦

    初~中級者向け
 
 • 実用git 第3版
 ◦ 今回説明したような内部構造の話がじっくり書かれている 
 ◦ サブコマンドの解説も豊富
 ◦ 上級者向け
 おすすめの本