dotnet/runtime · error · RuntimeError

Couldn't determine baseline git hash

Error message

Couldn't determine baseline git hash

What it means

Raised by determine_base_jit when 'git merge-base <current_hash> <main_hash>' returns nonzero. The merge-base identifies the common ancestor commit used as the baseline for JIT diffs. A nonzero code means git could not compute the merge-base, usually because the two hashes have no common history (unrelated refs) or one hash is invalid/unreachable in the current object database.

Solutions

  1. Deepen the clone to include the common ancestor: 'git fetch --unshallow' or 'git fetch --depth=N' with a larger N.
  2. Verify both hashes exist in the repo: 'git cat-file -t <hash>' for each.
  3. Ensure current and main share history; if using a fork, rebase onto upstream main.
  4. Pass --base_git_hash <sha> explicitly to skip merge-base computation.

Example fix

// before
command = ["git", "merge-base", current_hash, main_hash]
proc = subprocess.Popen(command, stdout=subprocess.PIPE)
stdout_git_merge_base, _ = proc.communicate()
if proc.returncode != 0:
    raise RuntimeError("Couldn't determine baseline git hash")
// after (fix invocation)
git -C <repo> fetch --unshallow origin
# Or pass the baseline directly:
python superpmi.py asmdiff --base_git_hash <merge-base-sha> ...
Defensive patterns

Strategy: validation

Validate before calling

import subprocess
def validate_merge_base(repo_location, current_hash, main_hash):
    for h in (current_hash, main_hash):
        proc = subprocess.run(['git', '-C', repo_location, 'cat-file', '-t', h], capture_output=True)
        if proc.returncode != 0:
            raise RuntimeError(f"hash not present in repo: {h}")
    proc = subprocess.run(['git', '-C', repo_location, 'merge-base', current_hash, main_hash], capture_output=True)
    if proc.returncode != 0:
        raise RuntimeError(f"merge-base failed (disjoint histories?): {proc.stderr.decode('utf-8','replace').strip()}")
    return proc.stdout.decode('utf-8').strip()

Prevention

When it happens

Trigger: subprocess.Popen(['git','merge-base', current_hash, main_hash]) returns nonzero. Happens when current_hash and main_hash come from disjoint histories (e.g. a fork unrelated to upstream main), when a hash is not present due to a shallow/partial clone, or when a hash string is malformed.

Common situations: Shallow clone missing the merge-base commit object; working on a fork whose history does not share commits with the main branch used; git alternates/multiple worktrees with incomplete object storage; a stale/wrong main_hash from a prior failed step.

Related errors


AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10). Data as JSON: /api/errors/9b3c2c75e3149f8b. Report an issue: GitHub.

Appendix: source

Thrown at src/coreclr/scripts/superpmi.py:4892

            # First find the newest hash for any branch matching */main.
            command = [ "git", "branch", "-r", "--sort=-committerdate", "-v", "--list", "*/main" ]
            logging.debug("Invoking: %s", " ".join(command))
            proc = subprocess.Popen(command, stdout=subprocess.PIPE)
            stdout_git_main_branch, _ = proc.communicate()
            return_code = proc.returncode
            if return_code != 0:
                raise RuntimeError("Couldn't determine newest 'main' git hash")

            main_hash = stdout_git_main_branch.decode('utf-8').strip().split()[1]

            # Get the merge-base between the newest main and our current rev
            command = [ "git", "merge-base", current_hash, main_hash ]
            logging.debug("Invoking: %s", " ".join(command))
            proc = subprocess.Popen(command, stdout=subprocess.PIPE)
            stdout_git_merge_base, _ = proc.communicate()
            return_code = proc.returncode
            if return_code != 0:
                raise RuntimeError("Couldn't determine baseline git hash")

            baseline_hash = stdout_git_merge_base.decode('utf-8').strip()
            logging.info("Baseline hash: %s", baseline_hash)
        else:
            baseline_hash = coreclr_args.base_git_hash

        if coreclr_args.base_git_hash is None:
            # Enumerate the last 20 changes, starting with the baseline, that included JIT and JIT-EE GUID changes.
            command = [ "git", "log", "--pretty=format:%H", baseline_hash, "-20", "--", "src/coreclr/jit/*", "src/coreclr/inc/jiteeversionguid.h" ]
            logging.debug("Invoking: %s", " ".join(command))
            proc = subprocess.Popen(command, stdout=subprocess.PIPE)
            stdout_change_list, _ = proc.communicate()
            return_code = proc.returncode
            change_list_hashes = []
            if return_code == 0:
                change_list_hashes = stdout_change_list.decode('utf-8').strip().splitlines()
            else:
                raise RuntimeError("Couldn't determine list of JIT changes starting with baseline hash")

View on GitHub (pinned to 60108ba66e)