一覧SE-03-1 · Gitの変更管理

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 / シェル

1
git status --short git ls-files
.gitignore
README.md
settings.ini
2
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
 M README.md
 M settings.ini
?? notes.txt
3
git diff -- settings.ini
diff --git a/settings.ini b/settings.ini
index bdb130a..806265d 100644
--- a/settings.ini
+++ b/settings.ini
@@ -1 +1 @@
-timeout=10
+timeout=20
4
git add settings.ini git diff --cached -- settings.ini git status --short
diff --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
5
printf 'timeout=30\n' > settings.ini git status --short git diff -- settings.ini git diff --cached -- settings.ini
 M 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
6
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
7
git add README.md git restore --staged README.md git status --short cat README.md
 M README.md
 M settings.ini
?? notes.txt
Demo
Local note
8
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/
9
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
10
git diff -- README.md git status --short
diff --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

演習完了