mirror of
https://github.com/git/git
synced 2024-08-23 18:00:25 +00:00
![Calvin Wan](/assets/img/avatar_default.png)
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>
124 lines
2.9 KiB
Bash
Executable file
124 lines
2.9 KiB
Bash
Executable file
#!/bin/sh
|
|
#
|
|
# Copyright (c) 2008 Johannes Schindelin
|
|
#
|
|
|
|
test_description='Test rebasing, stashing, etc. with submodules'
|
|
|
|
. ./test-lib.sh
|
|
|
|
test_expect_success setup '
|
|
|
|
echo file > file &&
|
|
git add file &&
|
|
test_tick &&
|
|
git commit -m initial &&
|
|
git clone . submodule &&
|
|
git add submodule &&
|
|
test_tick &&
|
|
git commit -m submodule &&
|
|
echo second line >> file &&
|
|
(cd submodule && git pull) &&
|
|
test_tick &&
|
|
git commit -m file-and-submodule -a &&
|
|
git branch added-submodule
|
|
|
|
'
|
|
|
|
test_expect_success 'rebase with a dirty submodule' '
|
|
|
|
(cd submodule &&
|
|
echo 3rd line >> file &&
|
|
test_tick &&
|
|
git commit -m fork -a) &&
|
|
echo unrelated >> file2 &&
|
|
git add file2 &&
|
|
test_tick &&
|
|
git commit -m unrelated file2 &&
|
|
echo other line >> file &&
|
|
test_tick &&
|
|
git commit -m update file &&
|
|
CURRENT=$(cd submodule && git rev-parse HEAD) &&
|
|
EXPECTED=$(git rev-parse HEAD~2:submodule) &&
|
|
GIT_TRACE=1 git rebase --onto HEAD~2 HEAD^ &&
|
|
STORED=$(git rev-parse HEAD:submodule) &&
|
|
test $EXPECTED = $STORED &&
|
|
test $CURRENT = $(cd submodule && git rev-parse HEAD)
|
|
|
|
'
|
|
|
|
cat > fake-editor.sh << \EOF
|
|
#!/bin/sh
|
|
echo $EDITOR_TEXT
|
|
EOF
|
|
chmod a+x fake-editor.sh
|
|
|
|
test_expect_success 'interactive rebase with a dirty submodule' '
|
|
|
|
test submodule = $(git diff --name-only) &&
|
|
HEAD=$(git rev-parse HEAD) &&
|
|
GIT_EDITOR="\"$(pwd)/fake-editor.sh\"" EDITOR_TEXT="pick $HEAD" \
|
|
git rebase -i HEAD^ &&
|
|
test submodule = $(git diff --name-only)
|
|
|
|
'
|
|
|
|
test_expect_success 'rebase with dirty file and submodule fails' '
|
|
|
|
echo yet another line >> file &&
|
|
test_tick &&
|
|
git commit -m next file &&
|
|
echo rewrite > file &&
|
|
test_tick &&
|
|
git commit -m rewrite file &&
|
|
echo dirty > file &&
|
|
test_must_fail git rebase --onto HEAD~2 HEAD^
|
|
|
|
'
|
|
|
|
test_expect_success 'stash with a dirty submodule' '
|
|
|
|
echo new > file &&
|
|
CURRENT=$(cd submodule && git rev-parse HEAD) &&
|
|
git stash &&
|
|
test new != $(cat file) &&
|
|
test submodule = $(git diff --name-only) &&
|
|
test $CURRENT = $(cd submodule && git rev-parse HEAD) &&
|
|
git stash apply &&
|
|
test new = $(cat file) &&
|
|
test $CURRENT = $(cd submodule && git rev-parse HEAD)
|
|
|
|
'
|
|
|
|
test_expect_success 'rebasing submodule that should conflict' '
|
|
git reset --hard &&
|
|
git checkout added-submodule &&
|
|
git add submodule &&
|
|
test_tick &&
|
|
git commit -m third &&
|
|
(
|
|
cd submodule &&
|
|
git commit --allow-empty -m extra
|
|
) &&
|
|
git add submodule &&
|
|
test_tick &&
|
|
git commit -m fourth &&
|
|
|
|
test_must_fail git rebase --onto HEAD^^ HEAD^ HEAD^0 >actual_output &&
|
|
git ls-files -s submodule >actual &&
|
|
(
|
|
cd submodule &&
|
|
echo "160000 $(git rev-parse HEAD^) 1 submodule" &&
|
|
echo "160000 $(git rev-parse HEAD^^) 2 submodule" &&
|
|
echo "160000 $(git rev-parse HEAD) 3 submodule"
|
|
) >expect &&
|
|
test_cmp expect actual &&
|
|
if test "$GIT_TEST_MERGE_ALGORITHM" = ort
|
|
then
|
|
sub_expect="go to submodule (submodule), and either merge commit $(git -C submodule rev-parse --short HEAD^0)" &&
|
|
grep "$sub_expect" actual_output
|
|
fi
|
|
'
|
|
|
|
test_done
|