From 5d25d5d57b28c5e82ac92f4529f217bedbc18772 Mon Sep 17 00:00:00 2001 From: Justin Tobler Date: Fri, 10 Oct 2025 16:52:54 -0500 Subject: [PATCH] diff: add option to report whether files are binary When generating diff output, if either side of a filepair is detected as binary, Git omits the diff content and instead prints a "Binary files differ" message. In some cases, it can be useful to know which files were detected as binary and which were treated as text. Introduce a new `--report-binary-files` diff option that, when enabled, appends a line for each file indicating whether Git considered it binary or text. Signed-off-by: Justin Tobler --- Documentation/diff-options.adoc | 5 +++++ diff.c | 19 +++++++++++++++++++ diff.h | 7 +++++++ t/t4012-diff-binary.sh | 27 +++++++++++++++++++++++++++ 4 files changed, 58 insertions(+) diff --git a/Documentation/diff-options.adoc b/Documentation/diff-options.adoc index ae31520f7f1..6af1702bf50 100644 --- a/Documentation/diff-options.adoc +++ b/Documentation/diff-options.adoc @@ -544,6 +544,11 @@ ifndef::git-format-patch[] Implies `--patch`. endif::git-format-patch[] +`--report-binary-files`:: + In scenarios where Git detects a binary file and prints a "Binary files + differ" message, also report whether each file in the diff was + considered binary or text. + `--abbrev[=]`:: Instead of showing the full 40-byte hexadecimal object name in diff-raw format output and diff-tree header diff --git a/diff.c b/diff.c index 87fa16b730d..a8ca4550b93 100644 --- a/diff.c +++ b/diff.c @@ -3534,6 +3534,15 @@ static int set_diff_algorithm(struct diff_options *opts, return 0; } +static void report_binary_file(struct strbuf *buf, + struct repository *repo, + struct diff_filespec *spec, + const char *path) +{ + const char *type = diff_filespec_is_binary(repo, spec) ? "binary" : "text"; + strbuf_addf(buf, "%s: %s\n", path, type); +} + static void builtin_diff(const char *name_a, const char *name_b, struct diff_filespec *one, @@ -3675,6 +3684,10 @@ static void builtin_diff(const char *name_a, header.buf, header.len, 0); strbuf_addf(&sb, "%sBinary files %s and %s differ\n", diff_line_prefix(o), lbl[0], lbl[1]); + if (o->report_binary_files) { + report_binary_file(&sb, o->repo, one, lbl[0]); + report_binary_file(&sb, o->repo, two, lbl[1]); + } emit_diff_symbol(o, DIFF_SYMBOL_BINARY_FILES, sb.buf, sb.len, 0); strbuf_release(&sb); @@ -3699,6 +3712,10 @@ static void builtin_diff(const char *name_a, else { strbuf_addf(&sb, "%sBinary files %s and %s differ\n", diff_line_prefix(o), lbl[0], lbl[1]); + if (o->report_binary_files) { + report_binary_file(&sb, o->repo, one, lbl[0]); + report_binary_file(&sb, o->repo, two, lbl[1]); + } emit_diff_symbol(o, DIFF_SYMBOL_BINARY_FILES, sb.buf, sb.len, 0); strbuf_release(&sb); @@ -5741,6 +5758,8 @@ struct option *add_diff_options(const struct option *opts, OPT_CALLBACK_F(0, "binary", options, NULL, N_("output a binary diff that can be applied"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, diff_opt_binary), + OPT_BOOL(0, "report-binary-files", &options->report_binary_files, + N_("report if pre- and post-image blobs are binary")), OPT_BOOL(0, "full-index", &options->flags.full_index, N_("show full pre- and post-image object names on the \"index\" lines")), OPT_COLOR_FLAG(0, "color", &options->use_color, diff --git a/diff.h b/diff.h index 2fa256c3ef0..9024807ea9e 100644 --- a/diff.h +++ b/diff.h @@ -369,6 +369,13 @@ struct diff_options { */ int skip_resolving_statuses; + /* + * When generating patch diff output and a binary file is encountered, + * after printing the "Binary files differ" message, append a line for + * each file indicating whether Git considered it binary or text. + */ + int report_binary_files; + /* Callback which allows tweaking the options in diff_setup_done(). */ void (*set_default)(struct diff_options *); diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh index d1d30ac2a94..81793713158 100755 --- a/t/t4012-diff-binary.sh +++ b/t/t4012-diff-binary.sh @@ -130,4 +130,31 @@ test_expect_success 'diff --stat with binary files and big change count' ' test_cmp expect actual ' +test_expect_success 'diff --report-binary-files' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + + echo foo >foo && + git add foo && + git commit -m foo && + + printf "\0foo\0" >foo && + git commit -am binary && + + cat >expect <<-\EOF && + diff --git a/foo b/foo + index 257cc56..a60073c 100644 + Binary files a/foo and b/foo differ + a/foo: text + b/foo: binary + EOF + + git diff --report-binary-files HEAD~ HEAD >out && + + test_cmp expect out + ) +' + test_done -- GitLab