Skip to content

chore(worktree): keep Claude Code worktrees out of the working tree - #8

Merged
anilcancakir merged 3 commits into
masterfrom
chore/worktree-layout
Sep 3, 2026
Merged

chore(worktree): keep Claude Code worktrees out of the working tree#8
anilcancakir merged 3 commits into
masterfrom
chore/worktree-layout

Conversation

@anilcancakir

Copy link
Copy Markdown
Contributor

What

.gitignore: ignore .claude/worktrees/ (only that subdirectory; the rules under .claude/ stay tracked).

Why

Worktrees were opened beside the checkout as <repo>-<slug>, so they landed in the workspace directory next to the real repositories, and Claude Code's EnterWorktree could not be used at all: it writes to a fixed .claude/worktrees/<slug>. With them inside the repository, git has to be told to ignore them.

No .worktreeinclude here, because this repository keeps no pubspec_overrides.yaml; there is nothing gitignored that a worktree would need. Sibling repositories that do carry one get that file too, see fluttersdk/magic_starter#124.

Testing

Config only. No Dart, YAML or lib/ file is touched, so analyze, format and test have nothing to say about this diff.

Worktrees used to sit beside the checkout as <repo>-<slug>, which put them in the workspace directory next to the real repositories and left EnterWorktree unusable, since that tool writes to a fixed .claude/worktrees/<slug>. Pattern proven on fluttersdk/magic_starter#124.
@codecov

codecov Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@kodizm

kodizm Bot commented Sep 3, 2026

Copy link
Copy Markdown

Note

Kodizm (AI-generated). May contain mistakes; verify before acting.

The ignore rule does exactly what the description claims and nothing else - no findings.

The pattern is correctly scoped. .claude/worktrees/ with the trailing slash matches only that subdirectory, so the tracked rules under .claude/ are untouched, and the comment above it explains why the narrow scope is deliberate rather than restating the line.

I also checked the two things a nested worktree could plausibly break here, and neither applies:

  • Publishing - .pubignore already excludes .claude/ wholesale, so a worktree under it can never reach a pub.dev archive regardless of this rule.
  • The .worktreeinclude claim - accurate. The only gitignored paths a worktree could want are pubspec_overrides.yaml, which is absent from this checkout, and .env, which nothing under lib/ or test/ reads.

Tests

Nothing covers a .gitignore change and nothing should. No Dart, YAML or lib/ file is touched, so the four CI gates have no input from this diff - the author's testing note is correct.

Checks I ran

  • git check-ignore -v .claude/worktrees/foo/lib/x.dart → matched .gitignore:52:.claude/worktrees/, so nested worktree contents are ignored.
  • git check-ignore -v .claude/rules/cli.md and .claude/settings.jsonNOT IGNORED, confirming the rest of .claude/ stays visible to git.
  • git ls-files .claude → the four rule files remain tracked after the change.
  • ls pubspec_overrides.yamlNo such file or directory, and grep for .env across lib/, test/ and pubspec.yaml → no hits; together these confirm no .worktreeinclude is needed.
  • git status --porcelain → clean.
  • No linter, formatter or test run: the diff contains no code for them to read. I attempted to simulate a nested Dart worktree to confirm dart format . skips dot-directories, but creating those files was not permitted, so that point is reasoned rather than observed - it does not affect the verdict, since the rule cannot make analyze or format traverse anything they did not already traverse.

@kodizm

kodizm Bot commented Sep 3, 2026

Copy link
Copy Markdown

Note

Kodizm (AI-generated). May contain mistakes; verify before acting.

Since my last review the only change is comment text above the same ignore rule; ignore behaviour is unchanged, but the new comment contains a typo and a claim I could not reproduce.

Minor

.gitignore:51 — Stray # appended to # under it are part of the repository.#. It reads as an unterminated separator line; the intended blank comment line between the two paragraphs is missing. (maintainability)

.gitignore:52-55 — The new paragraph's central claim is wrong as written: git clean -xdf does not wipe a live nested worktree, and the gitfile does not defeat git's nested-repo guard. Git resolves a .git file the same way for that check, so it skips the directory and the contents survive; only -xdff would remove them. Someone following this comment would go looking for git worktree prune after a clean that in fact left the worktree intact. (maintainability)

Tests

Nothing covers a .gitignore comment change and nothing should. No Dart, YAML or lib/ file is touched in these commits, so the four CI gates have no input from this diff.

Checks I ran

  • git check-ignore -v .claude/worktrees/foo/lib/x.dart.gitignore:56:.claude/worktrees/, and .claude/rules/cli.md → NOT IGNORED. Ignore semantics are identical to what I verified before; only the comment moved the rule down four lines.
  • Reproduced the comment's scenario in a throwaway repo: git worktree add .claude/worktrees/slug with the same ignore rule, then git clean -xdfSkipping repository .claude/worktrees/slug, and ls -a .claude/worktrees/slug afterwards still showed f, .git, .gitignore. This is the evidence for the second finding.
  • git status --porcelain → clean.
  • No linter, formatter or test run: the diff contains no code for them to read.

The comment claimed plain -xdf wipes a live worktree because its .git is a file rather than a directory. Measured on a scratch repo: the dry run prints "Skipping repository .claude/worktrees/slug", the worktree survives -xdf with its untracked files intact, and only -xdff removes it and leaves the registration prunable. The guard keys on the gitlink, not on the form of .git. Also splits the stray # that joined the two comment blocks.
@kodizm

kodizm Bot commented Sep 3, 2026

Copy link
Copy Markdown

Note

Kodizm (AI-generated). May contain mistakes; verify before acting.

Both findings from my last review are fixed, and the corrected comment now matches what git actually does - no findings.

Since the last review the only change is the comment block above the same ignore rule. The stray # is gone and the two paragraphs are separated by a proper blank comment line, and the git clean claim has been inverted to the correct behaviour. I reproduced the whole new sentence in a throwaway repo rather than taking it on reasoning:

  • git clean -xdfSkipping repository .claude/worktrees/slug, and the worktree contents (f, .git, .gitignore) were still there afterwards.
  • git clean -xdffRemoving .claude/, the worktree directory was gone, and ls .git/worktrees still listed slug - exactly the stale registration the comment says git worktree prune has to clear.

The ignore rule itself is byte-identical to what I verified before; only its line number moved.

Tests

Nothing covers a .gitignore comment change and nothing should. No Dart, YAML or lib/ file is touched in these commits, so the four CI gates have no input from this diff.

Checks I ran

  • Reproduced both clean modes on a nested worktree with this exact ignore rule; output quoted above.
  • git check-ignore -v .claude/worktrees/foo/lib/x.dart.gitignore:58:.claude/worktrees/; git check-ignore -v .claude/rules/cli.md → not ignored. Scope unchanged.
  • git status --porcelain → clean.
  • No linter, formatter or test run: the diff contains no code for them to read.

@anilcancakir
anilcancakir merged commit e193931 into master Sep 3, 2026
4 checks passed
@anilcancakir
anilcancakir deleted the chore/worktree-layout branch September 3, 2026 18:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant