Skip to content

Repository files navigation

git-visualizer

A fast, dependency-light CLI that turns Git history into a graph — right in your terminal, or exported as PNG/SVG/HTML.

TypeScript Node License

Overview

git log --graph gets unreadable fast once a repo has real branch/merge structure. git-visualizer shells out to git log --topo-order with a NUL-delimited pretty-format, runs the commit DAG through its own lane-assignment algorithm, and renders the result as a clean, colored graph — either as box-drawing characters in your terminal or as a static PNG/SVG/HTML file you can drop in docs or a PR.

It's a portfolio project: no framework magic, no native-git bindings — just Node's child_process, a hand-rolled layout engine, and a renderer per output target.

Features

  • Terminal graph rendering — one line per commit with rounded box-drawing connectors (╭ ╮ ╰ ╯ ┼), colored lanes, [branch] / [origin/x] / [⚑ tag] badges, and relative timestamps. Adapts to terminal width and disables color automatically when piped or when NO_COLOR is set.
  • Static export--export svg|png|html renders the same graph to a file. PNG is rasterized with @resvg/resvg-js (no headless browser); HTML export produces a standalone report.
  • Filtering — narrow history by --branch, --author (regex), --since (e.g. "30 days ago"), and --max-commits (0 = unlimited), all translated directly into git log/git rev-list arguments.
  • Local web server--web starts a Node HTTP server (binds to 127.0.0.1 only) exposing a JSON API (/api/graph, /api/commit/:sha, /api/search, /api/branch-rows) with pagination, in-memory layout caching, and SHA/ref validation. The browser-side React app that consumes it (theming and typed fetch client are in place) is still under active development.
  • Handles big histories without choking — commits are parsed from a streamed git log, so memory stays flat on 50k+ commit repos; the lane-assignment layout is O(commits × active lanes), not O(commits²).
  • Clear failure modes — a GitError type distinguishes "not a git repo," "git not installed," and "unknown ref" and prints an actionable one-line message instead of a stack trace.

Tech Stack

  • TypeScript (strict, ESM) throughout
  • Commander for CLI flag parsing
  • Picocolors for terminal color (plus a small custom xterm-256 helper for the lane palette)
  • @resvg/resvg-js for native SVG → PNG rasterization
  • Node's http module for the embedded web server (no Express — four routes didn't justify a framework)
  • React 18 + Zustand + D3 (d3-selection, d3-zoom) + Tailwind + Vite for the in-progress browser UI
  • tsup to bundle the CLI, Vitest configured for the test suite
  • Zero dependency on git bindings — everything shells out to the system git binary via child_process

Installation

git clone https://github.com/advayiscoding/Git-visualizer-cli-tool.git
cd Git-visualizer-cli-tool
npm install
npm run build
npm link   # optional: exposes the `git-visualizer` command globally

Usage

Run inside any Git repository:

# Render the graph for the current repo in your terminal
git-visualizer

# Only a specific branch
git-visualizer --branch main

# Filter by author (regex) and time window
git-visualizer --author "advay" --since "30 days ago"

# Cap (or lift the cap on) how many commits are rendered
git-visualizer --max-commits 500
git-visualizer --max-commits 0   # unlimited

# Export a static graph instead of printing to the terminal
git-visualizer --export svg -o history.svg
git-visualizer --export png --theme light
git-visualizer --export html -o report.html

# Start the local web server (binds to 127.0.0.1)
git-visualizer --web --port 7644
git-visualizer --web --no-open

Full flag reference:

Usage: git-visualizer [options]

Visualize Git repository history as an interactive graph — in the terminal, the browser, or an exported file.

Options:
  -V, --version              output the version number
  -w, --web                  open an interactive graph in the browser
  -p, --port <number>        port for the web server (default: 7644)
  --no-open                  do not auto-open the browser in --web mode
  -b, --branch <name>        show only history reachable from this ref
  -a, --author <pattern>     filter commits by author (regex, like git log --author)
  -s, --since <date>         only commits newer than a date, e.g. "30 days ago"
  -e, --export <format>      export instead of displaying: png | svg | html
  -o, --output <file>        output file for --export (default: ./git-visualizer-export.<ext>)
  -t, --theme <theme>        export theme: dark | light (default: "dark")
  -n, --max-commits <count>  max commits in terminal/export mode, 0 = unlimited (default: 2000)
  -h, --help                 display help for command

How It Works

  1. src/git/repository.ts locates the repo root and runs/streams git; log.ts streams git log --topo-order with a NUL/RS-delimited custom format (no escaping concerns, flat memory on huge histories); refs.ts pulls branches/remotes/tags via git for-each-ref, peeling annotated tags to their commit SHA.
  2. src/graph/layout.ts — the core algorithm. Walks commits in topological order maintaining an array of "active lanes," each tracking the parent SHA it's traveling toward. Converging commits merge into the lowest matching lane; branch tips claim the lowest free lane so the graph stays compact instead of growing unbounded width. First parents continue their commit's lane (so a branch reads as one continuous line); merge parents either join an existing lane or open a transient one.
  3. src/render/ascii.ts turns the lane/edge layout into a terminal grid with box-drawing glyph merging (precedence: node > corner > crossing > line); svg.ts/html-report.ts render the same layout as static output; themes.ts defines the shared dark/light color tokens used by both static export and the web UI.
  4. src/export/ — dispatches to SVG, PNG (via resvg), or HTML, each with a row cap sized to keep output files sane (e.g. PNG caps at 1,500 rows to avoid multi-million-pixel images).
  5. src/server/ — a plain http.createServer exposing a small JSON API over the same snapshot/layout pipeline, with an in-memory LRU-ish cache keyed by filter combination and static-file serving (with path-traversal guards) for the browser UI build in dist/ui.

Skills Demonstrated

  • CLI design — flag parsing, validation, and help text with Commander; sane defaults; distinct exit paths for terminal/export/web modes
  • Git internals — driving git log/git for-each-ref/rev-list plumbing directly, understanding topological ordering, parent chains, detached HEAD, and annotated tag peeling
  • Algorithm design — a from-scratch DAG lane-assignment/layout algorithm (the same family of technique used by tig and GitKraken-style graph viewers), reasoned about for both correctness and complexity
  • Terminal UI rendering — building a character-grid renderer with Unicode box-drawing glyphs, ANSI 256-color output, glyph-merge precedence rules, and responsive width handling
  • Streaming & performance — parsing an unbounded git log stream incrementally instead of buffering, keeping memory flat on 50k+ commit repositories
  • Small-footprint HTTP services — a dependency-free Node http server with a JSON API, input validation, and static-asset traversal protection
  • TypeScript project structure — strict, ESM-first, modules cleanly separated by concern (git / graph / render / export / server / ui) with shared types

License

MIT

About

CLI that renders Git commit history as a colored graph in your terminal, or exports it to PNG/SVG/HTML — TypeScript, zero native git bindings.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages