Subject: [GSoC PATCH v6 0/3] graph: add --graph-lane-limit option

From: Pablo Sabater <[email-masked]>
Date: Sat, 28 Mar 2026 01:11:10 +0100

Repositories that have many active branches at the same time produce
wide graphs. A lane consists of two columns, the edge and the space
padding, each branch takes a lane in the graph and there is no way
to limit how many can be shown.

The limit is a horizontal truncation, each lane is cut at the lane limit:

  Without --graph-lane-limit:

  *   7_M1
  |\  
  | * 7_E
  * | 7_C
  | | *   7_M2
  | | |\  
  | | | * 7_H
  | | |/  
  | |/|   
  | * | 7_D
  | | * 7_G
  | | * 7_F
  | |/  
  |/|   
  * | 7_B
  |/  
  * 7_A

  With --graph-lane-limit=1:

  *   7_M1
  |\  
  | * 7_E
  * ~ 7_C
  | ~ 7_M2
  | ~ 7_H
  | ~ 
  | ~ 
  | * 7_D
  | ~ 7_G
  | ~ 7_F
  | ~ 
  |/~ 
  * ~ 7_B
  |/  
  * 7_A

The '~' is the truncation mark, not an actual lane. It was chosen because '.' is
already used in octopus merges and '~' is not used elsewhere in the graph. Yet
the edges between the last visible lane and the truncation mark are still
conserved.

The '*' commit mark is visible when it lives on a visible lane or the first
hidden lane, any deeper lane doesn't show the commit mark but keeps the commit
message visible. 

Merges where neither the commit nor its parents live on a visible lane are skipped
because they don't carry any visible information.

The original idea to limit columns was noted as a TODO in c12172d2ea
(Add history graph API, 2008-05-04).  This does not implement
gitk-style column rearrangement, it only truncates the visual output.

Possible future improvements:

- When all branches involved in collapsing or padding are over the limit, the
  truncated lane doesn't show any information, this lane could be removed to
  make the graph more compact. Currently these lanes still appear because
  graph_output_collapsing_line() mixes state handling with rendering, so it can't
  be skipped but callers always expect a non empty buffer. Fixing it would need
  to refactor the callers to handle empty buffers instead of expecting them to
  always have content.

- Collapsing and merges lanes that start on visible lanes but end on hidden ones
  are kept to maintain the most information possible on the visible lanes, but
  the information about where they go or come from is lost. They can be kept,
  removed or think of a way to show that information without showing the lanes.

Changes since v5:

- Changed patch structure
- Fixed octopus merge truncation check to commit_index + 1 + i.
- Added check for first_interesting_parent() NULL check.
- Shortened variable names.
- Added clarifications when converting between lanes and columns.

Pablo Sabater (3):
  graph: limit the graph width to a hard-coded max
  graph: add --graph-lane-limit option
  graph: add truncation mark to capped lanes

 Documentation/rev-list-options.adoc |   6 +
 graph.c                             | 178 ++++++++++++++++++++++++----
 revision.c                          |   6 +
 revision.h                          |   1 +
 t/t4215-log-skewed-merges.sh        | 144 ++++++++++++++++++++++
 5 files changed, 311 insertions(+), 24 deletions(-)

base-commit: 5361983c075154725be47b65cca9a2421789e410
-- 
2.43.0