はじめに
Riverlight Garden には正確な来園者向けガイドが必要です。用意された手元のコミットでは、入口の場所と来園者向けの電話番号が更新されています。一方、チームメンバーは段差のない新しい経路をすでに公開しています。来園者には、この3つの修正すべてが必要です。
チームメンバーの作業をフェッチし、互いに独立した変更をマージして、その結果を公開します。新しい受信用クローンから、実際に届いたファイルを確認します。共有リポジトリと2つのコピーは、1台の学習用マシン上にあるローカルディレクトリです。ホスティングサービス、サーバーのセットアップ、アカウントを使わずに、実際の Git による共同作業を行います。
コミット、ブランチ、git add、git commit、基本的な差分については、すでに知っていることが前提です。リモート名、フェッチ、マージ、プッシュ、クローンは、この実験で説明します。所要時間の35分は、読み進める時間や通常のミスへの対応を含む、著者による見積もりです。
チームメンバーの更新を見つける
このステップでは、用意された手元の更新をまだ届けられない理由を調べ、ファイルを変更せずにチームメンバーのリビジョンを取得します。
Terminal を開きます。用意された編集用リポジトリに移動して始めます。
cd /home/labex/project/guide-team/editor
cd は、このターミナルの作業ディレクトリを変更します。パスを打ち間違えた場合は、pwd で現在のディレクトリを表示し、ls で中身を一覧表示してから、上の完全な cd コマンドをもう一度実行してください。このような通常の移動ミスに、新しい VM は必要ありません。
新しいマージコミットには作成者情報が必要です。--local は、このリポジトリ内だけに設定を保存します。引用符で囲んだテキストは、空白を含んでいても1つの値として扱われます。サンプルのメールアドレスは架空のものです。自分で名前とメールアドレスを選んでも構いません。
git config --local user.name "Guide Editor"
git config --local user.email "guide@example.com"
既存の手元のコミットは、すでに完成しています。来園者向けの情報を読みます。
cat guide.txt
cat contacts.txt
South entrance と、来園者窓口の 010-555-0120 が表示されるはずです。ガイドの最終入場についての文は残してください。別の経路ファイルには、まだ Use the north ramp と書かれています。
cat access.txt
git status --short は、変更されたファイルを簡潔な一覧で表示します。ここで何も出力されなければ、用意された変更はコミット済みで、作業ツリーはクリーンです。
git status --short
リモートは、別のリポジトリへの接続に名前を付けたものです。origin はこの接続の名前であり、特別なサーバーではありません。-v はフェッチとプッシュのアドレスを表示します。
git remote -v
両方のアドレスは /home/labex/project/guide-team/shared.git を指しています。これはベアリポジトリです。編集可能な作業コピーを持たず、共有する履歴を保存します。内部のファイルを編集しないでください。
自分のブランチを届けてみます。push はコミットを送信し、main は origin で更新するブランチを指定します。この最初のプッシュは、非ゼロの終了ステータスで失敗することを想定しています。 単独で実行し、拒否された後も先へ進んでください。
git push origin main
[rejected]、main -> main、(fetch first) を探します。共有ブランチには現在の手元の履歴に含まれていない作業があるため、Git はその置き換えを拒否します。これは non-fast-forward の更新です。既存の共有ブランチの先端が、更新案の先端の祖先ではありません。強制プッシュすると、チームメンバーの変更をブランチから失わせることになり、このタスクの条件に反します。
fetch はリモートのコミットをダウンロードし、手元のリモート追跡ポインター origin/main を更新します。自分の main にマージしたり、作業ファイルを書き換えたりはしません。
git fetch origin
履歴を比較します。--oneline はコミットごとに短い1行を表示し、--graph は親子関係を描画します。--all はローカルブランチとリモート追跡ブランチの両方を含め、--decorate はそれらのラベルを追加します。--no-pager は直接出力します。試している途中でページャーが開いた場合は、q を押して終了してください。
git --no-pager log --oneline --graph --all --decorate
Move the gate and update the visitor desk が HEAD -> main に、Update the step-free route が origin/main にあることを確認します。どちらも Open the garden guide から分岐しています。HEAD は現在チェックアウトされているコミットを指します。2人の変更は異なっており、一方で他方を代用することはできません。
チームメンバーの経路を、そのスナップショットから直接読みます。show は revision:path という式を受け取ります。したがって、origin/main:access.txt は、フェッチしたリビジョンにあるそのファイルを意味します。
git --no-pager show origin/main:access.txt
Use the riverside ramp と書かれています。手元の作業中の経路には、まだ Use the north ramp と書かれています。この違いから、フェッチによって新しい履歴を利用できるようになっても、作業ツリーはそのまま残るとわかります。最初のチェックポイントでは、元の手元のコミットが保持された状態で、フェッチしたリビジョンを利用できることを確認します。
独立した変更を組み合わせる
このステップでは、2つの履歴を1つのリビジョンに組み合わせ、南側の入口、更新された来園者向け電話番号、川沿いのスロープをすべて含めます。
引き続き Terminal の /home/labex/project/guide-team/editor で作業します。マージは履歴を組み合わせる操作です。今回は変更対象のファイルが異なるため、Git がテキストを自動的に組み合わせられます。--no-edit は、Git が生成したマージメッセージをそのまま使い、エディターを開かないようにします。
git merge --no-edit origin/main
通常は Merge made by the 'ort' strategy. という、マージ成功の要約が表示されます。Git は、元の自分のコミットと元のチームメンバーのコミットという、2つの親を持つマージコミットを作成します。どちらの変更も書き換えられません。
実際に組み合わされたファイルを読みます。
cat guide.txt
cat access.txt
cat contacts.txt
ガイドには South entrance、09:00-17:00、最終入場についての文を残す必要があります。経路は Use the riverside ramp、電話番号は引き続き 010-555-0120 でなければなりません。独立した変更は問題なく組み合わされましたが、その内容が適切かは自分で判断する必要があります。
結果の履歴を確認します。
git --no-pager log --oneline --graph --all --decorate
HEAD -> main のマージは、両方の変更の履歴を結び付けます。プッシュするまでは、origin/main は以前フェッチしたチームメンバーのコミットを指したままです。これは正常です。マージによって変わったのは手元の main であり、共有側の main ではありません。
作業状態を確認します。
git status --short
何も出力されないはずです。別の試行によってマージが進行中のままになっている場合は、git merge --abort で未完了のマージを取り消し、マージ前の状態に戻せます。マージが進行中の場合だけ実行し、その後でマージコマンドを実行し直してください。完了済みのコミットを取り消すことはできません。チェックポイントでは、元の2つの親と3つの完全なファイルを持つ、統合されたマージコミットが1つ必要です。
完全なガイドを公開して受け取る
このステップでは、マージしたリビジョンを共有リポジトリに届け、新しい受信用コピーから読み取ります。手元でマージしただけでは、ほかのコピーには何も届いていません。
引き続き 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 リポジトリを通して、使えるファイル一式を届けられました。
まとめ
実際のプッシュ拒否に対応し、自分のファイルを上書きせずにチームメンバーのコミットをフェッチし、独立した2人の変更をマージして、完全なガイドを共有リポジトリ経由で届けました。実際の受信用クローンには、組み合わされたガイド、段差のない経路、来園者向け連絡先が含まれています。
元のコミットは履歴に残っています。次は、2人が同じ行を変更したために Git があなたの判断を必要とするマージを練習します。



