51 テンプレート内蔵の .gitignore ジェネレーター CLI を Python で作った

きっかけ

新しいプロジェクトを始めるたびに同じことをやる。ディレクトリを作り、git init して、gitignore.io か GitHub のテンプレートピッカーで .gitignore を組み立てる。3クリック、スクロール、前のプロジェクトからのコピペ。動くが、キャリアを通じて何百回も繰り返す摩擦。

gitignore-gen はその摩擦を消すツール。51のテンプレートを内蔵し、gitignore-gen python node macos で重複排除済みの .gitignore を生成する。ネットワークリクエストなし、API キーなし、Python 標準ライブラリのみ。

🔗 GitHub: https://github.com/sen-ltd/gitignore-gen

Screenshot

使い方

# テンプレートを結合して stdout に出力
$ gitignore-gen python node macos

# ファイルに直接書き出し
$ gitignore-gen python node --output .gitignore

# 51 テンプレートの一覧
$ gitignore-gen --list

# キーワードでテンプレートを検索
$ gitignore-gen --search ide

エイリアス

誰も毎回 objective-csublimetext とは打ちたくない。40以上のエイリアスをサポート。

# 同じ意味
$ gitignore-gen py js mac
$ gitignore-gen python node macos

# IDE エイリアス
$ gitignore-gen idea    # → jetbrains
$ gitignore-gen code    # → vscode

# 言語エイリアス
$ gitignore-gen rs      # → rust
$ gitignore-gen ts      # → typescript

アーキテクチャ

3つのモジュールが明確な責務分離で構成されている。

テンプレートデータベース(src/templates.py

テンプレート名から gitignore パターンのリストへの Python 辞書。

TEMPLATES: dict[str, list[str]] = {
    "python": [
        "# Python",
        "__pycache__/",
        "*.py[cod]",
        "*$py.class",
        "*.so",
        # ... 30+ パターン
    ],
    # ... 51 テンプレート
}

各テンプレートはコメントヘッダ(# Python# Node.js 等)で始まる。マージ後の出力でどのテンプレートがどのパターンを提供したかが一目でわかる。

テンプレートを外部ファイルや GitHub API ではなく Python の辞書に埋め込んだ理由は3つ。

  1. オフライン動作 — 電車、飛行機、企業ファイアウォール内でもツールが動く
  2. 速度 — 辞書ルックアップはマイクロ秒、API コールは数百ミリ秒
  3. 信頼性 — API レート制限、認証トークン、DNS 解決エラーが存在しない

gitignore パターンは滅多に変わらない。Python は10年以上 __pycache__/*.pyc を使っている。Node は最初から node_modules/

マージエンジン(src/merger.py

テンプレート名のリストを受け取り、クリーンな .gitignore 文字列を生成する。

  1. エイリアスを正式名に解決
  2. テンプレートの重複排除(python python と書いても1回だけ処理)
  3. パターンの重複排除(Python と Node の両方が .env を含んでいたら1つだけ出力)
  4. セクションヘッダ(コメント行)は重複排除しない
  5. テンプレート間に空行を挿入

重複排除は「先勝ち」方式。Python と Node が両方 .env を含んでいる場合、Python セクションに残る(先にリストされたから)。これによりパターンが論理的なコンテキストから分離されず、6ヶ月後にファイルを読んだときにも各パターンの出所がわかる。

CLI(src/cli.py

argparse を使い、外部依存なし。sys.exit() を直接呼ばず整数の exit code を返すので、テストで SystemExit をキャッチする必要がない。

--output はデフォルトで上書き、--append で追記モード。チームメンバーごとにエディタテンプレートを追加するときに便利。

テンプレートのカバレッジ

51テンプレートを6カテゴリに整理。

言語(27): Python, Node.js, Rust, Go, Java, PHP, Ruby, Swift, Kotlin, C, C++, Dart, Elixir, Haskell, Scala, R, Julia, Lua, Perl, TeX, C#, F#, TypeScript, Zig, Erlang, Clojure, Objective-C

ゲームエンジン(3): Unity, Unreal Engine, Godot

モバイル(3): Android, Xcode, Flutter

エディタ(5): JetBrains, VSCode, Vim, Emacs, Sublime Text

OS(3): macOS, Windows, Linux

ビルドツール(10): Terraform, Docker, CMake, Gradle, Maven, Bazel, Vagrant, Ansible, Rails, Next.js

各テンプレートはそのエコシステムで重要なパターンをキュレーションしている。Python テンプレートには __pycache__/ だけでなく、pytest(.pytest_cache/)、mypy(.mypy_cache/)、coverage(.coveragehtmlcov/)、tox、仮想環境(.venv/venv/ENV/)のパターンが含まれる。

テスト

32件の pytest テスト。

マージの重複排除テストが特に重要。テンプレート間で共有されるパターンが出力に1回だけ現れること、セクションヘッダは常に保持されること、テンプレートの順序がどのセクションが共有パターンを「所有」するかに影響することを検証する。

実際のワークフロー

# 新しい Python Web プロジェクト
$ mkdir my-project && cd my-project
$ git init
$ gitignore-gen python node macos vscode --output .gitignore
$ git add .gitignore && git commit -m "initial commit"

# 後からチームメイト用に JetBrains パターンを追加
$ gitignore-gen jetbrains --output .gitignore --append

# Rust プロジェクト用のテンプレートを確認
$ gitignore-gen --search rust

学んだこと

テンプレートのキュレーションはコードを書くより大変。 マージエンジンは半日で書けた。51テンプレートを適切なパターンでキュレーションするのはもっとかかった。各言語エコシステムの慣習、ビルドツール、エディタ連携を知る必要がある。

重複排除には順序のセマンティクスが必要。 最初の実装は set で全パターンをアルファベット順に並べた。正しいが読めない。「先勝ち」方式にしたら論理的なグルーピングが保持された。

エイリアスは UX 機能。 エイリアスシステムはマージエンジンに複雑さをゼロ追加する(解決ステップの辞書引きだけ)。しかし gitignore-gen py js mac と打てることでユーザー体験が劇的に改善する。

ソースは GitHub にある。pytest だけでテストスイートが動き、python main.py で次の .gitignore を生成できる。