mirror of
https://github.com/git/git.git
synced 2024-12-04 07:24:41 +08:00
68d03e4a6e
This implements a simple merge strategy for submodule hashes. We check whether one side of the merge candidates is already contained in the other and then merge automatically. If both sides contain changes we search for a merge in the submodule. In case a single one exists we check that out and suggest it as the merge resolution. A list of candidates is returned when we find multiple merges that contain both sides of the changes. This is useful for a workflow in which the developers can publish topic branches in submodules and a separate maintainer merges them. In case the developers always wait until their branch gets merged before tracking them in the superproject all merges of branches that contain submodule changes will be resolved automatically. If developers choose to track their feature branch the maintainer might get a conflict but git will search the submodule for a merge and suggest it/them as a resolution. Signed-off-by: Heiko Voigt <hvoigt@hvoigt.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
191 lines
3.7 KiB
Bash
Executable File
191 lines
3.7 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
test_description='merging with submodules'
|
|
|
|
. ./test-lib.sh
|
|
|
|
#
|
|
# history
|
|
#
|
|
# a --- c
|
|
# / \ /
|
|
# root X
|
|
# \ / \
|
|
# b --- d
|
|
#
|
|
|
|
test_expect_success setup '
|
|
|
|
mkdir sub &&
|
|
(cd sub &&
|
|
git init &&
|
|
echo original > file &&
|
|
git add file &&
|
|
test_tick &&
|
|
git commit -m sub-root) &&
|
|
git add sub &&
|
|
test_tick &&
|
|
git commit -m root &&
|
|
|
|
git checkout -b a master &&
|
|
(cd sub &&
|
|
echo A > file &&
|
|
git add file &&
|
|
test_tick &&
|
|
git commit -m sub-a) &&
|
|
git add sub &&
|
|
test_tick &&
|
|
git commit -m a &&
|
|
|
|
git checkout -b b master &&
|
|
(cd sub &&
|
|
echo B > file &&
|
|
git add file &&
|
|
test_tick &&
|
|
git commit -m sub-b) &&
|
|
git add sub &&
|
|
test_tick &&
|
|
git commit -m b &&
|
|
|
|
git checkout -b c a &&
|
|
git merge -s ours b &&
|
|
|
|
git checkout -b d b &&
|
|
git merge -s ours a
|
|
'
|
|
|
|
# History setup
|
|
#
|
|
# b
|
|
# / \
|
|
# a d
|
|
# \ /
|
|
# c
|
|
#
|
|
# a in the main repository records to sub-a in the submodule and
|
|
# analogous b and c. d should be automatically found by merging c into
|
|
# b in the main repository.
|
|
test_expect_success 'setup for merge search' '
|
|
mkdir merge-search &&
|
|
cd merge-search &&
|
|
git init &&
|
|
mkdir sub &&
|
|
(cd sub &&
|
|
git init &&
|
|
echo "file-a" > file-a &&
|
|
git add file-a &&
|
|
git commit -m "sub-a" &&
|
|
git branch sub-a) &&
|
|
git add sub &&
|
|
git commit -m "a" &&
|
|
git branch a &&
|
|
|
|
git checkout -b b &&
|
|
(cd sub &&
|
|
git checkout -b sub-b &&
|
|
echo "file-b" > file-b &&
|
|
git add file-b &&
|
|
git commit -m "sub-b") &&
|
|
git commit -a -m "b" &&
|
|
|
|
git checkout -b c a &&
|
|
(cd sub &&
|
|
git checkout -b sub-c sub-a &&
|
|
echo "file-c" > file-c &&
|
|
git add file-c &&
|
|
git commit -m "sub-c") &&
|
|
git commit -a -m "c" &&
|
|
|
|
git checkout -b d a &&
|
|
(cd sub &&
|
|
git checkout -b sub-d sub-b &&
|
|
git merge sub-c) &&
|
|
git commit -a -m "d" &&
|
|
git branch test b &&
|
|
cd ..
|
|
'
|
|
|
|
test_expect_success 'merge with one side as a fast-forward of the other' '
|
|
(cd merge-search &&
|
|
git checkout -b test-forward b &&
|
|
git merge d &&
|
|
git ls-tree test-forward sub | cut -f1 | cut -f3 -d" " > actual &&
|
|
(cd sub &&
|
|
git rev-parse sub-d > ../expect) &&
|
|
test_cmp actual expect)
|
|
'
|
|
|
|
test_expect_success 'merging should conflict for non fast-forward' '
|
|
(cd merge-search &&
|
|
git checkout -b test-nonforward b &&
|
|
(cd sub &&
|
|
git rev-parse sub-d > ../expect) &&
|
|
test_must_fail git merge c 2> actual &&
|
|
grep $(cat expect) actual > /dev/null &&
|
|
git reset --hard)
|
|
'
|
|
|
|
test_expect_success 'merging should fail for ambiguous common parent' '
|
|
cd merge-search &&
|
|
git checkout -b test-ambiguous b &&
|
|
(cd sub &&
|
|
git checkout -b ambiguous sub-b &&
|
|
git merge sub-c &&
|
|
git rev-parse sub-d > ../expect1 &&
|
|
git rev-parse ambiguous > ../expect2) &&
|
|
test_must_fail git merge c 2> actual &&
|
|
grep $(cat expect1) actual > /dev/null &&
|
|
grep $(cat expect2) actual > /dev/null &&
|
|
git reset --hard &&
|
|
cd ..
|
|
'
|
|
|
|
# in a situation like this
|
|
#
|
|
# submodule tree:
|
|
#
|
|
# sub-a --- sub-b --- sub-d
|
|
#
|
|
# main tree:
|
|
#
|
|
# e (sub-a)
|
|
# /
|
|
# bb (sub-b)
|
|
# \
|
|
# f (sub-d)
|
|
#
|
|
# A merge between e and f should fail because one of the submodule
|
|
# commits (sub-a) does not descend from the submodule merge-base (sub-b).
|
|
#
|
|
test_expect_success 'merging should fail for changes that are backwards' '
|
|
cd merge-search &&
|
|
git checkout -b bb a &&
|
|
(cd sub &&
|
|
git checkout sub-b) &&
|
|
git commit -a -m "bb" &&
|
|
|
|
git checkout -b e bb &&
|
|
(cd sub &&
|
|
git checkout sub-a) &&
|
|
git commit -a -m "e" &&
|
|
|
|
git checkout -b f bb &&
|
|
(cd sub &&
|
|
git checkout sub-d) &&
|
|
git commit -a -m "f" &&
|
|
|
|
git checkout -b test-backward e &&
|
|
test_must_fail git merge f &&
|
|
cd ..
|
|
'
|
|
|
|
test_expect_success 'merging with a modify/modify conflict between merge bases' '
|
|
|
|
git reset --hard HEAD &&
|
|
git checkout -b test2 c &&
|
|
git merge d
|
|
|
|
'
|
|
|
|
test_done
|