Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

75 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GitHawk

A git graph for VS Code that is just a git graph. No AI, no telemetry, no account, no cloud. MIT licensed.

The GitHawk graph panel

Preview. Everything documented here works and is covered by tests. What it does not do yet: stay fast on very long histories, or help you out of a conflicted merge.

Install

Search GitHawk in the Extensions view, or:

code --install-extension kfirzvi-com.githawk

Then press Cmd+9 (Ctrl+9 on Windows and Linux) — or run GitHawk: Open Git Graph. The graph opens in the panel at the bottom; changed files appear in a tree in the sidebar under the GitHawk icon.

Nothing to configure to get started.

Why another one

Git Graph is what most people used, and it has been abandoned (#913, #838) with millions of installs still depending on it. Its licence looks like MIT but removes the right to publish, distribute, sublicense, and/or sell derivative works — so it is not open source, and nobody can legally ship a maintained fork.

GitHawk is a clean-room replacement under a real MIT licence. Meanwhile the maintained alternatives keep adding AI to a tool whose entire job is drawing lines between commits.

What it does

Look like the rest of your editor

Every colour comes from VS Code's own theme tokens, so the panel is light on a light theme and high-contrast on a high-contrast one. Only the lane colours are fixed: a lane has to keep its colour as your eye follows it down the graph, and stay distinct from the seven beside it, so they are eight hues chosen to hold their contrast against white and near-black alike.

Read the graph

Commits in correct topological order — a parent is never drawn above its child, even after a rebase or a cherry-pick. Lanes are reused as soon as a branch ends, so the gutter stays narrow on repositories with dozens of branches. Branches, remote branches, tags, and a detached HEAD are each labelled distinctly.

See what a commit changed

Commit details and the changed-files tree

Click a commit: its full message, author, date, and hash appear on the right, and its files fill the Changes tree in the sidebar. Click a file to open it in VS Code's own diff editor.

The sidebar is surfaced the first time and then left alone — pulling focus on every click would make the graph unbrowsable. To ask for it deliberately, once it has been closed or covered, right-click a commit and choose "Show changes in the sidebar".

See what you have not committed

The graph panel

A row above the newest commit, whenever there is anything uncommitted, saying what kind — 2 staged, 1 modified, 3 untracked. Click it and the Changes tree fills with everything uncommitted, as one changeset against HEAD, and comes to the front. The row disappears when the tree is clean, so its presence is the answer to "is there anything here?".

Unlike a commit, clicking this row surfaces the sidebar every time. Browsing the graph is many clicks across many commits and the sidebar should not chase each one; there is only ever one of these rows, so clicking it is only ever a request to see the files.

Its marker is hollow and dashed rather than a commit dot, because it is not a commit: nothing points at it, it has no hash, and it looks different the moment you save a file. Nothing draws a line from it to HEAD either — the graph reads every ref, so the topmost row is often not the commit your changes sit on, and a line saying otherwise would be wrong more often than right.

One honest gap: untracked files are counted in the row but are not in the changeset. git diff HEAD has nothing to compare a file git has never seen against. GitHawk: Show Uncommitted Changes opens the same comparison without the panel.

See who wrote a line, and jump to why

Blame in the editor

Set gitHawk.blame.style to column and every line carries the date and author of the commit it came from, in a fixed-width column between the line numbers and the code — IntelliJ's annotate, in VS Code.

Each commit gets its own colour, and the colours run in order: cool for the oldest lines in the file, warm for the newest. So a run of lines from one commit reads as a block without needing a separator, and scrolling shows the order the file was built in rather than just that several people built it.

Hover any line for the full message, the author, the date, how many lines that commit owns here — and "show in the graph", which opens the panel, selects the commit, and fills the Changes tree. That is the part no standalone blame extension can do: the graph is already here.

endOfLine is the quieter option — one label per block, at the end of its first line, leaving your code where it is. Both blame the editor's buffer rather than the file on disk, so annotations stay honest while you are part-way through an edit.

Turn it on with GitHawk: Toggle Blame Annotations, the person icon in the editor's title bar, or right-click in the editor. Off is the default, and the toggle switches between off and the column — set gitHawk.blame.style directly for endOfLine. Annotations appear in the diff editor too — both sides, each blamed as of its own revision, which is the question a diff raises.

Give the graph the room

The panel is short and splits its width three ways. Either side pane folds away with the thin handle beside it — the handle stays where it is when the pane is gone, so the way back is where the way out was — and the graph takes the space. GitHawk remembers which panes you had.

Review a whole branch, or any set of commits

Several commits selected, with their combined changes

  • Click a branch → "Review my work against …" — everything your branch adds relative to that one, measured from the merge base, including work you have not committed yet.
  • Cmd/Ctrl-click several commits, or Shift-click for a run. Their combined changeset appears automatically — selecting is the request, there is no button. They do not have to be next to each other.
  • "Compare … with …" — any two branches, tags, or commits, directly. Neither side has to involve where you currently are, so you can sit on main and compare two other branches.

The tree always states how the comparison was made, because a merge-base diff, a direct diff, and a reconstruction answer different questions.

Act on branches and commits

The grouped branch menu

Click a branch, or right-click a commit, and you get a native VS Code menu — grouped by topic, with your keyboard shortcuts and theme, not a menu drawn inside a webview.

The branch labels drawn on the graph are the same click target as the branch list, so a branch is actionable wherever you happen to be looking at it. Both offer "Copy branch name" — a webview cannot be text-selected, and a branch name is what gets retyped into a checkout, a PR description, or a CI filter.

On a commit: create a branch or tag here, check it out, cherry-pick, revert, reset, copy the hash. On a branch: push, pull, check out, merge, rebase, rename, delete, or delete it on the remote.

Push and pull are per branch, and always there. The Sync group at the top of a branch's menu offers both every time, with the state in the description — 3 behind, nothing to push, already up to date — rather than appearing only when there is something to do. A branch that has never been pushed offers "Publish" instead, which sets its upstream so the next push needs no arguments. There is no --force anywhere, so git refusing a non-fast-forward is left to refuse.

main is behind while you are on a feature branch? That does not need a checkout. Pulling a branch you are not standing on writes the ref directly — your working tree, index, and HEAD are untouched — and the menu says so. The branch list shows ↓ behind, ↑ ahead, or gone at a glance, and GitHawk: Update All Branches From Upstream does every eligible one at once.

Anything destructive asks first, and says what will be lost.

Put work aside

Stash entries appear in the graph as rows of their own, hanging off the commit the work was left on, and in the sidebar beside the branches and worktrees. All four sidebar sections — local, remote, worktrees, stashes — are always there, each folding away and remembering it, and each saying what it is for when there is nothing in it. Remote, Worktrees and Stashes carry a Manage button.

GitHawk: Manage Stashes lists the stash with what each entry says it is, the branch it was made on, and when. An entry git named itself — WIP on main: 1234abc … — is marked (unnamed), because that wording describes the commit the work was sitting on rather than the work.

Apply an entry from the list in one click, or open it for the rest: show what is in it in the Changes tree, apply, pop, or drop. Stashing asks for a message and whether to include untracked files, which is never the default — it is the one variant that sweeps up a scratch file you had not thought about.

Popping and dropping ask first. Both remove the entry, and a dropped entry survives only as a dangling commit.

A stash entry is a commit, so showing what is in it is the same comparison machinery as everything else — it lands in the Changes tree and opens in the diff editor.

Manage remotes

Manage on the sidebar's Remote section, or GitHawk: Manage Remotes. Either lists every remote with its URL, and a remote with a separate push URL — the fork workflow, reading from upstream and writing to your own copy — shows both, because being shown one of two is how you push somewhere you did not mean to.

Add, rename, re-point, or remove one; fetch a single remote with pruning from the list without opening anything; or prune deleted branches without fetching. Removing a remote and pruning both ask first: they delete tracking refs, and nothing in the reflog brings those back.

Work across several repositories

The repository picker

Open a folder of projects and GitHawk finds the repositories inside it. The name at the left of the toolbar switches between them; so does GitHawk: Switch Repository. Switching moves everything with it — graph, menus, comparisons, and the Changes tree.

Submodules, linked worktrees, and repositories nested inside a monorepo are all found. How deep it looks is gitHawk.repositoryScanDepth.

Keep up with the repository

Commit in a terminal, check out from the Source Control view, let an agent rebase in a worktree — the graph reloads on its own. GitHawk watches git's metadata, not your working tree, and waits for an operation to finish rather than redrawing on every step of a rebase. Your place in the history is kept: the row you are looking at stays where it is instead of sliding down as commits arrive above it.

Manage worktrees

The worktree manager

A worktree is a second directory with a different branch checked out, sharing one repository. They stay niche because git's errors are opaque — it refuses a checkout because of a directory you deleted last month, and tells you only that the branch "is already used by worktree at …".

GitHawk names the rule instead:

  • A branch checked out in another worktree is badged in the branch list, so you can see before clicking that a checkout would be refused. Its menu offers to open that worktree instead.
  • A Worktrees section appears in the sidebar once you have more than one, flagging locked and missing.
  • Any free branch offers Create a worktree for …, suggesting a sibling of the repository named after the branch.
  • A worktree whose directory is gone is reported as missing with a Prune entry — until that record is cleared, git keeps refusing its branch everywhere.

Each row has buttons to open a new VS Code window, open a terminal, or start an AI CLI there — Claude Code, Codex, Gemini CLI, and opencode by default, configurable. That is the one place AI appears in GitHawk: launching your tool in the right directory. It reads nothing and sends nothing.

Settings

Setting Default What it does
gitHawk.commitLimit 500 How many commits to read. Higher shows more and loads slower.
gitHawk.blame.style off Blame in the editor: column for IntelliJ's annotate, endOfLine for one label per block.
gitHawk.autoRefresh true Reload the graph when the repository changes outside GitHawk. Watches git's metadata, never your working tree.
gitHawk.repositoryScanDepth 2 Directory levels below each opened folder to search for repositories. 0 searches the folders only; 2 covers a folder of projects, or a folder of buckets each holding projects.
gitHawk.aiTools Claude Code, Codex, Gemini CLI, opencode Commands offered by "Start an AI CLI here".

Commands

Command
GitHawk: Open Git Graph Cmd+9 / Ctrl+9
GitHawk: Refresh Git Graph Also rescans for new repositories
GitHawk: Switch Repository
GitHawk: Manage Worktrees
GitHawk: Manage Remotes Add, rename, re-point, remove, fetch, prune
GitHawk: Manage Stashes List, show, apply, pop, drop; stash the working tree
GitHawk: Show Uncommitted Changes Everything uncommitted, against HEAD
GitHawk: Start An AI CLI Here
GitHawk: Update All Branches From Upstream Fast-forwards every branch that can be
GitHawk: Show Log GitHawk's own output, when something goes wrong

Known limitations

Honest list, in the order they are likely to annoy you:

  • No row virtualisation. A large commitLimit renders every row; 500 is fine, 5000 is not.
  • A conflicting merge or rebase leaves you mid-operation. GitHawk reports git's message but offers no abort or resolution.
  • One repository at a time — there is no combined view across several.
  • Repositories are found by scanning on load, not watched. One cloned while the window is open needs a refresh.

Contributing

Bug reports and pull requests are welcome — issues. See CONTRIBUTING.md for the architecture, how to run it locally, and how the three tiers of tests work.

Licence

MIT — see LICENSE. Actually MIT, in the sense that you may fork it, ship it, and sell it.

About

A simple, fast git graph for VS Code. MIT licensed. No AI, no telemetry.

Topics

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages