submodule merge: update conflict error message
When attempting to merge in a superproject with conflicting submodule pointers that cannot be fast-forwarded or trivially resolved, the merge fails and Git prints an error message that accurately describes the failure, but does not provide steps for the user to resolve the error. Git is left in a conflicted state, which requires the user to: 1. merge submodules or update submodules to an already existing commit that reflects the merge 2. add submodules changes to the superproject 3. finish merging superproject These steps are non-obvious for newer submodule users to figure out based on the error message and neither `git submodule status` nor `git status` provide any useful pointers. Update error message to provide steps to resolve submodule merge conflict. Future work could involve adding an advice flag to the message. Although the message is long, it also has the id of the submodule commit that needs to be merged, which could be useful information for the user. Additionally, 5 merge failures that resulted in an early return have been updated to reflect the status of the merge. 1. Null merge base (null o): CONFLICT_SUBMODULE_NULL_MERGE_BASE added as a new conflict type and will print updated error message. 2. Null merge side a (null a): BUG(). See [1] for discussion 3. Null merge side b (null b): BUG(). See [1] for discussion 4. Submodule not checked out: added NEEDSWORK bit 5. Submodule commits not present: added NEEDSWORK bit The errors with a NEEDSWORK bit deserve a more detailed explanation of how to resolve them. See [2] for more context. [1] https://lore.kernel.org/git/CABPp-BE0qGwUy80dmVszkJQ+tcpfLRW0OZyErymzhZ9+HWY1mw@mail.gmail.com/ [2] https://lore.kernel.org/git/xmqqpmhjjwo9.fsf@gitster.g/ Signed-off-by: Calvin Wan <calvinwan@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
committed by
Junio C Hamano
parent
71a8fab31b
commit
4057523a40
@@ -103,8 +103,25 @@ test_expect_success 'setup for merge search' '
|
||||
echo "file-c" > file-c &&
|
||||
git add file-c &&
|
||||
git commit -m "sub-c") &&
|
||||
git commit -a -m "c" &&
|
||||
git commit -a -m "c")
|
||||
'
|
||||
|
||||
test_expect_success 'merging should conflict for non fast-forward' '
|
||||
test_when_finished "git -C merge-search reset --hard" &&
|
||||
(cd merge-search &&
|
||||
git checkout -b test-nonforward-a b &&
|
||||
if test "$GIT_TEST_MERGE_ALGORITHM" = ort
|
||||
then
|
||||
test_must_fail git merge c >actual &&
|
||||
sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" &&
|
||||
grep "$sub_expect" actual
|
||||
else
|
||||
test_must_fail git merge c 2> actual
|
||||
fi)
|
||||
'
|
||||
|
||||
test_expect_success 'finish setup for merge-search' '
|
||||
(cd merge-search &&
|
||||
git checkout -b d a &&
|
||||
(cd sub &&
|
||||
git checkout -b sub-d sub-b &&
|
||||
@@ -129,14 +146,16 @@ test_expect_success 'merge with one side as a fast-forward of the other' '
|
||||
test_cmp expect actual)
|
||||
'
|
||||
|
||||
test_expect_success 'merging should conflict for non fast-forward' '
|
||||
test_expect_success 'merging should conflict for non fast-forward (resolution exists)' '
|
||||
(cd merge-search &&
|
||||
git checkout -b test-nonforward b &&
|
||||
git checkout -b test-nonforward-b b &&
|
||||
(cd sub &&
|
||||
git rev-parse --short sub-d > ../expect) &&
|
||||
if test "$GIT_TEST_MERGE_ALGORITHM" = ort
|
||||
then
|
||||
test_must_fail git merge c >actual
|
||||
test_must_fail git merge c >actual &&
|
||||
sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" &&
|
||||
grep "$sub_expect" actual
|
||||
else
|
||||
test_must_fail git merge c 2> actual
|
||||
fi &&
|
||||
@@ -161,7 +180,9 @@ test_expect_success 'merging should fail for ambiguous common parent' '
|
||||
) &&
|
||||
if test "$GIT_TEST_MERGE_ALGORITHM" = ort
|
||||
then
|
||||
test_must_fail git merge c >actual
|
||||
test_must_fail git merge c >actual &&
|
||||
sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-c)" &&
|
||||
grep "$sub_expect" actual
|
||||
else
|
||||
test_must_fail git merge c 2> actual
|
||||
fi &&
|
||||
@@ -205,7 +226,12 @@ test_expect_success 'merging should fail for changes that are backwards' '
|
||||
git commit -a -m "f" &&
|
||||
|
||||
git checkout -b test-backward e &&
|
||||
test_must_fail git merge f)
|
||||
test_must_fail git merge f >actual &&
|
||||
if test "$GIT_TEST_MERGE_ALGORITHM" = ort
|
||||
then
|
||||
sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short sub-d)" &&
|
||||
grep "$sub_expect" actual
|
||||
fi)
|
||||
'
|
||||
|
||||
|
||||
@@ -476,4 +502,44 @@ test_expect_failure 'directory/submodule conflict; merge --abort works afterward
|
||||
)
|
||||
'
|
||||
|
||||
# Setup:
|
||||
# - Submodule has 2 commits: a and b
|
||||
# - Superproject branch 'a' adds and commits submodule pointing to 'commit a'
|
||||
# - Superproject branch 'b' adds and commits submodule pointing to 'commit b'
|
||||
# If these two branches are now merged, there is no merge base
|
||||
test_expect_success 'setup for null merge base' '
|
||||
mkdir no-merge-base &&
|
||||
(cd no-merge-base &&
|
||||
git init &&
|
||||
mkdir sub &&
|
||||
(cd sub &&
|
||||
git init &&
|
||||
echo "file-a" > file-a &&
|
||||
git add file-a &&
|
||||
git commit -m "commit a") &&
|
||||
git commit --allow-empty -m init &&
|
||||
git branch init &&
|
||||
git checkout -b a init &&
|
||||
git add sub &&
|
||||
git commit -m "a" &&
|
||||
git switch main &&
|
||||
(cd sub &&
|
||||
echo "file-b" > file-b &&
|
||||
git add file-b &&
|
||||
git commit -m "commit b"))
|
||||
'
|
||||
|
||||
test_expect_success 'merging should fail with no merge base' '
|
||||
(cd no-merge-base &&
|
||||
git checkout -b b init &&
|
||||
git add sub &&
|
||||
git commit -m "b" &&
|
||||
test_must_fail git merge a >actual &&
|
||||
if test "$GIT_TEST_MERGE_ALGORITHM" = ort
|
||||
then
|
||||
sub_expect="go to submodule (sub), and either merge commit $(git -C sub rev-parse --short HEAD^1)" &&
|
||||
grep "$sub_expect" actual
|
||||
fi)
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
Reference in New Issue
Block a user