コンテンツへスキップ

git add . から一つのファイルを除くには?

皆さんは、プロジェクトで多数の変更を行ったけれど、その中のごく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つのファイルだけをコミットに含めたくない場合に非常に役立ちます。

例えば、次のような状況が考えられます。

  1. うっかり変更してしまった設定ファイル: 開発中に、ローカル環境用の設定ファイル(例: APIキーを含むファイルやデータベース接続情報)を誤って変更してしまったとします。これを本番環境にコミットしてしまうとセキュリティ上の問題になる可能性がありますが、手動で他のファイルを一つずつgit addするのは面倒です。この場合、git add . ':!設定ファイルへのパス'を使うことで、すべての変更をステージングしつつ、その特定のファイルだけをきれいに除外できます。
  2. 一時的なデバッグコードやテストファイル: 新しい機能を開発している際に、一時的にデバッグ用のコードを書き込んだり、テスト用のファイルを作成したりすることがよくあります。これらは最終的なコミットには不要ですが、作業中は残しておきたいものです。git addで全体をステージングする際に、これらのファイルを「除外」指定することで、効率的にきれいなコミットを作成できます。
  3. 作業途中だがコミットしたくないファイル: 大規模なリファクタリング中に、まだ完成していない共通のベースファイルに変更を加えたとします。しかし、他の機能は完成しており、先にコミットしたい。この場合も、未完成のベースファイルだけを除外してコミットすることで、コミットの粒度を細かく保ち、後で問題が発生した際の追跡を容易にできます。

このように、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ツールなどで視覚的に変更を確認しながら、個別にステージングを解除したい場合にも有効です。

最後までお読みいただき、心より感謝申し上げます。

Posii株式会社は、AIプロダクト開発・運用を専門としています。
Webアプリケーション開発、データ分析基盤構築、クラウド活用支援など、お客様のビジネス課題に合わせた最適なソリューションをご提供いたします。

AI歴15年 代表取締役 大河原潤

より具体的な開発事例や実装の詳細は、下記ページでご紹介しております。