The seventh beta is about reading a diff, and about the rail knowing what it
draws. A changed line says which characters changed rather than tinting the
whole row, and the diff is finally text you can select, copy and scroll sideways
through. On the rail, the tooltip that was written for a badge and never once
appeared is replaced by a card that says which repository, which checkout and
which branch — and a repository whose own icon is no use at 30pt can be told to
show letters instead.
New
- Only what changed is marked — a changed line used to tint end to end, which
says a line is different without saying how. Each deletion is now compared
against the addition it faces, at word granularity, and only those characters
carry the mark. A pair that shares less than 30% of its characters keeps the
plain whole-row tint: below that the two lines are not a rewrite of each other,
and marking them word by word produces confetti rather than a reading. - Diff lines can be selected and copied — press, Shift, ⌘, drag, ⌘A, ⌘C and a
context menu, in the diff as in a list. The unit is the line, so the two halves
of a split pair are picked apart rather than taken together, and a range runs
along the column it is drawn in. What lands on the clipboard is plain: no+
and-markers, no line numbers — the text as it will be in the file. - Long lines can be reached — the diff body scrolls both ways, and in the
split view each pane scrolls horizontally inside its own half instead of
pushing the AFTER side off the window. The content width is measured rather
than guessed, because a lazy stack only measures the rows currently on screen
and a long line further down would otherwise not widen anything. - A card for a rail badge — the rail draws two or three letters per tab, and
the tooltip written to explain them never appeared. It is a card now, shown
while the pointer rests on a badge: the repository, the checkout, the branch
and the path on disk, one fact per line. It takes no mouse events at all —
switching repositories stays one click, where a popover's click-outside-to-
close ate the first one — and it follows the pointer from badge to badge as a
swap rather than a blink. VoiceOver reads the same facts, so two worktrees of
one project stop being two elements with the same name. - A repository's icon can be turned down — the rail draws whatever a
repository ships, and some of those are no use at 30pt: a white mark on white,
or the one icon every service in a monorepo carries. The customize sheet now
asks the question outright — repository icon, or letters — and appears only
when there is an icon to turn down, because otherwise letters are not a choice
but the only answer. The preview shows whichever badge is chosen. - Column widths belong to the tab — dragging AUTHOR wide enough for a
monorepo full offeature/PROJ-1234_…branch names used to widen every other
repository too. Widths are per repository now: they are a fit to what the rows
in front of you hold, not a preference that travels. Which columns to show
stays app-wide — that one is a reading preference, and it follows the reader. - A branch checked out elsewhere goes to its worktree — selecting such a
branch was answered with git's refusal and an Open Worktree button to press
afterwards. You had said where you wanted to go; the app made you say it twice.
git allows a branch in exactly one working tree, so "check it out here" has no
meaning for one — the app goes to the directory instead, from the toolbar menu,
the sidebar, the context menus and ⏎ alike. The refusal still appears when the
app's refs were stale, and then it offers what that path can still take: open
it if the worktree is there, prune it if git's record has outlived it, and
nothing at all if it is there but unreadable, where pruning would throw a live
association away to fix a permissions problem.
Fixed
- A tag whose name a branch also carries was unreachable — Checkout in the
tag's own menu asked git for the bare name, and git calls a name held by both a
tag and a branch ambiguous and picks the branch. The app then went further and
sent it to whichever worktree held that branch. A tag checkout detaches HEAD,
so it now asks forrefs/tags/<name>, which resolves to one thing. - The traffic lights rode above the row they label — macOS centres the window
buttons in the 32pt titlebar it draws itself, and the row beside them is 44pt,
which left the three buttons 6pt above the repository name and path. They sit
on the row's centre line now, and are put back there after every resize and
full-screen transition, where AppKit re-runs its own layout. - Switching between open tabs was slow — the rail wrapped the switch in an
animation so its accent marker could travel between icons, and that transaction
reached the pane as well: the window's whole contents crossfaded over a 0.28 s
spring on every click. ⌘⇧] and ⌘⇧[, which animate nothing, were already
instant — the same switch, one of them slow. The pane opts out now and the
marker keeps its travel. What is left is 84 ms for 240 commits, and 122 ms for
the same history carrying 300 branches; nothing in a switch runs git.
Requirements
- macOS 14 or later.
- A
git— whichever comes first on your login shell's PATH, else Apple's. With
none installed at all, the Welcome screen says so once, with the command that
fixes it.
Not here yet
- A command palette.
- Dragging a commit onto a branch. The rebase editor covers reordering a range;
history by drag-and-drop is a separate decision, and it hasn't been made.
During the beta
Free, for any use. Licensing starts at 1.0: free for personal projects, paid per
seat for commercial use — see the EULA.
The app updates itself — each update is checked against a signature before it is
applied. Settings ▸ Updates decides how much of that happens on its own. Bug
reports and requests go to the issue tracker.