]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'dl/opt-callback-cleanup'
authorJunio C Hamano <gitster@pobox.com>
Tue, 5 May 2020 21:54:27 +0000 (14:54 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 5 May 2020 21:54:27 +0000 (14:54 -0700)
Code cleanup.

* dl/opt-callback-cleanup:
  Use OPT_CALLBACK and OPT_CALLBACK_F

1  2 
builtin/blame.c
builtin/clean.c
builtin/commit.c
builtin/grep.c
builtin/log.c
builtin/ls-files.c
builtin/merge.c
builtin/pull.c
builtin/push.c
builtin/rebase.c

diff --combined builtin/blame.c
index 3c13634f2794b8a21b27125e842d4b646bb19fd0,6d86831f2dd9a3de6cf28173073bd1d602935866..94ef57c1cc304963452772e24125e5939dff0481
@@@ -864,8 -864,8 +864,8 @@@ int cmd_blame(int argc, const char **ar
                OPT_BIT(0, "minimal", &xdl_opts, N_("Spend extra cycles to find better match"), XDF_NEED_MINIMAL),
                OPT_STRING('S', NULL, &revs_file, N_("file"), N_("Use revisions from <file> instead of calling git-rev-list")),
                OPT_STRING(0, "contents", &contents_from, N_("file"), N_("Use <file>'s contents as the final image")),
-               { OPTION_CALLBACK, 'C', NULL, &opt, N_("score"), N_("Find line copies within and across files"), PARSE_OPT_OPTARG, blame_copy_callback },
-               { OPTION_CALLBACK, 'M', NULL, &opt, N_("score"), N_("Find line movements within and across files"), PARSE_OPT_OPTARG, blame_move_callback },
+               OPT_CALLBACK_F('C', NULL, &opt, N_("score"), N_("Find line copies within and across files"), PARSE_OPT_OPTARG, blame_copy_callback),
+               OPT_CALLBACK_F('M', NULL, &opt, N_("score"), N_("Find line movements within and across files"), PARSE_OPT_OPTARG, blame_move_callback),
                OPT_STRING_LIST('L', NULL, &range_list, N_("n,m"), N_("Process only line range n,m, counting from 1")),
                OPT__ABBREV(&abbrev),
                OPT_END()
@@@ -1061,14 -1061,6 +1061,14 @@@ parse_done
        string_list_clear(&ignore_revs_file_list, 0);
        string_list_clear(&ignore_rev_list, 0);
        setup_scoreboard(&sb, path, &o);
 +
 +      /*
 +       * Changed-path Bloom filters are disabled when looking
 +       * for copies.
 +       */
 +      if (!(opt & PICKAXE_BLAME_COPY))
 +              setup_blame_bloom_data(&sb, path);
 +
        lno = sb.num_lines;
  
        if (lno && !range_list.nr)
                printf("num get patch: %d\n", sb.num_get_patch);
                printf("num commits: %d\n", sb.num_commits);
        }
 +
 +      cleanup_scoreboard(&sb);
        return 0;
  }
diff --combined builtin/clean.c
index f14c21b8638db70a5fa070096f7853e9900b5edd,46664c1c85f1f8a888601c548a361891968439cd..4ca12bc0c0ba2c3bc3084a320835cf83600173ce
@@@ -906,8 -906,8 +906,8 @@@ int cmd_clean(int argc, const char **ar
                OPT_BOOL('i', "interactive", &interactive, N_("interactive cleaning")),
                OPT_BOOL('d', NULL, &remove_directories,
                                N_("remove whole directories")),
-               { OPTION_CALLBACK, 'e', "exclude", &exclude_list, N_("pattern"),
-                 N_("add <pattern> to ignore rules"), PARSE_OPT_NONEG, exclude_cb },
+               OPT_CALLBACK_F('e', "exclude", &exclude_list, N_("pattern"),
+                 N_("add <pattern> to ignore rules"), PARSE_OPT_NONEG, exclude_cb),
                OPT_BOOL('x', NULL, &ignored, N_("remove ignored files, too")),
                OPT_BOOL('X', NULL, &ignored_only,
                                N_("remove only ignored files")),
                if (!cache_name_is_other(ent->name, ent->len))
                        continue;
  
 -              if (pathspec.nr)
 -                      matches = dir_path_match(&the_index, ent, &pathspec, 0, NULL);
 -
 -              if (pathspec.nr && !matches)
 -                      continue;
 -
                if (lstat(ent->name, &st))
                        die_errno("Cannot lstat '%s'", ent->name);
  
diff --combined builtin/commit.c
index 4743ea5a4cc77030620a33db2a27bee72192404c,8c8620a18cb64e5d6e926b1cbb510b78358e63ea..a73de0a4c529f658c04e6a2a453b93c1c70718c8
@@@ -1372,9 -1372,9 +1372,9 @@@ int cmd_status(int argc, const char **a
                         N_("show stash information")),
                OPT_BOOL(0, "ahead-behind", &s.ahead_behind_flags,
                         N_("compute full ahead/behind values")),
-               { OPTION_CALLBACK, 0, "porcelain", &status_format,
+               OPT_CALLBACK_F(0, "porcelain", &status_format,
                  N_("version"), N_("machine-readable output"),
-                 PARSE_OPT_OPTARG, opt_parse_porcelain },
+                 PARSE_OPT_OPTARG, opt_parse_porcelain),
                OPT_SET_INT(0, "long", &status_format,
                            N_("show status in long format (default)"),
                            STATUS_FORMAT_LONG),
                  PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
                OPT_COLUMN(0, "column", &s.colopts, N_("list untracked files in columns")),
                OPT_BOOL(0, "no-renames", &no_renames, N_("do not detect renames")),
-               { OPTION_CALLBACK, 'M', "find-renames", &rename_score_arg,
+               OPT_CALLBACK_F('M', "find-renames", &rename_score_arg,
                  N_("n"), N_("detect renames, optionally set similarity index"),
-                 PARSE_OPT_OPTARG | PARSE_OPT_NONEG, opt_parse_rename_score },
+                 PARSE_OPT_OPTARG | PARSE_OPT_NONEG, opt_parse_rename_score),
                OPT_END(),
        };
  
@@@ -1700,7 -1700,9 +1700,7 @@@ int cmd_commit(int argc, const char **a
                      "new_index file. Check that disk is not full and quota is\n"
                      "not exceeded, and then \"git restore --staged :/\" to recover."));
  
 -      if (git_env_bool(GIT_TEST_COMMIT_GRAPH, 0) &&
 -          write_commit_graph_reachable(the_repository->objects->odb, 0, NULL))
 -              return 1;
 +      git_test_write_commit_graph_or_die();
  
        repo_rerere(the_repository, 0);
        run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
                                     &oid, flags);
        }
  
 +      apply_autostash(git_path_merge_autostash(the_repository));
 +
        UNLEAK(err);
        UNLEAK(sb);
        return 0;
diff --combined builtin/grep.c
index 5e150f5825b3a549c8b676a3cf91e23d9a72a85c,6216e43a029b981820ced580ecec9354e4ef090a..a5056f395aae16e21b032592558f4389b6953294
@@@ -295,38 -295,6 +295,38 @@@ static int grep_cmd_config(const char *
        return st;
  }
  
 +static void grep_source_name(struct grep_opt *opt, const char *filename,
 +                           int tree_name_len, struct strbuf *out)
 +{
 +      strbuf_reset(out);
 +
 +      if (opt->null_following_name) {
 +              if (opt->relative && opt->prefix_length) {
 +                      struct strbuf rel_buf = STRBUF_INIT;
 +                      const char *rel_name =
 +                              relative_path(filename + tree_name_len,
 +                                            opt->prefix, &rel_buf);
 +
 +                      if (tree_name_len)
 +                              strbuf_add(out, filename, tree_name_len);
 +
 +                      strbuf_addstr(out, rel_name);
 +                      strbuf_release(&rel_buf);
 +              } else {
 +                      strbuf_addstr(out, filename);
 +              }
 +              return;
 +      }
 +
 +      if (opt->relative && opt->prefix_length)
 +              quote_path_relative(filename + tree_name_len, opt->prefix, out);
 +      else
 +              quote_c_style(filename + tree_name_len, out, NULL, 0);
 +
 +      if (tree_name_len)
 +              strbuf_insert(out, 0, filename, tree_name_len);
 +}
 +
  static int grep_oid(struct grep_opt *opt, const struct object_id *oid,
                     const char *filename, int tree_name_len,
                     const char *path)
        struct strbuf pathbuf = STRBUF_INIT;
        struct grep_source gs;
  
 -      if (opt->relative && opt->prefix_length) {
 -              quote_path_relative(filename + tree_name_len, opt->prefix, &pathbuf);
 -              strbuf_insert(&pathbuf, 0, filename, tree_name_len);
 -      } else {
 -              strbuf_addstr(&pathbuf, filename);
 -      }
 -
 +      grep_source_name(opt, filename, tree_name_len, &pathbuf);
        grep_source_init(&gs, GREP_SOURCE_OID, pathbuf.buf, path, oid);
        strbuf_release(&pathbuf);
  
@@@ -360,7 -334,11 +360,7 @@@ static int grep_file(struct grep_opt *o
        struct strbuf buf = STRBUF_INIT;
        struct grep_source gs;
  
 -      if (opt->relative && opt->prefix_length)
 -              quote_path_relative(filename, opt->prefix, &buf);
 -      else
 -              strbuf_addstr(&buf, filename);
 -
 +      grep_source_name(opt, filename, 0, &buf);
        grep_source_init(&gs, GREP_SOURCE_FILE, buf.buf, filename, filename);
        strbuf_release(&buf);
  
@@@ -701,6 -679,8 +701,6 @@@ static int grep_directory(struct grep_o
  
        fill_directory(&dir, opt->repo->index, pathspec);
        for (i = 0; i < dir.nr; i++) {
 -              if (!dir_path_match(opt->repo->index, dir.entries[i], pathspec, 0, NULL))
 -                      continue;
                hit |= grep_file(opt, dir.entries[i]->name);
                if (hit && opt->status_only)
                        break;
@@@ -906,20 -886,20 +906,20 @@@ int cmd_grep(int argc, const char **arg
                OPT_GROUP(""),
                OPT_CALLBACK('f', NULL, &opt, N_("file"),
                        N_("read patterns from file"), file_callback),
-               { OPTION_CALLBACK, 'e', NULL, &opt, N_("pattern"),
-                       N_("match <pattern>"), PARSE_OPT_NONEG, pattern_callback },
-               { OPTION_CALLBACK, 0, "and", &opt, NULL,
-                 N_("combine patterns specified with -e"),
-                 PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback },
+               OPT_CALLBACK_F('e', NULL, &opt, N_("pattern"),
+                       N_("match <pattern>"), PARSE_OPT_NONEG, pattern_callback),
+               OPT_CALLBACK_F(0, "and", &opt, NULL,
+                       N_("combine patterns specified with -e"),
+                       PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback),
                OPT_BOOL(0, "or", &dummy, ""),
-               { OPTION_CALLBACK, 0, "not", &opt, NULL, "",
-                 PARSE_OPT_NOARG | PARSE_OPT_NONEG, not_callback },
-               { OPTION_CALLBACK, '(', NULL, &opt, NULL, "",
-                 PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
-                 open_callback },
-               { OPTION_CALLBACK, ')', NULL, &opt, NULL, "",
-                 PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
-                 close_callback },
+               OPT_CALLBACK_F(0, "not", &opt, NULL, "",
+                       PARSE_OPT_NOARG | PARSE_OPT_NONEG, not_callback),
+               OPT_CALLBACK_F('(', NULL, &opt, NULL, "",
+                       PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
+                       open_callback),
+               OPT_CALLBACK_F(')', NULL, &opt, NULL, "",
+                       PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
+                       close_callback),
                OPT__QUIET(&opt.status_only,
                           N_("indicate hit with exit status without output")),
                OPT_BOOL(0, "all-match", &opt.all_match,
diff --combined builtin/log.c
index bef7403d5e4abc7f2de1cb39789715a380655add,911d68c2dca1f5b63fb46d1559bbb3e614269c21..d104d5c6889ba2d2ffaaeafa08fbfcd759d8bc92
@@@ -166,24 -166,21 +166,24 @@@ static void cmd_log_init_finish(int arg
        int quiet = 0, source = 0, mailmap;
        static struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};
        static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;
 +      static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;
        static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;
        struct decoration_filter decoration_filter = {&decorate_refs_include,
 -                                                    &decorate_refs_exclude};
 +                                                    &decorate_refs_exclude,
 +                                                    &decorate_refs_exclude_config};
        static struct revision_sources revision_sources;
  
        const struct option builtin_log_options[] = {
                OPT__QUIET(&quiet, N_("suppress diff output")),
                OPT_BOOL(0, "source", &source, N_("show source")),
                OPT_BOOL(0, "use-mailmap", &mailmap, N_("Use mail map file")),
 +              OPT_ALIAS(0, "mailmap", "use-mailmap"),
                OPT_STRING_LIST(0, "decorate-refs", &decorate_refs_include,
                                N_("pattern"), N_("only decorate refs that match <pattern>")),
                OPT_STRING_LIST(0, "decorate-refs-exclude", &decorate_refs_exclude,
                                N_("pattern"), N_("do not decorate refs that match <pattern>")),
-               { OPTION_CALLBACK, 0, "decorate", NULL, NULL, N_("decorate options"),
-                 PARSE_OPT_OPTARG, decorate_callback},
+               OPT_CALLBACK_F(0, "decorate", NULL, NULL, N_("decorate options"),
+                              PARSE_OPT_OPTARG, decorate_callback),
                OPT_CALLBACK('L', NULL, &line_cb, "n,m:file",
                             N_("Process line range n,m in file, counting from 1"),
                             log_line_range_callback),
        }
  
        if (decoration_style) {
 +              const struct string_list *config_exclude =
 +                      repo_config_get_value_multi(the_repository,
 +                                                  "log.excludeDecoration");
 +
 +              if (config_exclude) {
 +                      struct string_list_item *item;
 +                      for_each_string_list_item(item, config_exclude)
 +                              string_list_append(&decorate_refs_exclude_config,
 +                                                 item->string);
 +              }
 +
                rev->show_decorations = 1;
 +
                load_ref_decorations(&decoration_filter, decoration_style);
        }
  
@@@ -1646,12 -1631,12 +1646,12 @@@ int cmd_format_patch(int argc, const ch
        int creation_factor = -1;
  
        const struct option builtin_format_patch_options[] = {
-               { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
+               OPT_CALLBACK_F('n', "numbered", &numbered, NULL,
                            N_("use [PATCH n/m] even with a single patch"),
-                           PARSE_OPT_NOARG, numbered_callback },
-               { OPTION_CALLBACK, 'N', "no-numbered", &numbered, NULL,
+                           PARSE_OPT_NOARG, numbered_callback),
+               OPT_CALLBACK_F('N', "no-numbered", &numbered, NULL,
                            N_("use [PATCH] even with multiple patches"),
-                           PARSE_OPT_NOARG | PARSE_OPT_NONEG, no_numbered_callback },
+                           PARSE_OPT_NOARG | PARSE_OPT_NONEG, no_numbered_callback),
                OPT_BOOL('s', "signoff", &do_signoff, N_("add Signed-off-by:")),
                OPT_BOOL(0, "stdout", &use_stdout,
                            N_("print patches to standard out")),
                            N_("start numbering patches at <n> instead of 1")),
                OPT_INTEGER('v', "reroll-count", &reroll_count,
                            N_("mark the series as Nth re-roll")),
-               { OPTION_CALLBACK, 0, "rfc", &rev, NULL,
+               OPT_CALLBACK_F(0, "rfc", &rev, NULL,
                            N_("Use [RFC PATCH] instead of [PATCH]"),
-                           PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback },
+                           PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback),
                OPT_STRING(0, "cover-from-description", &cover_from_description_arg,
                            N_("cover-from-description-mode"),
                            N_("generate parts of a cover letter based on a branch's description")),
-               { OPTION_CALLBACK, 0, "subject-prefix", &rev, N_("prefix"),
+               OPT_CALLBACK_F(0, "subject-prefix", &rev, N_("prefix"),
                            N_("Use [<prefix>] instead of [PATCH]"),
-                           PARSE_OPT_NONEG, subject_prefix_callback },
-               { OPTION_CALLBACK, 'o', "output-directory", &output_directory,
+                           PARSE_OPT_NONEG, subject_prefix_callback),
+               OPT_CALLBACK_F('o', "output-directory", &output_directory,
                            N_("dir"), N_("store resulting files in <dir>"),
-                           PARSE_OPT_NONEG, output_directory_callback },
-               { OPTION_CALLBACK, 'k', "keep-subject", &rev, NULL,
+                           PARSE_OPT_NONEG, output_directory_callback),
+               OPT_CALLBACK_F('k', "keep-subject", &rev, NULL,
                            N_("don't strip/add [PATCH]"),
-                           PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback },
+                           PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback),
                OPT_BOOL(0, "no-binary", &no_binary_diff,
                         N_("don't output binary diffs")),
                OPT_BOOL(0, "zero-commit", &zero_commit,
                              N_("show patch format instead of default (patch + stat)"),
                              1, PARSE_OPT_NONEG),
                OPT_GROUP(N_("Messaging")),
-               { OPTION_CALLBACK, 0, "add-header", NULL, N_("header"),
-                           N_("add email header"), 0, header_callback },
-               { OPTION_CALLBACK, 0, "to", NULL, N_("email"), N_("add To: header"),
-                           0, to_callback },
-               { OPTION_CALLBACK, 0, "cc", NULL, N_("email"), N_("add Cc: header"),
-                           0, cc_callback },
-               { OPTION_CALLBACK, 0, "from", &from, N_("ident"),
+               OPT_CALLBACK(0, "add-header", NULL, N_("header"),
+                           N_("add email header"), header_callback),
+               OPT_CALLBACK(0, "to", NULL, N_("email"), N_("add To: header"), to_callback),
+               OPT_CALLBACK(0, "cc", NULL, N_("email"), N_("add Cc: header"), cc_callback),
+               OPT_CALLBACK_F(0, "from", &from, N_("ident"),
                            N_("set From address to <ident> (or committer ident if absent)"),
-                           PARSE_OPT_OPTARG, from_callback },
+                           PARSE_OPT_OPTARG, from_callback),
                OPT_STRING(0, "in-reply-to", &in_reply_to, N_("message-id"),
                            N_("make first mail a reply to <message-id>")),
-               { OPTION_CALLBACK, 0, "attach", &rev, N_("boundary"),
+               OPT_CALLBACK_F(0, "attach", &rev, N_("boundary"),
                            N_("attach the patch"), PARSE_OPT_OPTARG,
-                           attach_callback },
-               { OPTION_CALLBACK, 0, "inline", &rev, N_("boundary"),
+                           attach_callback),
+               OPT_CALLBACK_F(0, "inline", &rev, N_("boundary"),
                            N_("inline the patch"),
                            PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
-                           inline_callback },
-               { OPTION_CALLBACK, 0, "thread", &thread, N_("style"),
+                           inline_callback),
+               OPT_CALLBACK_F(0, "thread", &thread, N_("style"),
                            N_("enable message threading, styles: shallow, deep"),
-                           PARSE_OPT_OPTARG, thread_callback },
+                           PARSE_OPT_OPTARG, thread_callback),
                OPT_STRING(0, "signature", &signature, N_("signature"),
                            N_("add a signature")),
                OPT_STRING(0, "base", &base_commit, N_("base-commit"),
diff --combined builtin/ls-files.c
index b87c22ac240834426e50c430ae1222f6866dc4b9,9ab9db7c59265241f13a077d7fd8d48453a8ebbc..30a4c10334982e9ea34729a979a83027fa83c940
@@@ -128,9 -128,8 +128,9 @@@ static void show_dir_entry(const struc
        if (len > ent->len)
                die("git ls-files: internal error - directory entry not superset of prefix");
  
 -      if (!dir_path_match(istate, ent, &pathspec, len, ps_matched))
 -              return;
 +      /* If ps_matches is non-NULL, figure out which pathspec(s) match. */
 +      if (ps_matched)
 +              dir_path_match(istate, ent, &pathspec, len, ps_matched);
  
        fputs(tag, stdout);
        write_eolinfo(istate, NULL, ent->name);
@@@ -555,18 -554,18 +555,18 @@@ int cmd_ls_files(int argc, const char *
                        N_("show unmerged files in the output")),
                OPT_BOOL(0, "resolve-undo", &show_resolve_undo,
                            N_("show resolve-undo information")),
-               { OPTION_CALLBACK, 'x', "exclude", &exclude_list, N_("pattern"),
+               OPT_CALLBACK_F('x', "exclude", &exclude_list, N_("pattern"),
                        N_("skip files matching pattern"),
-                       PARSE_OPT_NONEG, option_parse_exclude },
-               { OPTION_CALLBACK, 'X', "exclude-from", &dir, N_("file"),
+                       PARSE_OPT_NONEG, option_parse_exclude),
+               OPT_CALLBACK_F('X', "exclude-from", &dir, N_("file"),
                        N_("exclude patterns are read from <file>"),
-                       PARSE_OPT_NONEG, option_parse_exclude_from },
+                       PARSE_OPT_NONEG, option_parse_exclude_from),
                OPT_STRING(0, "exclude-per-directory", &dir.exclude_per_dir, N_("file"),
                        N_("read additional per-directory exclude patterns in <file>")),
-               { OPTION_CALLBACK, 0, "exclude-standard", &dir, NULL,
+               OPT_CALLBACK_F(0, "exclude-standard", &dir, NULL,
                        N_("add the standard git exclusions"),
                        PARSE_OPT_NOARG | PARSE_OPT_NONEG,
-                       option_parse_exclude_standard },
+                       option_parse_exclude_standard),
                OPT_SET_INT_F(0, "full-name", &prefix_len,
                              N_("make the output relative to the project top directory"),
                              0, PARSE_OPT_NONEG),
diff --combined builtin/merge.c
index 97066a5632cc6d6d6aa116de7841ccc880db4b20,35707003b63a37813cd97a358f0081a4ef7a5e8c..923e32acf1a969810077eb9c42d14bce132ecfc7
@@@ -40,7 -40,6 +40,7 @@@
  #include "branch.h"
  #include "commit-reach.h"
  #include "wt-status.h"
 +#include "commit-graph.h"
  
  #define DEFAULT_TWOHEAD (1<<0)
  #define DEFAULT_OCTOPUS (1<<1)
@@@ -83,7 -82,6 +83,7 @@@ static int show_progress = -1
  static int default_to_upstream = 1;
  static int signoff;
  static const char *sign_commit;
 +static int autostash;
  static int no_verify;
  
  static struct strategy all_strategy[] = {
@@@ -243,9 -241,9 +243,9 @@@ static int option_parse_n(const struct 
  }
  
  static struct option builtin_merge_options[] = {
-       { OPTION_CALLBACK, 'n', NULL, NULL, NULL,
+       OPT_CALLBACK_F('n', NULL, NULL, NULL,
                N_("do not show a diffstat at the end of the merge"),
-               PARSE_OPT_NOARG, option_parse_n },
+               PARSE_OPT_NOARG, option_parse_n),
        OPT_BOOL(0, "stat", &show_diffstat,
                N_("show a diffstat at the end of the merge")),
        OPT_BOOL(0, "summary", &show_diffstat, N_("(synonym to --stat)")),
        OPT_SET_INT(0, "progress", &show_progress, N_("force progress reporting"), 1),
        { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
          N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
 +      OPT_AUTOSTASH(&autostash),
        OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")),
        OPT_BOOL(0, "signoff", &signoff, N_("add Signed-off-by:")),
        OPT_BOOL(0, "no-verify", &no_verify, N_("bypass pre-merge-commit and commit-msg hooks")),
@@@ -478,7 -475,6 +478,7 @@@ static void finish(struct commit *head_
        /* Run a post-merge hook */
        run_hook_le(NULL, "post-merge", squash ? "1" : "0", NULL);
  
 +      apply_autostash(git_path_merge_autostash(the_repository));
        strbuf_release(&reflog_message);
  }
  
@@@ -640,9 -636,6 +640,9 @@@ static int git_merge_config(const char 
                return 0;
        } else if (!strcmp(k, "gpg.mintrustlevel")) {
                check_trust_level = 0;
 +      } else if (!strcmp(k, "merge.autostash")) {
 +              autostash = git_config_bool(k, v);
 +              return 0;
        }
  
        status = fmt_merge_msg_config(k, v, cb);
@@@ -1290,7 -1283,6 +1290,7 @@@ int cmd_merge(int argc, const char **ar
        if (abort_current_merge) {
                int nargc = 2;
                const char *nargv[] = {"reset", "--merge", NULL};
 +              struct strbuf stash_oid = STRBUF_INIT;
  
                if (orig_argc != 2)
                        usage_msg_opt(_("--abort expects no arguments"),
                if (!file_exists(git_path_merge_head(the_repository)))
                        die(_("There is no merge to abort (MERGE_HEAD missing)."));
  
 +              if (read_oneliner(&stash_oid, git_path_merge_autostash(the_repository),
 +                  READ_ONELINER_SKIP_IF_EMPTY))
 +                      unlink(git_path_merge_autostash(the_repository));
 +
                /* Invoke 'git reset --merge' */
                ret = cmd_reset(nargc, nargv, prefix);
 +
 +              if (stash_oid.len)
 +                      apply_autostash_oid(stash_oid.buf);
 +
 +              strbuf_release(&stash_oid);
                goto done;
        }
  
                        goto done;
                }
  
 +              if (autostash)
 +                      create_autostash(the_repository,
 +                                       git_path_merge_autostash(the_repository),
 +                                       "merge");
                if (checkout_fast_forward(the_repository,
                                          &head_commit->object.oid,
                                          &commit->object.oid,
        if (fast_forward == FF_ONLY)
                die(_("Not possible to fast-forward, aborting."));
  
 +      if (autostash)
 +              create_autostash(the_repository,
 +                               git_path_merge_autostash(the_repository),
 +                               "merge");
 +
        /* We are going to make a new commit. */
        git_committer_info(IDENT_STRICT);
  
                                   head_commit);
        }
  
 -      if (squash)
 +      if (squash) {
                finish(head_commit, remoteheads, NULL, NULL);
 -      else
 +
 +              git_test_write_commit_graph_or_die();
 +      } else
                write_merge_state(remoteheads);
  
        if (merge_was_ok)
diff --combined builtin/pull.c
index f1fa6db74e4cac95db249676aa348ecb370ea446,119b28a6e7801a5983dbd4ee344cb368530d860d..00e5857a8d18da3394d6e5a3316e8f56bb98fdb5
@@@ -118,17 -118,17 +118,17 @@@ static struct option pull_options[] = 
        OPT_PASSTHRU(0, "progress", &opt_progress, NULL,
                N_("force progress reporting"),
                PARSE_OPT_NOARG),
-       { OPTION_CALLBACK, 0, "recurse-submodules",
+       OPT_CALLBACK_F(0, "recurse-submodules",
                   &recurse_submodules, N_("on-demand"),
                   N_("control for recursive fetching of submodules"),
-                  PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules },
+                  PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules),
  
        /* Options passed to git-merge or git-rebase */
        OPT_GROUP(N_("Options related to merging")),
-       { OPTION_CALLBACK, 'r', "rebase", &opt_rebase,
+       OPT_CALLBACK_F('r', "rebase", &opt_rebase,
          "(false|true|merges|preserve|interactive)",
          N_("incorporate changes by rebasing rather than merging"),
-         PARSE_OPT_OPTARG, parse_opt_rebase },
+         PARSE_OPT_OPTARG, parse_opt_rebase),
        OPT_PASSTHRU('n', NULL, &opt_diffstat, NULL,
                N_("do not show a diffstat at the end of the merge"),
                PARSE_OPT_NOARG | PARSE_OPT_NONEG),
                N_("verify that the named commit has a valid GPG signature"),
                PARSE_OPT_NOARG),
        OPT_BOOL(0, "autostash", &opt_autostash,
 -              N_("automatically stash/stash pop before and after rebase")),
 +              N_("automatically stash/stash pop before and after")),
        OPT_PASSTHRU_ARGV('s', "strategy", &opt_strategies, N_("strategy"),
                N_("merge strategy to use"),
                0),
@@@ -695,10 -695,6 +695,10 @@@ static int run_merge(void
        argv_array_pushv(&args, opt_strategy_opts.argv);
        if (opt_gpg_sign)
                argv_array_push(&args, opt_gpg_sign);
 +      if (opt_autostash == 0)
 +              argv_array_push(&args, "--no-autostash");
 +      else if (opt_autostash == 1)
 +              argv_array_push(&args, "--autostash");
        if (opt_allow_unrelated_histories > 0)
                argv_array_push(&args, "--allow-unrelated-histories");
  
@@@ -946,6 -942,9 +946,6 @@@ int cmd_pull(int argc, const char **arg
        if (get_oid("HEAD", &orig_head))
                oidclr(&orig_head);
  
 -      if (!opt_rebase && opt_autostash != -1)
 -              die(_("--[no-]autostash option is only valid with --rebase."));
 -
        autostash = config_autostash;
        if (opt_rebase) {
                if (opt_autostash != -1)
diff --combined builtin/push.c
index 59c8acb556801ab92822e100767d2ccde3921d0b,56d1ad19084bbcb53f6ff6e2162facb959e62546..dbcb4922aaa385145e4f5c381325cf842bd8f3ab
@@@ -340,7 -340,6 +340,7 @@@ static int push_with_options(struct tra
  {
        int err;
        unsigned int reject_reasons;
 +      char *anon_url = transport_anonymize_url(transport->url);
  
        transport_set_verbosity(transport, verbosity, progress);
        transport->family = family;
        }
  
        if (verbosity > 0)
 -              fprintf(stderr, _("Pushing to %s\n"), transport->url);
 +              fprintf(stderr, _("Pushing to %s\n"), anon_url);
        trace2_region_enter("push", "transport_push", the_repository);
        err = transport_push(the_repository, transport,
                             rs, flags, &reject_reasons);
        trace2_region_leave("push", "transport_push", the_repository);
        if (err != 0) {
                fprintf(stderr, "%s", push_get_color(PUSH_COLOR_ERROR));
 -              error(_("failed to push some refs to '%s'"), transport->url);
 +              error(_("failed to push some refs to '%s'"), anon_url);
                fprintf(stderr, "%s", push_get_color(PUSH_COLOR_RESET));
        }
  
        err |= transport_disconnect(transport);
 +      free(anon_url);
        if (!err)
                return 0;
  
@@@ -550,10 -548,9 +550,9 @@@ int cmd_push(int argc, const char **arg
                OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN),
                OPT_BIT( 0,  "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN),
                OPT_BIT('f', "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE),
-               { OPTION_CALLBACK,
-                 0, CAS_OPT_NAME, &cas, N_("<refname>:<expect>"),
-                 N_("require old value of ref to be at this value"),
-                 PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP, parseopt_push_cas_option },
+               OPT_CALLBACK_F(0, CAS_OPT_NAME, &cas, N_("<refname>:<expect>"),
+                              N_("require old value of ref to be at this value"),
+                              PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP, parseopt_push_cas_option),
                { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules, "(check|on-demand|no)",
                        N_("control recursive pushing of submodules"),
                        PARSE_OPT_OPTARG, option_parse_recurse_submodules },
                OPT_BIT(0, "no-verify", &flags, N_("bypass pre-push hook"), TRANSPORT_PUSH_NO_HOOK),
                OPT_BIT(0, "follow-tags", &flags, N_("push missing but relevant tags"),
                        TRANSPORT_PUSH_FOLLOW_TAGS),
-               { OPTION_CALLBACK,
-                 0, "signed", &push_cert, "(yes|no|if-asked)", N_("GPG sign the push"),
-                 PARSE_OPT_OPTARG, option_parse_push_signed },
+               OPT_CALLBACK_F(0, "signed", &push_cert, "(yes|no|if-asked)", N_("GPG sign the push"),
+                               PARSE_OPT_OPTARG, option_parse_push_signed),
                OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC),
                OPT_STRING_LIST('o', "push-option", &push_options_cmdline, N_("server-specific"), N_("option to transmit")),
                OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
diff --combined builtin/rebase.c
index 8cbfc5106efae6aa196e36d97ee7e51558a98830,8f6fc829aedc5a8676380ce9408a78dad784284c..ca6aa0dc7a8685a7dbdd5e07f5b20be7e3a38756
@@@ -27,9 -27,6 +27,9 @@@
  #include "branch.h"
  #include "sequencer.h"
  #include "rebase-interactive.h"
 +#include "reset.h"
 +
 +#define DEFAULT_REFLOG_ACTION "rebase"
  
  static char const * const builtin_rebase_usage[] = {
        N_("git rebase [-i] [options] [--exec <cmd>] "
@@@ -477,10 -474,10 +477,10 @@@ int cmd_rebase__interactive(int argc, c
        struct option options[] = {
                OPT_NEGBIT(0, "ff", &opts.flags, N_("allow fast-forward"),
                           REBASE_FORCE),
-               { OPTION_CALLBACK, 'k', "keep-empty", &options, NULL,
+               OPT_CALLBACK_F('k', "keep-empty", &options, NULL,
                        N_("keep commits which start empty"),
                        PARSE_OPT_NOARG | PARSE_OPT_HIDDEN,
-                       parse_opt_keep_empty },
+                       parse_opt_keep_empty),
                OPT_BOOL_F(0, "allow-empty-message", &opts.allow_empty_message,
                           N_("allow commits with empty messages"),
                           PARSE_OPT_HIDDEN),
@@@ -593,6 -590,15 +593,6 @@@ static const char *state_dir_path(cons
        return path.buf;
  }
  
 -/* Read one file, then strip line endings */
 -static int read_one(const char *path, struct strbuf *buf)
 -{
 -      if (strbuf_read_file(buf, path, 0) < 0)
 -              return error_errno(_("could not read '%s'"), path);
 -      strbuf_trim_trailing_newline(buf);
 -      return 0;
 -}
 -
  /* Initialize the rebase options from the state directory. */
  static int read_basic_state(struct rebase_options *opts)
  {
        struct strbuf buf = STRBUF_INIT;
        struct object_id oid;
  
 -      if (read_one(state_dir_path("head-name", opts), &head_name) ||
 -          read_one(state_dir_path("onto", opts), &buf))
 +      if (!read_oneliner(&head_name, state_dir_path("head-name", opts),
 +                         READ_ONELINER_WARN_MISSING) ||
 +          !read_oneliner(&buf, state_dir_path("onto", opts),
 +                         READ_ONELINER_WARN_MISSING))
                return -1;
        opts->head_name = starts_with(head_name.buf, "refs/") ?
                xstrdup(head_name.buf) : NULL;
         */
        strbuf_reset(&buf);
        if (file_exists(state_dir_path("orig-head", opts))) {
 -              if (read_one(state_dir_path("orig-head", opts), &buf))
 +              if (!read_oneliner(&buf, state_dir_path("orig-head", opts),
 +                                 READ_ONELINER_WARN_MISSING))
                        return -1;
 -      } else if (read_one(state_dir_path("head", opts), &buf))
 +      } else if (!read_oneliner(&buf, state_dir_path("head", opts),
 +                                READ_ONELINER_WARN_MISSING))
                return -1;
        if (get_oid(buf.buf, &opts->orig_head))
                return error(_("invalid orig-head: '%s'"), buf.buf);
  
        if (file_exists(state_dir_path("allow_rerere_autoupdate", opts))) {
                strbuf_reset(&buf);
 -              if (read_one(state_dir_path("allow_rerere_autoupdate", opts),
 -                          &buf))
 +              if (!read_oneliner(&buf, state_dir_path("allow_rerere_autoupdate", opts),
 +                                 READ_ONELINER_WARN_MISSING))
                        return -1;
                if (!strcmp(buf.buf, "--rerere-autoupdate"))
                        opts->allow_rerere_autoupdate = RERERE_AUTOUPDATE;
  
        if (file_exists(state_dir_path("gpg_sign_opt", opts))) {
                strbuf_reset(&buf);
 -              if (read_one(state_dir_path("gpg_sign_opt", opts),
 -                          &buf))
 +              if (!read_oneliner(&buf, state_dir_path("gpg_sign_opt", opts),
 +                                 READ_ONELINER_WARN_MISSING))
                        return -1;
                free(opts->gpg_sign_opt);
                opts->gpg_sign_opt = xstrdup(buf.buf);
  
        if (file_exists(state_dir_path("strategy", opts))) {
                strbuf_reset(&buf);
 -              if (read_one(state_dir_path("strategy", opts), &buf))
 +              if (!read_oneliner(&buf, state_dir_path("strategy", opts),
 +                                 READ_ONELINER_WARN_MISSING))
                        return -1;
                free(opts->strategy);
                opts->strategy = xstrdup(buf.buf);
  
        if (file_exists(state_dir_path("strategy_opts", opts))) {
                strbuf_reset(&buf);
 -              if (read_one(state_dir_path("strategy_opts", opts), &buf))
 +              if (!read_oneliner(&buf, state_dir_path("strategy_opts", opts),
 +                                 READ_ONELINER_WARN_MISSING))
                        return -1;
                free(opts->strategy_opts);
                opts->strategy_opts = xstrdup(buf.buf);
@@@ -719,6 -719,51 +719,6 @@@ static int rebase_write_basic_state(str
        return 0;
  }
  
 -static int apply_autostash(struct rebase_options *opts)
 -{
 -      const char *path = state_dir_path("autostash", opts);
 -      struct strbuf autostash = STRBUF_INIT;
 -      struct child_process stash_apply = CHILD_PROCESS_INIT;
 -
 -      if (!file_exists(path))
 -              return 0;
 -
 -      if (read_one(path, &autostash))
 -              return error(_("Could not read '%s'"), path);
 -      /* Ensure that the hash is not mistaken for a number */
 -      strbuf_addstr(&autostash, "^0");
 -      argv_array_pushl(&stash_apply.args,
 -                       "stash", "apply", autostash.buf, NULL);
 -      stash_apply.git_cmd = 1;
 -      stash_apply.no_stderr = stash_apply.no_stdout =
 -              stash_apply.no_stdin = 1;
 -      if (!run_command(&stash_apply))
 -              printf(_("Applied autostash.\n"));
 -      else {
 -              struct argv_array args = ARGV_ARRAY_INIT;
 -              int res = 0;
 -
 -              argv_array_pushl(&args,
 -                               "stash", "store", "-m", "autostash", "-q",
 -                               autostash.buf, NULL);
 -              if (run_command_v_opt(args.argv, RUN_GIT_CMD))
 -                      res = error(_("Cannot store %s"), autostash.buf);
 -              argv_array_clear(&args);
 -              strbuf_release(&autostash);
 -              if (res)
 -                      return res;
 -
 -              fprintf(stderr,
 -                      _("Applying autostash resulted in conflicts.\n"
 -                        "Your changes are safe in the stash.\n"
 -                        "You can run \"git stash pop\" or \"git stash drop\" "
 -                        "at any time.\n"));
 -      }
 -
 -      strbuf_release(&autostash);
 -      return 0;
 -}
 -
  static int finish_rebase(struct rebase_options *opts)
  {
        struct strbuf dir = STRBUF_INIT;
        int ret = 0;
  
        delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
 -      apply_autostash(opts);
 +      apply_autostash(state_dir_path("autostash", opts));
        close_object_store(the_repository->objects);
        /*
         * We ignore errors in 'gc --auto', since the
@@@ -771,6 -816,144 +771,6 @@@ static void add_var(struct strbuf *buf
        }
  }
  
 -#define GIT_REFLOG_ACTION_ENVIRONMENT "GIT_REFLOG_ACTION"
 -
 -#define RESET_HEAD_DETACH (1<<0)
 -#define RESET_HEAD_HARD (1<<1)
 -#define RESET_HEAD_RUN_POST_CHECKOUT_HOOK (1<<2)
 -#define RESET_HEAD_REFS_ONLY (1<<3)
 -#define RESET_ORIG_HEAD (1<<4)
 -
 -static int reset_head(struct object_id *oid, const char *action,
 -                    const char *switch_to_branch, unsigned flags,
 -                    const char *reflog_orig_head, const char *reflog_head)
 -{
 -      unsigned detach_head = flags & RESET_HEAD_DETACH;
 -      unsigned reset_hard = flags & RESET_HEAD_HARD;
 -      unsigned run_hook = flags & RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
 -      unsigned refs_only = flags & RESET_HEAD_REFS_ONLY;
 -      unsigned update_orig_head = flags & RESET_ORIG_HEAD;
 -      struct object_id head_oid;
 -      struct tree_desc desc[2] = { { NULL }, { NULL } };
 -      struct lock_file lock = LOCK_INIT;
 -      struct unpack_trees_options unpack_tree_opts;
 -      struct tree *tree;
 -      const char *reflog_action;
 -      struct strbuf msg = STRBUF_INIT;
 -      size_t prefix_len;
 -      struct object_id *orig = NULL, oid_orig,
 -              *old_orig = NULL, oid_old_orig;
 -      int ret = 0, nr = 0;
 -
 -      if (switch_to_branch && !starts_with(switch_to_branch, "refs/"))
 -              BUG("Not a fully qualified branch: '%s'", switch_to_branch);
 -
 -      if (!refs_only && hold_locked_index(&lock, LOCK_REPORT_ON_ERROR) < 0) {
 -              ret = -1;
 -              goto leave_reset_head;
 -      }
 -
 -      if ((!oid || !reset_hard) && get_oid("HEAD", &head_oid)) {
 -              ret = error(_("could not determine HEAD revision"));
 -              goto leave_reset_head;
 -      }
 -
 -      if (!oid)
 -              oid = &head_oid;
 -
 -      if (refs_only)
 -              goto reset_head_refs;
 -
 -      memset(&unpack_tree_opts, 0, sizeof(unpack_tree_opts));
 -      setup_unpack_trees_porcelain(&unpack_tree_opts, action);
 -      unpack_tree_opts.head_idx = 1;
 -      unpack_tree_opts.src_index = the_repository->index;
 -      unpack_tree_opts.dst_index = the_repository->index;
 -      unpack_tree_opts.fn = reset_hard ? oneway_merge : twoway_merge;
 -      unpack_tree_opts.update = 1;
 -      unpack_tree_opts.merge = 1;
 -      init_checkout_metadata(&unpack_tree_opts.meta, switch_to_branch, oid, NULL);
 -      if (!detach_head)
 -              unpack_tree_opts.reset = 1;
 -
 -      if (repo_read_index_unmerged(the_repository) < 0) {
 -              ret = error(_("could not read index"));
 -              goto leave_reset_head;
 -      }
 -
 -      if (!reset_hard && !fill_tree_descriptor(the_repository, &desc[nr++], &head_oid)) {
 -              ret = error(_("failed to find tree of %s"),
 -                          oid_to_hex(&head_oid));
 -              goto leave_reset_head;
 -      }
 -
 -      if (!fill_tree_descriptor(the_repository, &desc[nr++], oid)) {
 -              ret = error(_("failed to find tree of %s"), oid_to_hex(oid));
 -              goto leave_reset_head;
 -      }
 -
 -      if (unpack_trees(nr, desc, &unpack_tree_opts)) {
 -              ret = -1;
 -              goto leave_reset_head;
 -      }
 -
 -      tree = parse_tree_indirect(oid);
 -      prime_cache_tree(the_repository, the_repository->index, tree);
 -
 -      if (write_locked_index(the_repository->index, &lock, COMMIT_LOCK) < 0) {
 -              ret = error(_("could not write index"));
 -              goto leave_reset_head;
 -      }
 -
 -reset_head_refs:
 -      reflog_action = getenv(GIT_REFLOG_ACTION_ENVIRONMENT);
 -      strbuf_addf(&msg, "%s: ", reflog_action ? reflog_action : "rebase");
 -      prefix_len = msg.len;
 -
 -      if (update_orig_head) {
 -              if (!get_oid("ORIG_HEAD", &oid_old_orig))
 -                      old_orig = &oid_old_orig;
 -              if (!get_oid("HEAD", &oid_orig)) {
 -                      orig = &oid_orig;
 -                      if (!reflog_orig_head) {
 -                              strbuf_addstr(&msg, "updating ORIG_HEAD");
 -                              reflog_orig_head = msg.buf;
 -                      }
 -                      update_ref(reflog_orig_head, "ORIG_HEAD", orig,
 -                                 old_orig, 0, UPDATE_REFS_MSG_ON_ERR);
 -              } else if (old_orig)
 -                      delete_ref(NULL, "ORIG_HEAD", old_orig, 0);
 -      }
 -
 -      if (!reflog_head) {
 -              strbuf_setlen(&msg, prefix_len);
 -              strbuf_addstr(&msg, "updating HEAD");
 -              reflog_head = msg.buf;
 -      }
 -      if (!switch_to_branch)
 -              ret = update_ref(reflog_head, "HEAD", oid, orig,
 -                               detach_head ? REF_NO_DEREF : 0,
 -                               UPDATE_REFS_MSG_ON_ERR);
 -      else {
 -              ret = update_ref(reflog_head, switch_to_branch, oid,
 -                               NULL, 0, UPDATE_REFS_MSG_ON_ERR);
 -              if (!ret)
 -                      ret = create_symref("HEAD", switch_to_branch,
 -                                          reflog_head);
 -      }
 -      if (run_hook)
 -              run_hook_le(NULL, "post-checkout",
 -                          oid_to_hex(orig ? orig : &null_oid),
 -                          oid_to_hex(oid), "1", NULL);
 -
 -leave_reset_head:
 -      strbuf_release(&msg);
 -      rollback_lock_file(&lock);
 -      while (nr)
 -              free((void *)desc[--nr].buffer);
 -      return ret;
 -}
 -
  static int move_to_original_branch(struct rebase_options *opts)
  {
        struct strbuf orig_head_reflog = STRBUF_INIT, head_reflog = STRBUF_INIT;
                    opts->head_name, oid_to_hex(&opts->onto->object.oid));
        strbuf_addf(&head_reflog, "rebase finished: returning to %s",
                    opts->head_name);
 -      ret = reset_head(NULL, "", opts->head_name, RESET_HEAD_REFS_ONLY,
 -                       orig_head_reflog.buf, head_reflog.buf);
 +      ret = reset_head(the_repository, NULL, "", opts->head_name,
 +                       RESET_HEAD_REFS_ONLY,
 +                       orig_head_reflog.buf, head_reflog.buf,
 +                       DEFAULT_REFLOG_ACTION);
  
        strbuf_release(&orig_head_reflog);
        strbuf_release(&head_reflog);
@@@ -877,9 -1058,8 +877,9 @@@ static int run_am(struct rebase_option
                free(rebased_patches);
                argv_array_clear(&am.args);
  
 -              reset_head(&opts->orig_head, "checkout", opts->head_name, 0,
 -                         "HEAD", NULL);
 +              reset_head(the_repository, &opts->orig_head, "checkout",
 +                         opts->head_name, 0,
 +                         "HEAD", NULL, DEFAULT_REFLOG_ACTION);
                error(_("\ngit encountered an error while preparing the "
                        "patches to replay\n"
                        "these revisions:\n"
@@@ -1038,7 -1218,7 +1038,7 @@@ finished_rebase
        } else if (status == 2) {
                struct strbuf dir = STRBUF_INIT;
  
 -              apply_autostash(opts);
 +              apply_autostash(state_dir_path("autostash", opts));
                strbuf_addstr(&dir, opts->state_dir);
                remove_dir_recursively(&dir, 0);
                strbuf_release(&dir);
@@@ -1279,6 -1459,7 +1279,6 @@@ static int check_exec_cmd(const char *c
        return 0;
  }
  
 -
  int cmd_rebase(int argc, const char **argv, const char *prefix)
  {
        struct rebase_options options = REBASE_OPTIONS_INIT;
                OPT_CMDMODE(0, "show-current-patch", &action,
                            N_("show the patch file being applied or merged"),
                            ACTION_SHOW_CURRENT_PATCH),
-               { OPTION_CALLBACK, 0, "apply", &options, NULL,
+               OPT_CALLBACK_F(0, "apply", &options, NULL,
                        N_("use apply strategies to rebase"),
                        PARSE_OPT_NOARG | PARSE_OPT_NONEG,
-                       parse_opt_am },
-               { OPTION_CALLBACK, 'm', "merge", &options, NULL,
+                       parse_opt_am),
+               OPT_CALLBACK_F('m', "merge", &options, NULL,
                        N_("use merging strategies to rebase"),
                        PARSE_OPT_NOARG | PARSE_OPT_NONEG,
-                       parse_opt_merge },
-               { OPTION_CALLBACK, 'i', "interactive", &options, NULL,
+                       parse_opt_merge),
+               OPT_CALLBACK_F('i', "interactive", &options, NULL,
                        N_("let the user edit the list of commits to rebase"),
                        PARSE_OPT_NOARG | PARSE_OPT_NONEG,
-                       parse_opt_interactive },
+                       parse_opt_interactive),
                OPT_SET_INT_F('p', "preserve-merges", &options.type,
                              N_("(DEPRECATED) try to recreate merges instead of "
                                 "ignoring them"),
                OPT_CALLBACK_F(0, "empty", &options, "{drop,keep,ask}",
                               N_("how to handle commits that become empty"),
                               PARSE_OPT_NONEG, parse_opt_empty),
-               { OPTION_CALLBACK, 'k', "keep-empty", &options, NULL,
+               OPT_CALLBACK_F('k', "keep-empty", &options, NULL,
                        N_("keep commits which start empty"),
                        PARSE_OPT_NOARG | PARSE_OPT_HIDDEN,
-                       parse_opt_keep_empty },
+                       parse_opt_keep_empty),
                OPT_BOOL(0, "autosquash", &options.autosquash,
                         N_("move commits that begin with "
                            "squash!/fixup! under -i")),
                { OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"),
                        N_("GPG-sign commits"),
                        PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
 -              OPT_BOOL(0, "autostash", &options.autostash,
 -                       N_("automatically stash/stash pop before and after")),
 +              OPT_AUTOSTASH(&options.autostash),
                OPT_STRING_LIST('x', "exec", &exec, N_("exec"),
                                N_("add exec lines after each commit of the "
                                   "editable list")),
                        die(_("cannot combine '--keep-base' with '--root'"));
        }
  
 +      if (options.root && fork_point > 0)
 +              die(_("cannot combine '--root' with '--fork-point'"));
 +
        if (action != ACTION_NONE && !in_progress)
                die(_("No rebase in progress?"));
        setenv(GIT_REFLOG_ACTION_ENVIRONMENT, "rebase", 0);
                rerere_clear(the_repository, &merge_rr);
                string_list_clear(&merge_rr, 1);
  
 -              if (reset_head(NULL, "reset", NULL, RESET_HEAD_HARD,
 -                             NULL, NULL) < 0)
 +              if (reset_head(the_repository, NULL, "reset", NULL, RESET_HEAD_HARD,
 +                             NULL, NULL, DEFAULT_REFLOG_ACTION) < 0)
                        die(_("could not discard worktree changes"));
                remove_branch_state(the_repository, 0);
                if (read_basic_state(&options))
  
                if (read_basic_state(&options))
                        exit(1);
 -              if (reset_head(&options.orig_head, "reset",
 +              if (reset_head(the_repository, &options.orig_head, "reset",
                               options.head_name, RESET_HEAD_HARD,
 -                             NULL, NULL) < 0)
 +                             NULL, NULL, DEFAULT_REFLOG_ACTION) < 0)
                        die(_("could not move back to %s"),
                            oid_to_hex(&options.orig_head));
                remove_branch_state(the_repository, 0);
                goto cleanup;
        }
        case ACTION_QUIT: {
 +              save_autostash(state_dir_path("autostash", &options));
                if (options.type == REBASE_MERGE) {
                        struct replay_opts replay = REPLAY_OPTS_INIT;
  
                die(_("could not read index"));
  
        if (options.autostash) {
 -              struct lock_file lock_file = LOCK_INIT;
 -              int fd;
 -
 -              fd = hold_locked_index(&lock_file, 0);
 -              refresh_cache(REFRESH_QUIET);
 -              if (0 <= fd)
 -                      repo_update_index_if_able(the_repository, &lock_file);
 -              rollback_lock_file(&lock_file);
 -
 -              if (has_unstaged_changes(the_repository, 1) ||
 -                  has_uncommitted_changes(the_repository, 1)) {
 -                      const char *autostash =
 -                              state_dir_path("autostash", &options);
 -                      struct child_process stash = CHILD_PROCESS_INIT;
 -                      struct object_id oid;
 -
 -                      argv_array_pushl(&stash.args,
 -                                       "stash", "create", "autostash", NULL);
 -                      stash.git_cmd = 1;
 -                      stash.no_stdin = 1;
 -                      strbuf_reset(&buf);
 -                      if (capture_command(&stash, &buf, GIT_MAX_HEXSZ))
 -                              die(_("Cannot autostash"));
 -                      strbuf_trim_trailing_newline(&buf);
 -                      if (get_oid(buf.buf, &oid))
 -                              die(_("Unexpected stash response: '%s'"),
 -                                  buf.buf);
 -                      strbuf_reset(&buf);
 -                      strbuf_add_unique_abbrev(&buf, &oid, DEFAULT_ABBREV);
 -
 -                      if (safe_create_leading_directories_const(autostash))
 -                              die(_("Could not create directory for '%s'"),
 -                                  options.state_dir);
 -                      write_file(autostash, "%s", oid_to_hex(&oid));
 -                      printf(_("Created autostash: %s\n"), buf.buf);
 -                      if (reset_head(NULL, "reset --hard",
 -                                     NULL, RESET_HEAD_HARD, NULL, NULL) < 0)
 -                              die(_("could not reset --hard"));
 -
 -                      if (discard_index(the_repository->index) < 0 ||
 -                              repo_read_index(the_repository) < 0)
 -                              die(_("could not read index"));
 -              }
 +              create_autostash(the_repository, state_dir_path("autostash", &options),
 +                               DEFAULT_REFLOG_ACTION);
        }
  
        if (require_clean_work_tree(the_repository, "rebase",
                                strbuf_addf(&buf, "%s: checkout %s",
                                            getenv(GIT_REFLOG_ACTION_ENVIRONMENT),
                                            options.switch_to);
 -                              if (reset_head(&options.orig_head, "checkout",
 +                              if (reset_head(the_repository,
 +                                             &options.orig_head, "checkout",
                                               options.head_name,
                                               RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
 -                                             NULL, buf.buf) < 0) {
 +                                             NULL, buf.buf,
 +                                             DEFAULT_REFLOG_ACTION) < 0) {
                                        ret = !!error(_("could not switch to "
                                                        "%s"),
                                                      options.switch_to);
  
        strbuf_addf(&msg, "%s: checkout %s",
                    getenv(GIT_REFLOG_ACTION_ENVIRONMENT), options.onto_name);
 -      if (reset_head(&options.onto->object.oid, "checkout", NULL,
 +      if (reset_head(the_repository, &options.onto->object.oid, "checkout", NULL,
                       RESET_HEAD_DETACH | RESET_ORIG_HEAD |
                       RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
 -                     NULL, msg.buf))
 +                     NULL, msg.buf, DEFAULT_REFLOG_ACTION))
                die(_("Could not detach HEAD"));
        strbuf_release(&msg);
  
                strbuf_addf(&msg, "rebase finished: %s onto %s",
                        options.head_name ? options.head_name : "detached HEAD",
                        oid_to_hex(&options.onto->object.oid));
 -              reset_head(NULL, "Fast-forwarded", options.head_name,
 -                         RESET_HEAD_REFS_ONLY, "HEAD", msg.buf);
 +              reset_head(the_repository, NULL, "Fast-forwarded", options.head_name,
 +                         RESET_HEAD_REFS_ONLY, "HEAD", msg.buf,
 +                         DEFAULT_REFLOG_ACTION);
                strbuf_release(&msg);
                ret = !!finish_rebase(&options);
                goto cleanup;