Gitのステージングとコミット
作業ファイル・ステージ・直近のコミットを比較し、今回記録する変更だけを選んでコミットします。
説明
Gitのコミットは、その時点の作業ファイルを無条件に全部保存する操作ではありません。次に記録する内容をステージへ登録し、その内容をコミットとして履歴へ追加します。ステージはindexとも呼ばれます。
初期コミットのある小さなリポジトリで、設定値とメモを編集します。設定だけをステージへ入れた後にもう一度変更し、三つの場所に異なる値がある状態を確認します。最後は設定の変更だけを記録し、今回の対象でないメモは作業ファイルに残します。
作業ファイル・ステージ・直近のコミットを比較し、今回記録する変更だけを選んでコミットします。
1追跡中のファイルを確認
リポジトリには初期コミットがあり、mainブランチで作業しています。statusは未記録の変更、ls-filesはステージで追跡しているパスを示します。
git status --short変更状態を短い形式で表示する
git ls-files追跡中のパスを列挙するstatusに行はなく、3ファイルだけが表示されます。この開始状態では作業ファイル・ステージ・HEADの内容が一致しています。
2設定とメモを別々に変更
設定値を20へ変更し、READMEへメモを追加します。未追跡のnotes.txtと、ignore対象のcache/item.txtも作ります。
printf 'timeout=20\n' > settings.ini設定ファイルを書き換える
printf 'Demo\nLocal note\n' > README.md
printf 'draft\n' > notes.txt
mkdir cache
printf 'temporary\n' > cache/item.txt
git status --short変更と未追跡ファイルを確認する先頭2列のうち右側のMは作業ファイルの変更です。??は未追跡を示します。cacheはignore対象なので通常のstatusには表示されません。
3作業ファイルとステージの差分
ステージにはまだ初期値10があります。設定ファイルの差分だけを確認します。
git diff -- settings.ini設定の未ステージ差分を表示する10から20への差分です。引数なしのgit diffは、主に作業ファイルとステージを比較します。--以降はパスとして扱われます。
4今回の設定だけをステージへ
settings.iniだけをステージに登録します。cachedの差分は、ステージとHEADを比較します。
git add settings.ini現在の設定内容をステージに登録する
git diff --cachedステージとHEADを比較する -- settings.ini
git status --short設定のMが左側へ移ります。READMEのMは右側、notes.txtは??のままです。ステージへ入れたのは設定の20という内容です。
5ステージ後にもう一度編集
作業ファイルだけを30へ変更します。ステージは自動では更新されません。
printf 'timeout=30\n'作業ファイルをさらに変更する > settings.ini
git status --short
git diff -- settings.ini20から30の差分
git diff --cached -- settings.ini10から20の差分設定はMMになります。左のMはHEADの10に対してステージが20、右のMはステージの20に対して作業ファイルが30という意味です。二つの差分がそれぞれ異なる比較を示しています。
6ステージに登録した内容がコミットされる
内容を確認してからコミットします。直後に履歴内の設定と、作業ファイルの設定を別々に読みます。
git commit -m変更の目的を添えて記録する "Increase timeout to 20"
git show HEAD:settings.ini直近コミット内のファイルを読む
cat settings.ini作業ファイルを読むコミットの設定は20、作業ファイルは30です。git commitはステージの内容を記録したため、後から加えた30はまだ未記録です。
7ステージから外しても編集は残る
READMEを一度ステージへ入れ、すぐにステージから外します。この操作は作業ファイルを元に戻すものではありません。
git add README.md
git restore --staged README.mdREADMEのステージだけをHEADへ戻す
git status --short
cat README.md作業ファイルのメモが残ることを確認するREADMEは未ステージのMに戻り、Local noteは残ります。--stagedを付けたrestoreは、既定でHEADの内容をステージへ戻します。
8ignoreされたファイルを確認
cacheが通常の一覧にない理由を調べます。check-ignoreは一致した規則を示します。
git check-ignore -vどのignore規則に一致したか表示する cache/item.txt
git status --short --ignoredignore対象も一覧に出す規則は.gitignoreの1行目です。--ignoredを付けたstatusでは!! cache/と表示されます。ignoreは主に未追跡ファイルを追加対象から外す規則であり、追跡済みのファイルの変更を隠す機能ではありません。
9残る設定変更を記録する
設定の30を改めてステージへ入れ、二つ目のコミットにします。メモには触れません。
git add settings.ini30という現在の内容を登録する
git diff --cached -- settings.ini
git commit -m "Increase timeout to 30"
git log -2直近2件の記録を確認する --format="%h %s"20から30への変更が別のコミットになりました。ステージは単なるファイル名の選択ではなく、記録する時点の内容を保持します。
10今回の対象外の編集を保持する
最後に残っている差分と状態を確認します。
git diff -- README.md今回コミットしなかったメモを確認する
git status --short設定の変更が記録済みか確認するREADMEの追記と未追跡のnotes.txtが残り、設定の変更は一覧から消えました。目的の変更だけを記録し、それ以外の作業を保った状態です。
まとめ
git addは、その時点の内容をステージへ登録します。後の編集は追加でaddするまで記録対象に入りません。
git diff、git diff --cached、git show HEAD:パスで、作業ファイル・ステージ・コミットをそれぞれ確認できます。
目的に合うパスと差分を選んでコミットし、今回の対象でない編集は保持します。
操作履歴と解説を振り返れます。
Git / シェル
git status --short
git ls-files.gitignore README.md settings.ini
printf 'timeout=20\n' > settings.ini
printf 'Demo\nLocal note\n' > README.md
printf 'draft\n' > notes.txt
mkdir cache
printf 'temporary\n' > cache/item.txt
git status --shortM README.md M settings.ini ?? notes.txt
git diff -- settings.inidiff --git a/settings.ini b/settings.ini index bdb130a..806265d 100644 --- a/settings.ini +++ b/settings.ini @@ -1 +1 @@ -timeout=10 +timeout=20
git add settings.ini
git diff --cached -- settings.ini
git status --shortdiff --git a/settings.ini b/settings.ini index bdb130a..806265d 100644 --- a/settings.ini +++ b/settings.ini @@ -1 +1 @@ -timeout=10 +timeout=20 M README.md M settings.ini ?? notes.txt
printf 'timeout=30\n' > settings.ini
git status --short
git diff -- settings.ini
git diff --cached -- settings.iniM README.md MM settings.ini ?? notes.txt diff --git a/settings.ini b/settings.ini index 806265d..9ff9b17 100644 --- a/settings.ini +++ b/settings.ini @@ -1 +1 @@ -timeout=20 +timeout=30 diff --git a/settings.ini b/settings.ini index bdb130a..806265d 100644 --- a/settings.ini +++ b/settings.ini @@ -1 +1 @@ -timeout=10 +timeout=20
git commit -m "Increase timeout to 20"
git show HEAD:settings.ini
cat settings.ini[main 7ef0771] Increase timeout to 20 1 file changed, 1 insertion(+), 1 deletion(-) timeout=20 timeout=30
git add README.md
git restore --staged README.md
git status --short
cat README.mdM README.md M settings.ini ?? notes.txt Demo Local note
git check-ignore -v cache/item.txt
git status --short --ignored.gitignore:1:cache/ cache/item.txt M README.md M settings.ini ?? notes.txt !! cache/
git add settings.ini
git diff --cached -- settings.ini
git commit -m "Increase timeout to 30"
git log -2 --format="%h %s"diff --git a/settings.ini b/settings.ini index 806265d..9ff9b17 100644 --- a/settings.ini +++ b/settings.ini @@ -1 +1 @@ -timeout=20 +timeout=30 [main d580347] Increase timeout to 30 1 file changed, 1 insertion(+), 1 deletion(-) d580347 Increase timeout to 30 7ef0771 Increase timeout to 20
git diff -- README.md
git status --shortdiff --git a/README.md b/README.md index 4f0b848..9d994df 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ Demo +Local note M README.md ?? notes.txt
演習完了