fix(project): detect the repo's default branch on add#209
fix(project): detect the repo's default branch on add#209codebanditssss wants to merge 1 commit into
Conversation
Register the repo's actual checked-out branch as the project default so session worktrees base off a ref that exists. Previously Config.DefaultBranch was left empty and defaulted to "main", so a repo on master/develop/trunk failed every spawn with BRANCH_NOT_FETCHED and had no CLI workaround. Detection is best-effort (symbolic-ref --short HEAD); a detached HEAD or git error falls back to the existing main default. Only persist when the branch diverges from main, so the common main repo keeps a NULL config. Closes #208
Greptile SummaryThis PR fixes
Confidence Score: 4/5Safe to merge with one caveat: the branch-detection helper resolves the current checkout rather than the remote's canonical default, which can silently misconfigure projects added from a feature branch. The fix works correctly for the targeted scenario — a repo whose initial/only branch is backend/internal/service/project/service.go — specifically the Important Files Changed
Sequence DiagramsequenceDiagram
participant CLI as ao CLI
participant Svc as project.Service.Add
participant Git as git (subprocess)
participant Store as SQLite store
CLI->>Svc: Add(path, config?)
Svc->>Svc: normalizePath / validateID / conflict checks
Svc->>Git: git -C path symbolic-ref --short HEAD
Git-->>Svc: branch name (or error)
alt "branch != "" && branch != "main" && config.DefaultBranch == """
Svc->>Svc: "row.Config.DefaultBranch = branch"
else "branch == "main" or error or explicit config set"
Svc->>Svc: DefaultBranch stays "" (WithDefaults fills "main" at spawn)
end
Svc->>Git: git -C path remote get-url origin
Git-->>Svc: origin URL (or "")
Svc->>Store: UpsertProject(row)
Store-->>Svc: ok
Svc-->>CLI: "Project{DefaultBranch: branch}"
Reviews (1): Last reviewed commit: "fix(project): detect the repo's default ..." | Re-trigger Greptile |
| func resolveDefaultBranch(path string) string { | ||
| out, err := exec.Command("git", "-C", path, "symbolic-ref", "--short", "HEAD").Output() | ||
| if err != nil { | ||
| return "" | ||
| } | ||
| return strings.TrimSpace(string(out)) | ||
| } |
There was a problem hiding this comment.
symbolic-ref HEAD captures the current checkout, not the repo's default branch
git symbolic-ref --short HEAD resolves whatever branch the user currently has checked out, not the repository's canonical default. If a developer runs ao project add while on feature/new-ui of a main-default repo, feature/new-ui != "main" is true and that transient branch gets persisted as DefaultBranch. Every subsequent ao spawn then bases worktrees off feature/new-ui; once the branch is deleted after merging, all spawns break in exactly the same way as the original bug.
A more reliable source is the remote-tracking ref refs/remotes/origin/HEAD, which records the remote's default branch locally without a network round-trip (set by git clone or git remote set-head). Falling back to symbolic-ref HEAD only when that ref is absent would preserve the current improvement while avoiding the false-positive case.
Closes #208.
Problem
ao project addnever inspected the repo's branch, soConfig.DefaultBranchstayed empty andWithDefaults()forced it tomain. Any repo whose default branch isn'tmain(master,develop,trunk, …) then failed everyao spawnwith a misleadingBRANCH_NOT_FETCHED— andproject addhas no--branchflag, so there was no CLI workaround. This breaks the README quickstart (project add→spawn) for a large class of repos.Change
resolveDefaultBranch(mirrorsresolveGitOriginURL: best-effortgit symbolic-ref --short HEAD, never failsadd).Service.Add(single-repo path), record the detected branch asDefaultBranchonly when the user set none and it diverges frommain— so the commonmainrepo keeps an empty (NULL) config and behavior is unchanged there. A detached HEAD or git error falls back to the existingmaindefault.Test
TestManager_AddDetectsNonMainDefaultBranch: amasterrepo recordsmaster; an explicit config still wins.gitRepotest helpers togit init -b mainso detection is deterministic regardless of the host'sinit.defaultBranch(this is also why two existing fixtures changed).go build ./...,go vet ./..., and the fullgo test ./...suite pass.masterrepo now reportsdefault branch: masteronproject addandao spawnsucceeds (idlesession in zellij) where it previously failedBRANCH_NOT_FETCHED.Scope note
Surgical to the single-repo path. Workspace-root projects already
git init -b main, so they are unaffected. The misleading "rungit fetch" wording in theBRANCH_NOT_FETCHEDmessage is left as-is — with correct detection it no longer fires for this case.