git/t/t7201-co.sh

726 lines
17 KiB
Bash
Raw Normal View History

#!/bin/sh
#
# Copyright (c) 2006 Junio C Hamano
#
test_description='git checkout tests.
Creates main, forks renamer and side branches from it.
Test switching across them.
! [main] Initial A one, A two
* [renamer] Renamer R one->uno, M two
! [side] Side M one, D two, A three
! [simple] Simple D one, M two
----
+ [simple] Simple D one, M two
+ [side] Side M one, D two, A three
* [renamer] Renamer R one->uno, M two
+*++ [main] Initial A one, A two
'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
tests: mark tests relying on the current default for `init.defaultBranch` In addition to the manual adjustment to let the `linux-gcc` CI job run the test suite with `master` and then with `main`, this patch makes sure that GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME is set in all test scripts that currently rely on the initial branch name being `master by default. To determine which test scripts to mark up, the first step was to force-set the default branch name to `master` in - all test scripts that contain the keyword `master`, - t4211, which expects `t/t4211/history.export` with a hard-coded ref to initialize the default branch, - t5560 because it sources `t/t556x_common` which uses `master`, - t8002 and t8012 because both source `t/annotate-tests.sh` which also uses `master`) This trick was performed by this command: $ sed -i '/^ *\. \.\/\(test-lib\|lib-\(bash\|cvs\|git-svn\)\|gitweb-lib\)\.sh$/i\ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master\ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\ ' $(git grep -l master t/t[0-9]*.sh) \ t/t4211*.sh t/t5560*.sh t/t8002*.sh t/t8012*.sh After that, careful, manual inspection revealed that some of the test scripts containing the needle `master` do not actually rely on a specific default branch name: either they mention `master` only in a comment, or they initialize that branch specificially, or they do not actually refer to the current default branch. Therefore, the aforementioned modification was undone in those test scripts thusly: $ git checkout HEAD -- \ t/t0027-auto-crlf.sh t/t0060-path-utils.sh \ t/t1011-read-tree-sparse-checkout.sh \ t/t1305-config-include.sh t/t1309-early-config.sh \ t/t1402-check-ref-format.sh t/t1450-fsck.sh \ t/t2024-checkout-dwim.sh \ t/t2106-update-index-assume-unchanged.sh \ t/t3040-subprojects-basic.sh t/t3301-notes.sh \ t/t3308-notes-merge.sh t/t3423-rebase-reword.sh \ t/t3436-rebase-more-options.sh \ t/t4015-diff-whitespace.sh t/t4257-am-interactive.sh \ t/t5323-pack-redundant.sh t/t5401-update-hooks.sh \ t/t5511-refspec.sh t/t5526-fetch-submodules.sh \ t/t5529-push-errors.sh t/t5530-upload-pack-error.sh \ t/t5548-push-porcelain.sh \ t/t5552-skipping-fetch-negotiator.sh \ t/t5572-pull-submodule.sh t/t5608-clone-2gb.sh \ t/t5614-clone-submodules-shallow.sh \ t/t7508-status.sh t/t7606-merge-custom.sh \ t/t9302-fast-import-unpack-limit.sh We excluded one set of test scripts in these commands, though: the range of `git p4` tests. The reason? `git p4` stores the (foreign) remote branch in the branch called `p4/master`, which is obviously not the default branch. Manual analysis revealed that only five of these tests actually require a specific default branch name to pass; They were modified thusly: $ sed -i '/^ *\. \.\/lib-git-p4\.sh$/i\ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master\ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\ ' t/t980[0167]*.sh t/t9811*.sh Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-11-18 23:44:19 +00:00
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
test_tick
fill () {
for i
do
echo "$i"
done
}
test_expect_success setup '
fill x y z >same &&
fill 1 2 3 4 5 6 7 8 >one &&
fill a b c d e >two &&
git add same one two &&
git commit -m "Initial A one, A two" &&
git checkout -b renamer &&
rm -f one &&
fill 1 3 4 5 6 7 8 >uno &&
git add uno &&
fill a b c d e f >two &&
git commit -a -m "Renamer R one->uno, M two" &&
git checkout -b side main &&
fill 1 2 3 4 5 6 7 >one &&
fill A B C D E >three &&
rm -f two &&
git update-index --add --remove one two three &&
git commit -m "Side M one, D two, A three" &&
git checkout -b simple main &&
rm -f one &&
fill a c e >two &&
git commit -a -m "Simple D one, M two" &&
git checkout main
'
test_expect_success 'checkout from non-existing branch' '
git checkout -b delete-me main &&
git update-ref -d --no-deref refs/heads/delete-me &&
test refs/heads/delete-me = "$(git symbolic-ref HEAD)" &&
git checkout main &&
test refs/heads/main = "$(git symbolic-ref HEAD)"
'
test_expect_success 'checkout with dirty tree without -m' '
fill 0 1 2 3 4 5 6 7 8 >one &&
if git checkout side
then
echo Not happy
false
else
echo "happy - failed correctly"
fi
'
test_expect_success 'checkout with unrelated dirty tree without -m' '
git checkout -f main &&
fill 0 1 2 3 4 5 6 7 8 >same &&
cp same kept &&
git checkout side >messages &&
test_cmp same kept &&
printf "M\t%s\n" same >messages.expect &&
test_cmp messages.expect messages
'
test_expect_success 'checkout -m with dirty tree' '
git checkout -f main &&
git clean -f &&
fill 0 1 2 3 4 5 6 7 8 >one &&
git checkout -m side >messages &&
test "$(git symbolic-ref HEAD)" = "refs/heads/side" &&
printf "M\t%s\n" one >expect.messages &&
test_cmp expect.messages messages &&
fill "M one" "A three" "D two" >expect.main &&
git diff --name-status main >current.main &&
test_cmp expect.main current.main &&
fill "M one" >expect.side &&
git diff --name-status side >current.side &&
test_cmp expect.side current.side &&
git diff --cached >current.index &&
tests: use 'test_must_be_empty' instead of 'test_cmp <empty> <out>' Using 'test_must_be_empty' is shorter and more idiomatic than >empty && test_cmp empty out as it saves the creation of an empty file. Furthermore, sometimes the expected empty file doesn't have such a descriptive name like 'empty', and its creation is far away from the place where it's finally used for comparison (e.g. in 't7600-merge.sh', where two expected empty files are created in the 'setup' test, but are used only about 500 lines later). These cases were found by instrumenting 'test_cmp' to error out the test script when it's used to compare empty files, and then converted manually. Note that even after this patch there still remain a lot of cases where we use 'test_cmp' to check empty files: - Sometimes the expected output is not hard-coded in the test, but 'test_cmp' is used to ensure that two similar git commands produce the same output, and that output happens to be empty, e.g. the test 'submodule update --merge - ignores --merge for new submodules' in 't7406-submodule-update.sh'. - Repetitive common tasks, including preparing the expected results and running 'test_cmp', are often extracted into a helper function, and some of this helper's callsites expect no output. - For the same reason as above, the whole 'test_expect_success' block is within a helper function, e.g. in 't3070-wildmatch.sh'. - Or 'test_cmp' is invoked in a loop, e.g. the test 'cvs update (-p)' in 't9400-git-cvsserver-server.sh'. Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-19 21:57:25 +00:00
test_must_be_empty current.index
'
test_expect_success 'checkout -m with dirty tree, renamed' '
git checkout -f main && git clean -f &&
fill 1 2 3 4 5 7 8 >one &&
if git checkout renamer
then
echo Not happy
false
else
echo "happy - failed correctly"
fi &&
git checkout -m renamer &&
fill 1 3 4 5 7 8 >expect &&
test_cmp expect uno &&
! test -f one &&
git diff --cached >current &&
test_must_be_empty current
'
test_expect_success 'checkout -m with merge conflict' '
git checkout -f main && git clean -f &&
fill 1 T 3 4 5 6 S 8 >one &&
if git checkout renamer
then
echo Not happy
false
else
echo "happy - failed correctly"
fi &&
git checkout -m renamer &&
git diff main:one :3:uno |
sed -e "1,/^@@/d" -e "/^ /d" -e "s/^-/d/" -e "s/^+/a/" >current &&
fill d2 aT d7 aS >expect &&
test_cmp expect current &&
git diff --cached two >current &&
test_must_be_empty current
'
test_expect_success 'format of merge conflict from checkout -m' '
git checkout -f main &&
git clean -f &&
fill b d >two &&
git checkout -m simple &&
git ls-files >current &&
fill same two two two >expect &&
test_cmp expect current &&
cat <<-EOF >expect &&
<<<<<<< simple
a
c
e
=======
b
d
>>>>>>> local
EOF
test_cmp expect two
'
test_expect_success 'checkout --merge --conflict=diff3 <branch>' '
git checkout -f main &&
git reset --hard &&
git clean -f &&
fill b d >two &&
git checkout --merge --conflict=diff3 simple &&
cat <<-EOF >expect &&
<<<<<<< simple
a
c
e
||||||| main
a
b
c
d
e
=======
b
d
>>>>>>> local
EOF
test_cmp expect two
'
test_expect_success 'switch to another branch while carrying a deletion' '
git checkout -f main &&
git reset --hard &&
git clean -f &&
git rm two &&
test_must_fail git checkout simple 2>errs &&
test_grep overwritten errs &&
test_must_fail git read-tree --quiet -m -u HEAD simple 2>errs &&
checkout: prevent losing staged changes with --merge When --merge is specified, we may need to do a real merge (instead of three-way tree unpacking), the steps are best seen in git-checkout.sh version before it's removed: # Match the index to the working tree, and do a three-way. git diff-files --name-only | git update-index --remove --stdin && work=`git write-tree` && git read-tree $v --reset -u $new || exit git merge-recursive $old -- $new $work # Do not register the cleanly merged paths in the index yet. # this is not a real merge before committing, but just carrying # the working tree changes along. unmerged=`git ls-files -u` git read-tree $v --reset $new case "$unmerged" in '') ;; *) ( z40=0000000000000000000000000000000000000000 echo "$unmerged" | sed -e 's/^[0-7]* [0-9a-f]* /'"0 $z40 /" echo "$unmerged" ) | git update-index --index-info ;; esac Notice the last 'read-tree --reset' step. We restore worktree back to 'new' tree after worktree's messed up by merge-recursive. If there are staged changes before this whole command sequence is executed, they are lost because they are unlikely part of the 'new' tree to be restored. There is no easy way to fix this. Elijah may have something up his sleeves [1], but until then, check if there are staged changes and refuse to run and lose them. The user would need to do "git reset" to continue in this case. A note about the test update. 'checkout -m' in that test will fail because a deletion is staged. This 'checkout -m' was previously needed to verify quietness behavior of unpack-trees. But a different check has been put in place in the last patch. We can safely drop 'checkout -m' now. [1] CABPp-BFoL_U=bzON4SEMaQSKU2TKwnOgNqjt5MUaOejTKGUJxw@mail.gmail.com Reported-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-03-22 09:31:38 +00:00
test_must_be_empty errs
'
test_expect_success 'checkout to detach HEAD (with advice declined)' '
git config advice.detachedHead false &&
rev=$(git rev-parse --short renamer^) &&
git checkout -f renamer &&
git clean -f &&
git checkout renamer^ 2>messages &&
test_grep "HEAD is now at $rev" messages &&
test_line_count = 1 messages &&
H=$(git rev-parse --verify HEAD) &&
M=$(git show-ref -s --verify refs/heads/main) &&
test "z$H" = "z$M" &&
if git symbolic-ref HEAD >/dev/null 2>&1
then
echo "OOPS, HEAD is still symbolic???"
false
else
: happy
fi
'
test_expect_success 'checkout to detach HEAD' '
git config advice.detachedHead true &&
rev=$(git rev-parse --short renamer^) &&
git checkout -f renamer &&
git clean -f &&
git checkout renamer^ 2>messages &&
grep "HEAD is now at $rev" messages &&
i18n: make GETTEXT_POISON a runtime option Change the GETTEXT_POISON compile-time + runtime GIT_GETTEXT_POISON test parameter to only be a GIT_TEST_GETTEXT_POISON=<non-empty?> runtime parameter, to be consistent with other parameters documented in "Running tests with special setups" in t/README. When I added GETTEXT_POISON in bb946bba76 ("i18n: add GETTEXT_POISON to simulate unfriendly translator", 2011-02-22) I was concerned with ensuring that the _() function would get constant folded if NO_GETTEXT was defined, and likewise that GETTEXT_POISON would be compiled out unless it was defined. But as the benchmark in my [1] shows doing a one-off runtime getenv("GIT_TEST_[...]") is trivial, and since GETTEXT_POISON was originally added the GIT_TEST_* env variables have become the common idiom for turning on special test setups. So change GETTEXT_POISON to work the same way. Now the GETTEXT_POISON=YesPlease compile-time option is gone, and running the tests with GIT_TEST_GETTEXT_POISON=[YesPlease|] can be toggled on/off without recompiling. This allows for conditionally amending tests to test with/without poison, similar to what 859fdc0c3c ("commit-graph: define GIT_TEST_COMMIT_GRAPH", 2018-08-29) did for GIT_TEST_COMMIT_GRAPH. Do some of that, now we e.g. always run the t0205-gettext-poison.sh test. I did enough there to remove the GETTEXT_POISON prerequisite, but its inverse C_LOCALE_OUTPUT is still around, and surely some tests using it can be converted to e.g. always set GIT_TEST_GETTEXT_POISON=. Notes on the implementation: * We still compile a dedicated GETTEXT_POISON build in Travis CI. Perhaps this should be revisited and integrated into the "linux-gcc" build, see ae59a4e44f ("travis: run tests with GIT_TEST_SPLIT_INDEX", 2018-01-07) for prior art in that area. Then again maybe not, see [2]. * We now skip a test in t0000-basic.sh under GIT_TEST_GETTEXT_POISON=YesPlease that wasn't skipped before. This test relies on C locale output, but due to an edge case in how the previous implementation of GETTEXT_POISON worked (reading it from GIT-BUILD-OPTIONS) wasn't enabling poison correctly. Now it does, and needs to be skipped. * The getenv() function is not reentrant, so out of paranoia about code of the form: printf(_("%s"), getenv("some-env")); call use_gettext_poison() in our early setup in git_setup_gettext() so we populate the "poison_requested" variable in a codepath that's won't suffer from that race condition. * We error out in the Makefile if you're still saying GETTEXT_POISON=YesPlease to prompt users to change their invocation. * We should not print out poisoned messages during the test initialization itself to keep it more readable, so the test library hides the variable if set in $GIT_TEST_GETTEXT_POISON_ORIG during setup. See [3]. See also [4] for more on the motivation behind this patch, and the history of the GETTEXT_POISON facility. 1. https://public-inbox.org/git/871s8gd32p.fsf@evledraar.gmail.com/ 2. https://public-inbox.org/git/20181102163725.GY30222@szeder.dev/ 3. https://public-inbox.org/git/20181022202241.18629-2-szeder.dev@gmail.com/ 4. https://public-inbox.org/git/878t2pd6yu.fsf@evledraar.gmail.com/ Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-11-08 21:15:29 +00:00
test_line_count -gt 1 messages &&
H=$(git rev-parse --verify HEAD) &&
M=$(git show-ref -s --verify refs/heads/main) &&
test "z$H" = "z$M" &&
if git symbolic-ref HEAD >/dev/null 2>&1
then
echo "OOPS, HEAD is still symbolic???"
false
else
: happy
fi
'
test_expect_success 'checkout to detach HEAD with branchname^' '
git checkout -f main &&
git clean -f &&
git checkout renamer^ &&
H=$(git rev-parse --verify HEAD) &&
M=$(git show-ref -s --verify refs/heads/main) &&
test "z$H" = "z$M" &&
if git symbolic-ref HEAD >/dev/null 2>&1
then
echo "OOPS, HEAD is still symbolic???"
false
else
: happy
fi
'
test_expect_success 'checkout to detach HEAD with :/message' '
git checkout -f main &&
git clean -f &&
git checkout ":/Initial" &&
H=$(git rev-parse --verify HEAD) &&
M=$(git show-ref -s --verify refs/heads/main) &&
test "z$H" = "z$M" &&
if git symbolic-ref HEAD >/dev/null 2>&1
then
echo "OOPS, HEAD is still symbolic???"
false
else
: happy
fi
'
test_expect_success 'checkout to detach HEAD with HEAD^0' '
git checkout -f main &&
git clean -f &&
git checkout HEAD^0 &&
H=$(git rev-parse --verify HEAD) &&
M=$(git show-ref -s --verify refs/heads/main) &&
test "z$H" = "z$M" &&
if git symbolic-ref HEAD >/dev/null 2>&1
then
echo "OOPS, HEAD is still symbolic???"
false
else
: happy
fi
'
test_expect_success 'checkout with ambiguous tag/branch names' '
git tag both side &&
git branch both main &&
git reset --hard &&
git checkout main &&
git checkout both &&
H=$(git rev-parse --verify HEAD) &&
M=$(git show-ref -s --verify refs/heads/main) &&
test "z$H" = "z$M" &&
name=$(git symbolic-ref HEAD 2>/dev/null) &&
test "z$name" = zrefs/heads/both
'
test_expect_success 'checkout with ambiguous tag/branch names' '
git reset --hard &&
git checkout main &&
git tag frotz side &&
git branch frotz main &&
git reset --hard &&
git checkout main &&
git checkout tags/frotz &&
H=$(git rev-parse --verify HEAD) &&
S=$(git show-ref -s --verify refs/heads/side) &&
test "z$H" = "z$S" &&
if name=$(git symbolic-ref HEAD 2>/dev/null)
then
echo "Bad -- should have detached"
false
else
: happy
fi
'
test_expect_success 'switch branches while in subdirectory' '
git reset --hard &&
git checkout main &&
mkdir subs &&
git -C subs checkout side &&
! test -f subs/one &&
rm -fr subs
'
test_expect_success 'checkout specific path while in subdirectory' '
git reset --hard &&
git checkout side &&
mkdir subs &&
>subs/bero &&
git add subs/bero &&
git commit -m "add subs/bero" &&
git checkout main &&
mkdir -p subs &&
git -C subs checkout side -- bero &&
test -f subs/bero
'
test_expect_success 'checkout w/--track sets up tracking' '
git config branch.autosetupmerge false &&
git checkout main &&
git checkout --track -b track1 &&
test "$(git config branch.track1.remote)" &&
test "$(git config branch.track1.merge)"
'
test_expect_success 'checkout w/autosetupmerge=always sets up tracking' '
test_when_finished git config branch.autosetupmerge false &&
git config branch.autosetupmerge always &&
git checkout main &&
git checkout -b track2 &&
test "$(git config branch.track2.remote)" &&
test "$(git config branch.track2.merge)"
'
test_expect_success 'checkout w/--track from non-branch HEAD fails' '
git checkout main^0 &&
test_must_fail git symbolic-ref HEAD &&
test_must_fail git checkout --track -b track &&
test_must_fail git rev-parse --verify track &&
test_must_fail git symbolic-ref HEAD &&
test "z$(git rev-parse main^0)" = "z$(git rev-parse HEAD)"
'
test_expect_success 'checkout w/--track from tag fails' '
git checkout main^0 &&
test_must_fail git symbolic-ref HEAD &&
test_must_fail git checkout --track -b track frotz &&
test_must_fail git rev-parse --verify track &&
test_must_fail git symbolic-ref HEAD &&
test "z$(git rev-parse main^0)" = "z$(git rev-parse HEAD)"
'
test_expect_success 'detach a symbolic link HEAD' '
git checkout main &&
git config --bool core.prefersymlinkrefs yes &&
git checkout side &&
git checkout main &&
it=$(git symbolic-ref HEAD) &&
test "z$it" = zrefs/heads/main &&
here=$(git rev-parse --verify refs/heads/main) &&
git checkout side^ &&
test "z$(git rev-parse --verify refs/heads/main)" = "z$here"
'
test_expect_success 'checkout with --track fakes a sensible -b <name>' '
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" &&
git update-ref refs/remotes/origin/koala/bear renamer &&
git checkout --track origin/koala/bear &&
test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
git checkout main && git branch -D koala/bear &&
git checkout --track refs/remotes/origin/koala/bear &&
test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
git checkout main && git branch -D koala/bear &&
git checkout --track remotes/origin/koala/bear &&
test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"
'
test_expect_success 'checkout with --track, but without -b, fails with too short tracked name' '
test_must_fail git checkout --track renamer
'
setup_conflicting_index () {
rm -f .git/index &&
O=$(echo original | git hash-object -w --stdin) &&
A=$(echo ourside | git hash-object -w --stdin) &&
B=$(echo theirside | git hash-object -w --stdin) &&
(
echo "100644 $A 0 fild" &&
echo "100644 $O 1 file" &&
echo "100644 $A 2 file" &&
echo "100644 $B 3 file" &&
echo "100644 $A 0 filf"
) | git update-index --index-info
}
test_expect_success 'checkout an unmerged path should fail' '
setup_conflicting_index &&
echo "none of the above" >sample &&
cat sample >fild &&
cat sample >file &&
cat sample >filf &&
test_must_fail git checkout fild file filf &&
test_cmp sample fild &&
test_cmp sample filf &&
test_cmp sample file
'
test_expect_success 'checkout with an unmerged path can be ignored' '
setup_conflicting_index &&
echo "none of the above" >sample &&
echo ourside >expect &&
cat sample >fild &&
cat sample >file &&
cat sample >filf &&
git checkout -f fild file filf &&
test_cmp expect fild &&
test_cmp expect filf &&
test_cmp sample file
'
test_expect_success 'checkout unmerged stage' '
setup_conflicting_index &&
echo "none of the above" >sample &&
echo ourside >expect &&
cat sample >fild &&
cat sample >file &&
cat sample >filf &&
git checkout --ours . &&
test_cmp expect fild &&
test_cmp expect filf &&
test_cmp expect file &&
git checkout --theirs file &&
test ztheirside = "z$(cat file)"
'
test_expect_success 'checkout path with --merge from tree-ish is a no-no' '
setup_conflicting_index &&
test_must_fail git checkout -m HEAD -- file
'
test_expect_success 'checkout with --merge' '
setup_conflicting_index &&
echo "none of the above" >sample &&
echo ourside >expect &&
cat sample >fild &&
cat sample >file &&
cat sample >filf &&
git checkout -m -- fild file filf &&
(
echo "<<<<<<< ours" &&
echo ourside &&
echo "=======" &&
echo theirside &&
echo ">>>>>>> theirs"
) >merged &&
test_cmp expect fild &&
test_cmp expect filf &&
test_cmp merged file
'
test_expect_success 'checkout -m works after (mistaken) resolution' '
setup_conflicting_index &&
echo "none of the above" >sample &&
cat sample >fild &&
cat sample >file &&
cat sample >filf &&
# resolve to something
git add file &&
git checkout --merge -- fild file filf &&
{
echo "<<<<<<< ours" &&
echo ourside &&
echo "=======" &&
echo theirside &&
echo ">>>>>>> theirs"
} >merged &&
test_cmp expect fild &&
test_cmp expect filf &&
test_cmp merged file
'
test_expect_success 'checkout -m works after (mistaken) resolution to remove' '
setup_conflicting_index &&
echo "none of the above" >sample &&
cat sample >fild &&
cat sample >file &&
cat sample >filf &&
# resolve to remove
git rm file &&
git checkout --merge -- fild file filf &&
{
echo "<<<<<<< ours" &&
echo ourside &&
echo "=======" &&
echo theirside &&
echo ">>>>>>> theirs"
} >merged &&
test_cmp expect fild &&
test_cmp expect filf &&
test_cmp merged file
'
test_expect_success 'checkout with --merge, in diff3 -m style' '
git config merge.conflictstyle diff3 &&
setup_conflicting_index &&
echo "none of the above" >sample &&
echo ourside >expect &&
cat sample >fild &&
cat sample >file &&
cat sample >filf &&
git checkout -m -- fild file filf &&
(
echo "<<<<<<< ours" &&
echo ourside &&
echo "||||||| base" &&
echo original &&
echo "=======" &&
echo theirside &&
echo ">>>>>>> theirs"
) >merged &&
test_cmp expect fild &&
test_cmp expect filf &&
test_cmp merged file
'
test_expect_success 'checkout --conflict=merge, overriding config' '
git config merge.conflictstyle diff3 &&
setup_conflicting_index &&
echo "none of the above" >sample &&
echo ourside >expect &&
cat sample >fild &&
cat sample >file &&
cat sample >filf &&
git checkout --conflict=merge -- fild file filf &&
(
echo "<<<<<<< ours" &&
echo ourside &&
echo "=======" &&
echo theirside &&
echo ">>>>>>> theirs"
) >merged &&
test_cmp expect fild &&
test_cmp expect filf &&
test_cmp merged file
'
test_expect_success 'checkout --conflict=diff3' '
test_unconfig merge.conflictstyle &&
setup_conflicting_index &&
echo "none of the above" >sample &&
echo ourside >expect &&
cat sample >fild &&
cat sample >file &&
cat sample >filf &&
git checkout --conflict=diff3 -- fild file filf &&
(
echo "<<<<<<< ours" &&
echo ourside &&
echo "||||||| base" &&
echo original &&
echo "=======" &&
echo theirside &&
echo ">>>>>>> theirs"
) >merged &&
test_cmp expect fild &&
test_cmp expect filf &&
test_cmp merged file
'
test_expect_success 'failing checkout -b should not break working tree' '
git clean -fd && # Remove untracked files in the way
git reset --hard main &&
git symbolic-ref HEAD refs/heads/main &&
test_must_fail git checkout -b renamer side^ &&
test $(git symbolic-ref HEAD) = refs/heads/main &&
git diff --exit-code &&
git diff --cached --exit-code
'
test_expect_success 'switch out of non-branch' '
git reset --hard main &&
git checkout main^0 &&
echo modified >one &&
test_must_fail git checkout renamer 2>error.log &&
! grep "^Previous HEAD" error.log
'
(
echo "#!$SHELL_PATH"
cat <<\EOF
O=$1 A=$2 B=$3
cat "$A" >.tmp
exec >"$A"
echo '<<<<<<< filfre-theirs'
cat "$B"
echo '||||||| filfre-common'
cat "$O"
echo '======='
cat ".tmp"
echo '>>>>>>> filfre-ours'
rm -f .tmp
exit 1
EOF
) >filfre.sh
chmod +x filfre.sh
test_expect_success 'custom merge driver with checkout -m' '
git reset --hard &&
git config merge.filfre.driver "./filfre.sh %O %A %B" &&
git config merge.filfre.name "Feel-free merge driver" &&
git config merge.filfre.recursive binary &&
echo "arm merge=filfre" >.gitattributes &&
git checkout -b left &&
echo neutral >arm &&
git add arm .gitattributes &&
test_tick &&
git commit -m neutral &&
git branch right &&
echo left >arm &&
test_tick &&
git commit -a -m left &&
git checkout right &&
echo right >arm &&
test_tick &&
git commit -a -m right &&
test_must_fail git merge left &&
(
for t in filfre-common left right
do
grep $t arm || exit 1
done
) &&
mv arm expect &&
git checkout -m arm &&
test_cmp expect arm
'
test_expect_success 'tracking info copied with autoSetupMerge=inherit' '
git reset --hard main &&
# default config does not copy tracking info
git checkout -b foo-no-inherit koala/bear &&
test_cmp_config "" --default "" branch.foo-no-inherit.remote &&
test_cmp_config "" --default "" branch.foo-no-inherit.merge &&
# with autoSetupMerge=inherit, we copy tracking info from koala/bear
test_config branch.autoSetupMerge inherit &&
git checkout -b foo koala/bear &&
test_cmp_config origin branch.foo.remote &&
test_cmp_config refs/heads/koala/bear branch.foo.merge &&
# no tracking info to inherit from main
git checkout -b main2 main &&
test_cmp_config "" --default "" branch.main2.remote &&
test_cmp_config "" --default "" branch.main2.merge
'
test_done