チーム作業を円滑に行えるようになるために、競合解決手続きをぼっちシミュレーション。
Githubでレポジトリを作成
レポジトリ名を「gitsim」として、テスト用のファイルとして「conflict.txt」という空のファイルを作成しました。
二人の仮想ユーザーを準備
適当なディレクトリに2つのディレクトリを用意します。これらを各ユーザーのローカル環境と想定して、それぞれにgitsimレポジトリのクローンを導入します。
mkdir user1
mkdir user2
cd user1
git clone https://github.com/kota7/gitsim.git
cd ../user2
git clone https://github.com/kota7/gitsim.git
二人が独立して作業・競合を発生させる
ユーザー1がローカルで作業、githubへpushします。
cd ../user1/gitsim
echo コーヒーを1つ > conflict.txt
git add .
git commit -m 'edited conflict.txt'
git push # ここで認証が必要
一方、ユーザー2もまた独立して作業し、githubへpushしたとします。すると、gitは、ユーザー2の環境にあるファイルが最新のものではない(ユーザー1の作業を反映していないので)ことを指摘して、先にpullやfetchで最新の状態にしてからpushするように指摘します。
cd ../../user2/gitsim
echo 紅茶を1つ > conflict.txt
git add .
git commit -m 'edited conflict.txt'
git push # ここで認証が必要
# ! [rejected] master -> master (fetch first)
#error: failed to push some refs to 'https://github.com/kota7/gitsim.git'
#hint: Updates were rejected because the remote contains work that you do
#hint: not have locally. This is usually caused by another repository pushing
#hint: to the same ref. You may want to first integrate the remote changes
#hint: (e.g., 'git pull ...') before pushing again.
#hint: See the 'Note about fast-forwards' in 'git push --help' for details.
そこで、fetch + "merge FETCH_HEAD" で最新の状態への更新を試みます(pullでも同じことになります)。この時、ユーザー1と2の編集が競合している(つまり互いに相容れない)と判断されると、該当するファイルの箇所が下記のように自動的に変更されます。
git fetch
git merge FETCH_HEAD
#Auto-merging conflict.txt
#CONFLICT (content): Merge conflict in conflict.txt
#Automatic merge failed; fix conflicts and then commit the result.
cat conflict.txt
#<<<<<<< HEAD
#紅茶を1つ
#=======
#コーヒーを1つ
#>>>>>>> FETCH_HEAD
競合の解決とその結果
競合の解決とは、<<<< ~ >>>>
とされた箇所をどうするかを決定していく作業です。具体的には、ファイル内の該当する箇所を編集して再コミットします。その際、通常はそのコミットが競合を解決するためのものであることを明記するとプロセスの透明性が高くなります。
echo 紅ヒーを2つ > conflict.txt
git add .
git commit -m 'resolved the conflict'
git push
ログには、ユーザー1と2がそれぞれ独自に行ったコミットも残っているし、その後競合を解決したコミットも残ります。
git log --oneline
#9ada39b resolved the conflict
#4f939d1 edited conflict.txt
#b45b03b edited conflict.txt
#ac1a498 Create conflict.txt
#7674da8 Initial commit