Skip to content

perf: batch branch commit-message lookups in shell completion#187

Merged
k1LoW merged 1 commit into
k1LoW:mainfrom
tksm:perf/completion
May 14, 2026
Merged

perf: batch branch commit-message lookups in shell completion#187
k1LoW merged 1 commit into
k1LoW:mainfrom
tksm:perf/completion

Conversation

@tksm

@tksm tksm commented May 10, 2026

Copy link
Copy Markdown
Contributor

Summary

git wt's shell completion previously forked git log -1 once per branch to fetch each branch's commit subject, which became slow in repositories with many local or remote-tracking branches. This change batches the lookup into a single git for-each-ref call. In a 500-branch reproduction, completion drops from ~2.2s to ~0.12s (~20x faster).

Reproduction

The reproduction below uses local branches only for simplicity. git-wt is the released binary and git-wt-fixed is built from this branch.

tmp=$(mktemp -d) && cd "$tmp"
git init -q && git commit -q --allow-empty -m init
for i in $(seq 1 500); do git branch "b-$i"; done

time git-wt __complete "" >/dev/null
Completion ended with directive: ShellCompDirectiveNoFileComp
git-wt __complete "" > /dev/null  1.01s user 0.88s system 84% cpu 2.227 total

With the fix applied:

time git-wt-fixed __complete "" >/dev/null
Completion ended with directive: ShellCompDirectiveNoFileComp
git-wt-fixed __complete "" > /dev/null  0.05s user 0.06s system 87% cpu 0.119 total

I confirmed the completion output is identical before/after.

diff <(git-wt __complete "" 2>/dev/null) <(git-wt-fixed __complete "" 2>/dev/null)
# (no output → outputs are identical)

@k1LoW k1LoW added enhancement New feature or request tagpr:minor labels May 14, 2026
@k1LoW

k1LoW commented May 14, 2026

Copy link
Copy Markdown
Owner

Note: behavioral diffs between old BranchCommitMessage and new BranchCommitMessages

Leaving these as a memo for the record. None are likely to cause issues in practice, but they are real semantic differences from the previous code path.

1. Multi-line subject handling

  • Old: git log -1 --format=%s <branch> returns the first line only.
  • New: git for-each-ref --format=%(contents:subject) collapses newlines within the subject paragraph into spaces.
  • Identical output for the standard "subject + blank line + body" convention. Diverges only for commits whose subject itself spans multiple lines without a blank line. The added test uses subject + blank + body, so this edge case is not covered.

2. Trailing whitespace

  • Old: strings.TrimSpace(out) strips leading/trailing whitespace.
  • New: only strings.TrimRight(out, "\n") runs before strings.Cut, so a trailing space in the subject would be preserved.
  • Negligible in practice.

3. Error-fallback granularity

  • Old: a per-branch git log failure only drops that branch's description.
  • New: a single BranchCommitMessages error leaves commitMessages nil, so all branches fall back to no-message descriptions. for-each-ref with explicit patterns is unlikely to fail, but the granularity changed.

4. Short-name collision between refs/heads and refs/remotes (pathological)

  • Old: git log -1 origin/foo follows git's DWIM rules (refs/heads wins), returning the local branch's subject.
  • New: both refs hit the same %(refname:short) map key, and for-each-ref emits refs/heads/... before refs/remotes/..., so the remote-tracking entry overwrites and returns the remote subject instead.
  • Only matters if a local branch is named like a remote-tracking ref (e.g. a local branch literally called origin/foo).

The completeBranches side using only refs/heads is fine on closer inspection. git worktree list --porcelain emits branch refs/heads/... for non-detached worktrees, so wt.Branch is structurally always a local branch short-name, and the refs/heads-only scope matches prior behavior exactly.

@k1LoW k1LoW left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tksm GREAT WORK!!! Thank you!!

@k1LoW k1LoW merged commit 924272b into k1LoW:main May 14, 2026
3 checks passed
@github-actions github-actions Bot mentioned this pull request May 14, 2026
@tksm tksm deleted the perf/completion branch May 14, 2026 04:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants