-
Notifications
You must be signed in to change notification settings - Fork 14
feat(worktree): Add git worktree support #508
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #508 +/- ##
==========================================
+ Coverage 80.52% 81.29% +0.77%
==========================================
Files 16 18 +2
Lines 2192 2727 +535
Branches 454 552 +98
==========================================
+ Hits 1765 2217 +452
- Misses 277 341 +64
- Partials 150 169 +19 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request adds comprehensive git worktree support to vcspull, enabling users to manage multiple checkouts of the same repository at different branches, tags, or commits. The feature addresses issue #507, which requested the ability to rapidly clone repositories at different refs for LLM context harvesting and parallel work.
Changes:
- Adds new
WorktreeConfigDicttype for worktree configuration with support for tags, branches, commits, detachment, and locking options - Introduces comprehensive worktree sync logic including planning, creation, updating, pruning, and dirty state detection
- Adds new
vcspull worktreeCLI command withlist,sync, andprunesubcommands - Integrates
--include-worktreesflag across existing commands (sync, list, status, search, discover) - Implements worktree detection to exclude them from discovery by default
- Adds 30 tests covering config parsing, path resolution, sync planning, execution, and pruning
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
src/vcspull/types.py |
Defines WorktreeConfigDict with fields for dir, tag/branch/commit refs, detach, lock, and lock_reason |
src/vcspull/exc.py |
Adds worktree-specific exception classes (WorktreeError, WorktreeExistsError, WorktreeRefNotFoundError, WorktreeConfigError, WorktreeDirtyError) |
src/vcspull/_internal/worktree_sync.py |
Core worktree synchronization logic including planning, creation, update, pruning, and validation functions |
src/vcspull/config.py |
Adds _validate_worktrees_config function to parse and validate worktree configuration from YAML/JSON |
src/vcspull/cli/worktree.py |
New CLI command with list/sync/prune subcommands, output formatting, and color-coded status indicators |
src/vcspull/cli/__init__.py |
Integrates worktree command into main CLI parser and routing |
src/vcspull/cli/sync.py |
Adds --include-worktrees flag and integrates worktree sync after main repo sync |
src/vcspull/cli/list.py |
Adds --include-worktrees flag to display worktrees in flat and tree views |
src/vcspull/cli/status.py |
Adds --include-worktrees flag stub for future status integration |
src/vcspull/cli/search.py |
Adds --include-worktrees flag stub for future search integration |
src/vcspull/cli/discover.py |
Adds is_git_worktree() helper and --include-worktrees flag to control worktree discovery |
tests/test_worktree.py |
Comprehensive test suite with 30 tests covering config parsing, validation, sync, prune, and CLI integration |
tests/test_log.py |
Updates logger name list to include vcspull.cli.worktree |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
why: Enable LLMs and developers to access repositories at multiple versions simultaneously for context harvesting and parallel work (Issue #507). what: - Add WorktreeConfigDict type and extend ConfigDict in types.py - Add worktree exceptions (WorktreeError, WorktreeExistsError, etc.) in exc.py - Create worktree_sync.py module with sync/prune/planning logic - Add worktree config validation in extract_repos() - Create vcspull worktree CLI subcommand (list, sync, prune actions) - Add --include-worktrees flag to sync, list, status, search, discover - Add is_git_worktree() helper to filter worktrees from discovery - Add 30 comprehensive tests for worktree functionality
why: The flags were added but never implemented - silently ignored. what: - Remove --include-worktrees from search subparser - Remove --include-worktrees from status subparser
…ent comparison why: Path mismatch between resolved configured paths and unresolved git paths could cause valid worktrees to be incorrectly identified as orphaned. what: - Resolve worktree paths in list_existing_worktrees() before returning
why: CLAUDE.md requires all functions have working doctests. what: - Add doctest examples to all 14 functions - Use doctest_namespace fixtures where git operations needed
why: Improve test coverage from 75.57% to 82%. what: - Add CLI tests for worktree list, sync, prune commands - Add edge case tests for _is_worktree_dirty, _ref_exists, _get_worktree_head - Add tests for validate_worktree_config edge cases - Add test for plan_worktree_sync with invalid config - Add test for sync_worktree branch UPDATE action
why: Fill 5 specific coverage gaps identified by analysis to improve worktree module coverage from 81%→88% and CLI from 78%→83%. what: - Add test_sync_worktree_executes_update for UPDATE execution path - Add test_sync_all_worktrees_counts_mixed for action counting - Add test_cli_worktree_sync_no_repos for empty repos path - Add test_cli_worktree_prune_no_repos for empty repos path - Add test_cli_worktree_prune_no_orphans for no-orphans path
… CLI why: Improve test coverage for worktree modules from 88%/83% toward 95%. what: - Add CreateWorktreeOptionsFixture for lock/detach options (lines 606-619) - Add CLIFilteringFixture for pattern/workspace filtering (lines 133-153) - Add test_worktree_exists_path_no_git for edge case (line 346) - Add test_prune_worktree_failure for error handling (lines 824-826) - Add test_cli_sync_skips_empty_worktrees (lines 201, 288) - Add exception handling tests for _ref_exists, _is_worktree_dirty, _get_worktree_head
why: Improve test coverage from 94% toward 98%. what: - Add WorktreeActionOutputFixture for color branch coverage (lines 227-231) - Add test_sync_worktree_unchanged_execution (lines 549-552) - Add test_sync_worktree_oserror_exception (lines 557-559) - Add test_handle_list_with_empty_worktrees_direct (line 201) - Add test_handle_sync_with_empty_worktrees_direct (line 288) - Add test_cli_prune_no_existing_worktrees (line 356) - Add test_get_worktree_head_oserror (lines 305-306)
why: Submodules also have .git files with "gitdir:" but point to .git/modules/ what: - Add check for "/worktrees/" in gitdir path to distinguish from submodules - Worktrees point to .git/worktrees/, submodules point to .git/modules/
why: --dry-run flag was ignored for worktree operations what: - Pass dry_run parameter to sync_all_worktrees() instead of hardcoded False
why: Recursive and non-recursive discovery had inconsistent .git detection what: - Change (item / ".git").exists() to (item / ".git").is_dir() - Both branches now consistently match only regular repos with .git directories
…onal doctests why: CLAUDE.md requires doctests to actually execute and test behavior what: - Remove try/except pass workarounds from _create_worktree and _update_worktree - Replace Examples sections with Notes sections referencing integration tests
why: NumPy docstring style requires all parameters to be documented what: - Add include_worktrees parameter to list_repos docstring
why: CLAUDE.md requires proper docstrings for all functions what: - Add Parameters sections to _add_common_args, _handle_list, _emit_worktree_entry, _handle_sync, _handle_prune - Add Notes sections referencing integration tests
why: CLAUDE.md requires all functions to have working doctests what: - Add Examples section with valid config doctests - Add error case doctests for invalid configurations
why: CLAUDE.md requires namespace imports for stdlib modules what: - Change from dataclasses import to import dataclasses - Update @DataClass to @dataclasses.dataclass - Update field() to dataclasses.field()
why: Git worktrees have .git as a file, not a directory what: - Add .is_file() check for non-recursive discovery - Add .git file check for recursive discovery via os.walk - Enables --include-worktrees to actually discover worktrees
…octests why: CLAUDE.md requires all functions to have working doctests what: - Replace Notes section with Raises and Examples sections - Add doctests showing FileNotFoundError for invalid paths - Document subprocess.CalledProcessError and FileNotFoundError raises
why: Document bug where mappings inside YAML lists are incorrectly flagged as duplicate top-level keys what: - Add test_duplicate_aware_reader_ignores_nested_list_mappings - Mark with xfail until fix is applied - Document root cause: PyYAML constructs list items after parent mappings
… in nested lists why: PyYAML constructs sequence items after exiting parent mappings, causing list item mappings to incorrectly appear as top-level keys what: - Replace _mapping_depth counter with _root_mapping_node tracking - Only treat keys as top-level if their parent node IS the root - Add docstring explaining PyYAML's construction order behavior
why: The nested list mapping bug is now fixed what: - Remove pytest.mark.xfail decorator - Remove unused pytest import
…git command why: git worktree add --lock does not support --reason option what: - Remove --reason from git worktree add command - Call git worktree lock --reason separately after creation - Add regression test for lock_reason functionality
why: branch parameter was unused, could pull wrong branch what: - Check current branch with git symbolic-ref - Checkout expected branch if different - Add regression test for branch verification
…tion why: silent except clause made debugging difficult what: - Add log.debug explaining exception handling rationale
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
why: Documentation incorrectly stated lock_reason requires lock=True what: - Update docstring to reflect actual behavior: lock_reason implies lock=True
Summary
Resolves #507
vcspull worktree list|sync|prunesubcommand--include-worktreesflag added to sync, list, status, search, discover.gitfile detection)Changes
types.pyWorktreeConfigDict, extendConfigDictexc.py_internal/worktree_sync.pyconfig.pycli/worktree.pycli/*.py--include-worktreesflagcli/discover.pyis_git_worktree()helpertest_worktree.pyExample Config
Test plan