Code

Documentation: Add diff.<driver>.* to config
[git.git] / builtin / merge.c
index c24a7be020d10540581b41c21a2ecf83df5563d9..f9fb26dc3319200de96181d9e30aad75693d1704 100644 (file)
@@ -57,6 +57,7 @@ static const char *branch;
 static int option_renormalize;
 static int verbosity;
 static int allow_rerere_auto;
+static int abort_current_merge;
 
 static struct strategy all_strategy[] = {
        { "recursive",  DEFAULT_TWOHEAD | NO_TRIVIAL },
@@ -194,9 +195,11 @@ static struct option builtin_merge_options[] = {
        OPT_CALLBACK('X', "strategy-option", &xopts, "option=value",
                "option for selected merge strategy", option_parse_x),
        OPT_CALLBACK('m', "message", &merge_msg, "message",
-               "message to be used for the merge commit (if any)",
+               "merge commit message (for a non-fast-forward merge)",
                option_parse_message),
        OPT__VERBOSITY(&verbosity),
+       OPT_BOOLEAN(0, "abort", &abort_current_merge,
+               "abort the current in-progress merge"),
        OPT_END()
 };
 
@@ -792,6 +795,32 @@ static void add_strategies(const char *string, unsigned attr)
 
 }
 
+static void write_merge_msg(void)
+{
+       int fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666);
+       if (fd < 0)
+               die_errno("Could not open '%s' for writing",
+                         git_path("MERGE_MSG"));
+       if (write_in_full(fd, merge_msg.buf, merge_msg.len) != merge_msg.len)
+               die_errno("Could not write to '%s'", git_path("MERGE_MSG"));
+       close(fd);
+}
+
+static void read_merge_msg(void)
+{
+       strbuf_reset(&merge_msg);
+       if (strbuf_read_file(&merge_msg, git_path("MERGE_MSG"), 0) < 0)
+               die_errno("Could not read from '%s'", git_path("MERGE_MSG"));
+}
+
+static void run_prepare_commit_msg(void)
+{
+       write_merge_msg();
+       run_hook(get_index_file(), "prepare-commit-msg",
+                git_path("MERGE_MSG"), "merge", NULL, NULL);
+       read_merge_msg();
+}
+
 static int merge_trivial(void)
 {
        unsigned char result_tree[20], result_commit[20];
@@ -803,6 +832,7 @@ static int merge_trivial(void)
        parent->next = xmalloc(sizeof(*parent->next));
        parent->next->item = remoteheads->item;
        parent->next->next = NULL;
+       run_prepare_commit_msg();
        commit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL);
        finish(result_commit, "In-index merge");
        drop_save();
@@ -832,6 +862,7 @@ static int finish_automerge(struct commit_list *common,
        }
        free_commit_list(remoteheads);
        strbuf_addch(&merge_msg, '\n');
+       run_prepare_commit_msg();
        commit_tree(merge_msg.buf, result_tree, parents, result_commit, NULL);
        strbuf_addf(&buf, "Merge made by %s.", wt_strategy);
        finish(result_commit, buf.buf);
@@ -919,22 +950,9 @@ 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).");
-       }
+       if (argc == 2 && !strcmp(argv[1], "-h"))
+               usage_with_options(builtin_merge_usage, builtin_merge_options);
 
-       resolve_undo_clear();
        /*
         * Check if we are _not_ on a detached HEAD, i.e. if there is a
         * current branch.
@@ -953,6 +971,34 @@ 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 (abort_current_merge) {
+               int nargc = 2;
+               const char *nargv[] = {"reset", "--merge", NULL};
+
+               if (!file_exists(git_path("MERGE_HEAD")))
+                       die("There is no merge to abort (MERGE_HEAD missing).");
+
+               /* Invoke 'git reset --merge' */
+               return cmd_reset(nargc, nargv, prefix);
+       }
+
+       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;
 
@@ -1298,14 +1344,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                        die_errno("Could not write to '%s'", git_path("MERGE_HEAD"));
                close(fd);
                strbuf_addch(&merge_msg, '\n');
-               fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666);
-               if (fd < 0)
-                       die_errno("Could not open '%s' for writing",
-                                 git_path("MERGE_MSG"));
-               if (write_in_full(fd, merge_msg.buf, merge_msg.len) !=
-                       merge_msg.len)
-                       die_errno("Could not write to '%s'", git_path("MERGE_MSG"));
-               close(fd);
+               write_merge_msg();
                fd = open(git_path("MERGE_MODE"), O_WRONLY | O_CREAT | O_TRUNC, 0666);
                if (fd < 0)
                        die_errno("Could not open '%s' for writing",