Skip to content

数字を信じてよいか

このサイトのすべては 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.comalice@personal.comAlice でコミットしている。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 は、たとえ都合の悪い答えでも、必ず自分の範囲を示します。

MIT ライセンスで公開されています