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

[PATCH 2/2] merge-one-file: fix broken merges with GIT_WORK_TREE

From
Jeff King <peff@peff.net>
Date
Apr 28, 2011, 22:41 UTC
Message-ID
<20110428224125.GB16027@sigill.intra.peff.net>
In-Reply-To
<20110428223822.GA16004@sigill.intra.peff.net>

The merge-one-file tool predates the invention of GIT_WORK_TREE. By the time GIT_WORK_TREE was invented, most people were using the merge-recursive strategy, which handles resolving internally. Therefore these features have had very little testing together.

For the most part, merge-one-file just works with GIT_WORK_TREE; most of its heavy lifting is done by plumbing commands which do respect GIT_WORK_TREE properly. The one exception is a shell redirection which touches the worktree directly, writing results to the wrong place in the presence of a GIT_WORK_TREE variable.

This means that merges won't even fail; they will silently produce incorrect results, throwing out the entire "theirs" side of files which need content-level merging!

This patch properly prefixes the path in the shell redirection. An alternative strategy would be to have merge-one-file use git-sh-setup, and cd_to_toplevel beforehand. I opted for the minimal fix here, as changing directories would impact where merge-one-file is unpacking and working with files.

While we're at it, we'll also error-check the call to cat. Merging a file in a subdirectory could in fact fail, as the redirection relies on the "checkout-index" call just prior to create leading directories. But we never noticed, since we ignored the error return from running cat.

Signed-off-by: Jeff King <peff@peff.net>
---
 git-merge-one-file.sh  |    4 +++-
 t/t6060-merge-index.sh |    2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/git-merge-one-file.sh b/git-merge-one-file.sh
index b86402a..0b5e3f6 100755
--- a/git-merge-one-file.sh
+++ b/git-merge-one-file.sh
@@ -132,7 +132,9 @@ case "${1:-.}${2:-.}${3:-.}" in
 
 	# Create the working tree file, using "our tree" version from the
 	# index, and then store the result of the merge.
-	git checkout-index -f --stage=2 -- "$4" && cat "$src1" >"$4"
+	git checkout-index -f --stage=2 -- "$4" &&
+		cat "$src1" >"${GIT_WORK_TREE:+$GIT_WORK_TREE/}$4" ||
+		exit 1
 	rm -f -- "$orig" "$src1" "$src2"
 
 	if [ "$6" != "$7" ]; then
diff --git a/t/t6060-merge-index.sh b/t/t6060-merge-index.sh
index 8f8ec77..fd90e70 100755
--- a/t/t6060-merge-index.sh
+++ b/t/t6060-merge-index.sh
@@ -51,7 +51,7 @@ test_expect_success 'git merge-index git-merge-one-file resolves' '
 	test_cmp expect-merged file-index
 '
 
-test_expect_failure 'merge-one-file respects GIT_WORK_TREE' '
+test_expect_success 'merge-one-file respects GIT_WORK_TREE' '
 	git clone . bare.git &&
 	(cd bare.git &&
 	 mkdir work &&
-- 
1.7.5.rc3.17.g5e09b
Previous: Junio C HamanoNext: Junio C Hamano
Message 5 of 6 in “merge-one-file and GIT_WORK_TREE”
  1. 0/2 merge-one-file and GIT_WORK_TREEJeff King, Apr 28, 2011
  2. 1/2 add tests for merge-index / merge-one-fileJeff King, Apr 28, 2011
  3. Johannes SixtApr 29, 2011
  4. Junio C HamanoApr 29, 2011
  5. 2/2 merge-one-file: fix broken merges with GIT_WORK_TREEJeff King, Apr 28, 2011
  6. Junio C HamanoApr 29, 2011

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.