koala73/worldmonitor · error · Error

git is required to prove the merge commit reached the defaul

Error message

git is required to prove the merge commit reached the default branch

What it means

check-stacked-merge verifies that a merged PR's merge commit is actually reachable from the remote default branch (origin/<defaultBranch>). Proving ancestry requires running git; when the injected `git` dependency is not a function (dependency not provided/wired), the script throws rather than silently skipping the ancestry proof, which would let an unmerged-to-default merge pass.

Solutions

  1. Pass a working git executor function to checkStackedMerge (e.g. the script's own runGit helper)
  2. Fix the test/mock so `git` is a vi.fn/exec-style function, not undefined or a plain value
  3. Ensure the host environment has git installed if the executor shells out to it
  4. Confirm the option name matches the current function signature after any refactor

Example fix

// before
await checkStackedMerge({ pull });
// after
await checkStackedMerge({ pull, git: runGit });
Defensive patterns

Strategy: validation

Validate before calling

if (typeof git !== 'function') throw new Error('checkStackedMerge requires a git executor function');
await checkStackedMerge({ pull, git });

Type guard

const hasGitExecutor = (opts) => typeof opts.git === 'function';

Try / catch

try {
  await checkStackedMerge({ pull, git });
} catch (e) {
  if (e.message.includes('git is required')) {
    console.error('Wire the git executor dependency into checkStackedMerge');
  } else throw e;
}

Prevention

When it happens

Trigger: Calling checkStackedMerge for an already-merged PR while the `git` option was omitted, passed as null/undefined, or set to a non-function (e.g. a wrong mock or a string command instead of an executor function).

Common situations: Test harness refactored the dependency injection and stopped passing the git executor; a caller imported the check in a new script and forgot the git option; environment without git binary combined with a lazy git wrapper that resolves to undefined.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15). Data as JSON: /api/errors/32180cae9d637f41. Report an issue: GitHub.

Appendix: source

Thrown at scripts/check-stacked-merge.mjs:300

      }
      baseHeadPulls = listPullsByHead({ gh, repository, owner, headRef: baseRef });
    }
    const verdict = evaluatePreMergeGuard({ defaultBranch, baseRef, baseHeadPulls });
    if (verdict.ok) {
      return { ...verdict, exitCode: 0 };
    }
    return {
      ...verdict,
      exitCode: 1,
      annotation: preMergeAnnotation(verdict, baseRef),
    };
  }

  const mergeSha = pull.merge_commit_sha;
  const merged = isMergedPull(pull);
  if (!merged) return { ok: true, reason: 'not-merged', exitCode: 0 };
  if (typeof git !== 'function') {
    throw new Error('git is required to prove the merge commit reached the default branch');
  }
  const ref = `origin/${defaultBranch}`;
  const isAncestor = merged && typeof mergeSha === 'string' && mergeSha.length > 0
    ? confirmAncestry({
      git,
      commit: mergeSha,
      ref,
      defaultBranch,
      shouldRetry: baseRef === defaultBranch,
      sleep,
    })
    : false;
  const { parents = [], pendingParent } = !isAncestor && mergeSha && typeof gh === 'function'
    ? findPendingParent({ gh, git, repository, defaultBranch, pull, mergeSha })
    : {};
  const verdict = evaluatePostMergeAncestry({ merged, mergeSha, isAncestor, pendingParent });

  const alarm = formatOrphanIssue({

View on GitHub (pinned to 7d06c8633d)