13
44
Gitの歴史:コミットがつながったもの
ブランチ:コミットについたラベル
カレントブランチ:HEADが指しているブランチ
branch
HEAD branch
HEAD
other other
コミットするとコミットが作られカレントブランチが指していたコミットにつながる
さらにカレントブランチが新たに作られたコミットを指す
他のブランチは動かない
ブランチを切り替えてコミットすると歴史が分岐する
18
44
main feature
+ + + =
main
feature
$ git merge feature
HEAD
HEAD
カレントブランチがマージしたいブランチの直接の祖先であるとき
カレントブランチを
移動するだけでマージ完了
Slide 19
Slide 19 text
19
44
main
feature
HEAD
main
feature
HEAD
$ git merge feature
新に作られたコミットを
マージコミットと呼ぶ
Slide 20
Slide 20 text
20
44
main
branch
HEAD
+
+ =
=
non fast-forwardマージで作られるコミット
親コミットを二つ持つ
二つの線は、それぞれの親からの差分を表している
Slide 21
Slide 21 text
21
44
main feature
HEAD
main
feature
HEAD
+
$ git merge --no-ff feature
Fast-forwardマージ可能な場合でもマージコミットを作ることができる
Slide 22
Slide 22 text
22
44
main
feature
HEAD
マージコミットを作ると、機能追加をしようとした
ブランチがどこから分岐したかの情報が残る
main
feature
HEAD
fast-forwardすると歴史が一本になって見やすい
どこから分岐したかの情報が失われ、マージを取り消しづらい
Slide 23
Slide 23 text
23
44
$ git branch -d ブランチ名
指定したブランチを削除する
削除されるのはブランチだけで、コミットは消えない
main
feature
HEAD
$ git branch –d feature
Deleted branch feature (was 1c168e1).
main
HEAD
1c168e1
削除前に指していたコミットハッシュが表示される
Slide 24
Slide 24 text
24
44
main
HEAD
feature
$ git branch -d branch
error: The branch 'feature' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature'.
マージされていないブランチを削除しようとするとエラーになる
もしどうしても削除したいのなら「-D」オプションをつけろ
Slide 25
Slide 25 text
25
44
main
HEAD
もし削除したら?
コミットは失われない
しかし、既存のブランチからたどれなくなる
mainブランチからたどれるコミット
各コミットは「親コミット」を覚えている
「親コミット」をたどることで自分のルーツを知ることができる
「子供コミット」は知らない
マージされていないブランチを削除すると、たどれないコミットが生じる
どのブランチからもたどれない
27
44
分岐した歴史をマージする際、Gitは可能な限り、両方の修正を取り込もうとする
main
HEAD
feature
main
HEAD
$ git merge feature
異なるファイルが修正されていたら、両方の修正を取り込む
同じファイルでも、修正箇所が重なってなければ取り込む
Slide 28
Slide 28 text
28
44
同じファイルの同じ場所が同時に修正されていた場合、Gitは
どのようにマージすれば良いか判断できない。これを衝突
(conflict)と呼ぶ。
main
HEAD
feature
main
HEAD
$ git merge feature
Slide 29
Slide 29 text
29
44
mainとfeatureで同時にtest.txtを修正した状態でマージしようとした
$ git merge feature
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.
• test.txtを自動マージしようとした
• 衝突(CONFLICT)が発生した
• 衝突を解決(fix)して、結果をコミットせよ
Gitは衝突を検出すると、ユーザに解決を求める
Slide 30
Slide 30 text
30
44
Hello merge!
This line is modified on main.
カレントブランチ
(HEAD)でのtest.txt
featureブランチ
でのtest.txt
Hello merge!
This line is modified on feature.
マージに失敗し、衝突状態のtest.txt
Hello Merge!
<<<<<<< HEAD
This line is modified on main.
=======
This line is modified on feature.
>>>>>>> feature
ここがHEADではこう
なってるけど
featureブランチではで
はこうなってるよ
Slide 31
Slide 31 text
31
44
test.txtを適切に修正したあと、git add、git commitする
main
HEAD
「マージコミット」を作っている
Gitが自動でマージコミットを作れなかったので、マージ
コミットのあるべき姿をインデックスに登録してコミット
33
44
• カレントブランチとリベース先のブランチの共通祖先から
• カレントブランチまでの修正を
• リベース先のブランチにぶら下げる
操作のこと
リベースとは
main
branch
HEAD
main branch
HEAD
mainとbranchの共通祖先
$ git rebase branch
Slide 34
Slide 34 text
34
44
main branch HEAD
c1 c2
c1’ c2’
$ git rebase main
+ +
+
+ branch
HEAD
main
Slide 35
Slide 35 text
35
44
main
branch
HEAD
main branch
HEAD
$ git rebase branch
branchブランチのベース(赤丸)を、mainブランチの指すコ
ミットに張り替えたように見えるのでリベース
移動しているのは「線(パッチ)」であってコミットではない
コミットは新たに作られる
Slide 36
Slide 36 text
36
44
Alice
Bob
main
feature_B
機能Aを実装
機能Bを実装
mainにマージ
• mainブランチから、Aliceがfeature_Aを、Bobがfeature_Bを分岐
• Aliceが機能Aを実装してmainにマージ(fast-forward)
• Bobが機能Bを実装してmainにマージ(non-fast-forward)
Slide 37
Slide 37 text
37
44
• mainブランチから、Aliceがfeature_Aを、Bobがfeature_Bを分岐
• Aliceが機能Aを実装してmainにマージ(fast-forward)
• Bobが機能Bを実装してmainへリベース
• feature_Bがfast-forwardマージ可能になる
main
feature_B
main feature_B
main
rebase
merge
機能A
を実装
機能B
を実装
順番に開発したような歴史が作られた
Slide 38
Slide 38 text
38
44
HEAD main feature_A
A1追加 A2追加 Doc追加
フィーチャーブランチをそのままmainにマージすると
「中途半端な状態のコミット」が残ることがある
このままfast-forwardマージすると、「途中経過」も歴史に残る
mainブランチは「常にきれいな状態」であって欲しい
機能A実現のためのサブタスク
Slide 39
Slide 39 text
39
44
HEAD main feature_A
A1追加 A2追加 Doc追加
HEAD main feature_A
機能A追加
+
マージする前にコミットをまとめて歴史を整理しておく
歴史の整理にもリベースを使う