Browse Source

merge-one-file: fix broken merges with alternate work trees

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 makes merge-one-file chdir to the toplevel of the
working tree (and exit if we don't have one). This most
closely matches the assumption made by the original script
(before separate work trees were invented), and matches what
happens when the script is called as part of a merge
strategy.

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>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Jeff King 14 years ago committed by Junio C Hamano
parent
commit
6aaeca900b
  1. 7
      git-merge-one-file.sh
  2. 4
      t/t6060-merge-index.sh

7
git-merge-one-file.sh

@ -22,6 +22,11 @@ LONG_USAGE="Usage: git merge-one-file $USAGE


Blob ids and modes should be empty for missing files." Blob ids and modes should be empty for missing files."


SUBDIRECTORY_OK=Yes
. git-sh-setup
cd_to_toplevel
require_work_tree

if ! test "$#" -eq 7 if ! test "$#" -eq 7
then then
echo "$LONG_USAGE" echo "$LONG_USAGE"
@ -132,7 +137,7 @@ case "${1:-.}${2:-.}${3:-.}" in


# Create the working tree file, using "our tree" version from the # Create the working tree file, using "our tree" version from the
# index, and then store the result of the merge. # 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" >"$4" || exit 1
rm -f -- "$orig" "$src1" "$src2" rm -f -- "$orig" "$src1" "$src2"


if [ "$6" != "$7" ]; then if [ "$6" != "$7" ]; then

4
t/t6060-merge-index.sh

@ -68,7 +68,7 @@ test_expect_success 'merge-one-file fails without a work tree' '
) )
' '


test_expect_failure 'merge-one-file respects GIT_WORK_TREE' ' test_expect_success 'merge-one-file respects GIT_WORK_TREE' '
(cd bare.git && (cd bare.git &&
mkdir work && mkdir work &&
GIT_WORK_TREE=$PWD/work && GIT_WORK_TREE=$PWD/work &&
@ -82,7 +82,7 @@ test_expect_failure 'merge-one-file respects GIT_WORK_TREE' '
test_cmp expect-merged bare.git/work/file-index test_cmp expect-merged bare.git/work/file-index
' '


test_expect_failure 'merge-one-file respects core.worktree' ' test_expect_success 'merge-one-file respects core.worktree' '
mkdir subdir && mkdir subdir &&
git clone . subdir/child && git clone . subdir/child &&
(cd subdir && (cd subdir &&

Loading…
Cancel
Save