* [PATCH v4 0/3] Avoid hardcoded "good"/"bad" bisect terms
@ 2026-05-14 9:07 Jonas Rebmann
2026-05-14 9:07 ` [PATCH v4 1/3] bisect: use selected alternate terms in status output Jonas Rebmann
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Jonas Rebmann @ 2026-05-14 9:07 UTC (permalink / raw)
To: git; +Cc: Chris Down, Jeff King, Jonas Rebmann, Phillip Wood
While checking whether all output messages of git bisect were covered by
[PATCH 1/3] bisect: use selected alternate terms in status output I
found hardcoded good/bad refs leading to incompatibility of git
rev-parse --bisect with alternate bisect run terms. This is addressed by
[PATCH 3/3] rev-parse: use selected alternate terms to look up refs
Signed-off-by: Jonas Rebmann <kernel@schlaraffenlan.de>
---
Changes in v4:
- Always print bisect terms in single quote (Thanks, Junio)
- Split out quoting of bisect terms into separate commit
- Link to v3: https://patch.msgid.link/20260417-bisect-terms-v3-0-d659fa547261@schlaraffenlan.de
Changes in v3:
- when referencing newly introduced terms, reference them in single
quotes (Thanks, Phillip)
- Prefer test_grep over grep in updated Tests (Thanks, Phillip)
- Improve commit messages (Thanks, Phillip)
- Don't leak memory after read_bisect_terms() (Thanks, Phillip)
- Don't leak memory after xstrfmt() (Thanks, Junio)
- Add test case to patch 2/2
- Link to v2: https://patch.msgid.link/20260323-bisect-terms-v2-0-8d6bdb2c9c7e@schlaraffenlan.de
Changes in v2:
- Improve commit message
- Add tests
- Include second patch for hardcoded good/bad in rev-parse
- Link to v1: https://lore.kernel.org/r/20260320-bisect-terms-v1-1-c30c9540542a@schlaraffenlan.de
---
Jonas Rebmann (3):
bisect: use selected alternate terms in status output
bisect: print bisect terms in single quotes
rev-parse: use selected alternate terms to look up refs
bisect.c | 16 +++---
builtin/bisect.c | 31 ++++++-----
builtin/rev-parse.c | 15 +++++-
t/t1500-rev-parse.sh | 25 +++++++++
t/t6030-bisect-porcelain.sh | 124 ++++++++++++++++++++++++--------------------
5 files changed, 131 insertions(+), 80 deletions(-)
---
base-commit: 59ff4886a579f4bc91e976fe18590b9ae02c7a08
change-id: 20260320-bisect-terms-76036676769c
Best regards,
--
Jonas Rebmann <kernel@schlaraffenlan.de>
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v4 1/3] bisect: use selected alternate terms in status output
2026-05-14 9:07 [PATCH v4 0/3] Avoid hardcoded "good"/"bad" bisect terms Jonas Rebmann
@ 2026-05-14 9:07 ` Jonas Rebmann
2026-05-14 9:07 ` [PATCH v4 2/3] bisect: print bisect terms in single quotes Jonas Rebmann
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Jonas Rebmann @ 2026-05-14 9:07 UTC (permalink / raw)
To: git; +Cc: Chris Down, Jeff King, Jonas Rebmann, Phillip Wood
Alternate bisect terms are helpful when the terms "good" and "bad" are
confusing such as when bisecting for the resolution of an issue (the
first good commit) rather than the introduction of a regression.
These terms must be used when marking a commit (e.g. `git bisect new`),
they will be used in reference names (e.g. refs/bisect/new) and they are
used in parts of git's log output such as "<sha> was both old and new"
in git bisect skip's output.
However, hardcoded "good"/"bad" terms are still used in a few status
messages and can cause confusion about the status of the bisect such as:
$ git bisect old
[sha] is the first new commit
or about the required action such as:
status: waiting for bad commit, 1 good commit known
$ git bisect bad
error: Invalid command: you're currently in a new/old bisect
fatal: unknown command: 'bad'
This commit updates all remaining output messages which use hardcoded
"good" and "bad" terms to use the selected terms consistently across the
bisect output and adds tests.
Signed-off-by: Jonas Rebmann <kernel@schlaraffenlan.de>
---
builtin/bisect.c | 23 +++++++++++++----------
t/t6030-bisect-porcelain.sh | 16 ++++++++++++++--
2 files changed, 27 insertions(+), 12 deletions(-)
diff --git a/builtin/bisect.c b/builtin/bisect.c
index 4520e585d0..ee6a2c83b8 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -465,13 +465,16 @@ static void bisect_print_status(const struct bisect_terms *terms)
return;
if (!state.nr_good && !state.nr_bad)
- bisect_log_printf(_("status: waiting for both good and bad commits\n"));
+ bisect_log_printf(_("status: waiting for both %s and %s commits\n"),
+ terms->term_good, terms->term_bad);
else if (state.nr_good)
- bisect_log_printf(Q_("status: waiting for bad commit, %d good commit known\n",
- "status: waiting for bad commit, %d good commits known\n",
- state.nr_good), state.nr_good);
+ bisect_log_printf(Q_("status: waiting for %s commit, %d %s commit known\n",
+ "status: waiting for %s commit, %d %s commits known\n",
+ state.nr_good),
+ terms->term_bad, state.nr_good, terms->term_good);
else
- bisect_log_printf(_("status: waiting for good commit(s), bad commit known\n"));
+ bisect_log_printf(_("status: waiting for %s commit(s), %s commit known\n"),
+ terms->term_good, terms->term_bad);
}
static int bisect_next_check(const struct bisect_terms *terms,
@@ -1262,14 +1265,14 @@ static int bisect_run(struct bisect_terms *terms, int argc, const char **argv)
int rc = verify_good(terms, command.buf);
is_first_run = 0;
if (rc < 0 || 128 <= rc) {
- error(_("unable to verify %s on good"
- " revision"), command.buf);
+ error(_("unable to verify %s on %s"
+ " revision"), command.buf, terms->term_good);
res = BISECT_FAILED;
break;
}
if (rc == res) {
- error(_("bogus exit code %d for good revision"),
- rc);
+ error(_("bogus exit code %d for %s revision"),
+ rc, terms->term_good);
res = BISECT_FAILED;
break;
}
@@ -1314,7 +1317,7 @@ static int bisect_run(struct bisect_terms *terms, int argc, const char **argv)
puts(_("bisect run success"));
res = BISECT_OK;
} else if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND) {
- puts(_("bisect found first bad commit"));
+ printf(_("bisect found first %s commit\n"), terms->term_bad);
res = BISECT_OK;
} else if (res) {
error(_("bisect run failed: 'git bisect %s'"
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 1ba9ca219e..9d28d1eedb 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -1077,8 +1077,10 @@ test_expect_success 'bisect terms shows good/bad after start' '
test_expect_success 'bisect start with one term1 and term2' '
git bisect reset &&
- git bisect start --term-old term2 --term-new term1 &&
- git bisect term2 $HASH1 &&
+ git bisect start --term-old term2 --term-new term1 >bisect_result &&
+ grep "status: waiting for both term2 and term1 commits" bisect_result &&
+ git bisect term2 $HASH1 >bisect_result &&
+ grep "status: waiting for term1 commit, 1 term2 commit known" bisect_result &&
git bisect term1 $HASH4 &&
git bisect term1 &&
git bisect term1 >bisect_result &&
@@ -1103,6 +1105,16 @@ test_expect_success 'bisect replay with term1 and term2' '
git bisect reset
'
+test_expect_success 'bisect run term1 term2' '
+ git bisect reset &&
+ git bisect start --term-new term1 --term-old term2 $HASH4 $HASH1 &&
+ git bisect term1 &&
+ git bisect run false >bisect_result &&
+ grep "bisect found first term1 commit" bisect_result &&
+ git bisect log >log_to_replay.txt &&
+ git bisect reset
+'
+
test_expect_success 'bisect start term1 term2' '
git bisect reset &&
git bisect start --term-new term1 --term-old term2 $HASH4 $HASH1 &&
--
2.54.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v4 2/3] bisect: print bisect terms in single quotes
2026-05-14 9:07 [PATCH v4 0/3] Avoid hardcoded "good"/"bad" bisect terms Jonas Rebmann
2026-05-14 9:07 ` [PATCH v4 1/3] bisect: use selected alternate terms in status output Jonas Rebmann
@ 2026-05-14 9:07 ` Jonas Rebmann
2026-05-14 9:07 ` [PATCH v4 3/3] rev-parse: use selected alternate terms to look up refs Jonas Rebmann
2026-05-14 19:56 ` [PATCH v4 0/3] Avoid hardcoded "good"/"bad" bisect terms Junio C Hamano
3 siblings, 0 replies; 6+ messages in thread
From: Jonas Rebmann @ 2026-05-14 9:07 UTC (permalink / raw)
To: git; +Cc: Chris Down, Jeff King, Jonas Rebmann, Phillip Wood
As bisect terms can be arbitrarily chosen, they have been quoted in some
status messages, and in even more by translators.
To make the role of bisect terms more clear, including in translations,
and for consistency, 'enquote' all occurrences of bisect terms in status
messages.
Signed-off-by: Jonas Rebmann <kernel@schlaraffenlan.de>
---
bisect.c | 16 +++----
builtin/bisect.c | 24 +++++-----
t/t6030-bisect-porcelain.sh | 114 ++++++++++++++++++++++----------------------
3 files changed, 77 insertions(+), 77 deletions(-)
diff --git a/bisect.c b/bisect.c
index ef17a442e5..905a9afb05 100644
--- a/bisect.c
+++ b/bisect.c
@@ -711,7 +711,7 @@ static enum bisect_error error_if_skipped_commits(struct commit_list *tried,
return BISECT_OK;
printf("There are only 'skip'ped commits left to test.\n"
- "The first %s commit could be any of:\n", term_bad);
+ "The first '%s' commit could be any of:\n", term_bad);
for ( ; tried; tried = tried->next)
printf("%s\n", oid_to_hex(&tried->item->object.oid));
@@ -810,7 +810,7 @@ static enum bisect_error handle_bad_merge_base(void)
"between %s and [%s].\n"),
bad_hex, bad_hex, good_hex);
} else {
- fprintf(stderr, _("The merge base %s is %s.\n"
+ fprintf(stderr, _("The merge base %s is '%s'.\n"
"This means the first '%s' commit is "
"between %s and [%s].\n"),
bad_hex, term_bad, term_good, bad_hex, good_hex);
@@ -820,9 +820,9 @@ static enum bisect_error handle_bad_merge_base(void)
return BISECT_MERGE_BASE_CHECK;
}
- fprintf(stderr, _("Some %s revs are not ancestors of the %s rev.\n"
+ fprintf(stderr, _("Some '%s' revs are not ancestors of the '%s' rev.\n"
"git bisect cannot work properly in this case.\n"
- "Maybe you mistook %s and %s revs?\n"),
+ "Maybe you mistook '%s' and '%s' revs?\n"),
term_good, term_bad, term_good, term_bad);
return BISECT_FAILED;
}
@@ -835,7 +835,7 @@ static void handle_skipped_merge_base(const struct object_id *mb)
warning(_("the merge base between %s and [%s] "
"must be skipped.\n"
- "So we cannot be sure the first %s commit is "
+ "So we cannot be sure the first '%s' commit is "
"between %s and %s.\n"
"We continue anyway."),
bad_hex, good_hex, term_bad, mb_hex, bad_hex);
@@ -928,7 +928,7 @@ static enum bisect_error check_good_are_ancestors_of_bad(struct repository *r,
struct commit **rev;
if (!current_bad_oid)
- return error(_("a %s revision is needed"), term_bad);
+ return error(_("a '%s' revision is needed"), term_bad);
filename = repo_git_path(the_repository, "BISECT_ANCESTORS_OK");
@@ -1090,7 +1090,7 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix)
res = error_if_skipped_commits(tried, NULL);
if (res < 0)
goto cleanup;
- printf(_("%s was both %s and %s\n"),
+ printf(_("%s was both '%s' and '%s'\n"),
oid_to_hex(current_bad_oid),
term_good,
term_bad);
@@ -1113,7 +1113,7 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix)
res = error_if_skipped_commits(tried, current_bad_oid);
if (res)
goto cleanup;
- printf("%s is the first %s commit\n", oid_to_hex(bisect_rev),
+ printf("%s is the first '%s' commit\n", oid_to_hex(bisect_rev),
term_bad);
show_commit(revs.commits->item);
diff --git a/builtin/bisect.c b/builtin/bisect.c
index ee6a2c83b8..606698b21e 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -465,15 +465,15 @@ static void bisect_print_status(const struct bisect_terms *terms)
return;
if (!state.nr_good && !state.nr_bad)
- bisect_log_printf(_("status: waiting for both %s and %s commits\n"),
+ bisect_log_printf(_("status: waiting for both '%s' and '%s' commits\n"),
terms->term_good, terms->term_bad);
else if (state.nr_good)
- bisect_log_printf(Q_("status: waiting for %s commit, %d %s commit known\n",
- "status: waiting for %s commit, %d %s commits known\n",
+ bisect_log_printf(Q_("status: waiting for '%s' commit, %d '%s' commit known\n",
+ "status: waiting for '%s' commit, %d '%s' commits known\n",
state.nr_good),
terms->term_bad, state.nr_good, terms->term_good);
else
- bisect_log_printf(_("status: waiting for %s commit(s), %s commit known\n"),
+ bisect_log_printf(_("status: waiting for '%s' commit(s), '%s' commit known\n"),
terms->term_good, terms->term_bad);
}
@@ -516,8 +516,8 @@ static int bisect_terms(struct bisect_terms *terms, const char *option)
return error(_("no terms defined"));
if (!option) {
- printf(_("Your current terms are %s for the old state\n"
- "and %s for the new state.\n"),
+ printf(_("Your current terms are '%s' for the old state\n"
+ "and '%s' for the new state.\n"),
terms->term_good, terms->term_bad);
return 0;
}
@@ -635,7 +635,7 @@ static int bisect_skipped_commits(struct bisect_terms *terms)
strbuf_reset(&commit_name);
repo_format_commit_message(the_repository, commit, "%s",
&commit_name, &pp);
- fprintf(fp, "# possible first %s commit: [%s] %s\n",
+ fprintf(fp, "# possible first '%s' commit: [%s] %s\n",
terms->term_bad, oid_to_hex(&commit->object.oid),
commit_name.buf);
}
@@ -666,7 +666,7 @@ static int bisect_successful(struct bisect_terms *terms)
repo_format_commit_message(the_repository, commit, "%s", &commit_name,
&pp);
- res = append_to_file(git_path_bisect_log(), "# first %s commit: [%s] %s\n",
+ res = append_to_file(git_path_bisect_log(), "# first '%s' commit: [%s] %s\n",
terms->term_bad, oid_to_hex(&commit->object.oid),
commit_name.buf);
@@ -1265,13 +1265,13 @@ static int bisect_run(struct bisect_terms *terms, int argc, const char **argv)
int rc = verify_good(terms, command.buf);
is_first_run = 0;
if (rc < 0 || 128 <= rc) {
- error(_("unable to verify %s on %s"
- " revision"), command.buf, terms->term_good);
+ error(_("unable to verify %s on '%s' revision"),
+ command.buf, terms->term_good);
res = BISECT_FAILED;
break;
}
if (rc == res) {
- error(_("bogus exit code %d for %s revision"),
+ error(_("bogus exit code %d for '%s' revision"),
rc, terms->term_good);
res = BISECT_FAILED;
break;
@@ -1317,7 +1317,7 @@ static int bisect_run(struct bisect_terms *terms, int argc, const char **argv)
puts(_("bisect run success"));
res = BISECT_OK;
} else if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND) {
- printf(_("bisect found first %s commit\n"), terms->term_bad);
+ printf(_("bisect found first '%s' commit\n"), terms->term_bad);
res = BISECT_OK;
} else if (res) {
error(_("bisect run failed: 'git bisect %s'"
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 9d28d1eedb..081116220a 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -258,7 +258,7 @@ test_expect_success 'bisect skip: successful result' '
git bisect start $HASH4 $HASH1 &&
git bisect skip &&
git bisect bad > my_bisect_log.txt &&
- grep "$HASH2 is the first bad commit" my_bisect_log.txt
+ grep "$HASH2 is the first '\''bad'\'' commit" my_bisect_log.txt
'
# $HASH1 is good, $HASH4 is bad, we skip $HASH3 and $HASH2
@@ -269,7 +269,7 @@ test_expect_success 'bisect skip: cannot tell between 3 commits' '
git bisect start $HASH4 $HASH1 &&
git bisect skip &&
test_expect_code 2 git bisect skip >my_bisect_log.txt &&
- grep "first bad commit could be any of" my_bisect_log.txt &&
+ grep "first '\''bad'\'' commit could be any of" my_bisect_log.txt &&
! grep $HASH1 my_bisect_log.txt &&
grep $HASH2 my_bisect_log.txt &&
grep $HASH3 my_bisect_log.txt &&
@@ -285,7 +285,7 @@ test_expect_success 'bisect skip: cannot tell between 2 commits' '
git bisect start $HASH4 $HASH1 &&
git bisect skip &&
test_expect_code 2 git bisect good >my_bisect_log.txt &&
- grep "first bad commit could be any of" my_bisect_log.txt &&
+ grep "first '\''bad'\'' commit could be any of" my_bisect_log.txt &&
! grep $HASH1 my_bisect_log.txt &&
! grep $HASH2 my_bisect_log.txt &&
grep $HASH3 my_bisect_log.txt &&
@@ -304,7 +304,7 @@ test_expect_success 'bisect skip: with commit both bad and skipped' '
git bisect good $HASH1 &&
git bisect skip &&
test_expect_code 2 git bisect good >my_bisect_log.txt &&
- grep "first bad commit could be any of" my_bisect_log.txt &&
+ grep "first '\''bad'\'' commit could be any of" my_bisect_log.txt &&
! grep $HASH1 my_bisect_log.txt &&
! grep $HASH2 my_bisect_log.txt &&
grep $HASH3 my_bisect_log.txt &&
@@ -348,8 +348,8 @@ test_expect_success 'git bisect run: args, stdout and stderr with no arguments'
test_bisect_run_args <<-'EOF_ARGS' 6<<-EOF_OUT 7<<-'EOF_ERR'
EOF_ARGS
running './run.sh'
- $HASH4 is the first bad commit
- bisect found first bad commit
+ $HASH4 is the first 'bad' commit
+ bisect found first 'bad' commit
EOF_OUT
EOF_ERR
"
@@ -359,8 +359,8 @@ test_expect_success 'git bisect run: args, stdout and stderr: "--" argument' "
<-->
EOF_ARGS
running './run.sh' '--'
- $HASH4 is the first bad commit
- bisect found first bad commit
+ $HASH4 is the first 'bad' commit
+ bisect found first 'bad' commit
EOF_OUT
EOF_ERR
"
@@ -373,8 +373,8 @@ test_expect_success 'git bisect run: args, stdout and stderr: "--log foo --no-lo
<bar>
EOF_ARGS
running './run.sh' '--log' 'foo' '--no-log' 'bar'
- $HASH4 is the first bad commit
- bisect found first bad commit
+ $HASH4 is the first 'bad' commit
+ bisect found first 'bad' commit
EOF_OUT
EOF_ERR
"
@@ -384,8 +384,8 @@ test_expect_success 'git bisect run: args, stdout and stderr: "--bisect-start" a
<--bisect-start>
EOF_ARGS
running './run.sh' '--bisect-start'
- $HASH4 is the first bad commit
- bisect found first bad commit
+ $HASH4 is the first 'bad' commit
+ bisect found first 'bad' commit
EOF_OUT
EOF_ERR
"
@@ -418,7 +418,7 @@ test_expect_success 'git bisect run: unable to verify on good' "
fi
EOF
cat <<-'EOF' >expect &&
- unable to verify './fail.sh' on good revision
+ unable to verify './fail.sh' on 'good' revision
EOF
test_when_finished 'git bisect reset' &&
git bisect start &&
@@ -439,7 +439,7 @@ test_expect_success '"git bisect run" simple case' '
git bisect good $HASH1 &&
git bisect bad $HASH4 &&
git bisect run ./test_script.sh >my_bisect_log.txt &&
- grep "$HASH3 is the first bad commit" my_bisect_log.txt &&
+ grep "$HASH3 is the first '\''bad'\'' commit" my_bisect_log.txt &&
git bisect reset
'
@@ -461,7 +461,7 @@ test_expect_success '"git bisect run" with more complex "git bisect start"' '
EOF
git bisect start $HASH4 $HASH1 &&
git bisect run ./test_script.sh >my_bisect_log.txt &&
- grep "$HASH4 is the first bad commit" my_bisect_log.txt &&
+ grep "$HASH4 is the first '\''bad'\'' commit" my_bisect_log.txt &&
git bisect reset
'
@@ -474,7 +474,7 @@ test_expect_success 'bisect run accepts exit code 126 as bad' '
git bisect good $HASH1 &&
git bisect bad $HASH4 &&
git bisect run ./test_script.sh >my_bisect_log.txt &&
- grep "$HASH3 is the first bad commit" my_bisect_log.txt
+ grep "$HASH3 is the first '\''bad'\'' commit" my_bisect_log.txt
'
test_expect_success POSIXPERM 'bisect run fails with non-executable test script' '
@@ -485,7 +485,7 @@ test_expect_success POSIXPERM 'bisect run fails with non-executable test script'
git bisect good $HASH1 &&
git bisect bad $HASH4 &&
test_must_fail git bisect run ./not-executable.sh >my_bisect_log.txt &&
- ! grep "is the first bad commit" my_bisect_log.txt
+ ! grep "is the first '\''bad'\'' commit" my_bisect_log.txt
'
test_expect_success 'bisect run accepts exit code 127 as bad' '
@@ -497,7 +497,7 @@ test_expect_success 'bisect run accepts exit code 127 as bad' '
git bisect good $HASH1 &&
git bisect bad $HASH4 &&
git bisect run ./test_script.sh >my_bisect_log.txt &&
- grep "$HASH3 is the first bad commit" my_bisect_log.txt
+ grep "$HASH3 is the first '\''bad'\'' commit" my_bisect_log.txt
'
test_expect_success 'bisect run fails with missing test script' '
@@ -507,7 +507,7 @@ test_expect_success 'bisect run fails with missing test script' '
git bisect good $HASH1 &&
git bisect bad $HASH4 &&
test_must_fail git bisect run ./does-not-exist.sh >my_bisect_log.txt &&
- ! grep "is the first bad commit" my_bisect_log.txt
+ ! grep "is the first '\''bad'\'' commit" my_bisect_log.txt
'
# $HASH1 is good, $HASH5 is bad, we skip $HASH3
@@ -520,14 +520,14 @@ test_expect_success 'bisect skip: add line and then a new test' '
git bisect start $HASH5 $HASH1 &&
git bisect skip &&
git bisect good > my_bisect_log.txt &&
- grep "$HASH5 is the first bad commit" my_bisect_log.txt &&
+ grep "$HASH5 is the first '\''bad'\'' commit" my_bisect_log.txt &&
git bisect log > log_to_replay.txt &&
git bisect reset
'
test_expect_success 'bisect skip and bisect replay' '
git bisect replay log_to_replay.txt > my_bisect_log.txt &&
- grep "$HASH5 is the first bad commit" my_bisect_log.txt &&
+ grep "$HASH5 is the first '\''bad'\'' commit" my_bisect_log.txt &&
git bisect reset
'
@@ -541,7 +541,7 @@ test_expect_success 'bisect run & skip: cannot tell between 2' '
EOF
git bisect start $HASH6 $HASH1 &&
test_expect_code 2 git bisect run ./test_script.sh >my_bisect_log.txt &&
- grep "first bad commit could be any of" my_bisect_log.txt &&
+ grep "first '\''bad'\'' commit could be any of" my_bisect_log.txt &&
! grep $HASH3 my_bisect_log.txt &&
! grep $HASH6 my_bisect_log.txt &&
grep $HASH4 my_bisect_log.txt &&
@@ -560,7 +560,7 @@ test_expect_success 'bisect run & skip: find first bad' '
EOF
git bisect start $HASH7 $HASH1 &&
git bisect run ./test_script.sh >my_bisect_log.txt &&
- grep "$HASH6 is the first bad commit" my_bisect_log.txt
+ grep "$HASH6 is the first '\''bad'\'' commit" my_bisect_log.txt
'
test_expect_success 'bisect skip only one range' '
@@ -569,7 +569,7 @@ test_expect_success 'bisect skip only one range' '
git bisect skip $HASH1..$HASH5 &&
test "$HASH6" = "$(git rev-parse --verify HEAD)" &&
test_must_fail git bisect bad > my_bisect_log.txt &&
- grep "first bad commit could be any of" my_bisect_log.txt
+ grep "first '\''bad'\'' commit could be any of" my_bisect_log.txt
'
test_expect_success 'bisect skip many ranges' '
@@ -578,7 +578,7 @@ test_expect_success 'bisect skip many ranges' '
git bisect skip $HASH2 $HASH2.. ..$HASH5 &&
test "$HASH6" = "$(git rev-parse --verify HEAD)" &&
test_must_fail git bisect bad > my_bisect_log.txt &&
- grep "first bad commit could be any of" my_bisect_log.txt
+ grep "first '\''bad'\'' commit could be any of" my_bisect_log.txt
'
test_expect_success 'bisect starting with a detached HEAD' '
@@ -594,7 +594,7 @@ test_expect_success 'bisect starting with a detached HEAD' '
test_expect_success 'bisect errors out if bad and good are mistaken' '
git bisect reset &&
test_must_fail git bisect start $HASH2 $HASH4 2> rev_list_error &&
- test_grep "mistook good and bad" rev_list_error &&
+ test_grep "mistook '\''good'\'' and '\''bad'\''" rev_list_error &&
git bisect reset
'
@@ -610,7 +610,7 @@ test_expect_success 'bisect does not create a "bisect" branch' '
rev_hash6=$(git rev-parse --verify HEAD) &&
test "$rev_hash6" = "$HASH6" &&
git bisect good > my_bisect_log.txt &&
- grep "$HASH7 is the first bad commit" my_bisect_log.txt &&
+ grep "$HASH7 is the first '\''bad'\'' commit" my_bisect_log.txt &&
git bisect reset &&
rev_hash6=$(git rev-parse --verify bisect) &&
test "$rev_hash6" = "$HASH6" &&
@@ -703,7 +703,7 @@ test_expect_success '"git bisect run --first-parent" simple case' '
git bisect good $HASH4 &&
git bisect bad $B_HASH &&
git bisect run ./test_script.sh >my_bisect_log.txt &&
- grep "$B_HASH is the first bad commit" my_bisect_log.txt &&
+ grep "$B_HASH is the first '\''bad'\'' commit" my_bisect_log.txt &&
git bisect reset &&
test_path_is_missing .git/BISECT_FIRST_PARENT
'
@@ -777,7 +777,7 @@ test_expect_success 'restricting bisection on one dir' '
para1=$(git rev-parse --verify HEAD) &&
test "$para1" = "$PARA_HASH1" &&
git bisect bad > my_bisect_log.txt &&
- grep "$PARA_HASH1 is the first bad commit" my_bisect_log.txt
+ grep "$PARA_HASH1 is the first '\''bad'\'' commit" my_bisect_log.txt
'
test_expect_success 'restricting bisection on one dir and a file' '
@@ -795,7 +795,7 @@ test_expect_success 'restricting bisection on one dir and a file' '
para1=$(git rev-parse --verify HEAD) &&
test "$para1" = "$PARA_HASH1" &&
git bisect good > my_bisect_log.txt &&
- grep "$PARA_HASH4 is the first bad commit" my_bisect_log.txt
+ grep "$PARA_HASH4 is the first '\''bad'\'' commit" my_bisect_log.txt
'
test_expect_success 'skipping away from skipped commit' '
@@ -826,7 +826,7 @@ test_expect_success 'test bisection on bare repo - --no-checkout specified' '
"test \$(git rev-list BISECT_HEAD ^$HASH2 --max-count=1 | wc -l) = 0" \
>../nocheckout.log
) &&
- grep "$HASH3 is the first bad commit" nocheckout.log
+ grep "$HASH3 is the first '\''bad'\'' commit" nocheckout.log
'
@@ -841,7 +841,7 @@ test_expect_success 'test bisection on bare repo - --no-checkout defaulted' '
"test \$(git rev-list BISECT_HEAD ^$HASH2 --max-count=1 | wc -l) = 0" \
>../defaulted.log
) &&
- grep "$HASH3 is the first bad commit" defaulted.log
+ grep "$HASH3 is the first '\''bad'\'' commit" defaulted.log
'
#
@@ -969,7 +969,7 @@ cat > expected.bisect-log <<EOF
git bisect start '$HASH4' '$HASH2'
# good: [$HASH3] Add <3: Another new day for git> into <hello>.
git bisect good $HASH3
-# first bad commit: [$HASH4] Add <4: Ciao for now> into <hello>.
+# first 'bad' commit: [$HASH4] Add <4: Ciao for now> into <hello>.
EOF
test_expect_success 'bisect log: successful result' '
@@ -988,8 +988,8 @@ git bisect start '$HASH4' '$HASH2'
# skip: [$HASH3] Add <3: Another new day for git> into <hello>.
git bisect skip $HASH3
# only skipped commits left to test
-# possible first bad commit: [$HASH4] Add <4: Ciao for now> into <hello>.
-# possible first bad commit: [$HASH3] Add <3: Another new day for git> into <hello>.
+# possible first 'bad' commit: [$HASH4] Add <4: Ciao for now> into <hello>.
+# possible first 'bad' commit: [$HASH3] Add <3: Another new day for git> into <hello>.
EOF
test_expect_success 'bisect log: only skip commits left' '
@@ -1031,21 +1031,21 @@ test_expect_success 'bisect start with one new and old' '
git bisect new $HASH4 &&
git bisect new &&
git bisect new >bisect_result &&
- grep "$HASH2 is the first new commit" bisect_result &&
+ grep "$HASH2 is the first '\''new'\'' commit" bisect_result &&
git bisect log >log_to_replay.txt &&
git bisect reset
'
test_expect_success 'bisect replay with old and new' '
git bisect replay log_to_replay.txt >bisect_result &&
- grep "$HASH2 is the first new commit" bisect_result &&
+ grep "$HASH2 is the first '\''new'\'' commit" bisect_result &&
git bisect reset
'
test_expect_success 'bisect replay with CRLF log' '
append_cr <log_to_replay.txt >log_to_replay_crlf.txt &&
git bisect replay log_to_replay_crlf.txt >bisect_result_crlf &&
- grep "$HASH2 is the first new commit" bisect_result_crlf &&
+ grep "$HASH2 is the first '\''new'\'' commit" bisect_result_crlf &&
git bisect reset
'
@@ -1078,13 +1078,13 @@ test_expect_success 'bisect terms shows good/bad after start' '
test_expect_success 'bisect start with one term1 and term2' '
git bisect reset &&
git bisect start --term-old term2 --term-new term1 >bisect_result &&
- grep "status: waiting for both term2 and term1 commits" bisect_result &&
+ test_grep "status: waiting for both '\''term2'\'' and '\''term1'\'' commits" bisect_result &&
git bisect term2 $HASH1 >bisect_result &&
- grep "status: waiting for term1 commit, 1 term2 commit known" bisect_result &&
+ test_grep "status: waiting for '\''term1'\'' commit, 1 '\''term2'\'' commit known" bisect_result &&
git bisect term1 $HASH4 &&
git bisect term1 &&
git bisect term1 >bisect_result &&
- grep "$HASH2 is the first term1 commit" bisect_result &&
+ test_grep "$HASH2 is the first '\''term1'\'' commit" bisect_result &&
git bisect log >log_to_replay.txt &&
git bisect reset
'
@@ -1101,7 +1101,7 @@ test_expect_success 'bogus command does not start bisect' '
test_expect_success 'bisect replay with term1 and term2' '
git bisect replay log_to_replay.txt >bisect_result &&
- grep "$HASH2 is the first term1 commit" bisect_result &&
+ grep "$HASH2 is the first '\''term1'\'' commit" bisect_result &&
git bisect reset
'
@@ -1110,7 +1110,7 @@ test_expect_success 'bisect run term1 term2' '
git bisect start --term-new term1 --term-old term2 $HASH4 $HASH1 &&
git bisect term1 &&
git bisect run false >bisect_result &&
- grep "bisect found first term1 commit" bisect_result &&
+ test_grep "bisect found first '\''term1'\'' commit" bisect_result &&
git bisect log >log_to_replay.txt &&
git bisect reset
'
@@ -1120,7 +1120,7 @@ test_expect_success 'bisect start term1 term2' '
git bisect start --term-new term1 --term-old term2 $HASH4 $HASH1 &&
git bisect term1 &&
git bisect term1 >bisect_result &&
- grep "$HASH2 is the first term1 commit" bisect_result &&
+ grep "$HASH2 is the first '\''term1'\'' commit" bisect_result &&
git bisect log >log_to_replay.txt &&
git bisect reset
'
@@ -1154,8 +1154,8 @@ test_expect_success 'bisect start --term-* does store terms' '
git bisect start --term-bad=one --term-good=two &&
git bisect terms >actual &&
cat <<-EOF >expected &&
- Your current terms are two for the old state
- and one for the new state.
+ Your current terms are '\''two'\'' for the old state
+ and '\''one'\'' for the new state.
EOF
test_cmp expected actual &&
git bisect terms --term-bad >actual &&
@@ -1212,7 +1212,7 @@ test_expect_success 'bisect handles annotated tags' '
git bisect good tag-one &&
git bisect bad tag-two >output &&
bad=$(git rev-parse --verify tag-two^{commit}) &&
- grep "$bad is the first bad commit" output
+ grep "$bad is the first '\''bad'\'' commit" output
'
test_expect_success 'bisect run fails with exit code equals or greater than 128' '
@@ -1236,29 +1236,29 @@ test_expect_success 'bisect visualize with a filename with dash and space' '
test_expect_success 'bisect state output with multiple good commits' '
git bisect reset &&
git bisect start >output &&
- grep "waiting for both good and bad commits" output &&
+ grep "waiting for both '\''good'\'' and '\''bad'\'' commits" output &&
git bisect log >output &&
- grep "waiting for both good and bad commits" output &&
+ grep "waiting for both '\''good'\'' and '\''bad'\'' commits" output &&
git bisect good "$HASH1" >output &&
- grep "waiting for bad commit, 1 good commit known" output &&
+ grep "waiting for '\''bad'\'' commit, 1 '\''good'\'' commit known" output &&
git bisect log >output &&
- grep "waiting for bad commit, 1 good commit known" output &&
+ grep "waiting for '\''bad'\'' commit, 1 '\''good'\'' commit known" output &&
git bisect good "$HASH2" >output &&
- grep "waiting for bad commit, 2 good commits known" output &&
+ grep "waiting for '\''bad'\'' commit, 2 '\''good'\'' commits known" output &&
git bisect log >output &&
- grep "waiting for bad commit, 2 good commits known" output
+ grep "waiting for '\''bad'\'' commit, 2 '\''good'\'' commits known" output
'
test_expect_success 'bisect state output with bad commit' '
git bisect reset &&
git bisect start >output &&
- grep "waiting for both good and bad commits" output &&
+ grep "waiting for both '\''good'\'' and '\''bad'\'' commits" output &&
git bisect log >output &&
- grep "waiting for both good and bad commits" output &&
+ grep "waiting for both '\''good'\'' and '\''bad'\'' commits" output &&
git bisect bad "$HASH4" >output &&
- grep -F "waiting for good commit(s), bad commit known" output &&
+ grep -F "waiting for '\''good'\'' commit(s), '\''bad'\'' commit known" output &&
git bisect log >output &&
- grep -F "waiting for good commit(s), bad commit known" output
+ grep -F "waiting for '\''good'\'' commit(s), '\''bad'\'' commit known" output
'
test_expect_success 'verify correct error message' '
--
2.54.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v4 3/3] rev-parse: use selected alternate terms to look up refs
2026-05-14 9:07 [PATCH v4 0/3] Avoid hardcoded "good"/"bad" bisect terms Jonas Rebmann
2026-05-14 9:07 ` [PATCH v4 1/3] bisect: use selected alternate terms in status output Jonas Rebmann
2026-05-14 9:07 ` [PATCH v4 2/3] bisect: print bisect terms in single quotes Jonas Rebmann
@ 2026-05-14 9:07 ` Jonas Rebmann
2026-05-14 19:56 ` [PATCH v4 0/3] Avoid hardcoded "good"/"bad" bisect terms Junio C Hamano
3 siblings, 0 replies; 6+ messages in thread
From: Jonas Rebmann @ 2026-05-14 9:07 UTC (permalink / raw)
To: git; +Cc: Chris Down, Jeff King, Jonas Rebmann, Phillip Wood
git rev-parse --bisect does not work when alternate bisect terms are
used, simply listing no revisions at all.
This is because a such bisect using e.g. "old" and "new" in place of
"good" and "bad" will name refs "refs/bisect/old" (or new) accordingly
so the hardcoded "refs/bisect/bad" (and good) yields no results in a
bisect using alternate terms.
Use the current bisect_terms to make rev-parse --bisect work in an
alternate term bisect.
Signed-off-by: Jonas Rebmann <kernel@schlaraffenlan.de>
---
builtin/rev-parse.c | 15 +++++++++++++--
t/t1500-rev-parse.sh | 25 +++++++++++++++++++++++++
2 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 218b5f34d6..7531edae9e 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -10,6 +10,7 @@
#include "builtin.h"
#include "abspath.h"
+#include "bisect.h"
#include "config.h"
#include "commit.h"
#include "environment.h"
@@ -940,13 +941,23 @@ int cmd_rev_parse(int argc,
continue;
}
if (!strcmp(arg, "--bisect")) {
+ char *prefix;
+ char *term_bad = NULL;
+ char *term_good = NULL;
struct refs_for_each_ref_options opts = { 0 };
- opts.prefix = "refs/bisect/bad";
+ read_bisect_terms(&term_bad, &term_good);
+ prefix = xstrfmt("refs/bisect/%s", term_bad);
+ opts.prefix = prefix;
refs_for_each_ref_ext(get_main_ref_store(the_repository),
show_reference, NULL, &opts);
- opts.prefix = "refs/bisect/good";
+ free(prefix);
+ prefix = xstrfmt("refs/bisect/%s", term_good);
+ opts.prefix = prefix;
refs_for_each_ref_ext(get_main_ref_store(the_repository),
anti_reference, NULL, &opts);
+ free(prefix);
+ free(term_good);
+ free(term_bad);
continue;
}
if (opt_with_value(arg, "--branches", &arg)) {
diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh
index 98c5a772bd..38067d95f7 100755
--- a/t/t1500-rev-parse.sh
+++ b/t/t1500-rev-parse.sh
@@ -337,6 +337,31 @@ test_expect_success 'rev-parse --bisect includes bad, excludes good' '
test_cmp expect actual
'
+test_expect_success 'rev-parse --bisect works with alternate terms' '
+ test_commit_bulk 6 &&
+
+ git bisect start --term-old=known --term-new=curious &&
+
+ git update-ref refs/bisect/curious-1 HEAD~1 &&
+ git update-ref refs/bisect/bad HEAD~2 &&
+ git update-ref refs/bisect/curious-3 HEAD~3 &&
+ git update-ref refs/bisect/known-3 HEAD~3 &&
+ git update-ref refs/bisect/curious-4 HEAD~4 &&
+ git update-ref refs/bisect/good HEAD~4 &&
+
+ # Note: refs/bisect/bad and refs/bisect/goood should be ignored because this
+ # is a bisect with custom terms (known/curious)
+ cat >expect <<-EOF &&
+ refs/bisect/curious-1
+ refs/bisect/curious-3
+ refs/bisect/curious-4
+ ^refs/bisect/known-3
+ EOF
+
+ git rev-parse --symbolic-full-name --bisect >actual &&
+ test_cmp expect actual
+'
+
test_expect_success '--short= truncates to the actual hash length' '
git rev-parse HEAD >expect &&
git rev-parse --short=100 HEAD >actual &&
--
2.54.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v4 0/3] Avoid hardcoded "good"/"bad" bisect terms
2026-05-14 9:07 [PATCH v4 0/3] Avoid hardcoded "good"/"bad" bisect terms Jonas Rebmann
` (2 preceding siblings ...)
2026-05-14 9:07 ` [PATCH v4 3/3] rev-parse: use selected alternate terms to look up refs Jonas Rebmann
@ 2026-05-14 19:56 ` Junio C Hamano
2026-05-15 8:07 ` Jonas Rebmann
3 siblings, 1 reply; 6+ messages in thread
From: Junio C Hamano @ 2026-05-14 19:56 UTC (permalink / raw)
To: Jonas Rebmann; +Cc: git, Chris Down, Jeff King, Phillip Wood
Jonas Rebmann <kernel@schlaraffenlan.de> writes:
> While checking whether all output messages of git bisect were covered by
> [PATCH 1/3] bisect: use selected alternate terms in status output I
> found hardcoded good/bad refs leading to incompatibility of git
> rev-parse --bisect with alternate bisect run terms. This is addressed by
> [PATCH 3/3] rev-parse: use selected alternate terms to look up refs
>
> Signed-off-by: Jonas Rebmann <kernel@schlaraffenlan.de>
> ---
> Changes in v4:
> - Always print bisect terms in single quote (Thanks, Junio)
> - Split out quoting of bisect terms into separate commit
>> - Link to v3: https://patch.msgid.link/20260417-bisect-terms-v3-0-d659fa547261@schlaraffenlan.de
Having this "Link" is better than nothing, but it alone is not
sufficient to help those who mechanise patch consumption with b4.
https://b4.docs.kernel.org/en/latest/index.html
Please make sure that your cover letter of the (i+1)th iteration
[v(i+1) 0/N] is a reply to the cover letter of the i-th iteration
[v(i) 0/M]. With that, anybody who has the i-th iteration can
1. Check out the i-th iteration, e.g.,
$ git checkout jr/bisect-custom-terms-in-output
2. Peek at any of the commits on the topic branch with notes/amlog
e.g.,
$ git notes --ref=amlog show HEAD
3. Check out the base, e.g.,
$ git checkout --detach master...
Note that the branch that holds the i-th iteration can now be
accessed via @{-1} (i.e., the branch previously checked out).
4. Tell B4 to fetch the latest round of the same series, by giving
one/any of the message-ID we learned earlier, and apply them.
$ b4 am -o- \
"<20260417-bisect-terms-v3-2-d659fa547261@schlaraffenlan.de>" |
git am -s
5. See what changed with range-diff
$ git range-diff @{-1}...
6. When satisified, replace the topic with the new iteration.
$ git checkout -B @{-1}
It is crucial that b4 can find the newer iteration when given a
message-ID from the older iteration in step 4 for this workflow to
work, and for that, [v4 0/3] must be a reply to [v3 0/2]. Otherwise
b4 will say that v3 is still the last iteration and we cannot make
progress.
> Changes in v3:
> - when referencing newly introduced terms, reference them in single
> quotes (Thanks, Phillip)
> - Prefer test_grep over grep in updated Tests (Thanks, Phillip)
> - Improve commit messages (Thanks, Phillip)
> - Don't leak memory after read_bisect_terms() (Thanks, Phillip)
> - Don't leak memory after xstrfmt() (Thanks, Junio)
> - Add test case to patch 2/2
> - Link to v2: https://patch.msgid.link/20260323-bisect-terms-v2-0-8d6bdb2c9c7e@schlaraffenlan.de
With these improvements, v3 was already in a quite good shape, but
the latest makes it look even better. Will replace. Thanks.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v4 0/3] Avoid hardcoded "good"/"bad" bisect terms
2026-05-14 19:56 ` [PATCH v4 0/3] Avoid hardcoded "good"/"bad" bisect terms Junio C Hamano
@ 2026-05-15 8:07 ` Jonas Rebmann
0 siblings, 0 replies; 6+ messages in thread
From: Jonas Rebmann @ 2026-05-15 8:07 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Chris Down, Jeff King, Phillip Wood
On 14/05/2026 21.56, Junio C Hamano wrote:
> Please make sure that your cover letter of the (i+1)th iteration
> [v(i+1) 0/N] is a reply to the cover letter of the i-th iteration
> [v(i) 0/M]. With that, anybody who has the i-th iteration can
> [...]
Thanks, I never knew! I've now set
git config b4.send-same-thread yes
so b4 will send future rerolls In-Reply-To the cover of the
previous version.
Regards,
Jonas
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-05-15 8:07 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-14 9:07 [PATCH v4 0/3] Avoid hardcoded "good"/"bad" bisect terms Jonas Rebmann
2026-05-14 9:07 ` [PATCH v4 1/3] bisect: use selected alternate terms in status output Jonas Rebmann
2026-05-14 9:07 ` [PATCH v4 2/3] bisect: print bisect terms in single quotes Jonas Rebmann
2026-05-14 9:07 ` [PATCH v4 3/3] rev-parse: use selected alternate terms to look up refs Jonas Rebmann
2026-05-14 19:56 ` [PATCH v4 0/3] Avoid hardcoded "good"/"bad" bisect terms Junio C Hamano
2026-05-15 8:07 ` Jonas Rebmann
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.