はじめに
庭園ガイドの次の更新では、同じ行に2つの正しい情報が関わります。用意された自分のコミットでは、来園者を南側の入口へ案内し、来園者窓口の電話番号を更新しています。チームメンバーが公開したコミットでは、開園時間と段差のない経路を変更しています。最終的なガイドには、両方の情報が必要です。
この実験は専用の独立したリポジトリで始まるため、前の VM のファイルは必要ありません。実際の内容の競合を確認し、未完了のマージを取り消す練習をしてから、正しい項目を組み合わせ、新しい受信用クローンへ結果を届けます。
前のガイド付き実験を完了しているか、リモート名、フェッチ、マージ、プッシュ、クローンをすでに理解していることが必要です。ターミナルでの基本的な移動、コミット、差分も前提です。所要時間の45分は、著者による見積もりです。
競合を読み取り、安全にやり直す
このステップでは、2人の変更を比較し、自動マージが止まる理由を確認して、元の手元の状態へ安全に戻る練習をします。
Terminal を開き、この実験用に独立して用意されたリポジトリへ移動します。
cd /home/labex/project/guide-team/editor
このリポジトリだけで使う作成者情報を設定します。--local はグローバル設定を変更せず、引用符は名前を1つにまとめます。次の架空の値は例であり、必須の個人情報ではありません。
git config --local user.name "Guide Editor"
git config --local user.email "guide@example.com"
用意された手元のガイドを読み、チームメンバーの更新をフェッチします。
cat guide.txt
git fetch origin
チームメンバーのバージョンを読みます。revision:path は実際にコミットされたファイルを選び、--no-pager はそれを直接出力します。
git --no-pager show origin/main:guide.txt
自分のバージョンには South entrance と 09:00-17:00、チームメンバーのバージョンには North entrance と 10:00-18:00 が記載されています。業務上の判断は互いに独立しています。自分の南側の入口と、チームメンバーの新しい開園時間を使ってください。最終入場についての文は残します。ほかのページにある、自分の来園者窓口の電話番号と、チームメンバーの川沿いのスロープも保持します。
マージを開始します。--no-edit は、マージが自動的に完了する場合にエディターを開かないようにします。ここでは非ゼロのステータスを返し、内容の競合で停止することを想定しています。 単独で実行し、その後も先へ進んでください。
git merge --no-edit origin/main
CONFLICT (content): Merge conflict in guide.txt と Automatic merge failed; fix conflicts and then commit the result. が表示されるはずです。Git はまだ新しいコミットを作成していません。
短い形式のステータスと、競合したファイルを読みます。
git status --short
cat guide.txt
UU guide.txt は、ファイルが未マージであることを示します。ファイル内では、<<<<<<< HEAD が自分のバージョンの始まり、======= が選択肢の区切り、>>>>>>> origin/main がチームメンバーのバージョンの終わりを表します。これらのマーカーは内容の不一致を示しています。マーカーだけを削除しても、矛盾する行が残ります。経路のページは、Git がその独立した変更を正常にマージできたため、すでに M access.txt としてステージされている場合があります。
解決する前に、復旧を練習します。git merge --abort は未完了のマージだけを取り消し、追跡済みファイルとインデックスをマージ前の状態に戻します。この環境はクリーンな状態から始まっています。通常の作業では、マージを始める前に無関係な編集をコミットするか、別に退避してください。
git merge --abort
git status --short
変更は表示されないはずです。ガイドをもう一度読みます。元の南側の入口と古い開園時間に戻っています。
cat guide.txt
ここで、同じマージをやり直します。再び競合と非ゼロのステータスになることを想定しています。 この2回目の競合は、次のステップのために未解決のまま残してください。
git merge --no-edit origin/main
git status --short
チェックポイントでは、guide.txt の未解決の競合が進行中であることを確認します。パスを打ち間違えた場合は、pwd と ls を使い、上の完全な cd コマンドで戻ってください。通常の移動ミスから復旧するために、.git を削除したり、VM をリセットしたりしないでください。
情報を整理してマージを完了する
このステップでは、Git がすでにマージしたページを保持しながら、競合を1行の使えるガイドにまとめます。
前のステップの競合を未解決のままにして、引き続き Terminal の /home/labex/project/guide-team/editor で作業します。自分の変更から South entrance、チームメンバーの変更から 10:00-18:00 が必要です。どちらか一方のファイル全体を選ぶと、承認済みの変更が1つ失われます。
次のコマンドは、**guide.txt だけ**を、完成した3行の内容に置き換えます。> は出力をそのファイルへリダイレクトし、内容を置き換えます。<<'GUIDE' はヒアドキュメントです。後続の行は、GUIDE だけを含む行まで、そのまま入力として扱われます。最後のマーカーを含め、ブロック全体をコピーしてください。マーカーを引用符で囲むことで、テキスト内でシェル展開が起きるのを防ぎます。プログラミングは必要ありません。
cat > guide.txt <<'GUIDE'
RIVERLIGHT GARDEN
Gate: South entrance; Hours: 10:00-18:00
Last entry is 30 minutes before closing.
GUIDE
ステージする前に、3つのファイルをすべて読みます。最終入場についての文が残っていること、access.txt に川沿いのスロープが含まれること、contacts.txt に自分が更新した電話番号が含まれることが必要です。
cat guide.txt
cat access.txt
cat contacts.txt
ほかのページに期待される内容は次のとおりです。
Step-free route: Use the riverside ramp
Visitor desk: 010-555-0120
git add は、解決したファイルをインデックスに記録し、競合を解決済みとして扱います。この操作自体でコミットが作成されるわけではありません。
git add guide.txt
元の手元のコミットと比べ、マージで何が追加されるかを確認します。diff --cached は、ステージされた結果と HEAD を比較します。--no-pager によって、出力はこのターミナルに表示されます。
git --no-pager diff --cached
guide.txt の開園時間の変更と、access.txt のスロープの変更が表示されるはずです。南側の入口と来園者向け電話番号は、すでに手元の親コミットに含まれていたため、この比較では新しく追加された行として表示される必要はありません。この差分だけでなく、最終的なファイルも確認してください。
つづりの誤りがあれば、ガイドのブロック全体を修正して再実行し、git add guide.txt をもう一度実行します。未完了の試行をすべて取りやめたい場合は、前のステップの git merge --abort を使い、マージを再開して解決を繰り返してください。コミットを完了した後に abort を使わないでください。
内容を説明するメッセージを付けてマージを完了します。-m は、エディターを開かずにメッセージを直接指定します。意味のある別の文言でも構いません。
git commit -m "Combine gate and opening hours"
2系統の祖先履歴と、クリーンな作業ツリーを確認します。
git --no-pager log --oneline --graph --all --decorate
git status --short
ステータスは何も出力されないはずです。新しいマージの下には、元の両方の変更メッセージが残っていなければなりません。チェックポイントでは、単に競合マーカーがないだけでなく、その履歴と完全で正しいファイルが必要です。
完全なガイドを公開して受け取る
このステップでは、マージしたリビジョンを共有リポジトリに届け、新しい受信用コピーから読み取ります。手元でマージしただけでは、ほかのコピーには何も届いていません。
引き続き Terminal の /home/labex/project/guide-team/editor で作業します。push origin main は、手元の main の履歴を、origin という名前のリポジトリに送ります。今回は共有側の変更がマージの祖先になっているため、それを取り除くことなく共有側の main を先へ進められます。
git push origin main
拒否されずに main -> main と表示されるはずです。拒否された場合は、フェッチしてグラフを再確認してください。強制するオプションは追加しないでください。この学習用環境にはバックグラウンドで変更するメンバーはいませんが、実際のチームでは、いつでも新しい作業が公開される可能性があります。
次に、両方のリポジトリが入っているディレクトリに移動します。
cd /home/labex/project/guide-team
git clone は、コピー元から新しいリポジトリと作業ファイルを作成します。ここでは shared.git が既存のローカルのコピー元パス、received-guide が新しいコピー先ディレクトリです。受信用コピーは共有リポジトリを起点として作る必要があるため、マージが実際に届いたかを確認できます。
git clone shared.git received-guide
Cloning into 'received-guide'... と done. が表示されるはずです。試行中にすでにクローンした場合は、そのコピーを残してください。received-guide に入り、すでに学んだ git fetch origin、続いて git merge --no-edit origin/main を使って最新の状態へ進めます。クローンをやり直すために、元の編集用リポジトリを削除しないでください。
受信用コピーに移動します。
cd received-guide
実際のファイルを1つずつ読みます。cat はファイルを変更せずに表示します。
cat guide.txt
cat access.txt
cat contacts.txt
前のステップで組み合わせた業務上の要件と情報を比較します。変更していない行も含めて、3つのファイルがすべて完全でなければなりません。クローン成功のメッセージだけでは、情報が正しいと証明できません。
最後に、受信側の履歴を読みます。--oneline は各コミットの表示を短くし、--graph は親へのつながりを描き、--decorate はブランチポインターにラベルを付けます。--no-pager はスクロール可能なビューアーを開かず、直接出力します。
git --no-pager log --oneline --graph --decorate
先頭のマージには、元の両方の変更メッセージと最初のコミットを含む、2系統の祖先履歴があります。具体的なコミット ID は実行ごとに異なります。内容が失われていないことと、受信用コピーが main 上にあり、追跡済みファイルの作業ツリーがクリーンであることを確認します。
git status --short
何も出力されなければ、ステージされた変更、ステージされていない変更、未追跡の変更はありません。この1台の学習用マシン上で動く実際の Git リポジトリを通して、使えるファイル一式を届けられました。
まとめ
実際の競合の両側を読み、git merge --abort で安全に復旧してから、片側全体を選ぶのではなく正しい項目を組み合わせました。自動マージされた経路、自分の来園者向け電話番号、変更していないガイドの文も保持しました。
公開されたマージと独立した受信用クローンには、元の両方の変更を保持した完全なガイドが含まれています。チャレンジではハンドブックが変わり、正しい各項目を持っている担当者も逆になります。



