次は衝突がある場合の演習を行います。
この場合はプルした後に手作業で衝突している部分を修正し、改めてプル、コミット、プッシュをする必要があります。


まずBさんが作業するので、他のメンバーはBさんの作業を後から見る
試しに B さんはプッシュを実行してみる

git push

すると

! [rejected]

と表示される
これはリモートリポジトリが自分より先に他の人(Aさん)により更新されているので、先にプルしないとプッシュ出来ないということを示している

Bさんはプルを実行し、リモートリポジトリの更新内容をローカルリポジトリに取り込む

git pull --no-edit

すると

CONFLICT (content)

と表示されるが、これは衝突が起きたのでファイルを修正しろということを示している

Bさんは git status でどのファイルで衝突が起きたか確認する

git status

すると

both modified: hoge.txt

と表示されるので、hoge.txt に衝突が起きていることが分かる

Bさんは hoge.txt を開いて中身が以下のようになっていることを確認する

name?
<<<<<<< HEAD
B
=======
A
>>>>>>> ハッシュ値

ここで「=======」「<<<<<<<」「>>>>>>>」をマーカーという

上の「<<<<<<<」と「=======」で囲まれた部分が自分がローカルリポジトリに対して行った更新内容を表す
下の「=======」「>>>>>>>」で囲まれた部分が他の人がリモートリポジトリに対して行った更新内容を表す

この時点では以下の状態4になっています。

Bさんのワーキングツリーにある hoge.txt にマーカーが含まれていることに注目して下さい。
これは hoge.txt 同じ行にローカルとリモートで異なる文字(AとB)が追加されたため Git がどうすれば良いのか分からなくて困っていることを意味します。

また B さんのインデックスの hoge.txt には衝突フラグが付いています。
B さんの HEAD はそのままです。

ちなみに更新内容が被っていない時は Git は自動的に中身を修正してくれます(「マージ」といいます)。



状態 4 (README.md と HEAD 以前のコミットは省略)


Aさん


ワーキングツリー
hoge.txt
name?
A


インデックス
hoge.txt
name?
A


ローカルリポジトリ
HEAD
hoge.txt
name?
A
"my name is A"
Bさん


ワーキングツリー
hoge.txt
name?
<<<<<<< HEAD
B
=======
A
>>>>>>> ハッシュ値


インデックス
hoge.txt → 衝突


ローカルリポジトリ
HEAD
hoge.txt
name?
B
"my name is B"
Cさん


ワーキングツリー
hoge.txt
name?
C


インデックス
hoge.txt
name?
C


ローカルリポジトリ
HEAD
hoge.txt
name?
C
"my name is C"
Dさん


ワーキングツリー
hoge.txt
name?
D


インデックス
hoge.txt
name?
D


ローカルリポジトリ
HEAD
hoge.txt
name?
D
"my name is D"
リモートリポジトリ(origin/main)
HEAD
hoge.txt
name?
A
"my name is A"

では B さんは衝突している hoge.txt を修正してプッシュしてみましょう。

Bさんは A と B の文字を含む様に hoge.txt を修正する ※ この作業を「マージ(merge)」という

name? 
B 
A
(空行)

※ BとAの後ろにスペースが入らないように注意
※ 4行になっていることに注意

git add hoge.txt
git status で衝突フラグ(both modified)が消えている事を確認する
git commit -m "merged A and B"
git pull --no-edit を再実行

※ この時点では他の人はリモートリポジトリを更新してないので「Already up to date」と表示されて何も起きないがプッシュする前にプルする習慣を付けるために実行する

git push
全員がブラウザを開き、リモートリポジトリ「gitremote」の表示を更新し、hoge.txt の内容が変わっていることを確認する。

すると以下の状態5になります。
BさんのローカルリポジトリのHEADの内容がそのままリモートリポジトリにアップロードされている事が分かります。
ただし A、C、DさんのHEADはそのままです。



状態 5 (README.md と HEAD 以前のコミットは省略)


Aさん


ワーキングツリー
hoge.txt
name?
A


インデックス
hoge.txt
name?
A


ローカルリポジトリ
HEAD
hoge.txt
name?
A
"my name is A"
Bさん


ワーキングツリー
hoge.txt
name?
B
A


インデックス
hoge.txt
name?
B
A


ローカルリポジトリ
HEAD
hoge.txt
name?
B
A
"merged A and B"
Cさん


ワーキングツリー
hoge.txt
name?
C


インデックス
hoge.txt
name?
C


ローカルリポジトリ
HEAD
hoge.txt
name?
C
"my name is C"
Dさん


ワーキングツリー
hoge.txt
name?
D


インデックス
hoge.txt
name?
D


ローカルリポジトリ
HEAD
hoge.txt
name?
D
"my name is D"
リモートリポジトリ(origin/main)
HEAD
hoge.txt
name?
B
A
"merged A and B"

では続けてCさんがプルとプッシュを実行し、終わったら最後に Dさんがプルとプッシュを実行して以下の状態6にして下さい。
コミットのコメントは

Cさんは "merged C and AB"
Dさんは "merged D and ABC"

とします。


状態 6 (README.md と HEAD 以前のコミットは省略)


Aさん


ワーキングツリー
hoge.txt
name?
A


インデックス
hoge.txt
name?
A


ローカルリポジトリ
HEAD
hoge.txt
name?
A
"my name is A"
Bさん


ワーキングツリー
hoge.txt
name?
B
A


インデックス
hoge.txt
name?
B
A


ローカルリポジトリ
HEAD
hoge.txt
name?
B
A
"merged A and B"
Cさん


ワーキングツリー
hoge.txt
name?
C
B
A


インデックス
hoge.txt
name?
C
B
A


ローカルリポジトリ
HEAD
hoge.txt
name?
C
B
A
"merged C and AB"
Dさん


ワーキングツリー
hoge.txt
name?
D
C
B
A


インデックス
hoge.txt
name?
D
C
B
A


ローカルリポジトリ
HEAD
hoge.txt
name?
D
C
B
A
"merged D and ABC"
リモートリポジトリ(origin/main)
HEAD
hoge.txt
name?
D
C
B
A
"merged D and ABC"