curl -O https://geekychris.github.io/tools/git-relay.py
python3 git-relay.py # http://127.0.0.1:8097, standard library only
Git client
A git client in the browser: open a local repository (read-only unless you switch on write mode), see the commit graph, diffs, blame, file history, status and stashes; browse GitHub and GitLab repositories, pull requests and issues; clone over HTTPS through a relay you run.
Added
How to use it
How to use it
Local repository — Open a repository folder… and pick the folder that contains .git (or a
bare repository). It needs the File System Access API: Chrome, Edge or Opera on a desktop. The
browser grants read access only and nothing leaves your machine — the repository is read in the tab
by isomorphic-git (1.38.10, loaded once from jsDelivr) through an
adapter over the folder handle. Loose objects, packfiles, packed-refs, the index and the stash
reflog all work. Try a demo repository builds a small one in memory, in any browser.
-
History — every branch, tag, remote-tracking branch and stash in one commit graph, newest first by commit date (like
git log --all --date-order --graph). The list is virtualised and the graph lanes are laid out in a Web Worker, so 10,000+ commits scroll smoothly; more load as you scroll, or Load all. Arrow keys orj/kmove. Search filters the loaded commits: words (message, author, id),author:ada,sha:3f2a, andpath:src/app.jslists the commits that changed a file (following renames). -
Commit details — message, parents (click to jump), author and committer, the files changed against the first parent (renames detected as git’s default
-M50%does), and each file’s diff, unified or side by side, with changed words highlighted. Binary files show sizes (and images side by side); files over 1 MB ask before diffing. -
Files — the tree at any branch, tag or commit; view a file, its History (commits that changed it, following renames, each with its diff), Blame (who last changed every line, across merges), or download it raw.
-
Status — staged, not staged and untracked files (respecting
.gitignore), with diffs against the index and HEAD. Read-only, the client does not even refresh the index’s stat cache (realgit statuswould). -
Branches & tags — local and remote-tracking branches, tags (annotated ones marked), and the stash list.
-
Compare — two refs: their merge base, the commits only on each side, and the files changed since the merge base (like
git diff A…B).
Write mode is off until you tick it for that repository, confirm the warning, and the browser
grants write permission. Then you can stage and unstage, commit (author from the repository’s
user.name/user.email, or entered), create branches (and switch to one when the working
directory is clean), switch branches, and tag HEAD (lightweight, or annotated with a message).
Nothing destructive is offered — no reset, no force, no history rewriting, no deleting. It lasts
until you reload or switch it off. Work on a copy if you are unsure.
GitHub / GitLab — type owner/repo (or group/project, or paste a URL) and Load: the commit
graph per branch (with parents, so merges draw), branches and tags, the file tree, pull/merge
requests with their diffs, reviews and review comments, and issues with comments. These are the
providers' public REST APIs, which allow cross-origin requests. Without a token GitHub allows 60
requests an hour (shown above the results). A personal access token (read-only, fine-grained,
with an expiry, please) is kept in this page’s memory and sent only to the provider in a header;
remember on this device stores it in local storage after a warning. It never goes into a link.
Clone via relay — cloning speaks git’s "smart HTTP" protocol (GET …/info/refs?service=git-upload-pack,
then POST …/git-upload-pack). GitHub, GitLab and the rest serve it without CORS headers, so a web
page may not read the replies — no browser-only git client can clone directly. With the gitwebsite
app (or gw serve) running on your computer the page clones through its companion’s git relay
(fetch only; github.com, gitlab.com, codeberg.org, bitbucket.org and hosts you add in the app) —
nothing to start; from this site press ⚡ Use the gitwebsite app once and approve the code in the
app. Not needed if the gitwebsite app is running — otherwise run the relay on your own computer:
It forwards only clone/fetch requests (never pushes, unless you start it with --allow-push) to
github.com, gitlab.com, codeberg.org and bitbucket.org (add others with --allow-host), answers only
this site and local previews (--allow-origin for others), checks the Host header against DNS
rebinding, binds to 127.0.0.1, and is not an open proxy. The page never uses a third-party proxy.
The clone (single branch, shallow if you like) lives in memory and is browsed read-only.
Press f or ⛶ Full screen to give the graph and diffs the whole screen; Escape leaves.
Limits
-
Local folders need the File System Access API (desktop Chromium browsers). Safari, Firefox and phones can use the demo, the GitHub/GitLab tab and the relay clone.
-
Symbolic links are invisible to the browser; a
.gitfile (a worktree or submodule) points outside the picked folder, so open the main repository. Submodule contents are not followed. -
isomorphic-git is fetched from jsDelivr the first time; after that the browser cache serves it, so local repositories work offline only once it has been loaded.
-
History is in commit-date order; with badly skewed clocks a parent can appear above a child. Diffs are git’s Myers algorithm (a port of xdiff, identical to
git diff --no-indent-heuristic), so a few hunks may slide differently from git’s default indent heuristic. Blame follows content through all parents but not code moved between files (git blame -C). -
Big repositories: everything is read in the tab, so a first
Load allon 100k commits takes a while and memory; file history and blame walk at most 5,000 commits. Clones are kept in memory. -
Status hashes changed files to compare them; very large working trees are slow.
-
The REST views show the first page of pull requests and issues (50) and 100 files per commit or pull request; GitHub truncates very large trees and patches.
Tests compare the client with the git CLI on throwaway repositories: refs (including packed-refs
and annotated tags), objects from packs and loose files byte for byte, git log --all --date-order
on a 3,000-commit history with merges, git status --porcelain, git stash list, git blame,
git log --follow, git diff --name-status -M, unified diffs, and git fsck --full --strict after
commits, branches and tags made in write mode; plus the relay’s allow-lists.
Linking to an example
Links open the GitHub / GitLab tab on a public repository (never a token, never a local folder):
| Parameter | Meaning |
|---|---|
|
|
|
|
|
|
For example isomorphic-git’s commit graph or GitLab Runner’s merge requests.
Feedback is a gift. Something to improve, a feature to add, or a bug? Tell me.
Runs entirely in your browser; nothing you type leaves this page.