Merges
-
git merge
- 単一リポジトリ内の2つ以上のブランチを統合する
- 多くの場合2つ
-
コンフリクト
- 同一ファイルの同一行の変更が競合
- 発生したら、“unmerged”としてインデックスにマークされる
- 解消は開発者に委ねられる
Merge Examples
git checkout branch # マージ先をチェックアウト
git merge other_branch # other_branchをbranchにマージ
Preparing for a Merge
-
cleanな状態で始めたほうがいいよ
- clean working directory
- clean index
- 【補】v2.17.1で、cleanじゃないとそもそもmergeできない感じだった
Merging Two Branches
- こんな状態
git log --branches --graph --oneline
* 3b21657 (alternate) Add alternate's line 4
| * 1cc6004 (HEAD -> master) Another file
|/
* a1225b9 Initial 3 line file
- 2つの変更は衝突していない
git diff master alternate
diff --git a/file b/file
index fe999ef..a3c4be1 100644
--- a/file
+++ b/file
@@ -1,3 +1,4 @@
Line 1 Stuff
Line 2 Stuff
Line 3 Stuff
+Line 4 alternate stuff
diff --git a/other_file b/other_file
deleted file mode 100644
index eaeeeba..0000000
--- a/other_file
+++ /dev/null
@@ -1 +0,0 @@
-Here is stuff on another file!
- マージはスムーズに済む
git merge alternate
Merge made by the 'recursive' strategy.
file | 1 +
1 file changed, 1 insertion(+)
- コミットグラフはこうなる
git log --graph --pretty=oneline --abbrev-commit
* 7a79684 (HEAD -> master) Merge branch 'alternate'
|\
| * 3b21657 (alternate) Add alternate's line 4
* | 1cc6004 Another file
|/
* a1225b9 Initial 3 line file
-
git merge other_branch
は、「今いるブランチにother_branch
をマージする」の意- 今いるブランチしか影響を受けない
- この操作ではalternateブランチは影響を受けていない
A Merge with a Conflict
git show-branch
* [alternate] Add alternate line 5 and 6
! [master] Add line 5 and 6
--
* [alternate] Add alternate line 5 and 6
+ [master] Add line 5 and 6
*+ [alternate^] Add alternate's line 4
-
5,6行目がコンフリクト
- master: line5,6追加
- alternate: alternate line5,6追加
git diff master alternate
diff --git a/file b/file
index c063061..1a7b51b 100644
--- a/file
+++ b/file
@@ -2,5 +2,5 @@ Line 1 Stuff
Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
-Line 5 stuff
-Line 6 stuff
+Line 5 alternate stuff
+Line 6 alternate stuff
diff --git a/other_file b/other_file
deleted file mode 100644
index eaeeeba..0000000
--- a/other_file
+++ /dev/null
@@ -1 +0,0 @@
-Here is stuff on another file!
- merge中断される
git checkout master
git merge alternate
Auto-merging file
CONFLICT (content): Merge conflict in file
Automatic merge failed; fix conflicts and then commit the result.
- コンフリクト
git diff
diff --cc file
index c063061,1a7b51b..0000000
--- a/file
+++ b/file
@@@ -2,5 -2,5 +2,10 @@@ Line 1 Stuf
Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
++<<<<<<< HEAD
+Line 5 stuff
+Line 6 stuff
++=======
+ Line 5 alternate stuff
+ Line 6 alternate stuff
++>>>>>>> alternate
- コンフリクトをどう解消するかは開発者次第
- 今回はこうした
(編集)
git add file
git diff --cached
diff --git a/file b/file
index c063061..89e2b8f 100644
--- a/file
+++ b/file
@@ -3,4 +3,4 @@ Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
Line 5 stuff
-Line 6 stuff
+Line 6 alternate stuff
git commit
するとマージコミットのテンプレートメッセージがEDITORで開く
Merge branch 'alternate'
# Conflicts:
# file
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
# .git/MERGE_HEAD
# and try again.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
# All conflicts fixed but you are still merging.
#
# Changes to be committed:
# modified: file
#
- コミットグラフはこうなる
* ffb7c83 (HEAD -> master) Merge branch 'alternate'
|\
| * 152d410 (alternate) Add alternate line 5 and 6
* | bf387d7 Add line 5 and 6
* | 7a79684 Merge branch 'alternate'
|\ \
| |/
| * 3b21657 Add alternate's line 4
* | 1cc6004 Another file
|/
* a1225b9 Initial 3 line file
Working with Merge Conflicts
Locating Conflicted Files
- git statusでコンフリクトが発生しているファイルを特定できる
git status
On branch tmp
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: file
no changes added to commit (use "git add" and/or "git commit -a")
- git ls-files -u でblobを特定できる
git ls-files -u
100644 a3c4be15bb92e24db3cc4a2db0aa889148a93afe 1 file
100644 c06306161c8c2bd4a16da3f6a3e7e130b9fcecca 2 file
100644 1a7b51bee6459775eb9f30df455ea327fe0d99fe 3 file
git cat-file -p a3c4be15
git cat-file -p c0630616
git cat-file -p 1a7b51be
Line 1 Stuff
Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
Line 1 Stuff
Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
Line 5 stuff
Line 6 stuff
Line 1 Stuff
Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
Line 5 alternate stuff
Line 6 alternate stuff
- git diffでむちゃくちゃ詳細にわかる
git diff
diff --cc file
index c063061,1a7b51b..0000000
--- a/file
+++ b/file
@@@ -2,5 -2,5 +2,10 @@@ Line 1 Stuf
Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
++<<<<<<< HEAD
+Line 5 stuff
+Line 6 stuff
++=======
+ Line 5 alternate stuff
+ Line 6 alternate stuff
++>>>>>>> alternate
Inspecting Conflicts
-
>>>>>>>
,=======
,<<<<<<<
は人間向けであってプログラム向けではない- コミットするまでにはちゃんと消そうね
git diff with conflicts
git diff
git diff --ours # git diff HEAD と同義
git diff --theirs # git diff MERGE_HEAD と同義
git diff --base # git diff $(git merge-base HEAD MERGE_HEAD) と同義
diff --cc file
index c063061,1a7b51b..0000000
--- a/file
+++ b/file
@@@ -2,5 -2,5 +2,10 @@@ Line 1 Stuf
Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
++<<<<<<< HEAD
+Line 5 stuff
+Line 6 stuff
++=======
+ Line 5 alternate stuff
+ Line 6 alternate stuff
++>>>>>>> alternate
* Unmerged path file
diff --git a/file b/file
index c063061..a5e02b0 100644
--- a/file
+++ b/file
@@ -2,5 +2,10 @@ Line 1 Stuff
Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
+<<<<<<< HEAD
Line 5 stuff
Line 6 stuff
+=======
+Line 5 alternate stuff
+Line 6 alternate stuff
+>>>>>>> alternate
* Unmerged path file
diff --git a/file b/file
index 1a7b51b..a5e02b0 100644
--- a/file
+++ b/file
@@ -2,5 +2,10 @@ Line 1 Stuff
Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
+<<<<<<< HEAD
+Line 5 stuff
+Line 6 stuff
+=======
Line 5 alternate stuff
Line 6 alternate stuff
+>>>>>>> alternate
* Unmerged path file
diff --git a/file b/file
index a3c4be1..a5e02b0 100644
--- a/file
+++ b/file
@@ -2,3 +2,10 @@ Line 1 Stuff
Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
+<<<<<<< HEAD
+Line 5 stuff
+Line 6 stuff
+=======
+Line 5 alternate stuff
+Line 6 alternate stuff
+>>>>>>> alternate
git log with conflicts
git log --merge --left-right -p
commit > 152d410b862f8f74966ed4b622a58704af67b51f
Author: Daiki Horiyama <xxxxxxxxx@gmail.com>
date: Sun Nov 24 16:04:36 2019 +0900
Add alternate line 5 and 6
diff --git a/file b/file
index a3c4be1..1a7b51b 100644
--- a/file
+++ b/file
@@ -2,3 +2,5 @@ Line 1 Stuff
Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
+Line 5 alternate stuff
+Line 6 alternate stuff
commit < bf387d7ce60288c102df6566b37d07d0679b99e4
Author: Daiki Horiyama <xxxxxxxxx@gmail.com>
date: Sun Nov 24 15:57:00 2019 +0900
Add line 5 and 6
diff --git a/file b/file
index a3c4be1..c063061 100644
--- a/file
+++ b/file
@@ -2,3 +2,5 @@ Line 1 Stuff
Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
+Line 5 stuff
+Line 6 stuff
-
oursとtheirsそれぞれについての情報が得られる
- いつ
- なぜ
- どのように
- 誰が
-
オプション解説
-
--merge
- コンフリクトを生じているファイルのみ表示
-
--left-right
- oursを
<
で、theirsを>
で表す
- oursを
-
-p
- 歴史にコミット情報とpatchも添えるやつ
-
- マージの苦痛を和らげるためには、小さなコミットをこまめにマージして
How Git Keeps Track of Conflicts
.git/MERGE_HEAD
-
.git/MERGE_MSG
- マージコミットのデフォルトメッセージ
-
インデックス
- base, ours, theirsの3つ保持する
git ls-files -u
で3つ出てきたやつ
-
作業ディレクトリ
-
>>>>>>>
等のマーカー付きのファイルはインデックスではなく作業ディレクトリにある- だから
--cached
なしのgit diff
で差分を表示できる
- だから
-
-
git diff
で、インデックス上の別バージョンのファイルの比較を行うことができる- 1: base
- 2: ours
- 3: theirs
git diff :2:file :3:file
diff --git a/file b/file
index c063061..1a7b51b 100644
--- a/file
+++ b/file
@@ -2,5 +2,5 @@ Line 1 Stuff
Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
-Line 5 stuff
-Line 6 stuff
+Line 5 alternate stuff
+Line 6 alternate stuff
- コンフリクト解消のコンテキストにおいて、
git checkout --ours/--theirs
で一方の変更を受け入れられる
cat file
Line 1 Stuff
Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
<<<<<<< HEAD
Line 5 stuff
Line 6 stuff
=======
Line 5 alternate stuff
Line 6 alternate stuff
>>>>>>> alternate
git checkout --theirs file
cat file
Line 1 Stuff
Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
Line 5 alternate stuff
Line 6 alternate stuff
Finishing Up a Conflict Resolution
git ls-files -s
100644 a3c4be15bb92e24db3cc4a2db0aa889148a93afe 1 file
100644 c06306161c8c2bd4a16da3f6a3e7e130b9fcecca 2 file
100644 1a7b51bee6459775eb9f30df455ea327fe0d99fe 3 file
100644 eaeeeba5973e46152dc758215c7e76dcecfd5f9b 0 other_file
-
SHA1とファイル名との間の数字は、ステージング番号
- 1: base
- 2: ours
- 3: thries
- 0: コンフリクトがないことを意味する
git add file
git ls-files -s
100644 1a7b51bee6459775eb9f30df455ea327fe0d99fe 0 file
100644 eaeeeba5973e46152dc758215c7e76dcecfd5f9b 0 other_file
-
コンフリクトを解消して
git add
等すると0になる>>>>>>>>
とかを消し忘れぬよう
git commit
(コミットメッセージ編集)
git show
Merge branch 'alternate' into tmp
# Conflicts:
# file
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
# .git/MERGE_HEAD
# and try again.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch tmp
# All conflicts fixed but you are still merging.
#
# Changes to be committed:
# modified: file
#
commit fb21453bd655788150e16cc43c4479ebe0ef2649 (HEAD -> tmp)
Merge: bf387d7 152d410
Author: Daiki Horiyama <xxxxxxxxx@gmail.com>
date: Sun Nov 24 17:22:49 2019 +0900
Merge branch 'alternate' into tmp
-
通常のコミットとマージコミットの違い
-
Merge: bf387d7 152d410
- 親が2つ(以上)ある
-
デフォルトコミットメッセージにコンフリクトのあったファイルが記述されている
#
でコメントアウトされている- マージ後に問題が発生したときはおそらくこのファイルが悪い
- diffはマージ元ブランチとの差分のみ
-
git checkout master
git diff HEAD^
diff --git a/file b/file
index c063061..89e2b8f 100644
--- a/file
+++ b/file
@@ -3,4 +3,4 @@ Line 2 Stuff
Line 3 Stuff
Line 4 alternate stuff
Line 5 stuff
-Line 6 stuff
+Line 6 alternate stuff
Aborting or Restarting a Merge
- コミット前なら
git reset --hard HEAD
- コミット直後なら
git reset --hard ORIG_HEAD
- ORIG_HEAD: マージ直後にやっぱりやめる用のref
- working directoryがdirtyな状態でmergeを始めていた場合、その変更分は失われるので注意
- 【補】
git merge --abort
というのもある
英語
-
octothorpe
- 「#」記号
-
disparty
- 差異
-
gory detail
- おぞましいまでの細部
-
mitigate the pain
- 苦痛をやわらげる
-
botch
- しくじる