数字を信じてよいか
このサイトのすべては 1 つの入力に乗っています ―― あなたの git 履歴です。その履歴は見かけよりずっと汚れていて、式の精度より汚染のほうが結果を左右します。このページは何が壊れるのか、そして dowse が各ケースに何をしているのかです。
「この数字を信じてよいか」への正直な答えでもあります。dowse が補正できない問題があなたのリポジトリにあるなら、信じるべきではありません。
1. もつれたコミット
問題。 リファクタとバグ修正とリネームを 1 コミットでやる。そのコミットに含まれる全ファイルが「一緒に変わった」ことになり、存在しない結合をでっち上げます。
dowse の対処。 50 ファイルを超えるコミットは coupling の計算から除外します。churn には含めます ―― ファイルは実際に変わっているからです。ただ結合について何も語らないだけです。
あなたに残るもの。 10 ファイルのもつれたコミットは、正当な 10 ファイルのコミットと区別がつきません。事後に直せるツールはありません。コミットを小さくする以外に手はありません。
2. 整形・生成・vendored なコミット
問題。 リポジトリ全体への Prettier 実行は巨大な変更に見え、触れた全ファイルの churn を膨らませます。生成コード(openapi-types.ts、protobuf の出力)は誰も考えないまま変わり続けます。
dowse の対処。
- 空白だけのコミットを
git log -wで検出して除外します。 - 生成ディレクトリ(
generated/、__generated__/)、生成ファイルのパターン(*.gen.ts、*.generated.ts)、ロックファイル、minified ファイル、vendor/は既定で対象外です。 --verify-churnを付けると各リビジョンの AST を比較し、行 diff では区別できないリネームや整形を実変更から分離します。
これはドッグフーディングで見つけました
実際のリポジトリで、この除外を入れる前は生成された openapi-types.ts が hotspot 1 位でした。スコアの非常に高い、純粋なノイズです。
3. リネームと移動
問題。 ファイルをリネームすると履歴がゼロから始まります。ディレクトリ再編が日常のモノレポでは、これが最も損害の大きい効果です。
dowse の対処。 ログ読み取り時にリネーム・コピー検出を有効にし、移動を追跡します。--verify-churn では、移動後に内容が変わっていないファイルを identical と判定し、churn に数えません。
4. パッケージ境界
問題。 モノレポで packages/ui への変更と apps/web への変更は、同種の出来事ではありません。リポジトリを平坦なファイルの山として扱うと、両者が混ざります。
dowse の対処。 最初に workspace 設定を読み、全ファイルをパッケージに帰属させます。メトリクスはファイル単位で計算し、LoC 重み付き平均でパッケージへ集約します。coupling はファイル粒度とパッケージ粒度の両方で計算します。
5. squash merge と rebase
問題。 squash merge では、ブランチの 30 コミットが 1 つになります。変更頻度が下がり、貢献者数が過小評価されます。
dowse の対処。 自動での対処はありません ―― 情報が失われているからです。できるのは、実際に使ったコミット数を報告することです。年 200 コミットで開発者 40 人のリポジトリなら、squash merge していると分かります。
あなたに残るもの。 マージ方針の異なるリポジトリ間ではなく、同一リポジトリ内の期間どうしで比較してください。
6. 開発者のアイデンティティ
問題。 同じ人が alice@corp.com、alice@personal.com、Alice でコミットしている。3 人として数えられ、ownership が薄まり、bus factor が過大評価されます ―― パッケージが実際より安全に見えます。
dowse の対処。 author の名前とメールを git log %aN/%aE 経由で読みます。これは .mailmap を適用します。
あなたに残るもの。 .mailmap が無いなら書いてください。この失敗は無言です。数字は正常に見えて、楽観方向に間違っています。
7. bot のコミット
問題。 dependabot、renovate、CI の bot は大量のコミットを生み、churn と ownership の両方を歪めます。
dowse の対処。 [bot] サフィックス、既知の bot 名、noreply アドレスを持つ author のコミットを、churn と ownership の計算前に除去します。除去した件数は表示されます。
8. shallow clone
問題。 fetch-depth: 1 ―― CI の既定 ―― では履歴がほとんど残りません。churn も coupling も age も無意味になります。
dowse の対処。 起動時に shallow clone を検出して明確に警告し、出力に shallow: true を残します。
最も多い「間違った数字」の出方
静かに失敗します。3 コミットから作られた、完全に見えるレポートが得られます。CI では必ず fetch-depth: 0 を指定してください。
9. ソース中の生の NUL バイト
問題。 ソースファイルに生の NUL バイトが入っていると、git はそれをバイナリとみなし、--numstat が行数ではなく - を返します。そのファイルの churn は静かに消えます。
dowse の対処。 - を 0 ではなく「不明」として解釈するので、変更なしとして黙って数えることはありません。
あなたに残るもの。 バイトを埋め込まず \0 エスケープで書いてください。dowse 自身のコードベースにも 3 ファイルありました。
すべての根底にある原則
上記の除外はすべて出力に表示されます。
excluded: 312 merge, 47 bot, 18 format-only, 0 ignore-revs (51 large changesets flagged)黙ってデータを落とす解析は、結果を「全部を見た上での結論」と読ませてしまいます。範囲の分からない数字は行動の根拠になりません ―― だから dowse は、たとえ都合の悪い答えでも、必ず自分の範囲を示します。