Merge branch 'maint-1.6.1' into maint
[gitweb.git] / builtin-commit.c
index 0c6d1f4f455fb3832809f03fd2748feea143006a..81371b1d2698a48dba36046d7ff9d849f830a762 100644 (file)
 #include "strbuf.h"
 #include "utf8.h"
 #include "parse-options.h"
-#include "path-list.h"
+#include "string-list.h"
+#include "rerere.h"
 #include "unpack-trees.h"
 
 static const char * const builtin_commit_usage[] = {
-       "git-commit [options] [--] <filepattern>...",
+       "git commit [options] [--] <filepattern>...",
        NULL
 };
 
 static const char * const builtin_status_usage[] = {
-       "git-status [options] [--] <filepattern>...",
+       "git status [options] [--] <filepattern>...",
        NULL
 };
 
@@ -50,7 +51,8 @@ static const char *template_file;
 static char *edit_message, *use_message;
 static char *author_name, *author_email, *author_date;
 static int all, edit_flag, also, interactive, only, amend, signoff;
-static int quiet, verbose, untracked_files, no_verify, allow_empty;
+static int quiet, verbose, no_verify, allow_empty;
+static char *untracked_files_arg;
 /*
  * The default commit message cleanup mode will remove the lines
  * beginning with # (shell comments) and leading and trailing
@@ -66,8 +68,8 @@ static enum {
 static char *cleanup_arg;
 
 static int use_editor = 1, initial_commit, in_merge;
-const char *only_include_assumed;
-struct strbuf message;
+static const char *only_include_assumed;
+static struct strbuf message;
 
 static int opt_parse_m(const struct option *opt, const char *arg, int unset)
 {
@@ -76,8 +78,7 @@ static int opt_parse_m(const struct option *opt, const char *arg, int unset)
                strbuf_setlen(buf, 0);
        else {
                strbuf_addstr(buf, arg);
-               strbuf_addch(buf, '\n');
-               strbuf_addch(buf, '\n');
+               strbuf_addstr(buf, "\n\n");
        }
        return 0;
 }
@@ -103,7 +104,7 @@ static struct option builtin_commit_options[] = {
        OPT_BOOLEAN('o', "only", &only, "commit only specified files"),
        OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"),
        OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
-       OPT_BOOLEAN('u', "untracked-files", &untracked_files, "show all untracked files"),
+       { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
        OPT_BOOLEAN(0, "allow-empty", &allow_empty, "ok to record an empty change"),
        OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
 
@@ -148,7 +149,7 @@ static int commit_index_files(void)
  * Take a union of paths in the index and the named tree (typically, "HEAD"),
  * and return the paths that match the given pattern in list.
  */
-static int list_paths(struct path_list *list, const char *with_tree,
+static int list_paths(struct string_list *list, const char *with_tree,
                      const char *prefix, const char **pattern)
 {
        int i;
@@ -165,26 +166,26 @@ static int list_paths(struct path_list *list, const char *with_tree,
                struct cache_entry *ce = active_cache[i];
                if (ce->ce_flags & CE_UPDATE)
                        continue;
-               if (!pathspec_match(pattern, m, ce->name, 0))
+               if (!match_pathspec(pattern, ce->name, ce_namelen(ce), 0, m))
                        continue;
-               path_list_insert(ce->name, list);
+               string_list_insert(ce->name, list);
        }
 
        return report_path_error(m, pattern, prefix ? strlen(prefix) : 0);
 }
 
-static void add_remove_files(struct path_list *list)
+static void add_remove_files(struct string_list *list)
 {
        int i;
        for (i = 0; i < list->nr; i++) {
                struct stat st;
-               struct path_list_item *p = &(list->items[i]);
+               struct string_list_item *p = &(list->items[i]);
 
-               if (!lstat(p->path, &st)) {
-                       if (add_to_cache(p->path, &st, 0))
+               if (!lstat(p->string, &st)) {
+                       if (add_to_cache(p->string, &st, 0))
                                die("updating files failed");
                } else
-                       remove_file_from_cache(p->path);
+                       remove_file_from_cache(p->string);
        }
 }
 
@@ -219,23 +220,24 @@ static void create_base_index(void)
 static char *prepare_index(int argc, const char **argv, const char *prefix)
 {
        int fd;
-       struct path_list partial;
+       struct string_list partial;
        const char **pathspec = NULL;
 
        if (interactive) {
-               interactive_add(argc, argv, prefix);
-               if (read_cache() < 0)
+               if (interactive_add(argc, argv, prefix) != 0)
+                       die("interactive add failed");
+               if (read_cache_preload(NULL) < 0)
                        die("index file corrupt");
                commit_style = COMMIT_AS_IS;
                return get_index_file();
        }
 
-       if (read_cache() < 0)
-               die("index file corrupt");
-
        if (*argv)
                pathspec = get_pathspec(prefix, argv);
 
+       if (read_cache_preload(pathspec) < 0)
+               die("index file corrupt");
+
        /*
         * Non partial, non as-is commit.
         *
@@ -303,7 +305,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)
                die("cannot do a partial commit during a merge.");
 
        memset(&partial, 0, sizeof(partial));
-       partial.strdup_paths = 1;
+       partial.strdup_strings = 1;
        if (list_paths(&partial, initial_commit ? NULL : "HEAD", prefix, pathspec))
                exit(1);
 
@@ -319,7 +321,9 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)
                die("unable to write new_index file");
 
        fd = hold_lock_file_for_update(&false_lock,
-                                      git_path("next-index-%d", getpid()), 1);
+                                      git_path("next-index-%"PRIuMAX,
+                                               (uintmax_t) getpid()),
+                                      LOCK_DIE_ON_ERROR);
 
        create_base_index();
        add_remove_files(&partial);
@@ -348,7 +352,7 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int
                s.reference = "HEAD^1";
        }
        s.verbose = verbose;
-       s.untracked = untracked_files;
+       s.untracked = (show_untracked_files == SHOW_ALL_UNTRACKED_FILES);
        s.index_file = index_file;
        s.fp = fp;
        s.nowarn = nowarn;
@@ -358,40 +362,6 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int
        return s.commitable;
 }
 
-static int run_hook(const char *index_file, const char *name, ...)
-{
-       struct child_process hook;
-       const char *argv[10], *env[2];
-       char index[PATH_MAX];
-       va_list args;
-       int i;
-
-       va_start(args, name);
-       argv[0] = git_path("hooks/%s", name);
-       i = 0;
-       do {
-               if (++i >= ARRAY_SIZE(argv))
-                       die ("run_hook(): too many arguments");
-               argv[i] = va_arg(args, const char *);
-       } while (argv[i]);
-       va_end(args);
-
-       snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
-       env[0] = index;
-       env[1] = NULL;
-
-       if (access(argv[0], X_OK) < 0)
-               return 0;
-
-       memset(&hook, 0, sizeof(hook));
-       hook.argv = argv;
-       hook.no_stdin = 1;
-       hook.stdout_to_stderr = 1;
-       hook.env = env;
-
-       return run_command(&hook);
-}
-
 static int is_a_merge(const unsigned char *sha1)
 {
        struct commit *commit = lookup_commit(sha1);
@@ -447,7 +417,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
 {
        struct stat statbuf;
        int commitable, saved_color_setting;
-       struct strbuf sb;
+       struct strbuf sb = STRBUF_INIT;
        char *buffer;
        FILE *fp;
        const char *hook_arg1 = NULL;
@@ -457,7 +427,6 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
        if (!no_verify && run_hook(index_file, "pre-commit", NULL))
                return 0;
 
-       strbuf_init(&sb, 0);
        if (message.len) {
                strbuf_addbuf(&sb, &message);
                hook_arg1 = "message";
@@ -503,16 +472,16 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
 
        fp = fopen(git_path(commit_editmsg), "w");
        if (fp == NULL)
-               die("could not open %s", git_path(commit_editmsg));
+               die("could not open %s: %s",
+                   git_path(commit_editmsg), strerror(errno));
 
        if (cleanup_mode != CLEANUP_NONE)
                stripspace(&sb, 0);
 
        if (signoff) {
-               struct strbuf sob;
+               struct strbuf sob = STRBUF_INIT;
                int i;
 
-               strbuf_init(&sob, 0);
                strbuf_addstr(&sob, sign_off_header);
                strbuf_addstr(&sob, fmt_name(getenv("GIT_COMMITTER_NAME"),
                                             getenv("GIT_COMMITTER_EMAIL")));
@@ -552,13 +521,18 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
 
                fprintf(fp,
                        "\n"
-                       "# Please enter the commit message for your changes.\n"
-                       "# (Comment lines starting with '#' will ");
+                       "# Please enter the commit message for your changes.");
                if (cleanup_mode == CLEANUP_ALL)
-                       fprintf(fp, "not be included)\n");
+                       fprintf(fp,
+                               " Lines starting\n"
+                               "# with '#' will be ignored, and an empty"
+                               " message aborts the commit.\n");
                else /* CLEANUP_SPACE, that is. */
-                       fprintf(fp, "be kept.\n"
-                               "# You can remove them yourself if you want to)\n");
+                       fprintf(fp,
+                               " Lines starting\n"
+                               "# with '#' will be kept; you may remove them"
+                               " yourself if you want to.\n"
+                               "# An empty message aborts the commit.\n");
                if (only_include_assumed)
                        fprintf(fp, "# %s\n", only_include_assumed);
 
@@ -588,7 +562,6 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
                commitable = run_status(fp, index_file, prefix, 1);
                wt_status_use_color = saved_color_setting;
        } else {
-               struct rev_info rev;
                unsigned char sha1[20];
                const char *parent = "HEAD";
 
@@ -600,16 +573,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
 
                if (get_sha1(parent, sha1))
                        commitable = !!active_nr;
-               else {
-                       init_revisions(&rev, "");
-                       rev.abbrev = 0;
-                       setup_revisions(0, NULL, &rev, parent);
-                       DIFF_OPT_SET(&rev.diffopt, QUIET);
-                       DIFF_OPT_SET(&rev.diffopt, EXIT_WITH_STATUS);
-                       run_diff_index(&rev, 1 /* cached */);
-
-                       commitable = !!DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES);
-               }
+               else
+                       commitable = index_differs_from(parent, 0);
        }
 
        fclose(fp);
@@ -617,7 +582,6 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
        if (!commitable && !in_merge && !allow_empty &&
            !(amend && is_a_merge(head_sha1))) {
                run_status(stdout, index_file, prefix, 0);
-               unlink(commit_editmsg);
                return 0;
        }
 
@@ -644,7 +608,11 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
                char index[PATH_MAX];
                const char *env[2] = { index, NULL };
                snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
-               launch_editor(git_path(commit_editmsg), NULL, env);
+               if (launch_editor(git_path(commit_editmsg), NULL, env)) {
+                       fprintf(stderr,
+                       "Please supply the message using either -m or -F option.\n");
+                       exit(1);
+               }
        }
 
        if (!no_verify &&
@@ -656,20 +624,19 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
 }
 
 /*
- * Find out if the message starting at position 'start' in the strbuf
- * contains only whitespace and Signed-off-by lines.
+ * Find out if the message in the strbuf contains only whitespace and
+ * Signed-off-by lines.
  */
-static int message_is_empty(struct strbuf *sb, int start)
+static int message_is_empty(struct strbuf *sb)
 {
-       struct strbuf tmpl;
+       struct strbuf tmpl = STRBUF_INIT;
        const char *nl;
-       int eol, i;
+       int eol, i, start = 0;
 
        if (cleanup_mode == CLEANUP_NONE && sb->len)
                return 0;
 
        /* See if the template is just a prefix of the message. */
-       strbuf_init(&tmpl, 0);
        if (template_file && strbuf_read_file(&tmpl, template_file, 0) > 0) {
                stripspace(&tmpl, cleanup_mode == CLEANUP_ALL);
                if (start + tmpl.len <= sb->len &&
@@ -699,6 +666,31 @@ static int message_is_empty(struct strbuf *sb, int start)
        return 1;
 }
 
+static const char *find_author_by_nickname(const char *name)
+{
+       struct rev_info revs;
+       struct commit *commit;
+       struct strbuf buf = STRBUF_INIT;
+       const char *av[20];
+       int ac = 0;
+
+       init_revisions(&revs, NULL);
+       strbuf_addf(&buf, "--author=%s", name);
+       av[++ac] = "--all";
+       av[++ac] = "-i";
+       av[++ac] = buf.buf;
+       av[++ac] = NULL;
+       setup_revisions(ac, av, &revs, NULL);
+       prepare_revision_walk(&revs);
+       commit = get_revision(&revs);
+       if (commit) {
+               strbuf_release(&buf);
+               format_commit_message(commit, "%an <%ae>", &buf, DATE_NORMAL);
+               return strbuf_detach(&buf, NULL);
+       }
+       die("No existing author found with '%s'", name);
+}
+
 static int parse_and_validate_options(int argc, const char *argv[],
                                      const char * const usage[],
                                      const char *prefix)
@@ -709,6 +701,9 @@ static int parse_and_validate_options(int argc, const char *argv[],
        logfile = parse_options_fix_filename(prefix, logfile);
        template_file = parse_options_fix_filename(prefix, template_file);
 
+       if (force_author && !strchr(force_author, '>'))
+               force_author = find_author_by_nickname(force_author);
+
        if (logfile || message.len || use_message)
                use_editor = 0;
        if (edit_flag)
@@ -799,6 +794,17 @@ static int parse_and_validate_options(int argc, const char *argv[],
        else
                die("Invalid cleanup mode %s", cleanup_arg);
 
+       if (!untracked_files_arg)
+               ; /* default already initialized */
+       else if (!strcmp(untracked_files_arg, "no"))
+               show_untracked_files = SHOW_NO_UNTRACKED_FILES;
+       else if (!strcmp(untracked_files_arg, "normal"))
+               show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
+       else if (!strcmp(untracked_files_arg, "all"))
+               show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
+       else
+               die("Invalid untracked files mode '%s'", untracked_files_arg);
+
        if (all && argc > 0)
                die("Paths with -a does not make sense.");
        else if (interactive && argc > 0)
@@ -817,6 +823,9 @@ int cmd_status(int argc, const char **argv, const char *prefix)
        if (wt_status_use_color == -1)
                wt_status_use_color = git_use_color_default;
 
+       if (diff_use_color_default == -1)
+               diff_use_color_default = git_use_color_default;
+
        argc = parse_and_validate_options(argc, argv, builtin_status_usage, prefix);
 
        index_file = prepare_index(argc, argv, prefix);
@@ -832,6 +841,9 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
 {
        struct rev_info rev;
        struct commit *commit;
+       static const char *format = "format:%h] %s";
+       unsigned char junk_sha1[20];
+       const char *head = resolve_ref("HEAD", junk_sha1, 0, NULL);
 
        commit = lookup_commit(sha1);
        if (!commit)
@@ -849,24 +861,30 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
 
        rev.verbose_header = 1;
        rev.show_root_diff = 1;
-       get_commit_format("format:%h: %s", &rev);
+       get_commit_format(format, &rev);
        rev.always_show_header = 0;
        rev.diffopt.detect_rename = 1;
        rev.diffopt.rename_limit = 100;
        rev.diffopt.break_opt = 0;
        diff_setup_done(&rev.diffopt);
 
-       printf("Created %scommit ", initial_commit ? "initial " : "");
+       printf("[%s%s ",
+               !prefixcmp(head, "refs/heads/") ?
+                       head + 11 :
+                       !strcmp(head, "HEAD") ?
+                               "detached HEAD" :
+                               head,
+               initial_commit ? " (root-commit)" : "");
 
        if (!log_tree_commit(&rev, commit)) {
                struct strbuf buf = STRBUF_INIT;
-               format_commit_message(commit, "%h: %s", &buf);
+               format_commit_message(commit, format + 7, &buf, DATE_NORMAL);
                printf("%s\n", buf.buf);
                strbuf_release(&buf);
        }
 }
 
-int git_commit_config(const char *k, const char *v, void *cb)
+static int git_commit_config(const char *k, const char *v, void *cb)
 {
        if (!strcmp(k, "commit.template"))
                return git_config_string(&template_file, k, v);
@@ -874,42 +892,22 @@ int git_commit_config(const char *k, const char *v, void *cb)
        return git_status_config(k, v, cb);
 }
 
-static const char commit_utf8_warn[] =
-"Warning: commit message does not conform to UTF-8.\n"
-"You may want to amend it after fixing the message, or set the config\n"
-"variable i18n.commitencoding to the encoding your project uses.\n";
-
-static void add_parent(struct strbuf *sb, const unsigned char *sha1)
-{
-       struct object *obj = parse_object(sha1);
-       const char *parent = sha1_to_hex(sha1);
-       const char *cp;
-
-       if (!obj)
-               die("Unable to find commit parent %s", parent);
-       if (obj->type != OBJ_COMMIT)
-               die("Parent %s isn't a proper commit", parent);
-
-       for (cp = sb->buf; cp && (cp = strstr(cp, "\nparent ")); cp += 8) {
-               if (!memcmp(cp + 8, parent, 40) && cp[48] == '\n') {
-                       error("duplicate parent %s ignored", parent);
-                       return;
-               }
-       }
-       strbuf_addf(sb, "parent %s\n", parent);
-}
-
 int cmd_commit(int argc, const char **argv, const char *prefix)
 {
-       int header_len;
-       struct strbuf sb;
+       struct strbuf sb = STRBUF_INIT;
        const char *index_file, *reflog_msg;
        char *nl, *p;
        unsigned char commit_sha1[20];
        struct ref_lock *ref_lock;
+       struct commit_list *parents = NULL, **pptr = &parents;
+       struct stat statbuf;
+       int allow_fast_forward = 1;
 
        git_config(git_commit_config, NULL);
 
+       if (wt_status_use_color == -1)
+               wt_status_use_color = git_use_color_default;
+
        argc = parse_and_validate_options(argc, argv, builtin_commit_usage, prefix);
 
        index_file = prepare_index(argc, argv, prefix);
@@ -921,13 +919,6 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                return 1;
        }
 
-       /*
-        * The commit object
-        */
-       strbuf_init(&sb, 0);
-       strbuf_addf(&sb, "tree %s\n",
-                   sha1_to_hex(active_cache_tree->sha1));
-
        /* Determine parents */
        if (initial_commit) {
                reflog_msg = "commit (initial)";
@@ -941,14 +932,13 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                        die("could not parse HEAD commit");
 
                for (c = commit->parents; c; c = c->next)
-                       add_parent(&sb, c->item->object.sha1);
+                       pptr = &commit_list_insert(c->item, pptr)->next;
        } else if (in_merge) {
-               struct strbuf m;
+               struct strbuf m = STRBUF_INIT;
                FILE *fp;
 
                reflog_msg = "commit (merge)";
-               add_parent(&sb, head_sha1);
-               strbuf_init(&m, 0);
+               pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
                fp = fopen(git_path("MERGE_HEAD"), "r");
                if (fp == NULL)
                        die("could not open %s for reading: %s",
@@ -957,45 +947,49 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                        unsigned char sha1[20];
                        if (get_sha1_hex(m.buf, sha1) < 0)
                                die("Corrupt MERGE_HEAD file (%s)", m.buf);
-                       add_parent(&sb, sha1);
+                       pptr = &commit_list_insert(lookup_commit(sha1), pptr)->next;
                }
                fclose(fp);
                strbuf_release(&m);
+               if (!stat(git_path("MERGE_MODE"), &statbuf)) {
+                       if (strbuf_read_file(&sb, git_path("MERGE_MODE"), 0) < 0)
+                               die("could not read MERGE_MODE: %s",
+                                               strerror(errno));
+                       if (!strcmp(sb.buf, "no-ff"))
+                               allow_fast_forward = 0;
+               }
+               if (allow_fast_forward)
+                       parents = reduce_heads(parents);
        } else {
                reflog_msg = "commit";
-               strbuf_addf(&sb, "parent %s\n", sha1_to_hex(head_sha1));
+               pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
        }
 
-       strbuf_addf(&sb, "author %s\n",
-                   fmt_ident(author_name, author_email, author_date, IDENT_ERROR_ON_NO_NAME));
-       strbuf_addf(&sb, "committer %s\n", git_committer_info(IDENT_ERROR_ON_NO_NAME));
-       if (!is_encoding_utf8(git_commit_encoding))
-               strbuf_addf(&sb, "encoding %s\n", git_commit_encoding);
-       strbuf_addch(&sb, '\n');
-
        /* Finally, get the commit message */
-       header_len = sb.len;
+       strbuf_reset(&sb);
        if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {
                rollback_index_files();
                die("could not read commit message");
        }
 
        /* Truncate the message just before the diff, if any. */
-       p = strstr(sb.buf, "\ndiff --git a/");
-       if (p != NULL)
-               strbuf_setlen(&sb, p - sb.buf + 1);
+       if (verbose) {
+               p = strstr(sb.buf, "\ndiff --git ");
+               if (p != NULL)
+                       strbuf_setlen(&sb, p - sb.buf + 1);
+       }
 
        if (cleanup_mode != CLEANUP_NONE)
                stripspace(&sb, cleanup_mode == CLEANUP_ALL);
-       if (sb.len < header_len || message_is_empty(&sb, header_len)) {
+       if (message_is_empty(&sb)) {
                rollback_index_files();
-               die("no commit message?  aborting commit.");
+               fprintf(stderr, "Aborting commit due to empty commit message.\n");
+               exit(1);
        }
-       strbuf_addch(&sb, '\0');
-       if (is_encoding_utf8(git_commit_encoding) && !is_utf8(sb.buf))
-               fprintf(stderr, commit_utf8_warn);
 
-       if (write_sha1_file(sb.buf, sb.len - 1, commit_type, commit_sha1)) {
+       if (commit_tree(sb.buf, active_cache_tree->sha1, parents, commit_sha1,
+                       fmt_ident(author_name, author_email, author_date,
+                               IDENT_ERROR_ON_NO_NAME))) {
                rollback_index_files();
                die("failed to write commit object");
        }
@@ -1004,12 +998,11 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                                           initial_commit ? NULL : head_sha1,
                                           0);
 
-       nl = strchr(sb.buf + header_len, '\n');
+       nl = strchr(sb.buf, '\n');
        if (nl)
                strbuf_setlen(&sb, nl + 1 - sb.buf);
        else
                strbuf_addch(&sb, '\n');
-       strbuf_remove(&sb, 0, header_len);
        strbuf_insert(&sb, 0, reflog_msg, strlen(reflog_msg));
        strbuf_insert(&sb, strlen(reflog_msg), ": ", 2);
 
@@ -1024,6 +1017,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 
        unlink(git_path("MERGE_HEAD"));
        unlink(git_path("MERGE_MSG"));
+       unlink(git_path("MERGE_MODE"));
        unlink(git_path("SQUASH_MSG"));
 
        if (commit_index_files())