Skip to content

The recorded default_branch is written once and never revalidated #507

Description

@blooop

Found while resolving #477: the dangling HEAD symref turned out to be the small half, and this is the large half, recorded here so the trace is not lost. Not on map #444, because it is not a reclaim question.

The finding

metadata.json's default_branch is written exactly once and never revalidated. The only writers are repo_manager.rs:1240 (first bare clone) and :1267 (register_existing_bare). get_default_branch (repo_manager.rs:1664) short-circuits on the record, so the ls-remote --symref fallback that would notice a moved default is unreachable for any repository dl has already cloned.

After a remote deletes or renames its default branch:

  • dl owner/repo (no @branch) resolves to the dead name forever, via flows/launch.rs name_default_branch, workspace_clone.rs resolve_default_branch, and dl/src/target.rs:183. Workspace id, container, clone directory and tab title are all named after a branch the forge no longer has, and nothing ever prints "the default branch has moved".
  • Before the sweep's --prune removes the stale head from the bare, ensure_branch (workspace_clone.rs:606) answers BranchBase::Stale { NoBranchOnRemote } (a notice, not an error) and EnsureBranch::in_cache silently resurrects the deleted branch from the bare's copy.
  • After the prune, the launch fails loudly, but the message names a git refusal (EnsureBranchError::Branch), not the actual cause.

Why it is recorded rather than built

For the primary usage (own repositories, launches almost always by explicit branch) a deleted default branch is nearly a non-event, and the post-prune failure is at least loud. The fix is a policy question, when may dl rewrite a recorded fact, with blast radius across naming surfaces (target.rs, launch naming, workspace ids). The obvious shape when someone wants it: when the sweep's prune removes refs/heads/<recorded default> from the bare, refresh the record from the remote's HEAD in the same pass that noticed.

#477's reader fix covers the adopt path (a stale symref can no longer re-record a dead branch), so this ticket is only about records that already exist.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions