Git Graph #
A Git Graph fork that puts every worktree on the graph.
Why this fork
Git Graph by mhutchie stopped receiving updates in 2021.
Its last MIT-licensed commit is 4af8583;
everything after that is no longer MIT.
This extension starts from neo-git-graph, an MIT fork of that commit,
and keeps the original Git Graph layout: repository and branch pickers in the header, the commit table and graph
below. Git Graph # adds the feature the original never had:
- Uncommitted changes next to their branch: each dirty worktree has a row above its checked-out commit.
Clean worktrees do not duplicate commits; they stay accessible from the Worktrees manager.
- Branch labels follow worktree changes: a dirty worktree's local branch label appears on its worktree row,
not again on the commit below. Remote and tag labels stay on their actual commits. This only changes label placement, not Git refs.
- Uncommitted changes for every worktree, not just the main checkout, drawn as a dashed node in the same colour
as the worktree's branch.
- Worktree management: use the toolbar's Worktrees manager to create, move, lock, remove (optionally deleting
its branch), and prune stale records. Graph-row menus stay focused on changes.
- Expandable worktree changes: click a worktree row to list its staged, unstaged and untracked files; click a
file to diff HEAD against the working tree.
- Remote operations: fetch all or one remote, add/remove remotes, push/pull, pull with rebase, fetch into a local
branch, delete a remote branch, rebase, and create archives.
- Pull/rebase with auto-stash: tracked changes can be stashed and reapplied by native Git. Restoration may conflict;
this does not promise to protect all untracked or ignored files.
Worktree rows are labelled main worktree or linked worktree; local and remote branches are grouped separately in
the branch picker, and long names expand on hover.
Features
- Graph view: branches, tags, worktrees, and uncommitted changes in one graph
- Worktree changes: one row per dirty worktree, with its own uncommitted changes and file list
- Commit details: click a commit to see its message, files, and diffs
- Branch actions: create, checkout, rename, delete, merge, rebase, push, pull, and archive
- Tag actions: create, delete, push, and archive tags
- Commit actions: checkout, cherry-pick, revert, and reset
- Branch views: multi-select, exclude, clear/invert, local/remote groups, quick presets, saved views and collapsible ancestry/upstream/tip-time conditions
- Remote manager: inspect fetch/push addresses, add, edit, rename and remove remotes for any Git host; embedded credentials are redacted
- Remote actions: fetch, pull with rebase, delete remote branches
- Remote/container environments: require Git and the extension in the workspace host; environment-specific validation is still pending
- Internationalization: English, Simplified Chinese, and Traditional Chinese
Installation
Requires VS Code 1.125+, Git, and a trusted workspace. Extension ID: whw23.git-graph-sharp.
Marketplace listing
If you received a VSIX, use Extensions → … → Install from VSIX…, or:
code --install-extension git-graph-sharp-0.7.4.vsix
Run Developer: Reload Window after upgrading. Installing from a VSIX does not require the source repository,
Node.js, or project dependencies; use a new VSIX for subsequent manual upgrades.
Then run Git Graph #: View Git Graph from the Command Palette, or click the Git Graph # button in the Source
Control view title.
Repository discovery
You can open a parent folder that is not a Git repository. Discovery checks its child folders to depth 2 by default:
workspace/ ← opened in VS Code; no .git required here
packages/
service/.git ← discovered and selectable
website/.git ← also discovered
Set git-graph-sharp.maxDepthOfRepoSearch for deeper layouts. An explicitly configured 0 remains root-only.
Opened subfolders of an existing repository resolve to that repository's real root. Dependency/cache trees such as
node_modules are skipped, directory symlinks are not recursively followed, and large scans have a 2,000-directory
limit; open a narrower workspace if that limit is reached. Discovery runs on open/rescan events, not every graph refresh.
The header combines native VS Code-style icons with readable labels. Hover or focus an action to see its help text.
| Action |
Purpose |
| Refresh |
Reload local commits, refs and worktree changes; no network call |
| Fetch ▾ |
Fetch all remotes and prune stale remote-tracking branches by default; options can select one remote or disable pruning; no merge/rebase |
| Worktrees |
Manage all worktrees, including clean and detached ones; open/remove actions work with mouse, keyboard focus and touch |
| Remotes |
Inspect fetch/push addresses and add, edit, rename, remove or fetch a remote |
| Find |
Search loaded commits by message, hash or author |
| Settings |
Open graph settings and the graph-only language setting; no duplicate editor-wide language command |
The branch picker edits a draft; Apply performs one query and Cancel leaves the current view untouched. Multiple branches load a union of reachable history. Excluding branches hides their labels/worktree rows, not shared ancestors. An empty selection stays empty. “All” is dynamic and includes new branches after refresh. Conditions use commit ancestry, configured upstreams and tip committer time, never inferred branch creation dates.
The picker only filters the graph; it does not check out a branch. “Show Remote Branches” controls visibility, not fetching. Saved views belong to the repository state. Worktree actions do not toggle branch checkboxes. Context-menu commands wrap instead of truncating. Ref labels keep 96–192 px collapsed slots; only the hovered label expands as an opaque overlay, without moving neighbouring refs or the message. Long expanded names are bounded to the viewport.
Worktree development workflow
Choose Worktrees → Manage Changes, or use the button in an expanded dirty-worktree row. The panel keeps staged, unstaged and untracked files separate. File actions stage or unstage an explicitly chosen whole file; Select Changes previews individual text hunks and applies only checked hunks to the index. Working files are left unchanged. Binary, rename and permission-only changes use whole-file staging; splitting individual lines inside one hunk remains a VS Code Source Control feature. Staged diffs compare HEAD with the target index; unstaged diffs compare its index with its working files.
Stash Changes acts only on the named, registered worktree. Including untracked files is optional; ignored files are never included by this action.
Stashes lists the repository-shared backups. Choose the target worktree explicitly. Apply uses a stable stash OID, optionally restores staged state, and keeps the backup even if restoration conflicts. Delete revalidates its current selector and requires explicit acknowledgement. Pop is opt-in: Apply first, Delete only after verified conflict-free restoration; a failed deletion reports the completed Apply step so you do not apply twice. Native/external Git can still change shared refs concurrently, so these are guarded multi-step operations, not an atomic transaction.
Commit Staged Changes requires a message and confirms the previewed HEAD/index. A changed preview is rejected. Unstaged and untracked files are not automatically added; hooks and signing remain enabled; no automatic push.
Conflicts and pending Git operations are reported and block stash/normal commit actions. Continue / Abort handles merge, rebase, cherry-pick, revert and am in the explicitly named worktree. Continue requires resolved index entries and preserves native hooks/signing; Abort requires an unchecked-by-default discard acknowledgement. Both revalidate the displayed operation, HEAD and index before running. Native Abort may discard tracked-file edits or fail to restore earlier uncommitted changes; back up important files first.
Git is inspected again after Continue/Abort: a new conflict or autostash-restoration conflict is not reported as complete success, even when Git exits with code zero. Review Conflict opens the saved target file or the native three-way editor with immutable base/current/incoming Git blobs. Rebase sides are labelled by index stage, not guessed branch names. Mark Resolved requires acknowledgement, verifies the reviewed index and saved file, refuses remaining conflict markers, and stages the result without committing. Binary/missing/symlink files have explicit limitations and native Git/terminal fallbacks.
Discard Tracked Changes / Delete Untracked Files are separate actions in the dirty-worktree context menu and manager. They preview exact paths and default to a retained stash backup. Ignored files and other worktrees are excluded; without an existing HEAD, backup-dependent removal is refused. “Prune stale worktree records” only removes expired registration metadata, not file changes.
Open Worktree Terminal uses the validated target cwd and sends no shell commands. The manager shows configured-upstream ahead/behind without fetching; unfetched upstream counts remain unknown. Branch/commit context menus open a read-only comparison of immutable commit snapshots.
The disclosure arrow is a real button: mouse, Enter and Space expand/collapse changes; double-clicking it does not open another worktree. Remote Pull menus show source → current checked-out branch; filtering branches is not checkout.
Git mutation tests run only in temporary repositories. A fresh-profile VS Code integration test covers discovering
and loading a child repository from a non-Git parent workspace. Windows/Linux and remote/container-specific validation
still need separate environment coverage.
Configuration
All settings use the git-graph-sharp prefix.
| Setting |
Default |
Description |
autoCenterCommitDetailsView |
true |
Center commit details when opened |
dateFormat |
"Date & Time" |
"Date & Time", "Date Only", or "Relative" |
dateType |
"Author Date" |
"Author Date" or "Commit Date" |
fetchAvatars |
false |
Fetch avatars (sends email to external services); deprecated in v0.6.0 |
graphColours |
12 defaults |
Colors for graph lines |
graphStyle |
"rounded" |
"rounded" or "angular" |
initialLoadCommits |
300 |
Commits to load on open |
language |
"auto" |
"auto", "en", "zh-cn", or "zh-tw"; reopen the view to apply |
loadMoreCommits |
100 |
Commits to load on demand |
maxDepthOfRepoSearch |
2 |
Child-folder search depth; explicit 0 searches workspace roots only |
showCurrentBranchByDefault |
false |
Show only current branch on open |
showUncommittedChanges |
true |
Show uncommitted changes when the worktree dashboard is off |
showWorktrees |
true |
Show one uncommitted-changes row per worktree |
tabIconColourTheme |
"colour" |
"colour" or "grey" |
Development
pnpm install
pnpm compile # build the extension and webview into out/
pnpm test # backend, extension and webview unit tests
pnpm typecheck
pnpm lint
pnpm format
pnpm test:ext # integration tests in a real VS Code instance
Press F5 in VS Code to launch an Extension Development Host.
License
MIT — see LICENSE.
Git Graph # is based on neo-git-graph, which is based on the last MIT-licensed commit of mhutchie's Git Graph.
It is not affiliated with the original Git Graph project.
| |