Default new worktrees to the upstream branch (#2848)
* fix(workspaces): default new worktrees to upstream refs Use the daemon-resolved upstream as the untouched starting ref so unpushed local commits do not leak into new workspaces. Preserve exact base identity for fork remotes while keeping local-first behavior across version drift. * fix(workspaces): preserve exact base refs in git actions Resolve accepted display aliases back to the stored ref before comparisons and updates. Fail closed when a non-origin remote base has no explicit mutable merge target. * fix(workspaces): reject conflicting qualified base refs Display aliases remain accepted for compatibility, but a qualified ref carries remote identity and must not be canonicalized to a different stored upstream. * test(server): make upstream fixtures portable Keep the checkout-status fixture aligned with the optional upstream field, and select main explicitly when cloning a bare test remote whose default HEAD varies by platform. * fix(workspaces): preserve exact upstream refs Qualified remote refs now fail closed when pruned instead of switching lineage. Metadata accepts Git-valid upstream names rather than applying a narrower character whitelist. * fix(workspaces): preserve qualified local base refs Local tracking branches are exact upstream identities too. Keep heuristics only for legacy unqualified metadata so origin cannot replace a stored refs/heads base.
This commit is contained in:
@@ -1271,6 +1271,7 @@ export const createWorktree = async ({
|
||||
|
||||
writePaseoWorktreeMetadata(worktreePath, {
|
||||
baseRefName: sourcePlan.metadataBaseRefName,
|
||||
...(sourcePlan.metadataBaseRef ? { baseRef: sourcePlan.metadataBaseRef } : {}),
|
||||
...(sourcePlan.changeRequestLookupTarget
|
||||
? { changeRequestLookupTarget: sourcePlan.changeRequestLookupTarget }
|
||||
: {}),
|
||||
@@ -1300,7 +1301,11 @@ interface ResolveWorktreeSourcePlanOptions {
|
||||
|
||||
interface WorktreeSourcePlan {
|
||||
branchName: string;
|
||||
// Display name and exact ref are two different facts. The name cannot round-trip to a
|
||||
// commit — "main" resolves local-first even when the worktree was cut from a fork's
|
||||
// upstream — so comparisons and actions read the ref and the UI reads the name.
|
||||
metadataBaseRefName: string;
|
||||
metadataBaseRef?: string;
|
||||
changeRequestLookupTarget?: PaseoWorktreeChangeRequestHint;
|
||||
addArguments: string[];
|
||||
pushRemote?: {
|
||||
@@ -1334,6 +1339,7 @@ async function resolveWorktreeSourcePlan({
|
||||
return {
|
||||
branchName: newBranchName,
|
||||
metadataBaseRefName: normalizedBaseBranch,
|
||||
metadataBaseRef: resolvedBaseBranch,
|
||||
addArguments: ["-b", newBranchName, "--no-track", base],
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user