# Commit graph — map

> commitbrief map draws the commit DAG and highlights exactly which commits a filter selected, so you can check a filter before paying for a review. --branches switches to a branch topology summary. Deterministic, no provider call, always exits 0.

CommitBrief docs · v1.x · Reviewing

Canonical URL: https://commitbrief.com/docs/1.x/commit-graph/

---

`commitbrief map` draws the commit graph — and, when a filter is active,
shows exactly which commits it selected. It is deterministic: no provider
call, no cache, no cost, and it always exits `0` on a successful render.
A viewer, not a gate. New in v1.15.0 (ADR-0037).

## Why it exists

The [commit filters](/docs/1.x/review-scopes#commit-filters-v1150) can
select a non-contiguous set of commits from anywhere in the history. That
is what makes them powerful, and also what makes them invisible — the
only feedback was a count:

```text
$ commitbrief dry-run --author alice --start-date 2026-06-01
Commits (matched): 12
```

Which twelve? For a filter whose entire job is deciding what gets
reviewed, "trust me, twelve" is weak feedback, and a wrong filter quietly
reviews the wrong code. `map` shows them in place, against the commits
they were interleaved with.

## Usage

```sh
commitbrief map                            # the DAG, newest first
commitbrief map --max-commits 50
commitbrief map main..develop              # bound to a range
commitbrief map --author alice             # matches highlighted, rest dimmed
commitbrief map --branches                 # branch topology instead
commitbrief map --all                      # every ref, not just HEAD's history
```

## Commit graph (default)

One row per commit: lane gutter, short hash, ref labels, subject, author,
relative age.

```text
● a1b2c3d  (main) feat: add commit filters        alice  2h
│╲
│ ○ e4f5a6b  (payments/stripe) chore: bump sdk    bob    3d
│ ○ b7c8d9e  fix: rounding                        bob    3d
│╱
● f0a1b2c  docs: readme                           carol  1w

● matches the filter   ○ context
```

With no filter every commit is `●` and no legend is printed. With one,
matches are highlighted and the rest are drawn as **dimmed context** —
deliberately kept in the graph, because a picture of only the matches
would be a list, not a graph, and the lanes would be meaningless.

Merge commits are always drawn here, even though the filters exclude them
by default elsewhere. In a graph a merge is structure: hiding it leaves
lanes that fork and never rejoin.

## Branch topology — `--branches`

One row per branch, showing where it sits relative to the base and how
far it has drifted:

```text
main                      base       alice  2h
├─ payments/stripe        ▲3   ▼12   bob    3d
└─ feature/upgrade        ▲8   ▼0    alice  1h
```

`▲` is ahead (commits this branch has that the base does not), `▼` is
behind. The base is resolved from `origin/HEAD`, falling back to
`main` / `master` / `trunk`, then the current `HEAD` — it never fails,
because a topology view with an imperfect base beats an error. Capped at
200 refs.

Commit filters are **rejected** in this mode: a branch list has no
commits to select, and rendering an unchanged view that silently ignored
your flag would be worse than saying so.

## Flags

| Flag | Default | Notes |
|------|---------|-------|
| `--branches` | off | Branch topology summary instead of the commit graph. |
| `--all` | off | Walk every ref rather than the given range / `HEAD`. Graph mode only. |
| `--max-commits <N>` | `200` | How many commits to draw. Truncation is reported on stderr. |

All the [commit filters](/docs/1.x/review-scopes#commit-filters-v1150)
apply in graph mode.

## Rejected flags

`map` draws a graph, not findings, so flags that promise something else
are refused rather than quietly ignored:

- `--json` / `--markdown` — a graph JSON (nodes, edges, lanes) would be a
  **new versioned schema** for output whose consumer is a person looking
  at a terminal. Deferred until someone asks with a real use case. Use
  `--output <file>` to capture the plain-text graph.
- `--fail-on` / `--min-severity` / `--suggest-commit` — there are no
  findings to act on.

## Terminal behavior

- Rows **clip** to the terminal width rather than wrapping. A wrapped row
  would carry no lane gutter on its continuation line, visually detaching
  it from the graph. The gutter is drawn first, so the topology survives
  even when a subject is cut.
- Colour and box-drawing fall back **together**: a terminal that refused
  ANSI is also the one most likely to mangle `│`. A pipe, a file, or
  `--color=never` yields pure ASCII (`*`, `o`, `|`, `\`, `/`).
- Relative ages are coarse on purpose (`3d`, not `3 days 4 hours`) to
  keep the column scannable.
- A truncated walk closes lanes at the boundary rather than inventing
  edges to commits it was never given, so the graph shows where it stops.

## See also

- [Review scopes](/docs/1.x/review-scopes#commit-filters-v1150) — the
  filters this visualises.
- [Credential audit — leaks](/docs/1.x/leaks) — the other deterministic,
  provider-free command that walks the same commit selection.
- [Output formats](/docs/1.x/output-formats) — what a review renders once
  you've confirmed the selection.