Skip to content

Analyzing a merge

import { analyzeMerge } from 'git-edge';
const { canMerge, fastForward, diverged } = await analyzeMerge(repo, sourceRef, targetRef);

A cheap pre-merge check: resolve both refs, then check ancestry with git.isDescendent. It does not walk trees or attempt any content merge — that’s only knowable by calling threeWayMerge itself. Use this to decide whether to show a “fast-forward” vs. “will create a merge commit” hint in a UI before the user commits to the operation — not to predict whether a real merge will hit content conflicts.

Field Meaning
canMerge false only if a ref failed to resolve.
fastForward true if sourceRef is an ancestor of targetRef — a plain ref move, no merge commit.
diverged true if neither ref is an ancestor of the other — a real merge (with possible content conflicts) is needed.

canMerge: false means specifically that git.resolveRef threw a NotFoundError for one of the two refs — a deleted branch, a typo, a ref that was never created. Any other failure reading a ref (a network/storage error against remote object storage, a corrupted repo) is rethrown, not folded into canMerge: false:

try {
const sourceOid = await git.resolveRef({ ...repo, ref: sourceRef });
const targetOid = await git.resolveRef({ ...repo, ref: targetRef });
// ...
} catch (err) {
if ((err as { code?: string })?.code !== "NotFoundError") {
throw err;
}
return { canMerge: false, fastForward: false, diverged: false };
}

Relationship to git-fs-s3’s analyzeMerge

Section titled “Relationship to git-fs-s3’s analyzeMerge”

git-fs-s3/ops exports its own analyzeMerge with the same { canMerge, hasConflicts, conflictingFiles, fastForward }-shaped intent for apps already on that package’s Repo/OpsHooks conventions — see its merge guide. The two aren’t interchangeable (different Repo shapes, different return fields), but either is a reasonable pre-merge check depending on which package’s conventions the rest of your code already follows.