1

I'm writing a script which automatically finds a specific commit.

I've reached the part when I'm calling git bisect start --no-checkout and git bisect run ./my_check_commit_script.sh. It finds and displays the correct commit. However, I don't know how can I get the hash of this commit in my script.

The reference BISECT_HEAD seems to still point at the previous old revision. Other than that, using git show-ref, I've found a ref refs/bisect/new which seems to point to the correct commit but I don't know if I can rely on it existing. There is a bunch of refs/bisect/old* and I suspect it may be an accident that there is only a single refs/bisect/new.

How can I get the hash of the commit found by git bisect in my script?


Here is a script that crates a repository and successfully calls git bisect run on it:

git init repo
cd repo

echo a >foo
git add foo
git commit -m "Initial commit"

echo b >foo
git commit -a -m "Some commit"

echo c >foo
git commit -a -m "First commit which matches criteria"

echo d >foo
git commit -a -m "Some commit"

echo e >foo
git commit -a -m "Last commit"

git bisect start --no-checkout
git bisect old HEAD~4
git bisect new HEAD
git bisect run git merge-base --is-ancestor BISECT_HEAD HEAD~3
Piotr Siupa
  • 3,929
  • 2
  • 29
  • 65
  • The rev under test is `HEAD` (always). If the test succeeds, use `git rev-parse HEAD` and you have the hash ID. – torek Aug 26 '22 at 23:55
  • @torek No. It would work if I wasn't using `--no-checkout` but with this flag Git doesn't checkout the rev under test so `HEAD` stays where it was before `git bisect`. – Piotr Siupa Aug 27 '22 at 07:58
  • When `git bisect start --no-checkout` doesn't check out a rev under test, the rev in the working tree (which is the one under test) is `HEAD`. Are you talking about using `git bisect` in a bare repository? (Here the idea is different, as you're not actually testing any checked-out version, but here `BISECT_HEAD` *should* work. If it doesn't, that would seem to be a bug, either in the docs or the implementation or both. I've never actually used this mode myself.) – torek Aug 27 '22 at 22:24
  • @torek I'm not doing it in a bare repository but it is the same situation. In a bare repository `--no-checkout` is implied. – Piotr Siupa Aug 28 '22 at 08:12
  • In that case, what does your `run` script look like? It should explicitly use `BISECT_HEAD` for everything and not examine the working tree at all. – torek Aug 28 '22 at 08:28
  • @torek Yes, it uses `BISECT_HEAD` for everything. I'm doing it so I'm able to run the script without disturbing the current working copy. Wait a moment. I'm preparing a complete example. – Piotr Siupa Aug 28 '22 at 08:34
  • Note that you can use `git worktree add` to create a new worktree for bisection, without disturbing the current working tree. If there is some issue with BISECT_HEAD here that would provide a workaround. – torek Aug 28 '22 at 08:41

1 Answers1

1

The reference refs/bisect/new that you've found is the correct one to use. The command rev-parse bisect/new guarantees to always return the hash of the first "new" commit.

The Git manual tells that in the section "Basic bisect commands: start, bad, good" (emphasis mine):

Eventually there will be no more revisions left to inspect, and the command will print out a description of the first bad commit. The reference refs/bisect/bad will be left pointing at that commit.

The manual calls it refs/bisect/bad but because you're using old & new instead of good & bad, the reference name also changes. (Using options --term-good and --term-bad you can change this name to anything you want.)

Piotr Siupa
  • 3,929
  • 2
  • 29
  • 65