Git development
 help / color / mirror / Atom feed
* [PATCH] combine-diff: honor --relative when printing paths
@ 2026-10-07  5:17 Muhammed Dilshad A
  2026-10-07 14:45 ` Junio C Hamano
  0 siblings, 1 reply; 7+ messages in thread
From: Muhammed Dilshad A @ 2026-10-07  5:17 UTC (permalink / raw)
  To: git; +Cc: Muhammed Dilshad A

During a merge conflict, "git diff --relative" in a subdirectory still
prints paths from the repository root. Combined raw output does the same.

Strip the requested prefix when printing these paths. Keep the original
paths for reading files from the working tree.

Make the known failure in t4045 a passing test, and cover explicit
prefixes, --no-relative, raw and NUL-separated output, quoted filenames
and renamed parent paths.

Signed-off-by: Muhammed Dilshad A <dilsheddilu123@gmail.com>
---
 combine-diff.c           | 19 +++++++++---
 t/t4038-diff-combined.sh | 22 ++++++++++++++
 t/t4045-diff-relative.sh | 62 +++++++++++++++++++++++++++++++++++++++-
 3 files changed, 98 insertions(+), 5 deletions(-)

diff --git a/combine-diff.c b/combine-diff.c
index 717d537688..78d2852cce 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -902,6 +902,14 @@ static void reuse_combine_diff(struct sline *sline, unsigned long cnt,
 	sline->p_lno[i] = sline->p_lno[j];
 }
 
+static const char *strip_relative_prefix(const struct diff_options *opt,
+					const char *path)
+{
+	if (opt->prefix && skip_prefix(path, opt->prefix, &path) && *path == '/')
+		path++;
+	return path;
+}
+
 static void dump_quoted_path(const char *head,
 			     const char *prefix,
 			     const char *path,
@@ -932,6 +940,7 @@ static void show_combined_header(struct combine_diff_path *elem,
 	const char *b_prefix = opt->b_prefix ? opt->b_prefix : "b/";
 	const char *c_meta = diff_get_color_opt(opt, DIFF_METAINFO);
 	const char *c_reset = diff_get_color_opt(opt, DIFF_RESET);
+	const char *name = strip_relative_prefix(opt, elem->path);
 	const char *abb;
 	int added = 0;
 	int deleted = 0;
@@ -942,7 +951,7 @@ static void show_combined_header(struct combine_diff_path *elem,
 		show_log(rev);
 
 	dump_quoted_path(dense ? "diff --cc " : "diff --combined ",
-			 "", elem->path, line_prefix, c_meta, c_reset);
+			 "", name, line_prefix, c_meta, c_reset);
 	printf("%s%sindex ", line_prefix, c_meta);
 	for (i = 0; i < num_parent; i++) {
 		abb = repo_find_unique_abbrev(the_repository,
@@ -987,6 +996,7 @@ static void show_combined_header(struct combine_diff_path *elem,
 			const char *path = elem->parent[i].path ?
 					   elem->parent[i].path :
 					   elem->path;
+			path = strip_relative_prefix(opt, path);
 			if (elem->parent[i].status == DIFF_STATUS_ADDED)
 				dump_quoted_path("--- ", "", "/dev/null",
 						 line_prefix, c_meta, c_reset);
@@ -999,14 +1009,14 @@ static void show_combined_header(struct combine_diff_path *elem,
 			dump_quoted_path("--- ", "", "/dev/null",
 					 line_prefix, c_meta, c_reset);
 		else
-			dump_quoted_path("--- ", a_prefix, elem->path,
+			dump_quoted_path("--- ", a_prefix, name,
 					 line_prefix, c_meta, c_reset);
 	}
 	if (deleted)
 		dump_quoted_path("+++ ", "", "/dev/null",
 				 line_prefix, c_meta, c_reset);
 	else
-		dump_quoted_path("+++ ", b_prefix, elem->path,
+		dump_quoted_path("+++ ", b_prefix, name,
 				 line_prefix, c_meta, c_reset);
 }
 
@@ -1270,9 +1280,10 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re
 			const char *path = p->parent[i].path ?
 					   p->parent[i].path :
 					   p->path;
+			path = strip_relative_prefix(opt, path);
 			write_name_quoted(path, stdout, inter_name_termination);
 		}
-	write_name_quoted(p->path, stdout, line_termination);
+	write_name_quoted(strip_relative_prefix(opt, p->path), stdout, line_termination);
 }
 
 /*
diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh
index e11b711388..2575c06360 100755
--- a/t/t4038-diff-combined.sh
+++ b/t/t4038-diff-combined.sh
@@ -492,6 +492,28 @@ test_expect_success '--combined-all-paths and --cc' '
 	test_cmp expect actual
 '
 
+test_expect_success '--combined-all-paths and --raw with relative renamed paths' '
+	cat <<-EOF >expect &&
+	::100644 100644 100644 $side1cf $side2cf $mergedf RR	side1c	side2c	merged
+	EOF
+	git diff-tree -c -M --raw --combined-all-paths \
+		--relative=filename- HEAD >actual.tmp &&
+	sed 1d <actual.tmp >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '--combined-all-paths and --cc with relative renamed paths' '
+	cat <<-\EOF >expect &&
+	--- a/side1c
+	--- a/side2c
+	+++ b/merged
+	EOF
+	git diff-tree --cc -M --combined-all-paths \
+		--relative=filename- HEAD >actual.tmp &&
+	grep ^[-+][-+][-+] <actual.tmp >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success FUNNYNAMES 'setup for --combined-all-paths with funny names' '
 	git branch side1d &&
 	git branch side2d &&
diff --git a/t/t4045-diff-relative.sh b/t/t4045-diff-relative.sh
index 167be0bdcc..f105ddcfd1 100755
--- a/t/t4045-diff-relative.sh
+++ b/t/t4045-diff-relative.sh
@@ -223,7 +223,7 @@ test_expect_success 'diff --relative --name-only with change in subdir' '
 	test_cmp expected out
 '
 
-test_expect_failure 'diff --relative with change in subdir' '
+test_expect_success 'diff --relative with change in subdir' '
 	git switch br3 &&
 	br1_blob=$(git rev-parse --short --verify br1:subdir/file0) &&
 	br3_blob=$(git rev-parse --short --verify br3:subdir/file0) &&
@@ -242,6 +242,44 @@ test_expect_failure 'diff --relative with change in subdir' '
 	++>>>>>>> br1
 	EOF
 	git -C subdir diff --relative >out &&
+	test_cmp expected out &&
+	git diff --relative=subdir >out &&
+	test_cmp expected out &&
+	git diff --relative=subdir/ >out &&
+	test_cmp expected out &&
+	sed "s,file0,dir/file0,g" expected >expected-short &&
+	git diff --relative=sub >out &&
+	test_cmp expected-short out &&
+	sed "s,file0,subdir/file0,g" expected >expected-full &&
+	git diff --relative=subdir --no-relative -- subdir/file0 >out &&
+	test_cmp expected-full out
+'
+
+test_expect_success 'combined raw diff with relative paths' '
+	git switch br3 &&
+	br1_blob=$(git rev-parse --short --verify br1:subdir/file0) &&
+	br3_blob=$(git rev-parse --short --verify br3:subdir/file0) &&
+	test_when_finished "git merge --abort" &&
+	test_must_fail git merge br1 &&
+	printf "::100644 100644 100644 %s %s 0000000 MM\tfile0\n" \
+		"$br3_blob" "$br1_blob" >expected &&
+	git -C subdir diff --cc --raw --relative >out &&
+	test_cmp expected out &&
+	printf "::100644 100644 100644 %s %s 0000000 MM\0file0\0" \
+		"$br3_blob" "$br1_blob" >expected &&
+	git diff --cc --raw -z --relative=subdir >out &&
+	test_cmp expected out
+'
+
+test_expect_success 'combined raw diff lists all relative paths' '
+	git switch br3 &&
+	br1_blob=$(git rev-parse --short --verify br1:subdir/file0) &&
+	br3_blob=$(git rev-parse --short --verify br3:subdir/file0) &&
+	test_when_finished "git merge --abort" &&
+	test_must_fail git merge br1 &&
+	printf "::100644 100644 100644 %s %s 0000000 MM\tfile0\tfile0\tfile0\n" \
+		"$br3_blob" "$br1_blob" >expected &&
+	git diff --cc --raw --combined-all-paths --relative=subdir >out &&
 	test_cmp expected out
 '
 
@@ -254,4 +292,26 @@ test_expect_success 'diff --relative --cached with change in subdir' '
 	test_cmp expected out
 '
 
+test_expect_success FUNNYNAMES 'combined diff quotes relative paths' '
+	test_create_repo quoted &&
+	(
+		cd quoted &&
+		mkdir subdir &&
+		test_commit --no-tag base "subdir/quoted\"file" base &&
+		git switch -c side &&
+		test_commit --no-tag side "subdir/quoted\"file" side &&
+		git switch -c other HEAD^ &&
+		test_commit --no-tag other "subdir/quoted\"file" other &&
+		test_must_fail git merge side &&
+		cat >expected <<-\EOF &&
+		diff --cc "quoted\"file"
+		--- "a/quoted\"file"
+		+++ "b/quoted\"file"
+		EOF
+		git -C subdir diff --relative >out &&
+		sed -n "/^diff --cc /p; /^--- /p; /^+++ /p" out >actual &&
+		test_cmp expected actual
+	)
+'
+
 test_done

base-commit: 6de20f6092dcf9bdb1c8efe03db4b70c82b423dd
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-10-09 11:08 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-07  5:17 [PATCH] combine-diff: honor --relative when printing paths Muhammed Dilshad A
2026-10-07 14:45 ` Junio C Hamano
2026-10-07 16:35   ` [PATCH v2 0/2] combine-diff: honor relative paths consistently Muhammed Dilshad A
2026-10-07 16:35     ` [PATCH v2 1/2] combine-diff: honor --relative when printing paths Muhammed Dilshad A
2026-10-07 16:35     ` [PATCH v2 2/2] combine-diff: filter the fast scan by the relative prefix Muhammed Dilshad A
2026-10-07 17:53     ` [PATCH v2 0/2] combine-diff: honor relative paths consistently Junio C Hamano
2026-10-09 11:08       ` Muhammed Dilshad A

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox