Skip to content

hotspots: files most frequently changed #2

@simon-marcus

Description

@simon-marcus

Implement `commitlens hotspots [--top N]` — files ranked by how often they appear in commits.

Deliverable

Module: `src/commitlens/hotspots.py`. Register in `_register_subcommands`.

CLI args: `--top N` (default 20). `--ext .py,.ts` filter optional; if you skip it, leave a TODO comment but don't add the flag — keep scope tight.

Output schema

```json
{
"_render": "",
"hotspots": [
{"path": "src/foo.py", "commits": 42, "authors": 5, "last_commit": "2026-04-29T18:30:00+00:00"},
...
],
"total_commits": 213
}
```

`commits` is the count of commits that touched the file (added/modified/deleted/renamed all count). `authors` is the distinct author email count for those commits. `last_commit` is the most recent commit-time ISO that touched it.

Human render

Fixed-width table sorted by commits desc. Columns: path (truncate to 60), commits, authors, last (relative — "3d ago", "2w ago", "4mo ago"). Cap to `--top`.

Data source

`git log --name-only --pretty=format:%H|%aI|%ae` parsed in Python. (`--numstat` gives lines too if needed, but we don't need them for v1.)

Renames: pass `--follow` is per-file and slow on large repos — for v1, treat the post-rename path as a fresh file. The issue description should explicitly call this out as a known limitation in a comment.

Tests

`tests/test_hotspots.py` using `git_repo`. Build:

  • one file changed in 5 commits by 2 authors (high hotspot)
  • one file changed in 1 commit (low hotspot)
  • one binary file (should still count as touched)
  • one rename (treated as new path)

Assert ordering, counts, distinct-author counting, last_commit correctness.

Metadata

Metadata

Assignees

No one assigned

    Labels

    symphonyCreated by Symphony

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions