11 ポイント 投稿者 GN⁺ 4 시간 전 | 3件のコメント | WhatsAppで共有
  • Git のファイル無視ルールは共有範囲に応じて .gitignore.git/info/exclude~/.config/git/ignore3つのレベルに分かれる
  • .gitignore はリポジトリのコードと一緒にコミットされるため、チームやプロジェクトで一緒に適用すべき 共有ルール を置く場所である
  • 個人用ファイルやローカル作業用ファイルのように、リポジトリには存在していてもチームのルールにするには微妙な項目は .git/info/exclude に置くのが適している
  • macOS の .DS_Store のように、すべてのリポジトリで繰り返し除外したいファイルは マシン全体の ignore ファイル である ~/.config/git/ignore に入れられる
  • git check-ignore -v <ファイル名> は、どのルールがファイルを無視しているのかを追跡するときに便利で、マッチするルールがなければ何も出力されない

Git ignore ルールの適用場所

  • Git はファイル無視ルールを3つの場所で処理できる
    • .gitignore
    • .git/info/exclude
    • ~/.config/git/ignore

.gitignore: リポジトリにコミットされる共有ルール

  • .gitignore は無視するファイル名を書く一般的なファイルである
  • ほかのコードと一緒に Git にチェックイン される
  • .gitignore のルールにマッチするファイルは git コマンド実行時に考慮されない

.git/info/exclude: リポジトリごとの個人ルール

  • exclude ファイルはすべての Git リポジトリの .git ディレクトリ内にある
  • このファイルの変更は Git にチェックインされない
  • 新しい Git リポジトリでは通常、数行のコメントが入っている
  • リポジトリごとにだけ無視したいが .gitignore には入れたくないファイルに適している
    • 例: 個人のワークフローでのみ必要な notes.txt をリポジトリにコミットせず、プロジェクトの .gitignore にも追加したくないなら、.git/info/excludenotes.txt を追加する

~/.config/git/ignore: マシン全体のルール

  • グローバル ignore ファイルはホームディレクトリの ~/.config/git/ignore にある
  • ここに追加したファイル名は マシンレベルでグローバルに無視 される
  • Git にチェックインされず、特定のリポジトリにも結び付いていない
  • コンピュータ上のすべての Git リポジトリで無視したいファイルを入れるのに向いている
    • 例: macOS では .DS_Store をここに追加するのが適している

グローバル ignore ファイルのパスを変更する

  • グローバル ignore ファイルは別のファイルに指定できる
  • グローバル Git ignore ファイルを .gitignore_global にしたい場合は、次のコマンドを実行する
git config --global core.excludesFile ~/.gitignore_global
  • デフォルト設定に戻すには、次のコマンドを実行する
git config --global --unset core.excludesFile

どのルールがファイルを無視しているか確認する

  • git check-ignore -v <ファイル名> で、特定のファイルがどのルールによって無視されているか確認できる
  • .DS_Store がどのように無視されるか確認するには、Git リポジトリ内で次のコマンドを実行する
git check-ignore -v .DS_Store
  • リポジトリの .gitignore.DS_Store を無視している場合の出力例は次のとおり
$ git check-ignore -v .DS_Store
.gitignore:1:.DS_Store	.DS_Store
  • リポジトリの .git/info/exclude.DS_Store を無視している場合の出力例は次のとおり
$ git check-ignore -v .DS_Store
.git/info/exclude:7:.DS_Store	.DS_Store
  • グローバル ~/.config/git/ignore ファイルが .DS_Store を無視している場合の出力例は次のとおり
$ git check-ignore -v .DS_Store
/Users/nelson/.config/git/ignore:2:.DS_Store	.DS_Store
  • ユーザー指定のグローバル ignore ファイル .gitignore_global.DS_Store を無視している場合の出力例は次のとおり
$ git check-ignore -v .DS_Store
/Users/nelson/.gitignore_global:1:.DS_Store	.DS_Store
  • 特定のファイルを無視するルールがなければ、git check-ignore -v コマンドは 何も出力しない

3件のコメント

 
sudoeng 1 시간 전

作業のSpecやplan.mdのようなファイルを.git/info/excludeに入れておくのも便利そうですね

 
yangeok 2 시간 전

ルートに設定するものがあったんですね(笑)

 
GN⁺ 4 시간 전
Hacker Newsのコメント
  • 面白い記事だが、Gitで一番気に入っているほぼ無視する機能である.gitattributesが抜けている
    このファイルでは、特定のファイルの差分をGitに"無視"させるよう指定できる。たとえばNodeプロジェクトのpackage-lock.jsonは、Gitの観点ではほとんど純粋なノイズに近い。ライブラリの具体的なバージョンが入った巨大な差分ばかりが出て、人間が読みやすい実際のバージョン情報は別のpackage.jsonにある
    プロジェクトルートの.gitattributespackage-lock.json -diffと1行追加すれば、ファイルは引き続きステージング/コミットされるが、git diffでは意味のない巨大な差分が見えなくなる

    • package-lock.jsonがノイズであってはならない。意図的に更新しようとしているのでなければ更新すべきではないし、そうでなければ理由もなくサプライチェーンリスクにさらされる
      package-lock.jsonの変更がしばしば予期せず発生するなら、何かを間違っている
    • package-lock.jsonはすべての推移的依存関係を示し、package.jsonは直接依存関係しか示さない。後者が「人間が読める本当のバージョン」だというのは事実ではない
      両者は目的が異なり、ロックファイルの差分を常に無視してよいと言うのは危険だ
    • 依存関係のアップグレードやバグの原因追跡をする立場だと、git diffがロックファイルの差分を見せてくれないのは本当に腹が立ちそうだ
      行単位のノイズに見えるというのは理解できるが、必要なときには絶対に必要だ
  • グローバル/ユーザー単位の除外設定は、もっと広く知られてよい機能だ。IDE/OS/AI関連ファイルをすべてのプロジェクトの.gitignoreに追加しようとする変更をよく受けるが、標準設定に入れればどこでも無視され、各プロジェクトを触る必要もなく、.gitignoreを更新していないプロジェクトで誤ってコミットするリスクもないと伝えると、たいてい歓迎される
    個人的な原則として、リポジトリ内の.gitignoreはビルド成果物や依存関係フォルダのようなリポジトリ専用の項目にだけ使い、たいていのユーザーツールは各自のユーザー設定に置くべきだと思っている

    • グローバル.gitignore設定をたびたび案内しなければならないのは、リポジトリ内の.gitignoreをリポジトリ専用の項目にだけ使うという原則の当然の帰結だ
      みんなの時間を節約するには、そうしたファイルは単にすべてのプロジェクトの.gitignoreに入れてしまうほうがよい
    • 無知ゆえにそういうファイルをプロジェクトに追加してしまうことがないよう、いつもプロジェクトの.gitignoreに入れてきた
      どうせ後でGitから削除することになるし、その人にとってもつらいので、親切心で先回りして防いでいた。今後はそこまで親切にしないかもしれない
    • 開発コンテナを再ビルドしても残るので、gitignoreのほうを好む
      gitignoreを避けるなら、生成スクリプトやボリュームで設定を復元/維持できるが、.gitignore1行の代わりに追加スクリプトやdevcontainerのマウント設定が必要になる
    • 同じ誤った行動を繰り返し見ていながら、その行動を直す最も簡単な方法を明示的に禁じる厳格なルールを置くのは、互いに矛盾していないか
  • グローバルGit設定と無視ファイルは、~/.gitignore_globalを作って設定を変えるより、~/.config/git/ignore~/.config/git/configに置くのが正しいと思う
    ~/.config/をさまざまな用途に活用すれば、ルートレベルのdotfilesはずっと少なくなる
    Git excludeがあまり使われない理由は、リポジトリにコミットされないので、使いたくなるたびに作り直さなければならないからだ。悪いという意味ではなく、あまり使われない理由がそれだということ

    • おまけに、~/.configディレクトリをバージョン管理すれば、後で変更したり共有したりできる
    • 同じファイルを使うほかのツール向けに~/.cvsignoreを使ってもよい
  • どこで学んだのか覚えていないが、グローバルGit ignoreにatticを追加してある
    そうすると、どのプロジェクトでも絶対にコミットしてはいけない雑多なものを置くためのatticディレクトリを作れる。実際にそういうディレクトリをチェックするリポジトリはまだ見たことがない

    • 少し逆のやり方もできるが、ケースごとにやる必要がある
      atticのようなディレクトリがあるなら、その中にattic/.gitignoreを作って/**を入れれば、そのディレクトリと中のすべてが無視され、ignoreファイル自体も無視される
      普段は自分の版のディレクトリ名をU+1F4A9の1文字にしているが、HNはコメントにそれを入れるのを許していない
    • 自分はauxを使っている
      その中にアスタリスク1つ*だけ入った.gitignoreを置いて隠せば、自分自身と中身すべてを無視する
    • 私もこうしている。ただし名前は.localにしている
    • 私のはscratch/
      まだ足をすくわれたことはない
  • ユーザー別の無視について、macOSなら.DS_Storeをそこに追加するのが理想的だと言われるが、プロジェクトのすべてのMac利用者がそうしなければならない
    2人以上いるなら、各自に任せないほうがよいかもしれない

    • どこでできたのかははっきりしないが、手元のMac 2台(Ventura 1台、Sequoia 1台)の両方とも~/.gitignore_globalファイルに.DS_Storeの項目があり、グローバルGit設定にもそのファイルの項目を無視する設定が入っている
      新しいMacのこのファイルの日付は注文の2日前で、自分で設定した記憶がないので、最初から入っていた気がする。古いMacも似たようなものだったと思うし、macOSのバージョンを見ると、かなり前からこれがデフォルトだった可能性もある
      だから、.DS_Store/.gitignoreに追加しなければならなかった時代はもう終わったのかもしれない
    • 少数と多数の見方がかなり独特だ。macOSユーザー1人が10個のプロジェクトで作業しているなら、10個のプロジェクトすべてにその行を追加すべきなのか、それともその1人の手元で処理したほうがよいのか?
  • うわ、どうしてこれを知らなかったんだ? 20年選手のプロのソフトウェア開発者なのに、.gitignoreしか使ってこなかった
    自分にしか関係のないあらゆる除外項目で.gitignoreを散らかすよりよい方法があるのではと、自分に問いかけたことすらなかったと気づいた。ただ目の前の世界をそのまま受け入れていたんだ
    今日、世界が少しだけよくなった

  • .git/info/excludeを本当によく使う。ローカルでしか使わず、共同作業者には不要だったり使えなかったりするスクリプト/Makefileにとても向いている

    • ほかの共同作業者が使えないスクリプトとは、たとえばどんなものか気になる。PR作業フロー用のスクリプトのようなもの?
    • かなり前から、git statusに出てくる未追跡ファイルを全部.git/info/excludeに押し込むシェル関数を使っている
      たいていは、リポジトリに入れたいものをaddcommitしたあとで適用する
  • 複数のリポジトリが入っているプロジェクトディレクトリに対して、プロジェクト単位のGit設定を別々に適用するために、excludesファイルをこう使っている
    https://laszlo.nu/blog/project-level-git-config.html

  • 関連して使っているエイリアスがある
    assume = update-index --assume-unchanged
    unassume = update-index --no-assume-unchanged
    assumed = "!git ls-files -v | grep ^h | cut -c 3-"
    unassumeall = "!git assumed | xargs git update-index --no-assume-unchanged"
    assumeall = "!git st -s | awk {'print $2'} | xargs git assume"

  • すでに追跡中のファイルにはgit update-index --[no]-skip-worktreeもある
    ローカルでの実験に便利なことがあるが、Gitがあまり目立つ場所に出してくれない機能なので少し使いにくい。設定したことを覚えておく必要があり、忘れるとチェックアウトのような別の作業が妨げられることがある