はじめに
DAYLIGHT CAFE では、フラットホワイトの価格を修正しています。価格の更新と、それに対応する持ち帰り用メニューのダウンロードファイルは、すでに下書きされています。同じメニューファイルには未完成の季節限定メニューの告知も混在しており、非公開の試飲メモは公開用コミットに含めてはいけません。
ほかの作業を残したまま、1つの Git コミットに含める内容を正確に選びます。ターミナルでの基本的なディレクトリ移動と、簡単なテキストファイルの扱いに慣れていることが前提です。Git の作業ツリー、ステージングエリア、コミットのスナップショットは、この実験で説明します。Web サイトのプログラミングや GitHub アカウントは必要ありません。
コマンドには Workspace、編集中のファイルの表示には Working Copy、現在のコミットに保存されたファイルそのものの表示には Committed Menu を使います。2つのページは実際の内容を読み取り、不足するファイルを補完することはありません。カフェ、イラスト、メニューは独自に制作した学習用素材です。画面のラベルと実行時の出力は英語のままです。
2つのメニューバージョンを確認する
このステップでは、公開メニューと用意された作業ファイルを比較し、このリポジトリだけで使う作成者情報を設定します。
Committed Menu を開きます。フラットホワイトの価格は EUR 3.80 で、季節限定メニューの掲示にはドリンクを企画中と書かれています。Download takeaway menu から、実際にダウンロードされるテキストを開きます。こちらにも EUR 3.80 と記載されています。
Working Copy に切り替えます。フラットホワイトは EUR 4.20 になっていますが、季節限定メニューの掲示には非公開の試飲会の告知も含まれています。承認されているのは価格の修正だけです。2つの公開メニューファイルの価格を EUR 4.20 で一致させる必要があります。季節限定メニューの下書きと tasting-notes.txt は、コミットに含めず、手元のマシンに残さなければなりません。
Working Copy には、未完成の季節限定メニューの告知が表示されたままです。

Workspace に切り替えます。用意された Git リポジトリ /home/labex/project/daylight-menu で開きます。pwd で現在のディレクトリを表示します。
pwd
別の場所へ移動した場合は、完全なパスを指定して戻ります。
cd /home/labex/project/daylight-menu
リポジトリは、プロジェクトのスナップショットと履歴を保存します。作業ツリーは、編集できるファイルの集まりです。git status --short は、それらのファイルが直前のコミットやステージングエリアとどう異なるかを要約します。--short は簡潔な表示を指定します。
git status --short
変更済みの menu.txt と menu-download.txt、および ?? tasting-notes.txt が表示されるはずです。?? はメモが未追跡であること、つまり Git がまだスナップショットに追加していないことを表します。ファイルを変更しただけでは、自動的にコミットに含まれるわけではありません。
Git は各コミットに作成者名とメールアドレスを記録します。git config --local は、このリポジトリ内だけに設定を保存します。引用符は、名前の2つの単語を1つの値にまとめます。次の架空の学習用情報を使います。
git config --local user.name "Alex Morgan"
git config --local user.email "alex@example.test"
設定した値を読み返します。
git config --local user.name
git config --local user.email
Alex Morgan と alex@example.test が表示されるはずです。Git のグローバルな作成者情報や外部アカウントは変更されません。この実験で以降に実行するコマンドも、すべて同じリポジトリ内で実行します。
承認済み価格のハンクだけをステージする
このステップでは、季節限定メニューの下書きを含めずに、承認済みの価格修正をステージングエリアに入れます。
引き続き Workspace を使います。コミットは保存されたスナップショットです。HEAD は現在のコミットを指します。ステージングエリアはインデックスとも呼ばれ、次のコミットに記録する正確なスナップショットを保持します。ステージングは、選んだ内容をインデックスにコピーする操作です。ほかの作業中の変更を削除することはありません。
--no-pager は、対話型ビューアーを開かずに出力を直接表示する Git のオプションです。以下の比較で使います。以前の Git コマンドによって、すでに (END) と表示されたビューアーが開いている場合は、q を押してシェルに戻ってください。そのビューアーに次のコマンドを入力しないでください。
git --no-pager diff は作業ツリーとインデックスを比較します。区切りの -- は、後続の引数が Git のオプションではなくファイル名であることを示します。
git --no-pager diff -- menu.txt
ハンクと呼ばれる、2つの変更のまとまりを探します。- で始まる行は以前の内容、+ で始まる行は変更案です。最初のハンクは、フラットホワイトの価格を 3.80 から 4.20 に変更します。2つ目は季節限定メニューの告知を変更します。@@ の行は各ハンクの位置を示しており、メニューの内容ではありません。
git add --patch は、どのハンクをインデックスにコピーするかを尋ねます。作業ファイル全体には手を加えず、ステージされたスナップショットを変更します。
git add --patch menu.txt
フラットホワイトの価格のハンクでは、y を入力して Enter を押し、ステージします。季節限定メニューの掲示のハンクでは、n を入力して Enter を押し、ステージしないままにします。回答するたびに表示された内容を読んでください。y は「はい」、n は「いいえ」を意味します。
次に、実際にステージされた差分を確認します。--cached は HEAD とインデックスの比較を指定します。
git --no-pager diff --cached -- menu.txt
価格の修正だけが表示されるはずです。まだステージされていない内容と比較します。
git --no-pager diff -- menu.txt
こちらには季節限定メニューの告知だけが表示されるはずです。まだ何もコミットしていません。
間違ったハンクを選んだ場合は、git restore --staged で、このファイルのインデックスの内容を HEAD から復元します。--staged はインデックスだけを対象にするため、価格の修正も下書きも作業ファイルに残ります。
git restore --staged menu.txt
その後、git add --patch menu.txt をもう一度実行し、価格のハンクを選んで、両方の差分を再確認します。この復旧操作は作業ファイルを破棄しないので、コミット前に安全に使えます。
対応する持ち帰り用ダウンロードファイルを含める
このステップでは、対応するダウンロードファイルを追加し、ステージされたすべてのファイルを確認して、次のコミットだけで変更が完結するようにします。
引き続き Workspace を使います。カフェでは、ページと持ち帰り用メニューの両方を提供しています。片方だけを修正して公開すると、2つの価格が食い違ってしまいます。cat は小さなテキストファイルを表示します。
cat menu-download.txt
すでに Flat white: EUR 4.20 が含まれています。このファイルには承認済みの修正しかないので、ファイル全体をステージします。
git add menu-download.txt
通常の git add コマンドは、指定したファイルをステージします。ディレクトリ全体をステージするのは避けてください。非公開メモや未完成の告知も含まれているためです。
--name-only は、差分に含まれるパスを、内容を表示せずに一覧にします。ステージされたパスを確認します。
git --no-pager diff --cached --name-only
一覧には menu-download.txt と menu.txt だけが含まれていなければなりません。続いて、ステージされた差分全体を確認します。
git --no-pager diff --cached
両方の公開版の価格が 4.20 で一致しているはずです。季節限定メニューの告知と試飲メモが含まれていてはいけません。
差分ではなくステージされたファイル全体を読むには、git --no-pager show に :menu.txt を指定します。先頭のコロンはインデックスの内容を選択します。
git --no-pager show :menu.txt
ステージされたメニューでは、EUR 4.20 と、元の季節限定メニューの文章 Seasonal drinks are being planned. が組み合わされています。この組み合わせから、インデックスと作業ツリーの内容が異なり得るとわかります。
非公開メモを誤ってステージした場合は、ファイルを削除せずにステージから外します。
git restore --staged tasting-notes.txt
この復旧操作は、メモをステージした場合だけ実行してください。そうでなければ、未追跡のパスが不明だと Git が正しく報告することがあります。続行する前に、git --no-pager diff --cached をもう一度確認します。ファイル名を打ち間違えても何も変更されません。git status --short で実際の名前を確認し、目的のコマンドを実行し直してください。
コミットして実際の公開結果を確認する
このステップでは、目的を絞ったコミットを1つ記録し、その後も未完成の作業が利用できることを確かめます。
引き続き Workspace を使います。git commit はインデックス全体を新しいスナップショットとして記録します。-m は簡潔な説明メッセージを指定し、引用符はそのメッセージを1つにまとめます。
git commit -m "Correct the flat white price"
Git は新しいコミットと、2つの変更されたファイルを報告します。ハッシュは実行ごとに異なります。メッセージは作業を説明しますが、大切なのはスナップショットの実際の内容です。
git --no-pager show は、コミットからファイルを直接読み取れます。HEAD:menu.txt は、現在のコミットに保存された menu.txt というファイルを意味します。
git --no-pager show HEAD:menu.txt
git --no-pager show HEAD:menu-download.txt
どちらにも、承認済みの価格 4.20 が表示されます。コミットされた季節限定メニューの告知は、引き続きドリンクを企画中と書かれたままです。
残っている作業を確認します。
git status --short
M menu.txt と ?? tasting-notes.txt が表示されるはずです。2列のステータスは、左側がステージされた変更、右側がステージされていない作業中の変更を表します。2列目の M は、季節限定メニューの下書きがステージされずに残っていることを意味します。メモは引き続き未追跡です。このタスクでは、ステータスが空なら誤りです。残す必要がある未完成の作業が消えたか、コミットに入ってしまったことになるためです。
残っている差分とメモを読みます。
git --no-pager diff -- menu.txt
cat tasting-notes.txt
Committed Menu に切り替え、ページを更新します。フラットホワイトが EUR 4.20 になり、季節限定メニューの掲示に元の公開用文章が残っていることを確認します。持ち帰り用メニューをもう一度ダウンロードし、実際のファイルでも同じ価格を確認します。Working Copy に切り替えます。こちらには非公開の試飲会の下書きがまだ表示されています。
コミットされたメニューには、承認済み価格と元の公開用の季節限定メニューの告知が表示されます。

これで、無関係な作業をそのまま残しながら、公開用の修正を1つのコミットで完全にまとめられました。push は不要です。このプロジェクトではローカルのコミットに含める範囲を学びます。リモートでの共同作業は別のプロジェクトで扱います。
まとめ
作業ファイル、インデックス、コミットを区別し、ハンクを1つ選択して、対応するダウンロードファイルを含め、実際にコミットされたメニューを確認しました。季節限定メニューの下書きと非公開メモはコミットの外に残りました。有用なコミットには、たまたま変更されているすべてのファイルではなく、意図した変更全体を含めます。



