fix(git): resolve the base branch from the repository instead of its name
Follow-up to #2629, which stopped the walkthrough from comparing against a branch that does not exist. The same guessing, and the same near-misses in how the answer was applied, were left elsewhere: - The default branch travelled as `rootBranchHint`, whose documented meaning is "the branch the project root worktree is on". It gets its own option, because a parameter that means two things is one the next caller gets wrong. - A candidate equal to the branch being compared is skipped. In a plain checkout the root hint *is* the current branch, so it won every time and produced a comparison with itself; the repository default now wins there. - The Changes and pull-request surfaces read the default branch too. A pull request opened against a branch that does not exist is a worse failure than a walkthrough that will not generate. - `hasResolvableBaseBranch` matched `origin/feature/main` for a base of `main`, passing the check and then failing the comparison it exists to prevent. - `getRangeDiff` promoted only `origin/<base>`. A base carried by any other remote stayed a bare name, which git resolves against refs/heads and nowhere else, so it failed exactly as before. - `getBranches` dropped every branch of a remote that did not answer, turning "we could not ask" into "these branches are gone" — offline, that silently removed comparisons that work fine against local remote-tracking refs. - A remote with no `remote/HEAD` is asked once with `ls-remote --symref` rather than falling back to the guess this data exists to replace. The `defaultBranches` contract was documented under the status response; it belongs to the branches response, which now has a section of its own.
This commit is contained in:
@@ -1417,12 +1417,32 @@ export const GitView: React.FC<GitViewProps> = ({ isActive }) => {
|
||||
}));
|
||||
}, [remotes, remoteBranches, remoteUrl, status?.tracking]);
|
||||
|
||||
const currentBranch = status?.current ?? null;
|
||||
|
||||
// The repository's own default branch, so a repo whose default is neither
|
||||
// main, master nor develop stops being compared against a branch that does
|
||||
// not exist.
|
||||
const defaultBranch = React.useMemo(() => {
|
||||
const trackingRemote = status?.tracking?.trim().split('/')[0];
|
||||
return (trackingRemote && branches?.defaultBranches?.[trackingRemote])
|
||||
?? branches?.defaultBranches?.origin;
|
||||
}, [branches, status?.tracking]);
|
||||
|
||||
const baseBranch = React.useMemo(() => deriveBaseBranch({
|
||||
remoteNames: new Set(effectiveRemotes.map((remote) => remote.name)),
|
||||
localBranches,
|
||||
worktreeCreatedFromBranch: worktreeMetadata?.createdFromBranch,
|
||||
rootBranchHint,
|
||||
}), [effectiveRemotes, localBranches, rootBranchHint, worktreeMetadata?.createdFromBranch]);
|
||||
defaultBranch,
|
||||
headBranch: currentBranch,
|
||||
}), [
|
||||
currentBranch,
|
||||
defaultBranch,
|
||||
effectiveRemotes,
|
||||
localBranches,
|
||||
rootBranchHint,
|
||||
worktreeMetadata?.createdFromBranch,
|
||||
]);
|
||||
|
||||
const updateTargetBranch = React.useMemo(() => {
|
||||
const remoteNames = effectiveRemotes.map((remote) => remote.name);
|
||||
@@ -1511,7 +1531,6 @@ export const GitView: React.FC<GitViewProps> = ({ isActive }) => {
|
||||
|
||||
const stagedCount = stagedChangeEntries.length;
|
||||
const isBusy = isLoading || syncAction !== null || commitAction !== null;
|
||||
const currentBranch = status?.current ?? null;
|
||||
const canShowIntegrateCommitsSection = Boolean(
|
||||
worktreeMetadata && repoRootForIntegrate && sourceBranchForIntegrate && shouldShowIntegrateCommits
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user