History

Selecting a worktree draws its lineage graph — the commit history, as lanes, with branch chips on the tips and pull or merge request status where there is any.

The lineage graph

Each row is a commit: its lane marker, the subject, the author, and how long ago it landed. Clicking a commit loads its files into the rail on the right, whose first tab becomes Commit; clicking a file there opens that file’s diff for that commit. The whole commit as a single patch is one click further away, under Full diff.

The toolbar above the graph, labelled Lineage, holds:

The lane gutter draws at most ten lanes at once. Wider histories scroll the gutter sideways while the commit rows stay put.

The lineage graph for openclaw's main worktree; the header chip reads 3 behind upstream. A dashed trunk above HEAD carries upstream commits not yet in main, merged PRs #163647, #166229 and #166218 by Dallin Romney. HEAD, 10334ec, carries the main and origin chips. Rows show short hashes, subjects, author avatars and purple merged-PR chips.
Lanes, branch and request chips, and authors. Dashed lanes are fetched but not yet applied.

It draws fetched work, not just local work

A branch that is behind its upstream has commits sitting in the object store that no local ref points at. Walking only local tips would silently omit them — the lane would look current while the sidebar said ↓2, with the rows you were looking for simply absent.

PwrGit walks those upstream commits too, and draws them dashed as fetched-but-not-applied. Each remote gets its own dash pattern — the closest remote one, the next remote out another — so on a fork, work on upstream reads differently from work on origin. A branch that has diverged forks at the merge base, so its dashed leg runs past your own rows and bends back into your lane there.

That is the practical value: after a fetch, you can see what a pull would bring in before you run it.

Where squash and rebase merges landed

A squash or rebase merge leaves no git edge between a branch and the commit that landed it. Where a merged pull request connects the two, PwrGit draws a dotted purple landing lane from the branch’s tip to the commit on the default branch that carries its work, so the branch does not look abandoned.

Scope — Active or All branches

The scope toggle in the toolbar:

The branch of the worktree you are looking at is never dropped by either cap.

Active is the default. Settings → Experimental → Lineage Graph Scope → Default to all branches opens new graphs on All branches instead; the toggle still overrides it per view. See Settings.

Branch chips and their menu

Branch tips carry a chip with the branch name; remote branches carry the remote’s name too. A branch checked out in a worktree is marked, and clicking that mark opens the worktree. The chip’s menu offers:

Pull and merge request chips

A request shows as #n (GitHub) or !n (GitLab) beside its branch — merged #n or closed #n once it is settled. Hovering it opens a status card: the title, source and target branches, the state, the size of the change (files, additions, deletions), and a timeline — opened, merged or closed. The card is drawn from data PwrGit already has and issues no request of its own, so hovering around the graph does not generate forge traffic. Anything it does not know is left out, never shown as zero.

Clicking the chip opens the request on the forge in your browser. Option-click (Alt-click on Windows and Linux) copies its URL instead. To read a request inside PwrGit, see Pull requests.

Commit details and author identity

Right-clicking a commit gives you:

Hovering the short SHA opens the commit context card: when it was committed, its age, its change size, the branch you are viewing it from and the base branch, with copy buttons for the short and full hash.

Author avatars are proven, not guessed

Where a commit’s author has been matched to a forge account, PwrGit shows that account’s avatar. The match is deliberately conservative: it requires the exact commit SHA and the forge’s own record of the author. Where the forge has no linked account, a uniquely associated pull request can supply one — but only if its login matches the git author name or the local part of the email.

If none of that holds, you get initials and the local git authorship. PwrGit would rather show nothing than attach the wrong person’s face to a commit.

Hovering or clicking an author opens their person card:

Avatars are cached on disk and served to the UI through a local URL, so the source URL never reaches the page and the image is not re-fetched on every hover. See Forges → Commit author avatars.

The lineage graph for openclaw main with a person card open for Peter Steinberger, @steipete: avatar, email blurred, and GitHub account, proven by a commit. In this graph: 88 of 174 commits shown, latest 51 minutes ago at 10334ec, tip of main. Co-author line and Open on GitHub buttons. The header chip reads 3 behind upstream.
A person card. The forge link appears only when a commit proves the account.

The diff pane

The diff pane opens over the graph, from a changed file in the rail or from a commit. Its header has a close (✕) control, and Escape closes it too.

It renders a working-tree file’s diff, one file’s diff within a commit or a stash, and a whole commit as a single patch. For a working-tree file, Unstaged and Staged switch between the two sides of the index, and the pane is where hunk and line staging happens — see Changes → Staging.

From the header you can also open the file at that revision (View file), its File history, or its Blame — see File history and blame.

Images

Images are diffed as images rather than as binary hunks. Clicking one opens a full-window viewer with Before, After and Diff views — the diff highlights the changed pixels — and a shared zoom and pan across all three: + and − zoom, 0 fits, 1 shows actual size. Left Arrow and Right Arrow walk every image in the diff. A copy menu puts before, after, the diff, or the images side by side on the clipboard.

A Git LFS pointer, an image too large to preview, or one that does not exist on one side says so instead of drawing a blank.

When a pane fails

If the diff or file details pane hits an error, it stops drawing and says so — This pane hit an error and stopped drawing. — with Try again and Show logs, instead of taking the window down with it. The rest of the window keeps working.

File history and blame

File details opens beside the diff with three tabs:

Open it from:

File details for src/gateway/server.ts on the Blame tab, reading Working tree · through HEAD, with History and File tabs and a Lineage back button. Each block of lines carries a short hash, an author avatar and login — mostly @steipete, one @galiniliev — and an age from 6 days to 8 months, beside the line numbers and code.
Blame: the commit, author and age behind each block of lines.

The refs browser

View all n branches… (or tags, or worktrees) in the sidebar opens the repository’s Repository refs window. Its tabs are Worktrees, Branches, Tags, Remotes and Pull requests, each with a filter box.

The rows are keyboard-driven: Down Arrow from the filter enters the list, Up Arrow / Down Arrow walk it, Home and End jump, Space pins, and Enter — or a double-click — runs the row’s primary action.

The Repository refs window for openclaw on its Branches tab, filter All 11 (To push 1, Behind 1, Gone 0, Local only 0). Rows show branch, PR chip, last subject, upstream, status and age, with Show worktree, Switch here or New worktree; one branch is 3 ahead, 199 behind. The menu for fix/github-shared-rate-limit is open: Pin branch, Copy branch name, Rename…, Delete….
Every branch, filterable, with switch, worktree, rename and delete on each row.

Tags

Tag this commit… in the graph, or the Tags tab, opens Create tag in repo: a Tag name, a Target (HEAD, a branch, a tag or a commit ID, resolved to a commit before you confirm), and a Tag kind — Lightweight or Annotated with an Annotation.

The Tags tab lists every tag. Locate jumps to the tagged commit in the lineage; the menu has Copy tag name and Delete local tag…, which leaves tags on remotes alone. To send a tag to a remote, see Push to other remotes.

Not yet