From: Junio C Hamano <hidden> Date: 2026-03-05 19:13:17
Francesco Paparatto [off-list ref] writes:
Running `git` commands inside command substitutions like
test "$(git rev-parse A)" = "$(git rev-parse B)"
can hide failures from the `git` invocations and provide little
diagnostic information when `test` fails.
Use `test_cmp` when comparing against a stored expected value so
mismatches show both expected and actual output. Use `test_cmp_rev`
when comparing two revisions. These helpers produce clearer failure
output, making it easier to understand what went wrong.
Suggested-by: Junio C Hamano <redacted>
Hmph, did I suggest this? I know Eric had comments on a previous
round, and the improvements in this patch seems to be influenced a
lot stronger by his input than whatever I may have said.
From: Eric Sunshine <hidden> Date: 2026-03-05 22:34:34
On Thu, Mar 5, 2026 at 2:13 PM Junio C Hamano [off-list ref] wrote:
quoted
Running `git` commands inside command substitutions like
test "$(git rev-parse A)" = "$(git rev-parse B)"
can hide failures from the `git` invocations and provide little
diagnostic information when `test` fails.
Use `test_cmp` when comparing against a stored expected value so
mismatches show both expected and actual output. Use `test_cmp_rev`
when comparing two revisions. These helpers produce clearer failure
output, making it easier to understand what went wrong.
Suggested-by: Junio C Hamano <redacted>
Hmph, did I suggest this? I know Eric had comments on a previous
round, and the improvements in this patch seems to be influenced a
lot stronger by his input than whatever I may have said.
Indeed. The use of test_cmp and test_cmp_rev makes this version much
more developer-friendly than v1. Nice.
On top of what commit is this patch designed to apply?
What Junio probably means is that you appear to have based v2 atop v1,
but instead you should squash v1 and v2 into a single patch, and send
that as v3 so that when the patch is finally accepted into his tree,
it will appear to have been perfect from the start (because v1 and v2
will only exist in the mailing list archive, not in the Git project
history).
From: Francesco Paparatto <hidden> Date: 2026-03-05 22:42:24
Junio C Hamano [off-list ref] writes:
Hmph, did I suggest this? I know Eric had comments on a previous
round, and the improvements in this patch seems to be influenced a
lot stronger by his input than whatever I may have said.
Sorry about the Suggested-by line. I added it because of your earlier
comment here:
https://public-inbox.org/git/xmqqv7fioueg.fsf@gitster.g/
but you're right that the concrete changes in this version were mostly
influenced by Eric's review, so I'll drop that trailer.
On top of what commit is this patch designed to apply?
This patch is based on top of:
b3ec5aec2367262f464a33d6eab7a9f49fd413f1
("t3310: replace test -f/-d with test_path_is_file/test_path_is_dir")
I'll reroll and send a v3 of the patch shortly.
Thanks,
Francesco
From: Francesco Paparatto <hidden> Date: 2026-03-05 22:49:43
Eric Sunshine [off-list ref] writes:
What Junio probably means is that you appear to have based v2 atop v1,
but instead you should squash v1 and v2 into a single patch, and send
that as v3 so that when the patch is finally accepted into his tree,
it will appear to have been perfect from the start (because v1 and v2
will only exist in the mailing list archive, not in the Git project
history).
Sorry about that, and thanks for the clarification.
I've squashed the changes and rerolled the patch based on your
suggestions. I've just sent v3 to the list.
Thanks,
Francesco
From: Francesco Paparatto <hidden> Date: 2026-03-05 22:51:47
Running `git` commands inside command substitutions like
test "$(git rev-parse A)" = "$(git rev-parse B)"
can hide failures from the `git` invocations and provide little
diagnostic information when `test` fails.
Use `test_cmp` when comparing against a stored expected value so
mismatches show both expected and actual output. Use `test_cmp_rev`
when comparing two revisions. These helpers produce clearer failure
output, making it easier to understand what went wrong.
Suggested-by: Eric Sunshine <redacted>
Signed-off-by: Francesco Paparatto <redacted>
---
t/t3310-notes-merge-manual-resolve.sh | 48 +++++++++++++++++----------
1 file changed, 30 insertions(+), 18 deletions(-)
@@ -227,7 +227,8 @@ test_expect_success 'merge z into m (== y) with default ("manual") resolver => C# Verify that current notes tree (pre-merge) has not changed (m == y)verify_notesy&&verify_notesm&&-test"$(gitrev-parserefs/notes/m)"="$(catpre_merge_y)"+gitrev-parserefs/notes/m>actual&&+test_cmppre_merge_yactual' cat<<EOF|sort>expect_notes_z
@@ -375,8 +376,10 @@ EOFgitnotesmerge--commit&¬es_merge_files_gone&&# Merge commit has pre-merge y and pre-merge z as parents-test"$(gitrev-parserefs/notes/m^1)"="$(catpre_merge_y)"&&-test"$(gitrev-parserefs/notes/m^2)"="$(catpre_merge_z)"&&+gitrev-parserefs/notes/m^1>actual&&+test_cmppre_merge_yactual&&+gitrev-parserefs/notes/m^2>actual&&+test_cmppre_merge_zactual&&# Merge commit mentions the notes refs mergedgitlog-1--format=%Brefs/notes/m>merge_commit_msg&&grep-qrefs/notes/mmerge_commit_msg&&
@@ -428,14 +431,16 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol# Verify that current notes tree (pre-merge) has not changed (m == y)verify_notesy&&verify_notesm&&-test"$(gitrev-parserefs/notes/m)"="$(catpre_merge_y)"+gitrev-parserefs/notes/m>actual&&+test_cmppre_merge_yactual' test_expect_success'abort notes merge''gitnotesmerge--abort&¬es_merge_files_gone&&# m has not moved (still == y)-test"$(gitrev-parserefs/notes/m)"="$(catpre_merge_y)"&&+gitrev-parserefs/notes/m>actual&&+test_cmppre_merge_yactual&&# Verify that other notes refs has not changed (w, x, y and z)verify_notesw&&verify_notesx&&
@@ -460,7 +465,8 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol# Verify that current notes tree (pre-merge) has not changed (m == y)verify_notesy&&verify_notesm&&-test"$(gitrev-parserefs/notes/m)"="$(catpre_merge_y)"+gitrev-parserefs/notes/m>actual&&+test_cmppre_merge_yactual' cat<<EOF|sort>expect_notes_m
@@ -500,8 +506,10 @@ EOFgitnotesmerge--commit&¬es_merge_files_gone&&# Merge commit has pre-merge y and pre-merge z as parents-test"$(gitrev-parserefs/notes/m^1)"="$(catpre_merge_y)"&&-test"$(gitrev-parserefs/notes/m^2)"="$(catpre_merge_z)"&&+gitrev-parserefs/notes/m^1>actual&&+test_cmppre_merge_yactual&&+gitrev-parserefs/notes/m^2>actual&&+test_cmppre_merge_zactual&&# Merge commit mentions the notes refs mergedgitlog-1--format=%Brefs/notes/m>merge_commit_msg&&grep-qrefs/notes/mmerge_commit_msg&&
@@ -539,7 +547,8 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol# Verify that current notes tree (pre-merge) has not changed (m == y)verify_notesy&&verify_notesm&&-test"$(gitrev-parserefs/notes/m)"="$(catpre_merge_y)"+gitrev-parserefs/notes/m>actual&&+test_cmppre_merge_yactual' cpexpect_notes_wexpect_notes_m
@@ -548,7 +557,7 @@ cp expect_log_w expect_log_m test_expect_success'reset notes ref m to somewhere else (w)''gitupdate-refrefs/notes/mrefs/notes/w&&verify_notesm&&-test"$(gitrev-parserefs/notes/m)"="$(gitrev-parserefs/notes/w)"+test_cmp_revrefs/notes/mrefs/notes/w' test_expect_success'fail to finalize conflicting merge if underlying ref has moved in the meantime (m != NOTES_MERGE_PARTIAL^1)''
@@ -569,13 +578,15 @@ EOFtest_path_is_file.git/NOTES_MERGE_WORKTREE/$commit_sha3&&test_path_is_file.git/NOTES_MERGE_WORKTREE/$commit_sha4&&# Refs are unchanged-test"$(gitrev-parserefs/notes/m)"="$(gitrev-parserefs/notes/w)"&&-test"$(gitrev-parserefs/notes/y)"="$(gitrev-parseNOTES_MERGE_PARTIAL^1)"&&-test"$(gitrev-parserefs/notes/m)"!="$(gitrev-parseNOTES_MERGE_PARTIAL^1)"&&+test_cmp_revrefs/notes/mrefs/notes/w&&+test_cmp_revrefs/notes/yNOTES_MERGE_PARTIAL^1&&+test_cmp_rev!refs/notes/mNOTES_MERGE_PARTIAL^1&&# Mention refs/notes/m, and its current and expected value in outputtest_grep-q"refs/notes/m"output&&-test_grep-q"$(gitrev-parserefs/notes/m)"output&&-test_grep-q"$(gitrev-parseNOTES_MERGE_PARTIAL^1)"output&&+gitrev-parserefs/notes/m>actual&&+test_grep-q"$(catactual)"output&&+gitrev-parseNOTES_MERGE_PARTIAL^1>actual&&+test_grep-q"$(catactual)"output&&# Verify that other notes refs has not changed (w, x, y and z)verify_notesw&&verify_notesx&&
@@ -587,7 +598,7 @@ test_expect_success 'resolve situation by aborting the notes merge' 'gitnotesmerge--abort&¬es_merge_files_gone&&# m has not moved (still == w)-test"$(gitrev-parserefs/notes/m)"="$(gitrev-parserefs/notes/w)"&&+test_cmp_revrefs/notes/mrefs/notes/w&&# Verify that other notes refs has not changed (w, x, y and z)verify_notesw&&verify_notesx&&
From: Eric Sunshine <hidden> Date: 2026-03-07 06:29:45
On Thu, Mar 5, 2026 at 5:51 PM Francesco Paparatto
[off-list ref] wrote:
Running `git` commands inside command substitutions like
test "$(git rev-parse A)" = "$(git rev-parse B)"
can hide failures from the `git` invocations and provide little
diagnostic information when `test` fails.
Use `test_cmp` when comparing against a stored expected value so
mismatches show both expected and actual output. Use `test_cmp_rev`
when comparing two revisions. These helpers produce clearer failure
output, making it easier to understand what went wrong.
Suggested-by: Eric Sunshine <redacted>
Signed-off-by: Francesco Paparatto <redacted>
---
Thank you. This version looks much better and addresses my review
comments on the previous round. I do have one actionable
recommendation and one subjective comment, though...
Storing the output of git-rev-parse in a file only to read it back out
of that file a moment later is unnecessarily roundabout. It would
instead be cleaner to do it this way:
oid=$(git rev-parse refs/notes/m) &&
test_grep -q "$oid" output &&
oid=$(git rev-parse NOTES_MERGE_PARTIAL^1) &&
test_grep -q "$oid" output &&
Unlike this original in which git-rev-parse's exit code was lost due
to being embedded in the test_grep invocation, this rewrite is safe
because the exit code of git-rev-parse becomes the exit code of the
variable assignment, thus correctly aborts the test (due to the
&&-chain) if git-rev-parse fails.
This is purely subjective and you don't have to take the suggestion,
but although yours is a faithful rewrite (which is good), I probably
would have simplified this to:
oid=$(git rev-parse HEAD) &&
test_write_lines foo bar >"$oid" &&
Storing the output of git-rev-parse in a file only to read it back out
of that file a moment later is unnecessarily roundabout. It would
instead be cleaner to do it this way:
oid=$(git rev-parse refs/notes/m) &&
test_grep -q "$oid" output &&
oid=$(git rev-parse NOTES_MERGE_PARTIAL^1) &&
test_grep -q "$oid" output &&
Unlike this original in which git-rev-parse's exit code was lost due
to being embedded in the test_grep invocation, this rewrite is safe
because the exit code of git-rev-parse becomes the exit code of the
variable assignment, thus correctly aborts the test (due to the
&&-chain) if git-rev-parse fails.
This is purely subjective and you don't have to take the suggestion,
but although yours is a faithful rewrite (which is good), I probably
would have simplified this to:
oid=$(git rev-parse HEAD) &&
test_write_lines foo bar >"$oid" &&
Thanks for the review. Both suggestions make sense. I'll use the
variable assignment for the rev-parse cases and test_write_lines for
the foo/bar case. I will send v4 shortly.
From: Francesco Paparatto <hidden> Date: 2026-03-07 10:36:38
Running `git` commands inside command substitutions like
test "$(git rev-parse A)" = "$(git rev-parse B)"
can hide failures from the `git` invocations and provide little
diagnostic information when `test` fails.
Use `test_cmp` when comparing against a stored expected value so
mismatches show both expected and actual output. Use `test_cmp_rev`
when comparing two revisions. These helpers produce clearer failure
output, making it easier to understand what went wrong.
Suggested-by: Eric Sunshine <redacted>
Signed-off-by: Francesco Paparatto <redacted>
---
t/t3310-notes-merge-manual-resolve.sh | 47 +++++++++++++++++----------
1 file changed, 29 insertions(+), 18 deletions(-)
@@ -227,7 +227,8 @@ test_expect_success 'merge z into m (== y) with default ("manual") resolver => C# Verify that current notes tree (pre-merge) has not changed (m == y)verify_notesy&&verify_notesm&&-test"$(gitrev-parserefs/notes/m)"="$(catpre_merge_y)"+gitrev-parserefs/notes/m>actual&&+test_cmppre_merge_yactual' cat<<EOF|sort>expect_notes_z
@@ -375,8 +376,10 @@ EOFgitnotesmerge--commit&¬es_merge_files_gone&&# Merge commit has pre-merge y and pre-merge z as parents-test"$(gitrev-parserefs/notes/m^1)"="$(catpre_merge_y)"&&-test"$(gitrev-parserefs/notes/m^2)"="$(catpre_merge_z)"&&+gitrev-parserefs/notes/m^1>actual&&+test_cmppre_merge_yactual&&+gitrev-parserefs/notes/m^2>actual&&+test_cmppre_merge_zactual&&# Merge commit mentions the notes refs mergedgitlog-1--format=%Brefs/notes/m>merge_commit_msg&&grep-qrefs/notes/mmerge_commit_msg&&
@@ -428,14 +431,16 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol# Verify that current notes tree (pre-merge) has not changed (m == y)verify_notesy&&verify_notesm&&-test"$(gitrev-parserefs/notes/m)"="$(catpre_merge_y)"+gitrev-parserefs/notes/m>actual&&+test_cmppre_merge_yactual' test_expect_success'abort notes merge''gitnotesmerge--abort&¬es_merge_files_gone&&# m has not moved (still == y)-test"$(gitrev-parserefs/notes/m)"="$(catpre_merge_y)"&&+gitrev-parserefs/notes/m>actual&&+test_cmppre_merge_yactual&&# Verify that other notes refs has not changed (w, x, y and z)verify_notesw&&verify_notesx&&
@@ -460,7 +465,8 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol# Verify that current notes tree (pre-merge) has not changed (m == y)verify_notesy&&verify_notesm&&-test"$(gitrev-parserefs/notes/m)"="$(catpre_merge_y)"+gitrev-parserefs/notes/m>actual&&+test_cmppre_merge_yactual' cat<<EOF|sort>expect_notes_m
@@ -500,8 +506,10 @@ EOFgitnotesmerge--commit&¬es_merge_files_gone&&# Merge commit has pre-merge y and pre-merge z as parents-test"$(gitrev-parserefs/notes/m^1)"="$(catpre_merge_y)"&&-test"$(gitrev-parserefs/notes/m^2)"="$(catpre_merge_z)"&&+gitrev-parserefs/notes/m^1>actual&&+test_cmppre_merge_yactual&&+gitrev-parserefs/notes/m^2>actual&&+test_cmppre_merge_zactual&&# Merge commit mentions the notes refs mergedgitlog-1--format=%Brefs/notes/m>merge_commit_msg&&grep-qrefs/notes/mmerge_commit_msg&&
@@ -539,7 +547,8 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol# Verify that current notes tree (pre-merge) has not changed (m == y)verify_notesy&&verify_notesm&&-test"$(gitrev-parserefs/notes/m)"="$(catpre_merge_y)"+gitrev-parserefs/notes/m>actual&&+test_cmppre_merge_yactual' cpexpect_notes_wexpect_notes_m
@@ -548,7 +557,7 @@ cp expect_log_w expect_log_m test_expect_success'reset notes ref m to somewhere else (w)''gitupdate-refrefs/notes/mrefs/notes/w&&verify_notesm&&-test"$(gitrev-parserefs/notes/m)"="$(gitrev-parserefs/notes/w)"+test_cmp_revrefs/notes/mrefs/notes/w' test_expect_success'fail to finalize conflicting merge if underlying ref has moved in the meantime (m != NOTES_MERGE_PARTIAL^1)''
@@ -569,13 +578,15 @@ EOFtest_path_is_file.git/NOTES_MERGE_WORKTREE/$commit_sha3&&test_path_is_file.git/NOTES_MERGE_WORKTREE/$commit_sha4&&# Refs are unchanged-test"$(gitrev-parserefs/notes/m)"="$(gitrev-parserefs/notes/w)"&&-test"$(gitrev-parserefs/notes/y)"="$(gitrev-parseNOTES_MERGE_PARTIAL^1)"&&-test"$(gitrev-parserefs/notes/m)"!="$(gitrev-parseNOTES_MERGE_PARTIAL^1)"&&+test_cmp_revrefs/notes/mrefs/notes/w&&+test_cmp_revrefs/notes/yNOTES_MERGE_PARTIAL^1&&+test_cmp_rev!refs/notes/mNOTES_MERGE_PARTIAL^1&&# Mention refs/notes/m, and its current and expected value in outputtest_grep-q"refs/notes/m"output&&-test_grep-q"$(gitrev-parserefs/notes/m)"output&&-test_grep-q"$(gitrev-parseNOTES_MERGE_PARTIAL^1)"output&&+oid=$(gitrev-parserefs/notes/m)&&+test_grep-q"$oid"output&&+oid=$(gitrev-parseNOTES_MERGE_PARTIAL^1)&&+test_grep-q"$oid"output&&# Verify that other notes refs has not changed (w, x, y and z)verify_notesw&&verify_notesx&&
@@ -587,7 +598,7 @@ test_expect_success 'resolve situation by aborting the notes merge' 'gitnotesmerge--abort&¬es_merge_files_gone&&# m has not moved (still == w)-test"$(gitrev-parserefs/notes/m)"="$(gitrev-parserefs/notes/w)"&&+test_cmp_revrefs/notes/mrefs/notes/w&&# Verify that other notes refs has not changed (w, x, y and z)verify_notesw&&verify_notesx&&
From: Eric Sunshine <hidden> Date: 2026-03-08 04:13:15
On Sat, Mar 7, 2026 at 5:36 AM Francesco Paparatto
[off-list ref] wrote:
quoted hunk
Running `git` commands inside command substitutions like
test "$(git rev-parse A)" = "$(git rev-parse B)"
can hide failures from the `git` invocations and provide little
diagnostic information when `test` fails.
Use `test_cmp` when comparing against a stored expected value so
mismatches show both expected and actual output. Use `test_cmp_rev`
when comparing two revisions. These helpers produce clearer failure
output, making it easier to understand what went wrong.
Suggested-by: Eric Sunshine <redacted>
Signed-off-by: Francesco Paparatto <redacted>
---