Skip to content

Base new branches on repo's default branch - #31

Merged
blooop merged 3 commits into
mainfrom
base-new-branches-on-default-branch
Mar 12, 2026
Merged

blooop merged 3 commits into
mainfrom
base-new-branches-on-default-branch

Conversation

@blooop

@blooop blooop commented Mar 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add start_point parameter to BranchManager.ensure_branch_exists() (default "HEAD") so the branch base is explicit rather than implicit
  • Update WorkspaceCloneManager.ensure_branch() to resolve the repo's default branch via get_default_branch() and pass it as start_point
  • This ensures new branches are always based on the latest default branch (e.g. main), not a potentially stale HEAD if a prior fetch failed

Minimize network operations when opening a new branch

  • Add lazy_fetch() to RepositoryManager — only fetches when the fetch interval has elapsed, avoiding redundant network calls
  • Add use_local_refs parameter to BranchManager.ensure_branch_exists() — infers remote branch existence from local refs in bare repos instead of calling git ls-remote
  • Update WorkspaceCloneManager.ensure_branch() to use lazy_fetch and use_local_refs=True
  • Skip git fetch origin for newly-created workspaces (they were just cloned from a freshly-fetched bare repo)
Scenario Before After
First open (new repo) 4 network ops 1 (clone only)
New branch (within fetch interval) 3 0
New branch (outside fetch interval) 4 1 (single fetch)

Test plan

  • Updated existing tests to verify start_point is passed through correctly
  • Added test for custom start_point value in ensure_branch_exists
  • Updated ensure_branch tests to assert get_default_branch is called and result forwarded
  • Added tests for lazy_fetch() — interval elapsed, recent fetch, missing repo, fetch error propagation
  • Added tests for use_local_refs=True — branch exists (skips ls-remote), branch missing (creates without ls-remote), default behavior unchanged
  • Updated workspace clone tests — lazy_fetch instead of fetch_repo, newly-created workspaces skip fetch, existing workspaces still fetch
  • All 338 tests pass, lint 10.00/10

🤖 Generated with Claude Code

Add start_point parameter to BranchManager.ensure_branch_exists() so
callers can explicitly specify what to base new branches on. Update
WorkspaceCloneManager.ensure_branch() to resolve the repo's default
branch and pass it as start_point, ensuring new branches are always
based on the latest default branch rather than a potentially stale HEAD.
@sourcery-ai

sourcery-ai Bot commented Mar 1, 2026

Copy link
Copy Markdown

Reviewer's Guide

Makes branch creation explicitly base on a configurable start point and updates workspace cloning to always base new branches on the repository’s default branch instead of an implicit or stale HEAD, with tests updated accordingly.

Sequence diagram for ensuring a workspace branch based on default branch

sequenceDiagram
    actor Developer
    participant WorkspaceCloneManager
    participant RepoManager
    participant BranchManager

    Developer->>WorkspaceCloneManager: ensure_branch(owner, repo, branch)
    WorkspaceCloneManager->>RepoManager: fetch_repo(owner, repo)
    RepoManager-->>WorkspaceCloneManager: fetch result or error
    WorkspaceCloneManager->>RepoManager: get_default_branch(owner, repo)
    RepoManager-->>WorkspaceCloneManager: default_branch
    WorkspaceCloneManager->>BranchManager: ensure_branch_exists(bare_path, branch, remote, create_remote, ssh_key_path, start_point=default_branch)
    alt branch does not exist locally
        BranchManager->>BranchManager: create_local_branch(base_repo_path, branch, start_point)
        BranchManager-->>WorkspaceCloneManager: local branch created
    else branch exists locally
        BranchManager-->>WorkspaceCloneManager: no local creation needed
    end
    WorkspaceCloneManager-->>Developer: branch ensured
Loading

Updated class diagram for branch and workspace management

classDiagram
    class WorkspaceCloneManager {
        +ensure_branch(owner, repo, branch) void
        +ensure_workspace(owner, repo, branch) void
    }

    class RepoManager {
        +fetch_repo(owner, repo) void
        +get_default_branch(owner, repo) str
    }

    class BranchManager {
        +ensure_branch_exists(base_repo_path, branch, remote="origin", create_remote=true, ssh_key_path, start_point="HEAD") void
        +create_local_branch(base_repo_path, branch, start_point) void
    }

    WorkspaceCloneManager --> RepoManager : uses
    WorkspaceCloneManager --> BranchManager : uses
Loading

File-Level Changes

Change Details Files
Make branch base explicit in BranchManager.ensure_branch_exists and propagate a configurable start_point into local branch creation.
  • Add a start_point parameter with default 'HEAD' to ensure_branch_exists.
  • Pass start_point through to create_local_branch instead of relying on its internal default.
  • Update existing tests to assert create_local_branch is called with an explicit start_point, including a new test for a custom start_point value.
devlaunch/worktree/branch_manager.py
test/test_worktree_branch_manager.py
Ensure WorkspaceCloneManager bases new branches on the repo's default branch resolved via RepoManager.
  • In ensure_branch, resolve the bare repo’s default branch using repo_manager.get_default_branch after attempting fetch.
  • Pass the resolved default branch as start_point when calling branch_manager.ensure_branch_exists, even if fetch failed.
  • Update workspace clone tests to assert get_default_branch is called and that ensure_branch_exists receives start_point set to the default branch.
devlaunch/worktree/workspace_clone.py
test/test_workspace_clone.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 2 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="devlaunch/worktree/workspace_clone.py" line_range="92-93" />
<code_context>
             logger.warning(f"Failed to fetch before branch ensure: {e}")
-        self.branch_manager.ensure_branch_exists(bare_path, branch, create_remote=False)
+
+        default_branch = self.repo_manager.get_default_branch(owner, repo)
+        self.branch_manager.ensure_branch_exists(
+            bare_path, branch, create_remote=False, start_point=default_branch
+        )
</code_context>
<issue_to_address>
**issue (bug_risk):** Handle failures or unexpected values from get_default_branch to avoid breaking workspace creation.

If `get_default_branch` raises (e.g., no default branch, network/permissions issues) or returns an empty/invalid value, passing it as `start_point` will cause `ensure_branch_exists` to fail. Previously this defaulted to the underlying `HEAD`. Please handle failures from `get_default_branch` (e.g., `try/except` like `fetch_repo`) and fall back to a safe default such as `HEAD` when the default branch is unavailable or falsy, so workspace creation remains robust in misconfigured repos.
</issue_to_address>

### Comment 2
<location path="test/test_worktree_branch_manager.py" line_range="351-355" />
<code_context>
+        mock_local_exists.return_value = False
+        mock_remote_exists.return_value = False
+
+        branch_manager.ensure_branch_exists(
+            temp_repo, "new-branch", create_remote=False, start_point="origin/main"
+        )
+
+        mock_create.assert_called_once_with(temp_repo, "new-branch", "origin/main")


</code_context>
<issue_to_address>
**suggestion (testing):** Tighten the custom start_point test by asserting no remote operations occur when create_remote=False

In `test_branch_custom_start_point`, you’re already checking that the custom `start_point` is passed through. To fully cover the `create_remote=False` case, also assert that no remote operations occur (e.g., `mock_track.assert_not_called()`) so the test fails if remote behavior is accidentally reintroduced for this path.

Suggested implementation:

```python
        mock_push.assert_called_once()
        mock_track.assert_called_once()

        # Reset mocks before exercising create_remote=False path to ensure no remote operations occur
        mock_push.reset_mock()
        mock_track.reset_mock()

        branch_manager.ensure_branch_exists(temp_repo, "new-branch", create_remote=False)

        mock_push.assert_not_called()
        mock_track.assert_not_called()

```

In the `test_branch_custom_start_point` test (the one using `start_point="origin/main"`), also add assertions that no remote operations occur when `create_remote=False`. For example, after calling:
`branch_manager.ensure_branch_exists(temp_repo, "new-branch", create_remote=False, start_point="origin/main")`,
add:
`mock_push.assert_not_called()` and `mock_track.assert_not_called()`. If the same mocks were used earlier in that test with `create_remote=True`, remember to call `reset_mock()` on them before the `create_remote=False` invocation so the assertions are meaningful.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +92 to +93
default_branch = self.repo_manager.get_default_branch(owner, repo)
self.branch_manager.ensure_branch_exists(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): Handle failures or unexpected values from get_default_branch to avoid breaking workspace creation.

If get_default_branch raises (e.g., no default branch, network/permissions issues) or returns an empty/invalid value, passing it as start_point will cause ensure_branch_exists to fail. Previously this defaulted to the underlying HEAD. Please handle failures from get_default_branch (e.g., try/except like fetch_repo) and fall back to a safe default such as HEAD when the default branch is unavailable or falsy, so workspace creation remains robust in misconfigured repos.

Comment on lines +351 to +355
branch_manager.ensure_branch_exists(
temp_repo, "new-branch", create_remote=False, start_point="origin/main"
)

mock_create.assert_called_once_with(temp_repo, "new-branch", "origin/main")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (testing): Tighten the custom start_point test by asserting no remote operations occur when create_remote=False

In test_branch_custom_start_point, you’re already checking that the custom start_point is passed through. To fully cover the create_remote=False case, also assert that no remote operations occur (e.g., mock_track.assert_not_called()) so the test fails if remote behavior is accidentally reintroduced for this path.

Suggested implementation:

        mock_push.assert_called_once()
        mock_track.assert_called_once()

        # Reset mocks before exercising create_remote=False path to ensure no remote operations occur
        mock_push.reset_mock()
        mock_track.reset_mock()

        branch_manager.ensure_branch_exists(temp_repo, "new-branch", create_remote=False)

        mock_push.assert_not_called()
        mock_track.assert_not_called()

In the test_branch_custom_start_point test (the one using start_point="origin/main"), also add assertions that no remote operations occur when create_remote=False. For example, after calling:
branch_manager.ensure_branch_exists(temp_repo, "new-branch", create_remote=False, start_point="origin/main"),
add:
mock_push.assert_not_called() and mock_track.assert_not_called(). If the same mocks were used earlier in that test with create_remote=True, remember to call reset_mock() on them before the create_remote=False invocation so the assertions are meaningful.

- Add lazy_fetch() to RepositoryManager: only fetches when the fetch
  interval has elapsed, avoiding redundant network calls
- Add use_local_refs parameter to BranchManager.ensure_branch_exists():
  infers remote branch existence from local refs in bare repos instead
  of calling git ls-remote
- Update WorkspaceCloneManager.ensure_branch() to use lazy_fetch and
  use_local_refs=True
- Skip git fetch origin for newly-created workspaces since they were
  just cloned from a freshly-fetched bare repo
@codecov

codecov Bot commented Mar 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.47619% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.04%. Comparing base (45b805b) to head (713a352).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
devlaunch/worktree/workspace_clone.py 77.77% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #31      +/-   ##
==========================================
+ Coverage   82.68%   83.04%   +0.35%     
==========================================
  Files           9        9              
  Lines        1184     1197      +13     
==========================================
+ Hits          979      994      +15     
+ Misses        205      203       -2     
Files with missing lines Coverage Δ
devlaunch/worktree/branch_manager.py 100.00% <100.00%> (ø)
devlaunch/worktree/repo_manager.py 83.70% <100.00%> (+2.60%) ⬆️
devlaunch/worktree/workspace_clone.py 88.99% <77.77%> (+0.31%) ⬆️

Impacted file tree graph

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Reconcile skip-fetch optimization (this branch) with smart checkout
logic (main PR #34). Unify newly_created/is_new_workspace into a
single flag. Fix ruff format issues (extra blank lines, list
comprehension wrapping).
@blooop
blooop merged commit 54ce575 into main Mar 12, 2026
9 checks passed
@blooop
blooop deleted the base-new-branches-on-default-branch branch March 12, 2026 20:12
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