Reorder the initial part of builtin/merge.c:cmd_merge() so that command-line options are parsed _before_ we load the index and check for MERGE_HEAD (and exits if it exists). This does not change the behaviour of 'git merge', but is needed in preparation for the implementation of 'git merge --abort' (which requires MERGE_HEAD to be present). Signed-off-by: Johan Herland <johan@xxxxxxxxxxx> --- builtin/merge.c | 33 ++++++++-------- t/t7609-merge-abort.sh | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 16 deletions(-) create mode 100755 t/t7609-merge-abort.sh diff --git a/builtin/merge.c b/builtin/merge.c index 37ce4f5..702f399 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -895,22 +895,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix) const char *best_strategy = NULL, *wt_strategy = NULL; struct commit_list **remotes = &remoteheads; - if (read_cache_unmerged()) { - die_resolve_conflict("merge"); - } - if (file_exists(git_path("MERGE_HEAD"))) { - /* - * There is no unmerged entry, don't advise 'git - * add/rm <file>', just 'git commit'. - */ - if (advice_resolve_conflict) - die("You have not concluded your merge (MERGE_HEAD exists).\n" - "Please, commit your changes before you can merge."); - else - die("You have not concluded your merge (MERGE_HEAD exists)."); - } - - resolve_undo_clear(); /* * Check if we are _not_ on a detached HEAD, i.e. if there is a * current branch. @@ -929,6 +913,23 @@ int cmd_merge(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, builtin_merge_options, builtin_merge_usage, 0); + + if (read_cache_unmerged()) { + die_resolve_conflict("merge"); + } + if (file_exists(git_path("MERGE_HEAD"))) { + /* + * There is no unmerged entry, don't advise 'git + * add/rm <file>', just 'git commit'. + */ + if (advice_resolve_conflict) + die("You have not concluded your merge (MERGE_HEAD exists).\n" + "Please, commit your changes before you can merge."); + else + die("You have not concluded your merge (MERGE_HEAD exists)."); + } + resolve_undo_clear(); + if (verbosity < 0) show_diffstat = 0; diff --git a/t/t7609-merge-abort.sh b/t/t7609-merge-abort.sh new file mode 100755 index 0000000..88d76e1 --- /dev/null +++ b/t/t7609-merge-abort.sh @@ -0,0 +1,97 @@ +#!/bin/sh + +test_description='test aborting in-progress merges' +. ./test-lib.sh + +# Test git merge --abort with the following variables: +# - before/after successful merge (i.e. should fail if not in merge context) +# - with/without conflicts +# - clean/dirty worktree before merge (may fail to reconstruct dirty worktree) +# - clean/dirty index before merge (merge should fail on dirty index) +# - changed/unchanged worktree after merge +# - changed/unchanged index after merge + +test_done + +test_expect_success 'fails without MERGE_HEAD (unstarted merge)' ' + test_must_fail git merge --abort 2>output && + grep -q MERGE_HEAD output +' + +test_expect_success 'fails without MERGE_HEAD (completed merge)' ' + test_commit master-1 && + test_commit master-2 && + git checkout -b side HEAD^ && + test_commit side-1 && + git checkout master && + git merge side && + # Merge successfully completed + test_must_fail git merge --abort 2>output && + grep -q MERGE_HEAD output +' + +test_expect_success 'Abort successfully after --no-commit' ' + # Forget previous merge + git reset --hard master^ && + head=$(git rev-parse HEAD) && + git merge --no-commit side && + test -f .git/MERGE_HEAD && + git merge --abort && + test "$head" = "$(git rev-parse HEAD)" && + test -z "$(git diff HEAD)" && + test ! -f .git/MERGE_HEAD +' + + + +test_done + +test_expect_success 'merge local branch' ' + test_commit master-1 && + git checkout -b local-branch && + test_commit branch-1 && + git checkout master && + test_commit master-2 && + git merge local-branch && + check_oneline "Merge branch Qlocal-branchQ" +' + +test_expect_success 'merge octopus branches' ' + git checkout -b octopus-a master && + test_commit octopus-1 && + git checkout -b octopus-b master && + test_commit octopus-2 && + git checkout master && + git merge octopus-a octopus-b && + check_oneline "Merge branches Qoctopus-aQ and Qoctopus-bQ" +' + +test_expect_success 'merge tag' ' + git checkout -b tag-branch master && + test_commit tag-1 && + git checkout master && + test_commit master-3 && + git merge tag-1 && + check_oneline "Merge commit Qtag-1Q" +' + +test_expect_success 'ambiguous tag' ' + git checkout -b ambiguous master && + test_commit ambiguous && + git checkout master && + test_commit master-4 && + git merge ambiguous && + check_oneline "Merge commit QambiguousQ" +' + +test_expect_success 'remote branch' ' + git checkout -b remote master && + test_commit remote-1 && + git update-ref refs/remotes/origin/master remote && + git checkout master && + test_commit master-5 && + git merge origin/master && + check_oneline "Merge remote branch Qorigin/masterQ" +' + +test_done -- 1.7.3.98.g5ad7d9 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html