mirror of
https://github.com/git/git.git
synced 2024-12-12 03:14:11 +08:00
57f583c748
--ours, --theirs, and --union are already supported in `git merge-file` for automatically resolving conflicts in favor of one version or the other, instead of leaving conflict markers in the file. Support them in `git apply -3` as well because the two commands do the same kind of file-level merges. In case in the future --ours, --theirs, and --union gain a meaning outside of three-way-merges, they do not imply --3way but rather must be specified alongside it. Signed-off-by: Alex Henrie <alexhenrie24@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
338 lines
8.6 KiB
Bash
Executable File
338 lines
8.6 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
test_description='git apply --3way'
|
|
|
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
|
|
|
TEST_PASSES_SANITIZE_LEAK=true
|
|
. ./test-lib.sh
|
|
|
|
print_sanitized_conflicted_diff () {
|
|
git diff HEAD >diff.raw &&
|
|
sed -e '
|
|
/^index /d
|
|
s/^\(+[<>|][<>|][<>|][<>|]*\) .*/\1/
|
|
' diff.raw
|
|
}
|
|
|
|
test_expect_success setup '
|
|
test_tick &&
|
|
test_write_lines 1 2 3 4 5 6 7 >one &&
|
|
cat one >two &&
|
|
git add one two &&
|
|
git commit -m initial &&
|
|
|
|
git branch side &&
|
|
|
|
test_tick &&
|
|
test_write_lines 1 two 3 4 5 six 7 >one &&
|
|
test_write_lines 1 two 3 4 5 6 7 >two &&
|
|
git commit -a -m main &&
|
|
|
|
git checkout side &&
|
|
test_write_lines 1 2 3 4 five 6 7 >one &&
|
|
test_write_lines 1 2 3 4 five 6 7 >two &&
|
|
git commit -a -m side &&
|
|
|
|
git checkout main
|
|
'
|
|
|
|
test_expect_success 'apply without --3way' '
|
|
git diff side^ side >P.diff &&
|
|
|
|
# should fail to apply
|
|
git reset --hard &&
|
|
git checkout main^0 &&
|
|
test_must_fail git apply --index P.diff &&
|
|
# should leave things intact
|
|
git diff-files --exit-code &&
|
|
git diff-index --exit-code --cached HEAD
|
|
'
|
|
|
|
test_apply_with_3way () {
|
|
# Merging side should be similar to applying this patch
|
|
git diff ...side >P.diff &&
|
|
|
|
# The corresponding conflicted merge
|
|
git reset --hard &&
|
|
git checkout main^0 &&
|
|
test_must_fail git merge --no-commit side &&
|
|
git ls-files -s >expect.ls &&
|
|
print_sanitized_conflicted_diff >expect.diff &&
|
|
|
|
# should fail to apply
|
|
git reset --hard &&
|
|
git checkout main^0 &&
|
|
test_must_fail git apply --index --3way P.diff &&
|
|
git ls-files -s >actual.ls &&
|
|
print_sanitized_conflicted_diff >actual.diff &&
|
|
|
|
# The result should resemble the corresponding merge
|
|
test_cmp expect.ls actual.ls &&
|
|
test_cmp expect.diff actual.diff
|
|
}
|
|
|
|
test_expect_success 'apply with --3way' '
|
|
test_apply_with_3way
|
|
'
|
|
|
|
test_expect_success 'apply with --3way with merge.conflictStyle = diff3' '
|
|
test_config merge.conflictStyle diff3 &&
|
|
test_apply_with_3way
|
|
'
|
|
|
|
test_apply_with_3way_favoritism () {
|
|
apply_arg=$1
|
|
merge_arg=$2
|
|
|
|
# Merging side should be similar to applying this patch
|
|
git diff ...side >P.diff &&
|
|
|
|
# The corresponding conflicted merge
|
|
git reset --hard &&
|
|
git checkout main^0 &&
|
|
git merge --no-commit $merge_arg side &&
|
|
git ls-files -s >expect.ls &&
|
|
print_sanitized_conflicted_diff >expect.diff &&
|
|
|
|
# should apply successfully
|
|
git reset --hard &&
|
|
git checkout main^0 &&
|
|
git apply --index --3way $apply_arg P.diff &&
|
|
git ls-files -s >actual.ls &&
|
|
print_sanitized_conflicted_diff >actual.diff &&
|
|
|
|
# The result should resemble the corresponding merge
|
|
test_cmp expect.ls actual.ls &&
|
|
test_cmp expect.diff actual.diff
|
|
}
|
|
|
|
test_expect_success 'apply with --3way --ours' '
|
|
test_apply_with_3way_favoritism --ours -Xours
|
|
'
|
|
|
|
test_expect_success 'apply with --3way --theirs' '
|
|
test_apply_with_3way_favoritism --theirs -Xtheirs
|
|
'
|
|
|
|
test_expect_success 'apply with --3way --union' '
|
|
echo "* merge=union" >.gitattributes &&
|
|
test_apply_with_3way_favoritism --union &&
|
|
rm .gitattributes
|
|
'
|
|
|
|
test_expect_success 'apply with --3way with rerere enabled' '
|
|
test_config rerere.enabled true &&
|
|
|
|
# Merging side should be similar to applying this patch
|
|
git diff ...side >P.diff &&
|
|
|
|
# The corresponding conflicted merge
|
|
git reset --hard &&
|
|
git checkout main^0 &&
|
|
test_must_fail git merge --no-commit side &&
|
|
|
|
# Manually resolve and record the resolution
|
|
test_write_lines 1 two 3 4 five six 7 >one &&
|
|
git rerere &&
|
|
cat one >expect &&
|
|
|
|
# should fail to apply
|
|
git reset --hard &&
|
|
git checkout main^0 &&
|
|
test_must_fail git apply --index --3way P.diff &&
|
|
|
|
# but rerere should have replayed the recorded resolution
|
|
test_cmp expect one
|
|
'
|
|
|
|
test_expect_success 'apply -3 with add/add conflict setup' '
|
|
git reset --hard &&
|
|
|
|
git checkout -b adder &&
|
|
test_write_lines 1 2 3 4 5 6 7 >three &&
|
|
test_write_lines 1 2 3 4 5 6 7 >four &&
|
|
git add three four &&
|
|
git commit -m "add three and four" &&
|
|
|
|
git checkout -b another adder^ &&
|
|
test_write_lines 1 2 3 4 5 6 7 >three &&
|
|
test_write_lines 1 2 3 four 5 6 7 >four &&
|
|
git add three four &&
|
|
git commit -m "add three and four" &&
|
|
|
|
# Merging another should be similar to applying this patch
|
|
git diff adder...another >P.diff &&
|
|
|
|
git checkout adder^0 &&
|
|
test_must_fail git merge --no-commit another &&
|
|
git ls-files -s >expect.ls &&
|
|
print_sanitized_conflicted_diff >expect.diff
|
|
'
|
|
|
|
test_expect_success 'apply -3 with add/add conflict' '
|
|
# should fail to apply ...
|
|
git reset --hard &&
|
|
git checkout adder^0 &&
|
|
test_must_fail git apply --index --3way P.diff &&
|
|
# ... and leave conflicts in the index and in the working tree
|
|
git ls-files -s >actual.ls &&
|
|
print_sanitized_conflicted_diff >actual.diff &&
|
|
|
|
# The result should resemble the corresponding merge
|
|
test_cmp expect.ls actual.ls &&
|
|
test_cmp expect.diff actual.diff
|
|
'
|
|
|
|
test_expect_success 'apply -3 with add/add conflict (dirty working tree)' '
|
|
# should fail to apply ...
|
|
git reset --hard &&
|
|
git checkout adder^0 &&
|
|
echo >>four &&
|
|
cat four >four.save &&
|
|
cat three >three.save &&
|
|
git ls-files -s >expect.ls &&
|
|
test_must_fail git apply --index --3way P.diff &&
|
|
# ... and should not touch anything
|
|
git ls-files -s >actual.ls &&
|
|
test_cmp expect.ls actual.ls &&
|
|
test_cmp four.save four &&
|
|
test_cmp three.save three
|
|
'
|
|
|
|
test_expect_success 'apply -3 with ambiguous repeating file' '
|
|
git reset --hard &&
|
|
test_write_lines 1 2 1 2 1 2 1 2 1 2 1 >one_two_repeat &&
|
|
git add one_two_repeat &&
|
|
git commit -m "init one" &&
|
|
test_write_lines 1 2 1 2 1 2 1 2 one 2 1 >one_two_repeat &&
|
|
git commit -a -m "change one" &&
|
|
|
|
git diff HEAD~ >Repeat.diff &&
|
|
git reset --hard HEAD~ &&
|
|
|
|
test_write_lines 1 2 1 2 1 2 one 2 1 2 one >one_two_repeat &&
|
|
git commit -a -m "change surrounding one" &&
|
|
|
|
git apply --index --3way Repeat.diff &&
|
|
test_write_lines 1 2 1 2 1 2 one 2 one 2 one >expect &&
|
|
|
|
test_cmp expect one_two_repeat
|
|
'
|
|
|
|
test_expect_success 'apply with --3way --cached clean apply' '
|
|
# Merging side should be similar to applying this patch
|
|
git diff ...side >P.diff &&
|
|
|
|
# The corresponding cleanly applied merge
|
|
git reset --hard &&
|
|
git checkout main~ &&
|
|
git merge --no-commit side &&
|
|
git ls-files -s >expect.ls &&
|
|
|
|
# should succeed
|
|
git reset --hard &&
|
|
git checkout main~ &&
|
|
git apply --cached --3way P.diff &&
|
|
git ls-files -s >actual.ls &&
|
|
print_sanitized_conflicted_diff >actual.diff &&
|
|
|
|
# The cache should resemble the corresponding merge
|
|
# (both files at stage #0)
|
|
test_cmp expect.ls actual.ls &&
|
|
# However the working directory should not change
|
|
>expect.diff &&
|
|
test_cmp expect.diff actual.diff
|
|
'
|
|
|
|
test_expect_success 'apply with --3way --cached and conflicts' '
|
|
# Merging side should be similar to applying this patch
|
|
git diff ...side >P.diff &&
|
|
|
|
# The corresponding conflicted merge
|
|
git reset --hard &&
|
|
git checkout main^0 &&
|
|
test_must_fail git merge --no-commit side &&
|
|
git ls-files -s >expect.ls &&
|
|
|
|
# should fail to apply
|
|
git reset --hard &&
|
|
git checkout main^0 &&
|
|
test_must_fail git apply --cached --3way P.diff &&
|
|
git ls-files -s >actual.ls &&
|
|
print_sanitized_conflicted_diff >actual.diff &&
|
|
|
|
# The cache should resemble the corresponding merge
|
|
# (one file at stage #0, one file at stages #1 #2 #3)
|
|
test_cmp expect.ls actual.ls &&
|
|
# However the working directory should not change
|
|
>expect.diff &&
|
|
test_cmp expect.diff actual.diff
|
|
'
|
|
|
|
test_expect_success 'apply binary file patch' '
|
|
git reset --hard main &&
|
|
cp "$TEST_DIRECTORY/test-binary-1.png" bin.png &&
|
|
git add bin.png &&
|
|
git commit -m "add binary file" &&
|
|
|
|
cp "$TEST_DIRECTORY/test-binary-2.png" bin.png &&
|
|
|
|
git diff --binary >bin.diff &&
|
|
git reset --hard &&
|
|
|
|
# Apply must succeed.
|
|
git apply bin.diff
|
|
'
|
|
|
|
test_expect_success 'apply binary file patch with 3way' '
|
|
git reset --hard main &&
|
|
cp "$TEST_DIRECTORY/test-binary-1.png" bin.png &&
|
|
git add bin.png &&
|
|
git commit -m "add binary file" &&
|
|
|
|
cp "$TEST_DIRECTORY/test-binary-2.png" bin.png &&
|
|
|
|
git diff --binary >bin.diff &&
|
|
git reset --hard &&
|
|
|
|
# Apply must succeed.
|
|
git apply --3way --index bin.diff
|
|
'
|
|
|
|
test_expect_success 'apply full-index patch with 3way' '
|
|
git reset --hard main &&
|
|
cp "$TEST_DIRECTORY/test-binary-1.png" bin.png &&
|
|
git add bin.png &&
|
|
git commit -m "add binary file" &&
|
|
|
|
cp "$TEST_DIRECTORY/test-binary-2.png" bin.png &&
|
|
|
|
git diff --full-index >bin.diff &&
|
|
git reset --hard &&
|
|
|
|
# Apply must succeed.
|
|
git apply --3way --index bin.diff
|
|
'
|
|
|
|
test_expect_success 'apply delete then new patch with 3way' '
|
|
git reset --hard main &&
|
|
test_write_lines 2 > delnew &&
|
|
git add delnew &&
|
|
git diff --cached >> new.patch &&
|
|
git reset --hard &&
|
|
test_write_lines 1 > delnew &&
|
|
git add delnew &&
|
|
git commit -m "delnew" &&
|
|
rm delnew &&
|
|
git diff >> delete-then-new.patch &&
|
|
cat new.patch >> delete-then-new.patch &&
|
|
|
|
git checkout -- . &&
|
|
# Apply must succeed.
|
|
git apply --3way delete-then-new.patch
|
|
'
|
|
|
|
test_done
|