diff --git a/builtin/apply.c b/builtin/apply.c index 6c11e8bc73..9706ca73ab 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -3609,7 +3609,6 @@ static void build_fake_ancestor(struct patch *list, const char *filename) * worth showing the new sha1 prefix, but until then... */ for (patch = list; patch; patch = patch->next) { - const unsigned char *sha1_ptr; unsigned char sha1[20]; struct cache_entry *ce; const char *name; @@ -3617,20 +3616,23 @@ static void build_fake_ancestor(struct patch *list, const char *filename) name = patch->old_name ? patch->old_name : patch->new_name; if (0 < patch->is_new) continue; - else if (get_sha1_blob(patch->old_sha1_prefix, sha1)) - /* git diff has no index line for mode/type changes */ - if (!patch->lines_added && !patch->lines_deleted) { - if (get_current_sha1(patch->old_name, sha1)) - die("mode change for %s, which is not " - "in current HEAD", name); - sha1_ptr = sha1; - } else - die("sha1 information is lacking or useless " - "(%s).", name); - else - sha1_ptr = sha1; - ce = make_cache_entry(patch->old_mode, sha1_ptr, name, 0, 0); + if (S_ISGITLINK(patch->old_mode)) { + if (get_sha1_hex(patch->old_sha1_prefix, sha1)) + die("submoule change for %s without full index name", + name); + } else if (!get_sha1_blob(patch->old_sha1_prefix, sha1)) { + ; /* ok */ + } else if (!patch->lines_added && !patch->lines_deleted) { + /* mode-only change: update the current */ + if (get_current_sha1(patch->old_name, sha1)) + die("mode change for %s, which is not " + "in current HEAD", name); + } else + die("sha1 information is lacking or useless " + "(%s).", name); + + ce = make_cache_entry(patch->old_mode, sha1, name, 0, 0); if (!ce) die(_("make_cache_entry failed for path '%s'"), name); if (add_index_entry(&result, ce, ADD_CACHE_OK_TO_ADD)) diff --git a/git-am.sh b/git-am.sh index b4d95f58c6..202130f888 100755 --- a/git-am.sh +++ b/git-am.sh @@ -664,7 +664,7 @@ do sed -e '1,/^$/d' >"$dotest/msg-clean" echo "$commit" >"$dotest/original-commit" get_author_ident_from_commit "$commit" >"$dotest/author-script" - git diff-tree --root --binary "$commit" >"$dotest/patch" + git diff-tree --root --binary --full-index "$commit" >"$dotest/patch" else git mailinfo $keep $no_inbody_headers $scissors $utf8 "$dotest/msg" "$dotest/patch" \ <"$dotest/$msgnum" >"$dotest/info" || diff --git a/t/t7402-submodule-rebase.sh b/t/t7402-submodule-rebase.sh index f919c8d34d..8e32f19007 100755 --- a/t/t7402-submodule-rebase.sh +++ b/t/t7402-submodule-rebase.sh @@ -3,7 +3,7 @@ # Copyright (c) 2008 Johannes Schindelin # -test_description='Test rebasing and stashing with dirty submodules' +test_description='Test rebasing, stashing, etc. with submodules' . ./test-lib.sh @@ -20,7 +20,8 @@ test_expect_success setup ' echo second line >> file && (cd submodule && git pull) && test_tick && - git commit -m file-and-submodule -a + git commit -m file-and-submodule -a && + git branch added-submodule ' @@ -89,4 +90,29 @@ test_expect_success 'stash with a dirty submodule' ' ' +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 && + 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 +' + test_done