CH 12 / 75第2部 Gitの基礎 ── 手元で完結する操作

.gitignore で除外する

このページで分かること

  • 記録してはいけないファイルが何かが分かる
  • .gitignore にパターンを書いて、ファイルを記録の対象から外せる
  • どの行が効いているかを git check-ignore で確かめられる
  • すでに記録したファイルには .gitignore が効かない理由が分かる
このページの目次8 items

第2部の09で、git add . は意図しないファイルまで載せてしまうと書きました。このページでは、記録したくないファイルを最初から Git の視界から外す方法を扱います。

記録してはいけないもの#

種類 例 記録してはいけない理由
秘密情報 .env、鍵ファイル、パスワードを書いた設定 一度記録すると履歴に残り、あとから消すのが非常に難しい
自動で作られるもの ログ、キャッシュ、ビルドの出力 元のファイルから何度でも作り直せる。差分がノイズになる
OS やエディタが作るもの .DS_Store(macOS)、Thumbs.db(Windows) 内容と無関係で、人ごとに違う
大きな外部ファイル ダウンロードした素材、依存パッケージ リポジトリが重くなる。入手方法を書けば足りる

なかでも秘密情報は特別です。第2部の15で見るとおり、Git は消したはずの記録も取り戻せるように作られています。誤ってコミットしたパスワードは、ファイルを消しても履歴の中に残ります。だから「記録してから消す」ではなく、最初から記録に入らないようにする必要があります。

.gitignore を書く#

練習用に、記録してはいけないファイルを3種類作ります。

text11 lines
cd ~/git-practice
echo "PASSWORD=secret" > .env
echo "log" > debug.log
mkdir tmp
echo "cache" > tmp/cache.txt
git status -s

# 出力:
# ?? .env
# ?? debug.log
# ?? tmp/

3つとも ??(未追跡)として表示され、このままでは git add . で記録されてしまいます。リポジトリのいちばん上のフォルダに .gitignore という名前のファイルを作り、除外したいものを1行に1つずつ書きます。

text6 lines
# 秘密情報
.env

# ログと一時ファイル
*.log
tmp/

エディタで作るか、次のコマンドで作ります。

text5 lines
printf '# 秘密情報\n.env\n\n# ログと一時ファイル\n*.log\ntmp/\n' > .gitignore
git status -s

# 出力:
# ?? .gitignore

3つのファイルが表示されなくなり、代わりに .gitignore 自身が表示されました。

Git がファイルを記録の対象にするかの判定。一度でも記録したファイルは .gitignore に書いても記録され続け、記録していないファイルは .gitignore に一致すれば無視され、一致しなければ Untracked files として表示される

.gitignore が働くのは、図の2つ目の分かれ道です。1つ目の「一度でも記録した?」で Yes に進むファイルには効きません。この点はページの後半で確かめます。

.gitignore は記録しておくファイルです。同じフォルダで作業する人全員に同じ除外が効くようにするためです。

text2 lines
git add .gitignore
git commit -m ".gitignore を追加"

パターンの書き方#

書き方 意味 一致する例
.env この名前のファイル(どの階層でも) .env、config/.env
*.log * は任意の文字列 debug.log、error.log
tmp/ 末尾の / はフォルダだけ tmp/ の中身すべて
/todo.txt 先頭の / は .gitignore と同じ階層だけ todo.txt(sub/todo.txt は一致しない)
!important.log ! は除外の取り消し *.log で除外した中の important.log だけ記録する
# コメント # で始まる行はコメント —

空行は無視されます。種類ごとにコメントと空行で区切っておくと、あとから読み返しやすくなります。

効いているかを確かめる#

除外されているはずなのに表示される、またはその逆が起きたら、git check-ignore -v でどの行が効いているかを確かめます。

text6 lines
git check-ignore -v .env debug.log tmp/cache.txt

# 出力:
# .gitignore:2:.env .env
# .gitignore:5:*.log    debug.log
# .gitignore:6:tmp/ tmp/cache.txt

.gitignore の何行目のどのパターンで除外されたかが表示されます。何も表示されなければ、そのファイルはどのパターンにも一致していません。

除外したファイルを git add で指定すると、Git は止めてくれます。

text6 lines
git add .env

# 出力:
# The following paths are ignored by one of your .gitignore files:
# .env
# hint: Use -f if you really want to add them.

-f を付ければ強制的に載せられますが、秘密情報のファイルでは使わないでください。

すでに記録したファイルには効かない#

.gitignore は未追跡のファイルを無視するための仕組みです。一度でもコミットしたファイルは「追跡中」になり、あとから .gitignore にパターンを書いても、変更はこれまでどおり記録の対象になります。

試しに、記録済みの memo.txt に一致するパターンを足してみます。

text7 lines
echo "*.txt" >> .gitignore
echo "パンを買う" >> memo.txt
git status -s

# 出力:
#  M .gitignore
#  M memo.txt

memo.txt の変更は表示されたままです。確かめたら、2つとも元に戻しておきます。

text1 lines
git restore .gitignore memo.txt

git restore ファイル名 は、ワークツリーの変更を捨てて最後の記録の状態に戻すコマンドです。第2部の14で詳しく扱います。

記録済みのファイルを追跡から外すには、git rm --cached を使います。ファイルは手元に残したまま、Git の追跡だけをやめる操作で、第2部の13で扱います。

よくある疑問#

Q. どのプロジェクトでも除外したいファイル(.DS_Store など)を、毎回書くのが面倒です。
A. 自分のPC全体に効く除外ファイルを作れます。~/.config/git/ignore というファイルを作ってパターンを書くと、すべてのリポジトリで自動的に使われます。プロジェクトの .gitignore には、そのプロジェクト固有のものだけを書けば済みます。

Q. 空のフォルダを記録したいのですが、git add しても載りません。
A. Git はファイルだけを記録し、フォルダそのものは記録しません。中に何かファイルを1つ置く必要があります。慣習として、.gitkeep という名前の空ファイルを置くことが多いです(Git の機能ではなく、ただの名前の慣習です)。

まとめ#

  • 秘密情報は「記録してから消す」ではなく、最初から記録に入れない
  • .gitignore に1行1パターンで書き、.gitignore 自身はコミットする
  • git check-ignore -v で、どの行が効いているかを確かめられる
  • .gitignore は未追跡のファイルにだけ効く。記録済みのファイルには効かない
  • 漏れた秘密情報は、履歴から消すより先に無効化する

次のページ#

13. ファイルの移動・削除・追跡の解除 ── 記録済みのファイルの名前を変える、消す、手元に残したまま追跡だけやめる、の3つを使い分けます。