Slide 1

Slide 1 text

merge / rebase 勉強会 2022-02-26 14:00~ / 20:00~

Slide 2

Slide 2 text

自己紹介 上田直諒 - うえだなおあき 30 歳 株式会社ソリューションウェア 所属 ハッカー飯の中の人(開発はほとんどしてませんが…) https://twitter.com/na0x2c6

Slide 3

Slide 3 text

本スライドについて Git のライセンスに準じ 以降のページは GNU General Public License v2.0 で公開しています。 https://choosealicense.com/licenses/gpl-2.0/ (C)Naoaki Ueda

Slide 4

Slide 4 text

はじめに:Git の 3 つのオブジェクト - blob - ファイルの実体 - tree - フォルダ階層を保持 - commit - コミット情報の保持 - ルート tree と 1 つ前の commit 参照を保持

Slide 5

Slide 5 text

はじめに:Git の 3 つのオブジェクト - blob - ファイルの実体 - tree - フォルダ階層を保持 - commit - コミット情報の保持 - ルート tree と 1 つ前の commit 参照を保持 .git/objects/xx 配下のファイル

Slide 6

Slide 6 text

はじめに:Git の 3 つのオブジェクト - blob - ファイルの実体 - tree - フォルダ階層を保持 - commit - コミット情報の保持 - ルート tree と 1 つ前の commit 参照を保持 git cat-file コマンドでオブジェクトの内 容を見ることができます

Slide 7

Slide 7 text

はじめに:Git の 3 つのオブジェクト - blob - ファイルの実体 - tree - フォルダ階層を保持 - commit - コミット情報の保持 - ルート tree と 1 つ前の commit 参照を保持 ファイルパーミッション情報も保持

Slide 8

Slide 8 text

はじめに:Git の 3 つのオブジェクト - blob - ファイルの実体 - tree - フォルダ階層を保持 - commit - コミット情報の保持 - ルート tree と 1 つ前の commit 参照を保持

Slide 9

Slide 9 text

はじめに:Git の 3 つのオブジェクト - blob - ファイルの実体 - tree - フォルダ階層を保持 - commit - コミット情報の保持 - ルート tree と 1 つ前の commit 参照を保持

Slide 10

Slide 10 text

commit tree blob 凡例

Slide 11

Slide 11 text

はじめに:refs - オブジェクトハッシュの参照を保持 - .git/refs/ 配下に保存

Slide 12

Slide 12 text

- オブジェクトハッシュの参照を保持 - .git/refs/ 配下に保存 ブランチ HEAD はじめに:refs

Slide 13

Slide 13 text

- オブジェクトハッシュの参照を保持 - .git/refs/ 配下に保存 ブランチ HEAD ハッシュのポインタ はじめに:refs

Slide 14

Slide 14 text

main commit tree blob 凡例

Slide 15

Slide 15 text

- バージョン管理だからといって「履歴」「歴史」を主体に考えない はじめに:考え方のコツ

Slide 16

Slide 16 text

- バージョン管理だからといって「履歴」「歴史」を主体に考えない - 各コミットごとにスナップショットが置いてあるだけ はじめに:考え方のコツ

Slide 17

Slide 17 text

はじめに:diff と patch - diff コマンド :ファイル(ツリー)の差分を取る

Slide 18

Slide 18 text

はじめに:diff と patch - diff コマンド :ファイル(ツリー)の差分を取る → patch ファイルを作成する

Slide 19

Slide 19 text

はじめに:diff と patch - diff コマンド :ファイル(ツリー)の差分を取る → patch ファイルを作成する - patch コマンド:patch ファイルをファイル(ツリー)に適用する

Slide 20

Slide 20 text

はじめに:diff と patch - diff コマンド :ファイル(ツリー)の差分を取る → patch ファイルを作成する - patch コマンド:patch ファイルをファイル(ツリー)に適用する 一時期 kernel は tar でアーカイブされ patch ファイルで開発された

Slide 21

Slide 21 text

はじめに:diff と patch - diff コマンド :ファイル(ツリー)の差分を取る → patch ファイルを作成する - patch コマンド:patch ファイルをファイル(ツリー)に適用する 一時期 kernel は tar でアーカイブされ patch ファイルで開発された git は スナップショットの差分 を取る (tree と tree の diff を取る)

Slide 22

Slide 22 text

main commit tree blob 凡例 C 0 C 1 T 1 T 0

Slide 23

Slide 23 text

main commit tree blob 凡例 git は スナップショットの差分 を取る (tree と tree の diff を取る) C 0 C 1 T 1 T 0 B 1 B 0

Slide 24

Slide 24 text

main commit tree blob 凡例 git は スナップショットの差分 を取る (tree と tree の diff を取る) 差分は patch として利用できる C 0 C 1 T 1 T 0 B 1 B 0

Slide 25

Slide 25 text

main commit tree blob 凡例 git は スナップショットの差分 を取る (tree と tree の diff を取る) 差分は patch として利用できる git format-patch git am git cherry-pick git merge C 0 C 1 T 1 T 0 B 1 B 0

Slide 26

Slide 26 text

本題

Slide 27

Slide 27 text

git merge とは

Slide 28

Slide 28 text

「チェックアウト中のブランチへ を統合する」 git merge とは

Slide 29

Slide 29 text

「チェックアウト中のブランチへ を統合する」 - コミットハッシュ - ブランチ - タグ - refs git merge とは

Slide 30

Slide 30 text

「チェックアウト中のブランチへ を統合する」 git merge とは

Slide 31

Slide 31 text

「チェックアウト中のブランチへ を統合する」 git merge とは - 歴史の統合 - ブランチからコミットの履歴を辿れるようにする

Slide 32

Slide 32 text

「チェックアウト中のブランチへ を統合する」 git merge とは - 歴史の統合 - ブランチからコミットの履歴を辿れるようにする - 変更の統合 - ブランチへコミットに含まれる変更点を適用する

Slide 33

Slide 33 text

non fast-foward なマージ main topic git merge --no-ff topic main topic

Slide 34

Slide 34 text

non fast-foward なマージ main topic main topic merge で 新しいコミットを作る git merge --no-ff topic

Slide 35

Slide 35 text

「チェックアウト中のブランチへ を統合する」 git merge とは - 歴史の統合 - ブランチからコミットの履歴を辿れるようにする - 変更の統合 - ブランチへコミットに含まれる変更点を適用する

Slide 36

Slide 36 text

non fast-foward なマージによる「統合」の意味 main topic main topic git merge --no-ff topic

Slide 37

Slide 37 text

non fast-foward なマージによる「統合」の意味 main topic main topic main ブランチから topic の歴史を辿れる git merge --no-ff topic

Slide 38

Slide 38 text

non fast-foward なマージによる「統合」の意味 main topic main topic main ブランチから topic の歴史を辿れる → 歴史の統合 git merge --no-ff topic

Slide 39

Slide 39 text

non fast-foward なマージによる「統合」の意味 main topic main topic コミットを作るときに マージベースに各親コミットへのパッチ を適用する git merge --no-ff topic

Slide 40

Slide 40 text

non fast-foward なマージによる「統合」の意味 main topic main topic コミットを作るときに マージベースに各親コミットへのパッチ を適用する(3-way merge) git merge --no-ff topic

Slide 41

Slide 41 text

non fast-foward なマージによる「統合」の意味 main topic main topic コミットを作るときに マージベースに各親コミットへのパッチ を適用する(3-way merge) → 変更の統合 git merge --no-ff topic

Slide 42

Slide 42 text

non fast-foward なマージによる「統合」の意味 main topic main topic コミットを作るときに マージベースに各親コミットへのパッチ を適用する(3-way merge) → 変更の統合 ※変更を取り込んだ ということ git merge --no-ff topic

Slide 43

Slide 43 text

3-way merge をもう少し詳しく main topic

Slide 44

Slide 44 text

3-way merge をもう少し詳しく main topic git merge --no-ff topic

Slide 45

Slide 45 text

3-way merge をもう少し詳しく main topic 1. マージベース(共通祖先)を見つける git merge --no-ff topic

Slide 46

Slide 46 text

3-way merge をもう少し詳しく main topic git merge --no-ff topic 1. マージベース(共通祖先)を見つける C bas e C base = git merge-base main topic

Slide 47

Slide 47 text

3-way merge をもう少し詳しく main topic git merge --no-ff topic C bas e 1. マージベース(共通祖先)を見つける 2. マージする各コミット に対し、それぞれマージ ベースからパッチを作る C base = git merge-base main topic

Slide 48

Slide 48 text

3-way merge をもう少し詳しく main topic git merge --no-ff topic 1. マージベース(共通祖先)を見つける 2. マージする各コミット に対し、それぞれマージ ベースからパッチを作る C bas e C base = git merge-base main topic p main = git diff C base main p main

Slide 49

Slide 49 text

3-way merge をもう少し詳しく C bas e main topic git merge --no-ff topic 1. マージベース(共通祖先)を見つける 2. マージする各コミット に対し、それぞれマージ ベースからパッチを作る C base = git merge-base main topic p main = git diff C base main p topic = git diff C base topic p main p topic

Slide 50

Slide 50 text

3-way merge をもう少し詳しく C bas e main topic git merge --no-ff topic C base = git merge-base main topic p main = git diff C base main p topic = git diff C base topic p main p topic 1. マージベース(共通祖先)を見つける 2. マージする各コミット に対し、それぞれマージ ベースからパッチを作る 3. マージベースの tree に各パッチを当てる

Slide 51

Slide 51 text

C bas e main topic git merge --no-ff topic C base = git merge-base main topic p main = git diff C base main p topic = git diff C base topic p main p topic ※tree 1. マージベース(共通祖先)を見つける 2. マージする各コミット に対し、それぞれマージ ベースからパッチを作る 3. マージベースの tree に各パッチを当てる 3-way merge をもう少し詳しく

Slide 52

Slide 52 text

C bas e main topic 1. マージベース(共通祖先)を見つける 2. マージする各コミット に対し、それぞれマージ ベースからパッチを作る 3. マージベースの tree に各パッチを当てる git merge --no-ff topic C base = git merge-base main topic p main = git diff C base main p topic = git diff C base topic T base = C base ^{tree} p main p topic T base 3-way merge をもう少し詳しく

Slide 53

Slide 53 text

C bas e main topic 1. マージベース(共通祖先)を見つける 2. マージする各コミット に対し、それぞれマージ ベースからパッチを作る 3. マージベースの tree に各パッチを当てる git merge --no-ff topic C base = git merge-base main topic p main = git diff C base main p topic = git diff C base topic T base = C base ^{tree} p main p topic T base

Slide 54

Slide 54 text

C bas e main topic git merge --no-ff topic p main p topic T base 1. マージベース(共通祖先)を見つける 2. マージする各コミット に対し、それぞれマージ ベースからパッチを作る 3. マージベースの tree に各パッチを当てる C base = git merge-base main topic p main = git diff C base main p topic = git diff C base topic T base = C base ^{tree}

Slide 55

Slide 55 text

C bas e main topic git merge --no-ff topic 1. マージベース(共通祖先)を見つける 2. マージする各コミット に対し、それぞれマージ ベースからパッチを作る 3. マージベースの tree に各パッチを当てる p main p topic T merged T base C base = git merge-base main topic p main = git diff C base main p topic = git diff C base topic T base = C base ^{tree} T merged = T base + p main + p topic

Slide 56

Slide 56 text

C bas e main topic git merge --no-ff topic 1. マージベース(共通祖先)を見つける 2. マージする各コミット に対し、それぞれマージ ベースからパッチを作る 3. マージベースの tree に各パッチを当てる p main p topic T merged T base C base = git merge-base main topic p main = git diff C base main p topic = git diff C base topic T base = C base ^{tree} T merged = T base + p main + p topic git checkout T base -- . git apply --index p main p topic git write-tree

Slide 57

Slide 57 text

C bas e main topic git merge --no-ff topic 1. マージベース(共通祖先)を見つける 2. マージする各コミット に対し、それぞれマージ ベースからパッチを作る 3. マージベースの tree に各パッチを当てる p main p topic T merged T base C base = git merge-base main topic p main = git diff C base main p topic = git diff C base topic T base = C base ^{tree} T merged = T base + p main + p topic git checkout T base -- . git apply --index p main p topic T merged = $(git write-tree)

Slide 58

Slide 58 text

C bas e main topic git merge --no-ff topic 1. マージベース(共通祖先)を見つける 2. マージする各コミット に対し、それぞれマージ ベースからパッチを作る 3. マージベースの tree に各パッチを当てる 4. マージした各コミット を親コミットに、パッチを当 てた tree をルート tree にしたコミットを作る C base = git merge-base main topic p main = git diff C base main p topic = git diff C base topic T base = C base ^{tree} T merged = T base + p main + p topic main = C merged ^1 topic = C merged ^2 p main p topic T merged T base C merged

Slide 59

Slide 59 text

C bas e main topic git merge --no-ff topic 1. マージベース(共通祖先)を見つける 2. マージする各コミット に対し、それぞれマージ ベースからパッチを作る 3. マージベースの tree に各パッチを当てる 4. マージした各コミット を親コミットに、パッチを当 てた tree をルート tree にしたコミットを作る p main p topic T merged T base C base = git merge-base main topic p main = git diff C base main p topic = git diff C base topic T base = C base ^{tree} T merged = T base + p main + p topic = C merged ^{tree} main = C merged ^1 topic = C merged ^2 C merged

Slide 60

Slide 60 text

C bas e main topic git merge --no-ff topic 1. マージベース(共通祖先)を見つける 2. マージする各コミット に対し、それぞれマージ ベースからパッチを作る 3. マージベースの tree に各パッチを当てる 4. マージした各コミット を親コミットに、パッチを当 てた tree をルート tree にしたコミットを作る p main p topic T merged T base C base = git merge-base main topic p main = git diff C base main p topic = git diff C base topic T base = C base ^{tree} T merged = T base + p main + p topic = C merged ^{tree} main = C merged ^1 topic = C merged ^2 C merged git commit-tree -m “Merge branch ‘topic’” -p main -p topic T merged

Slide 61

Slide 61 text

fast-forward(早送り) な merge main topic main topic git merge --ff topic

Slide 62

Slide 62 text

fast-forward(早送り) な merge main topic main topic git merge --ff topic main は topic の歴史を辿れる

Slide 63

Slide 63 text

fast-forward(早送り) な merge main topic main topic git merge --ff topic main は topic の歴史を辿れる → topic の「歴史」を取り込んだ

Slide 64

Slide 64 text

fast-forward(早送り) な merge main topic main topic git merge --ff topic main は topic の歴史を辿れる → topic の「歴史」を取り込んだ main と topic の tree は同じ

Slide 65

Slide 65 text

fast-forward(早送り) な merge main topic main topic git merge --ff topic main は topic の歴史を辿れる → topic の「歴史」を取り込んだ main と topic の tree は同じ → topic の「変更」を取り込んだ

Slide 66

Slide 66 text

git rebase

Slide 67

Slide 67 text

git rebase ブランチの歴史を変えたい

Slide 68

Slide 68 text

git rebase ブランチの歴史を変えたい - fork 元(base)を変えたい

Slide 69

Slide 69 text

git rebase ブランチの歴史を変えたい - fork 元(base)を変えたい - fork 元が古い → fork した当時からの変更点がより多くなる → よりマージしにくくなる

Slide 70

Slide 70 text

git rebase ブランチの歴史を変えたい - fork 元(base)を変えたい - fork 元が古い → fork した当時からの変更点がより多くなる → よりマージしにくくなる - コミットをきれいにしたい

Slide 71

Slide 71 text

git rebase ブランチの歴史を変えたい - fork 元(base)を変えたい - fork 元が古い → fork した当時からの変更点がより多くなる → よりマージしにくくなる - コミットをきれいにしたい

Slide 72

Slide 72 text

これを base を変えたい main topic

Slide 73

Slide 73 text

これを base を変えたい main topic

Slide 74

Slide 74 text

これを base を変えたい main topic こうしたい main topic

Slide 75

Slide 75 text

main topic main topic re-base git rebase main topic

Slide 76

Slide 76 text

考え方 main topic main C 0 C 1 C 0 C 1 C’ 0 C’ 1 topic base を基点に同等のコミットを積み上げる

Slide 77

Slide 77 text

C 0 main topic C 1 基点の base を見つける C base C base = git merge-base main topic rebase 前

Slide 78

Slide 78 text

C 0 main topic C 1 topic ブランチ HEAD を main と一致させる git checkout topic git reset --hard main main topic rebase 前 C base rebase 途中

Slide 79

Slide 79 text

C 0 C 1 main C base topic 積み上げるコミットのパッチを取り出す p 0 = git diff C base C 0 p 1 = git diff C 0 C 1 main topic rebase 前 rebase 途中 p 0 p 1

Slide 80

Slide 80 text

C 0 C 1 main C base topic パッチを使ってコミットを作る git apply --index p 0 git commit main topic rebase 前 rebase 途中 p 0 p 1 C’ 0

Slide 81

Slide 81 text

C 0 C 1 main C base topic パッチを使ってコミットを作る main topic rebase 前 rebase 後 p 0 p 1 C’ 0 C’ 1 git apply --index p 1 git commit

Slide 82

Slide 82 text

C 0 C 1 main C base topic パッチを使ってコミットを作る = cherry-pick main topic rebase 前 p 0 p 1 C’ 0 C’ 1 git apply --index p 1 git commit git apply --index p 0 git commit git cherry-pick C 0 git cherry-pick C 1 rebase 後

Slide 83

Slide 83 text

C 0 C 1 main C base topic パッチを使ってコミットを作る = cherry-pick main topic rebase 前 p 0 p 1 C’ 0 C’ 1 git apply --index p 1 git commit git apply --index p 0 git commit git cherry-pick C 0 git cherry-pick C 1 rebase は reset と cherry-pick を駆使している rebase 後

Slide 84

Slide 84 text

C 0 C 1 main C base topic パッチを使ってコミットを作る = cherry-pick main topic rebase 前 p 0 p 1 C’ 0 C’ 1 git apply --index p 1 git commit git apply --index p 0 git commit git cherry-pick C 0 git cherry-pick C 1 rebase は reset と cherry-pick を駆使している 編集可能にしたのが git rebase --interactive rebase 後

Slide 85

Slide 85 text

C 0 C 1 main C base topic パッチを使ってコミットを作る = cherry-pick main topic rebase 前 p 0 p 1 C’ 0 C’ 1 git apply --index p 1 git commit git apply --index p 0 git commit git cherry-pick C 0 git cherry-pick C 1 rebase は reset と cherry-pick を駆使している 編集可能にしたのが git rebase --interactive rebase 後

Slide 86

Slide 86 text

C 0 C 1 main C base topic パッチを使ってコミットを作る = cherry-pick main topic rebase 前 p 0 p 1 C’ 0 C’ 1 git apply --index p 1 git commit git apply --index p 0 git commit git cherry-pick C 0 git cherry-pick C 1 rebase は reset と cherry-pick を駆使している 編集可能にしたのが git rebase --interactive rebase 後

Slide 87

Slide 87 text

よき git ライフを。 ご清聴ありがとうございました!!!