
皆さんは、プロジェクトで多数の変更を行ったけれど、その中のごく1つ2つのファイルだけをコミットから除外したい、という状況に遭遇したことはありませんか?もしかしたら、複数の機能を同時に作業していて、一部の変更だけを先にコミットしたい場合や、一時的な設定ファイルなど、コミットに含めたくないローカルな変更があるかもしれません。
これを実現するコマンドは git add . ':!パス/除外したい/ファイル.html'
です。詳しく見ていきましょう。
解決策:git add
を使った選択的ステージング
私たちの目標は、新しい機能に関連する変更(app_name
の更新とdb.sqlite3
の変更)だけをコミットし、another_app/templates/AnotherBase.html
の変更はステージしないままにしておくことです。
git add . ':!パス/除外したい/ファイル.html'
のコマンドを詳しく見ていきましょう。
git add .
: このコマンドは通常、現在のディレクトリとそのサブディレクトリ内のすべての変更をステージングします。':!パス/除外したい/ファイル.html'
: これが選択的ステージングの鍵となる部分です。:
の後に!
を付けることで、指定したファイルをステージングプロセスから除外するようGitに指示します。これにより、git add .
コマンドによって通常含まれるはずのファイルであっても、除外されます。
したがって、私の例では、another_app/templates/AnotherBase.html
以外のすべてをステージングするために、以下のコマンドを使用しました。
Bash
git add . ':!another_app/templates/AnotherBase.html'
このコマンドを実行した後、git status
を再度確認すると、意図した通りのステージングエリアになっていることが確認できます。
Bash
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: db.sqlite3
new file: app_name/templates/app_name/new_feature_history.html
modified: app_name/urls.py
modified: app_name/views.py
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: another_app/templates/AnotherBase.html
ご覧の通り、新しい機能ファイル(私の元のケースではuser_payment
関連、ここではapp_name
に一般化)とdb.sqlite3
はコミット準備ができていますが、another_app/templates/AnotherBase.html
の変更は「Changes not staged for commit」セクションに残っています。
なぜこれが便利なのか?
この選択的ステージングのテクニックは、特にたくさんの変更があった中で、たった1つか2つのファイルだけをコミットに含めたくない場合に非常に役立ちます。
例えば、次のような状況が考えられます。
- うっかり変更してしまった設定ファイル: 開発中に、ローカル環境用の設定ファイル(例: APIキーを含むファイルやデータベース接続情報)を誤って変更してしまったとします。これを本番環境にコミットしてしまうとセキュリティ上の問題になる可能性がありますが、手動で他のファイルを一つずつ
git add
するのは面倒です。この場合、git add . ':!設定ファイルへのパス'
を使うことで、すべての変更をステージングしつつ、その特定のファイルだけをきれいに除外できます。 - 一時的なデバッグコードやテストファイル: 新しい機能を開発している際に、一時的にデバッグ用のコードを書き込んだり、テスト用のファイルを作成したりすることがよくあります。これらは最終的なコミットには不要ですが、作業中は残しておきたいものです。
git add
で全体をステージングする際に、これらのファイルを「除外」指定することで、効率的にきれいなコミットを作成できます。 - 作業途中だがコミットしたくないファイル: 大規模なリファクタリング中に、まだ完成していない共通のベースファイルに変更を加えたとします。しかし、他の機能は完成しており、先にコミットしたい。この場合も、未完成のベースファイルだけを除外してコミットすることで、コミットの粒度を細かく保ち、後で問題が発生した際の追跡を容易にできます。
このように、git add . ':!ファイル/除外したい'
というコマンドを使いこなすことで、たくさんのファイルに変更があった中でも、意図しないファイルをコミットしてしまうリスクを減らし、より整理された効率的なGitワークフローを実現できます。
QA: 「git add . ':!ファイル名'
」と「git add .
+ git restore --staged ファイル名
」は同じですか?
結論から言うと、多くの場合において、これら2つの操作は最終的に同じ結果になりますが、厳密には実行順序と意図が異なります。
それぞれのコマンドが何をしているのかを見て、違いと共通点を理解しましょう。
1. git add . ':!dm/templates/ChatBase.html'
の場合
このコマンドは、Gitに対して以下のように指示しています。
git add .
: 現在のディレクトリ以下のすべての変更(新規ファイル、変更されたファイル、削除されたファイル)をステージングエリアに追加する準備をします。':!dm/templates/ChatBase.html'
: ただし、dm/templates/ChatBase.html
というファイルだけは、上記の**「すべて」から除外してステージングしないでください**。
つまり、このコマンドは「一括で追加するけれど、特定のファイルだけは最初からステージングしない」という意図で実行されます。一度の操作でステージングするファイルを選別できるのが特徴です。
2. git add .
の後で git restore --staged dm/templates/ChatBase.html
を実行する場合
この一連のコマンドは、Gitに対して以下のように指示しています。
git add .
: まず、現在のディレクトリ以下のすべての変更をステージングエリアに追加します。この時点ではdm/templates/ChatBase.html
もステージングされています。git restore --staged dm/templates/ChatBase.html
: 次に、ステージングエリアからdm/templates/ChatBase.html
の変更を取り消します(ステージングされていない状態に戻します)。
つまり、この操作は「とりあえず全部ステージングするけれど、後から特定のファイルをステージングから外す」という意図で実行されます。一度ステージングしたものを、後から取り消すというステップが入ります。
どちらを使うべきか?
どちらのコマンドも最終的な結果は同じですが、状況や個人の好みによって使い分けられます。
- **
git add . ':!ファイル名'
を使うのが適しているのは、最初から「このファイルは絶対にコミットしない」と決まっている場合です。余計なものをステージングエリアに一時的にも入れたくない場合に、より効率的です。 - **
git add .
の後でgit restore --staged ファイル名
を使うのが適しているのは、まず全体をステージングして状況を把握し、その後に「やっぱりこのファイルは外そう」と判断する場合です。あるいは、Git GUIツールなどで視覚的に変更を確認しながら、個別にステージングを解除したい場合にも有効です。