Skip to content

Mark branches checked out in other worktrees and offer to open them on checkout - #2834

Open
NikKovIos wants to merge 2 commits into
git-up:masterfrom
NikKovIos:feature/worktree-branch-marker
Open

NikKovIos wants to merge 2 commits into
git-up:masterfrom
NikKovIos:feature/worktree-branch-marker

Conversation

@NikKovIos

@NikKovIos NikKovIos commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Git doesn't allow checking out a branch that is already checked out in another worktree. Since #2803 GitUp no longer leaves the working directory dirty in that case, but you only get a bare "Branch '…' is already checked out in another worktree" error, and the graph gives no hint beforehand about which branches are taken.

Changes

  • Graph. A local branch checked out in another worktree (the main one or a linked one) gets a ⧉ worktree: <folder> line under its title, and a ⧉ marker after its name in node labels and in the selected commit tooltip. Detached HEADs are not marked, since a commit can be checked out in any number of worktrees.
  • Checkout. Checking out such a branch shows an alert that explains the restriction and where the branch is checked out, with Open Worktree (opens it in GitUp), Show in Finder and Cancel. Nothing is checked out.
  • Core. New -[GCRepository lookupWorktreePathsForCheckedOutBranches:]. The result is cached as GCHistoryLocalBranch.worktreePath and included in the history references checksum, and GCLiveRepository also watches .git/worktrees/, so the marker updates when a worktree is added, removed or switched to another branch.

Screenshots

1-graph 2-selected 3-checkout 4-open-worktree

Trade-off

The extra line makes the title block taller, so the existing overlap avoidance in _DrawBranchTitle may truncate a long title in the column to the left (marked in orange in the first screenshot). The same already happens when a tip has tags or several branches.

Tests

  • GCBranch-Tests.m: a branch checked out in a linked worktree is mapped to its directory; seen from a linked worktree, the branch of the main worktree is listed while its own branch is not; worktrees with a detached HEAD or a deleted directory are skipped.
  • GCHistory-Tests.m: the history branch carries the worktree path.
  • GCLiveRepository-Tests.m: an open repository drops the marker when the linked worktree is removed.

I AGREE TO THE GITUP CONTRIBUTOR LICENSE AGREEMENT

…n checkout

Git refuses to check out a branch that is already checked out in another worktree. GitUp now shows which branches are in that state and explains what to do instead of failing with a bare error.

Added -[GCRepository lookupWorktreePathsForCheckedOutBranches:] which maps the branches checked out in other worktrees, the main one or linked ones, to their working directories. Worktrees with a detached HEAD or a missing directory are skipped.

The result is cached in GCHistoryLocalBranch.worktreePath and included in the history references checksum, and GCLiveRepository now also watches ".git/worktrees/", so the graph updates when a worktree is added, removed or switched to another branch.

The graph shows a "⧉ worktree: <folder>" line under the title of such a branch and a ⧉ marker next to its name in node labels and in the selected commit tooltip.

Checking out such a branch shows an alert with Open Worktree, Show in Finder and Cancel instead of the "already checked out in another worktree" error.
@greptile-apps

greptile-apps Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; the previous watch gap is addressed and no new actionable issues were found.

Summary

Adds graph markers for branches checked out in other worktrees and offers to open those worktrees instead of checking out their branches.

  • GitUp tracks which worktree holds each local branch.
  • The graph marks branches checked out in another worktree.
  • Blocked branch checkouts offer a way to open the existing worktree.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Worktree records change] --> B[Git directory watch receives event]
  B --> C[Refresh history]
  C --> D[Look up branches in other worktrees]
  D --> E[Update graph markers]
  F[User checks out a marked branch] --> G[Look up its worktree again]
  G --> H[Offer Open Worktree, Show in Finder, or Cancel]
Loading

Reviews (2) · Last reviewed commit: "Watch the common git directory of linked..." · Reviewed by Greptile

Comment thread GitUpKit/Core/GCLiveRepository.m
When GitUp opens a linked worktree, its git directory is ".git/worktrees/<name>/", so the HEAD of the main worktree and the git directories of the other linked worktrees were not watched and the worktree markers stayed stale until the next history update.

GCLiveRepository now also watches the common git directory of a linked worktree and reloads the history when its root or "worktrees/" changes. Other changes in the common git directory are still ignored.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant