git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2] diff: stop output garbled message in dry run mode

From
Lidong Yan <yldhome2d2@gmail.com>
Date
Oct 18, 2025, 09:48 UTC
Message-ID
<20251018094823.31173-1-yldhome2d2@gmail.com>
In-Reply-To
<pull.2071.git.git.1760671049113.gitgitgadget@gmail.com>

Earlier, b55e6d36 (diff: ensure consistent diff behavior with ignore options, 2025-08-08) introduced "dry-run" mode to the diff machinery so that content-based diff filtering (like ignoring space changes or those that match -I<regex>) can first try to produce a patch without emitting any output to see if under the given diff filtering condition we would get any output lines, and a new helper function diff_flush_patch_quietly() was introduced to use the mode to see an individual filepair needs to be shown.

However, the solution was not complete. When files are deleted, file modes change, or there are unmerged entries in the index, dry-run mode still produces output because we overlooked these conditions, and as a result, dry-run mode was not quiet.

Since dry-run mode is only set in diff_flush_patch_quietly(), setting the output file to "/dev/null" within diff_flush_patch_quietly() ensures no output is emitted in dry-run mode. To improve performance of dry-run mode, add a check before outputting to determine if we should exit early to avoid unnecessary output processing.

Signed-off-by: Lidong Yan <yldhome2d2@gmail.com>
---
I copied Peff's code from https://lore.kernel.org/git/20251017083641.GB4073661@coredump.intra.peff.net/
 diff.c                  | 20 ++++++++++++++++++--
 t/t4013-diff-various.sh | 37 +++++++++++++++++++++++++++++++++++++
 t/t4035-diff-quiet.sh   |  4 ++++
 3 files changed, 59 insertions(+), 2 deletions(-)
diff --git a/diff.c b/diff.c
index 87fa16b730..ec05ac565b 100644
--- a/diff.c
+++ b/diff.c
@@ -1351,6 +1351,9 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
 	int len = eds->len;
 	unsigned flags = eds->flags;
 
+	if (o->dry_run)
+		return;
+
 	switch (s) {
 	case DIFF_SYMBOL_NO_LF_EOF:
 		context = diff_get_color_opt(o, DIFF_CONTEXT);
@@ -4420,7 +4423,7 @@ static void run_external_diff(const struct external_diff *pgm,
 {
 	struct child_process cmd = CHILD_PROCESS_INIT;
 	struct diff_queue_struct *q = &diff_queued_diff;
-	int quiet = !(o->output_format & DIFF_FORMAT_PATCH);
+	int quiet = !(o->output_format & DIFF_FORMAT_PATCH) || o->dry_run;
 	int rc;
 
 	/*
@@ -4615,7 +4618,8 @@ static void run_diff_cmd(const struct external_diff *pgm,
 		    p->status == DIFF_STATUS_RENAMED)
 			o->found_changes = 1;
 	} else {
-		fprintf(o->file, "* Unmerged path %s\n", name);
+		if (!o->dry_run)
+			fprintf(o->file, "* Unmerged path %s\n", name);
 		o->found_changes = 1;
 	}
 }
@@ -6194,14 +6198,26 @@ static int diff_flush_patch_quietly(struct diff_filepair *p, struct diff_options
 {
 	int saved_dry_run = o->dry_run;
 	int saved_found_changes = o->found_changes;
+	int saved_color_moved = o->color_moved;
+	int saved_close_file = o->close_file;
+	FILE *saved_file = o->file;
 	int ret;
 
 	o->dry_run = 1;
 	o->found_changes = 0;
+	o->color_moved = 0;
+	o->close_file = 1;
+	o->file = xfopen("/dev/null", "w");
 	diff_flush_patch(p, o);
 	ret = o->found_changes;
+	if (o->file)
+		fclose(o->file);
+
 	o->dry_run = saved_dry_run;
 	o->found_changes |= saved_found_changes;
+	o->color_moved = saved_color_moved;
+	o->close_file = saved_close_file;
+	o->file = saved_file;
 	return ret;
 }
 
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 55a06eadb3..2f8fe191b8 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -661,6 +661,43 @@ test_expect_success 'diff -I<regex>: ignore matching file' '
 	test_grep ! "file1" actual
 '
 
+test_expect_success 'diff -I<regex>: ignore all content changes' '
+	test_when_finished "git rm -f file1 file2 file3" &&
+	: >file1 &&
+	git add file1 &&
+	: >file2 &&
+	git add file2 &&
+	: >file3 &&
+	git add file3 &&
+
+	echo "A" >file3 &&
+	A_hash=$(git hash-object -w file3) &&
+	echo "B" >file3 &&
+	B_hash=$(git hash-object -w file3) &&
+	cat <<-EOF | git update-index --index-info &&
+	100644 $A_hash 1	file3
+	100644 $B_hash 2	file3
+	EOF
+
+	rm -f file1 file2 &&
+	mkdir file2 &&
+	test_diff_no_content_changes () {
+		git diff $1 --ignore-blank-lines -I".*" >actual &&
+		test_line_count = 3 actual &&
+		test_grep "file1" actual &&
+		test_grep "file2" actual &&
+		test_grep "file3" actual &&
+		test_grep ! "diff --git" actual
+	} &&
+	test_diff_no_content_changes "--raw" &&
+	test_diff_no_content_changes "--name-only" &&
+	test_diff_no_content_changes "--name-status" &&
+
+	: >actual &&
+	test_must_fail git diff --quiet -I".*" >actual &&
+	test_must_be_empty actual
+'
+
 # check_prefix <patch> <src> <dst>
 # check only lines with paths to avoid dependency on exact oid/contents
 check_prefix () {
diff --git a/t/t4035-diff-quiet.sh b/t/t4035-diff-quiet.sh
index 0352bf81a9..35eaf0855f 100755
--- a/t/t4035-diff-quiet.sh
+++ b/t/t4035-diff-quiet.sh
@@ -50,6 +50,10 @@ test_expect_success 'git diff-tree HEAD HEAD' '
 	test_expect_code 0 git diff-tree --quiet HEAD HEAD >cnt &&
 	test_line_count = 0 cnt
 '
+test_expect_success 'git diff-tree -w HEAD^ HEAD' '
+	test_expect_code 1 git diff-tree --quiet -w HEAD^ HEAD >cnt &&
+	test_line_count = 0 cnt
+'
 test_expect_success 'git diff-files' '
 	test_expect_code 0 git diff-files --quiet >cnt &&
 	test_line_count = 0 cnt
-- 
2.50.1 (Apple Git-155)
Previous: Junio C HamanoNext: Lidong Yan
Message 15 of 21 in “diff: stop output garbled message in dry run mode”
  1. diff: stop output garbled message in dry run modeLidong Yan via GitGitGadget, Oct 17, 2025
  2. Johannes SchindelinOct 17, 2025
  3. Junio C HamanoOct 17, 2025
  4. Junio C HamanoOct 17, 2025
  5. Junio C HamanoOct 17, 2025
  6. Junio C HamanoOct 17, 2025
  7. Lidong YanOct 18, 2025
  8. Junio C HamanoOct 18, 2025
  9. Jeff KingOct 18, 2025
  10. Lidong YanOct 18, 2025
  11. Jeff KingOct 18, 2025
  12. Junio C HamanoOct 18, 2025
  13. Lidong YanOct 19, 2025
  14. Junio C HamanoOct 19, 2025
  15. diff: stop output garbled message in dry run modeLidong Yan, Oct 18, 2025
  16. diff: stop output garbled message in dry run modeLidong Yan, Oct 19, 2025
  17. diff: stop output garbled message in dry run modeLidong Yan, Oct 19, 2025
  18. Junio C HamanoOct 22, 2025
  19. Junio C HamanoOct 22, 2025
  20. Lidong YanOct 23, 2025
  21. Jeff KingOct 23, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.