about summary refs log tree commit diff
path: root/third_party/git/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/git/builtin')
-rw-r--r--third_party/git/builtin/add.c112
-rw-r--r--third_party/git/builtin/am.c119
-rw-r--r--third_party/git/builtin/bisect--helper.c134
-rw-r--r--third_party/git/builtin/blame.c40
-rw-r--r--third_party/git/builtin/branch.c2
-rw-r--r--third_party/git/builtin/bundle.c217
-rw-r--r--third_party/git/builtin/cat-file.c7
-rw-r--r--third_party/git/builtin/check-ignore.c37
-rw-r--r--third_party/git/builtin/checkout.c137
-rw-r--r--third_party/git/builtin/clean.c27
-rw-r--r--third_party/git/builtin/clone.c61
-rw-r--r--third_party/git/builtin/commit-graph.c135
-rw-r--r--third_party/git/builtin/commit.c67
-rw-r--r--third_party/git/builtin/config.c46
-rw-r--r--third_party/git/builtin/describe.c46
-rw-r--r--third_party/git/builtin/difftool.c56
-rw-r--r--third_party/git/builtin/fast-export.c88
-rw-r--r--third_party/git/builtin/fetch.c344
-rw-r--r--third_party/git/builtin/fmt-merge-msg.c9
-rw-r--r--third_party/git/builtin/fsck.c126
-rw-r--r--third_party/git/builtin/gc.c19
-rw-r--r--third_party/git/builtin/grep.c111
-rw-r--r--third_party/git/builtin/index-pack.c26
-rw-r--r--third_party/git/builtin/log.c210
-rw-r--r--third_party/git/builtin/ls-files.c8
-rw-r--r--third_party/git/builtin/merge-recursive.c4
-rw-r--r--third_party/git/builtin/merge-tree.c5
-rw-r--r--third_party/git/builtin/merge.c40
-rw-r--r--third_party/git/builtin/mktag.c7
-rw-r--r--third_party/git/builtin/multi-pack-index.c18
-rw-r--r--third_party/git/builtin/name-rev.c289
-rw-r--r--third_party/git/builtin/notes.c6
-rw-r--r--third_party/git/builtin/pack-objects.c336
-rw-r--r--third_party/git/builtin/patch-id.c16
-rw-r--r--third_party/git/builtin/pull.c48
-rw-r--r--third_party/git/builtin/push.c80
-rw-r--r--third_party/git/builtin/range-diff.c7
-rw-r--r--third_party/git/builtin/read-tree.c2
-rw-r--r--third_party/git/builtin/rebase.c414
-rw-r--r--third_party/git/builtin/receive-pack.c86
-rw-r--r--third_party/git/builtin/reflog.c9
-rw-r--r--third_party/git/builtin/remote.c192
-rw-r--r--third_party/git/builtin/repack.c14
-rw-r--r--third_party/git/builtin/replace.c12
-rw-r--r--third_party/git/builtin/reset.c27
-rw-r--r--third_party/git/builtin/rev-list.c126
-rw-r--r--third_party/git/builtin/rev-parse.c18
-rw-r--r--third_party/git/builtin/rm.c28
-rw-r--r--third_party/git/builtin/show-branch.c2
-rw-r--r--third_party/git/builtin/show-index.c13
-rw-r--r--third_party/git/builtin/sparse-checkout.c631
-rw-r--r--third_party/git/builtin/stash.c133
-rw-r--r--third_party/git/builtin/submodule--helper.c78
-rw-r--r--third_party/git/builtin/unpack-objects.c6
-rw-r--r--third_party/git/builtin/update-index.c12
-rw-r--r--third_party/git/builtin/worktree.c16
56 files changed, 1456 insertions, 3403 deletions
diff --git a/third_party/git/builtin/add.c b/third_party/git/builtin/add.c
index 18a0881ecf..dd18e5c9b6 100644
--- a/third_party/git/builtin/add.c
+++ b/third_party/git/builtin/add.c
@@ -20,7 +20,6 @@
 #include "bulk-checkin.h"
 #include "argv-array.h"
 #include "submodule.h"
-#include "add-interactive.h"
 
 static const char * const builtin_add_usage[] = {
 	N_("git add [<options>] [--] <pathspec>..."),
@@ -29,9 +28,6 @@ static const char * const builtin_add_usage[] = {
 static int patch_interactive, add_interactive, edit_interactive;
 static int take_worktree_changes;
 static int add_renormalize;
-static int pathspec_file_nul;
-static const char *pathspec_from_file;
-static int legacy_stash_p; /* support for the scripted `git stash` */
 
 struct update_callback_data {
 	int flags;
@@ -189,34 +185,6 @@ int run_add_interactive(const char *revision, const char *patch_mode,
 {
 	int status, i;
 	struct argv_array argv = ARGV_ARRAY_INIT;
-	int use_builtin_add_i =
-		git_env_bool("GIT_TEST_ADD_I_USE_BUILTIN", -1);
-
-	if (use_builtin_add_i < 0)
-		git_config_get_bool("add.interactive.usebuiltin",
-				    &use_builtin_add_i);
-
-	if (use_builtin_add_i == 1) {
-		enum add_p_mode mode;
-
-		if (!patch_mode)
-			return !!run_add_i(the_repository, pathspec);
-
-		if (!strcmp(patch_mode, "--patch"))
-			mode = ADD_P_ADD;
-		else if (!strcmp(patch_mode, "--patch=stash"))
-			mode = ADD_P_STASH;
-		else if (!strcmp(patch_mode, "--patch=reset"))
-			mode = ADD_P_RESET;
-		else if (!strcmp(patch_mode, "--patch=checkout"))
-			mode = ADD_P_CHECKOUT;
-		else if (!strcmp(patch_mode, "--patch=worktree"))
-			mode = ADD_P_WORKTREE;
-		else
-			die("'%s' not supported", patch_mode);
-
-		return !!run_add_p(the_repository, mode, revision, pathspec);
-	}
 
 	argv_array_push(&argv, "add--interactive");
 	if (patch_mode)
@@ -341,10 +309,6 @@ static struct option builtin_add_options[] = {
 		   N_("override the executable bit of the listed files")),
 	OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
 			N_("warn when adding an embedded repository")),
-	OPT_HIDDEN_BOOL(0, "legacy-stash-p", &legacy_stash_p,
-			N_("backend for `git stash -p`")),
-	OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
-	OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
 	OPT_END(),
 };
 
@@ -355,7 +319,6 @@ static int add_config(const char *var, const char *value, void *cb)
 		ignore_add_errors = git_config_bool(var, value);
 		return 0;
 	}
-
 	return git_default_config(var, value, cb);
 }
 
@@ -406,10 +369,7 @@ static int add_files(struct dir_struct *dir, int flags)
 		fprintf(stderr, _(ignore_error));
 		for (i = 0; i < dir->ignored_nr; i++)
 			fprintf(stderr, "%s\n", dir->ignored[i]->name);
-		if (advice_add_ignored_file)
-			advise(_("Use -f if you really want to add them.\n"
-				"Turn this message off by running\n"
-				"\"git config advice.addIgnoredFile false\""));
+		fprintf(stderr, _("Use -f if you really want to add them.\n"));
 		exit_status = 1;
 	}
 
@@ -442,28 +402,11 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 			  builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
 	if (patch_interactive)
 		add_interactive = 1;
-	if (add_interactive) {
-		if (pathspec_from_file)
-			die(_("--pathspec-from-file is incompatible with --interactive/--patch"));
+	if (add_interactive)
 		exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive));
-	}
-	if (legacy_stash_p) {
-		struct pathspec pathspec;
-
-		parse_pathspec(&pathspec, 0,
-			PATHSPEC_PREFER_FULL |
-			PATHSPEC_SYMLINK_LEADING_PATH |
-			PATHSPEC_PREFIX_ORIGIN,
-			prefix, argv);
-
-		return run_add_interactive(NULL, "--patch=stash", &pathspec);
-	}
 
-	if (edit_interactive) {
-		if (pathspec_from_file)
-			die(_("--pathspec-from-file is incompatible with --edit"));
+	if (edit_interactive)
 		return(edit_patch(argc, argv, prefix));
-	}
 	argc--;
 	argv++;
 
@@ -475,6 +418,10 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 	if (addremove && take_worktree_changes)
 		die(_("-A and -u are mutually incompatible"));
 
+	if (!take_worktree_changes && addremove_explicit < 0 && argc)
+		/* Turn "git add pathspec..." to "git add -A pathspec..." */
+		addremove = 1;
+
 	if (!show_only && ignore_missing)
 		die(_("Option --ignore-missing can only be used together with --dry-run"));
 
@@ -487,6 +434,19 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
 	hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
 
+	flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
+		 (show_only ? ADD_CACHE_PRETEND : 0) |
+		 (intent_to_add ? ADD_CACHE_INTENT : 0) |
+		 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
+		 (!(addremove || take_worktree_changes)
+		  ? ADD_CACHE_IGNORE_REMOVAL : 0));
+
+	if (require_pathspec && argc == 0) {
+		fprintf(stderr, _("Nothing specified, nothing added.\n"));
+		fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
+		return 0;
+	}
+
 	/*
 	 * Check the "pathspec '%s' did not match any files" block
 	 * below before enabling new magic.
@@ -496,38 +456,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		       PATHSPEC_SYMLINK_LEADING_PATH,
 		       prefix, argv);
 
-	if (pathspec_from_file) {
-		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
-
-		parse_pathspec_file(&pathspec, PATHSPEC_ATTR,
-				    PATHSPEC_PREFER_FULL |
-				    PATHSPEC_SYMLINK_LEADING_PATH,
-				    prefix, pathspec_from_file, pathspec_file_nul);
-	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
-	}
-
-	if (require_pathspec && pathspec.nr == 0) {
-		fprintf(stderr, _("Nothing specified, nothing added.\n"));
-		if (advice_add_empty_pathspec)
-			advise( _("Maybe you wanted to say 'git add .'?\n"
-				"Turn this message off by running\n"
-				"\"git config advice.addEmptyPathspec false\""));
-		return 0;
-	}
-
-	if (!take_worktree_changes && addremove_explicit < 0 && pathspec.nr)
-		/* Turn "git add pathspec..." to "git add -A pathspec..." */
-		addremove = 1;
-
-	flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
-		 (show_only ? ADD_CACHE_PRETEND : 0) |
-		 (intent_to_add ? ADD_CACHE_INTENT : 0) |
-		 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
-		 (!(addremove || take_worktree_changes)
-		  ? ADD_CACHE_IGNORE_REMOVAL : 0));
-
 	if (read_cache_preload(&pathspec) < 0)
 		die(_("index file corrupt"));
 
diff --git a/third_party/git/builtin/am.c b/third_party/git/builtin/am.c
index e3dfd93c25..1aea657a7f 100644
--- a/third_party/git/builtin/am.c
+++ b/third_party/git/builtin/am.c
@@ -24,6 +24,7 @@
 #include "sequencer.h"
 #include "revision.h"
 #include "merge-recursive.h"
+#include "revision.h"
 #include "log-tree.h"
 #include "notes-utils.h"
 #include "rerere.h"
@@ -81,11 +82,6 @@ enum signoff_type {
 	SIGNOFF_EXPLICIT /* --signoff was set on the command-line */
 };
 
-enum show_patch_type {
-	SHOW_PATCH_RAW = 0,
-	SHOW_PATCH_DIFF = 1,
-};
-
 struct am_state {
 	/* state directory path */
 	char *dir;
@@ -1076,6 +1072,19 @@ static const char *msgnum(const struct am_state *state)
 }
 
 /**
+ * Refresh and write index.
+ */
+static void refresh_and_write_cache(void)
+{
+	struct lock_file lock_file = LOCK_INIT;
+
+	hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
+	refresh_cache(REFRESH_QUIET);
+	if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
+		die(_("unable to write index file"));
+}
+
+/**
  * Dies with a user-friendly message on how to proceed after resolving the
  * problem. This message can be overridden with state->resolvemsg.
  */
@@ -1263,9 +1272,7 @@ static void get_commit_info(struct am_state *state, struct commit *commit)
 	buffer = logmsg_reencode(commit, NULL, get_commit_output_encoding());
 
 	ident_line = find_commit_header(buffer, "author", &ident_len);
-	if (!ident_line)
-		die(_("missing author line in commit %s"),
-		      oid_to_hex(&commit->object.oid));
+
 	if (split_ident_line(&id, ident_line, ident_len) < 0)
 		die(_("invalid ident line: %.*s"), (int)ident_len, ident_line);
 
@@ -1531,7 +1538,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
 	o.branch1 = "HEAD";
 	their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
 	o.branch2 = their_tree_name;
-	o.detect_directory_renames = MERGE_DIRECTORY_RENAMES_NONE;
+	o.detect_directory_renames = 0;
 
 	if (state->quiet)
 		o.verbosity = 0;
@@ -1696,8 +1703,7 @@ static void am_run(struct am_state *state, int resume)
 
 	unlink(am_path(state, "dirtyindex"));
 
-	if (refresh_and_write_cache(REFRESH_QUIET, 0, 0) < 0)
-		die(_("unable to write index file"));
+	refresh_and_write_cache();
 
 	if (repo_index_has_changes(the_repository, NULL, &sb)) {
 		write_state_bool(state, "dirtyindex", 1);
@@ -1768,7 +1774,7 @@ static void am_run(struct am_state *state, int resume)
 				linelen(state->msg), state->msg);
 
 			if (advice_amworkdir)
-				advise(_("Use 'git am --show-current-patch=diff' to see the failed patch"));
+				advise(_("Use 'git am --show-current-patch' to see the failed patch"));
 
 			die_user_resolve(state);
 		}
@@ -2066,7 +2072,7 @@ static void am_abort(struct am_state *state)
 	am_destroy(state);
 }
 
-static int show_patch(struct am_state *state, enum show_patch_type sub_mode)
+static int show_patch(struct am_state *state)
 {
 	struct strbuf sb = STRBUF_INIT;
 	const char *patch_path;
@@ -2083,17 +2089,7 @@ static int show_patch(struct am_state *state, enum show_patch_type sub_mode)
 		return ret;
 	}
 
-	switch (sub_mode) {
-	case SHOW_PATCH_RAW:
-		patch_path = am_path(state, msgnum(state));
-		break;
-	case SHOW_PATCH_DIFF:
-		patch_path = am_path(state, "patch");
-		break;
-	default:
-		BUG("invalid mode for --show-current-patch");
-	}
-
+	patch_path = am_path(state, msgnum(state));
 	len = strbuf_read_file(&sb, patch_path, 0);
 	if (len < 0)
 		die_errno(_("failed to read '%s'"), patch_path);
@@ -2133,7 +2129,7 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int
 	return 0;
 }
 
-enum resume_type {
+enum resume_mode {
 	RESUME_FALSE = 0,
 	RESUME_APPLY,
 	RESUME_RESOLVED,
@@ -2143,45 +2139,6 @@ enum resume_type {
 	RESUME_SHOW_PATCH
 };
 
-struct resume_mode {
-	enum resume_type mode;
-	enum show_patch_type sub_mode;
-};
-
-static int parse_opt_show_current_patch(const struct option *opt, const char *arg, int unset)
-{
-	int *opt_value = opt->value;
-	struct resume_mode *resume = container_of(opt_value, struct resume_mode, mode);
-
-	/*
-	 * Please update $__git_showcurrentpatch in git-completion.bash
-	 * when you add new options
-	 */
-	const char *valid_modes[] = {
-		[SHOW_PATCH_DIFF] = "diff",
-		[SHOW_PATCH_RAW] = "raw"
-	};
-	int new_value = SHOW_PATCH_RAW;
-
-	if (arg) {
-		for (new_value = 0; new_value < ARRAY_SIZE(valid_modes); new_value++) {
-			if (!strcmp(arg, valid_modes[new_value]))
-				break;
-		}
-		if (new_value >= ARRAY_SIZE(valid_modes))
-			return error(_("Invalid value for --show-current-patch: %s"), arg);
-	}
-
-	if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
-		return error(_("--show-current-patch=%s is incompatible with "
-			       "--show-current-patch=%s"),
-			     arg, valid_modes[resume->sub_mode]);
-
-	resume->mode = RESUME_SHOW_PATCH;
-	resume->sub_mode = new_value;
-	return 0;
-}
-
 static int git_am_config(const char *k, const char *v, void *cb)
 {
 	int status;
@@ -2199,7 +2156,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 	int binary = -1;
 	int keep_cr = -1;
 	int patch_format = PATCH_FORMAT_UNKNOWN;
-	struct resume_mode resume = { .mode = RESUME_FALSE };
+	enum resume_mode resume = RESUME_FALSE;
 	int in_progress;
 	int ret = 0;
 
@@ -2268,26 +2225,24 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 			PARSE_OPT_NOARG),
 		OPT_STRING(0, "resolvemsg", &state.resolvemsg, NULL,
 			N_("override error message when patch failure occurs")),
-		OPT_CMDMODE(0, "continue", &resume.mode,
+		OPT_CMDMODE(0, "continue", &resume,
 			N_("continue applying patches after resolving a conflict"),
 			RESUME_RESOLVED),
-		OPT_CMDMODE('r', "resolved", &resume.mode,
+		OPT_CMDMODE('r', "resolved", &resume,
 			N_("synonyms for --continue"),
 			RESUME_RESOLVED),
-		OPT_CMDMODE(0, "skip", &resume.mode,
+		OPT_CMDMODE(0, "skip", &resume,
 			N_("skip the current patch"),
 			RESUME_SKIP),
-		OPT_CMDMODE(0, "abort", &resume.mode,
+		OPT_CMDMODE(0, "abort", &resume,
 			N_("restore the original branch and abort the patching operation."),
 			RESUME_ABORT),
-		OPT_CMDMODE(0, "quit", &resume.mode,
+		OPT_CMDMODE(0, "quit", &resume,
 			N_("abort the patching operation but keep HEAD where it is."),
 			RESUME_QUIT),
-		{ OPTION_CALLBACK, 0, "show-current-patch", &resume.mode,
-		  "(diff|raw)",
-		  N_("show the patch being applied"),
-		  PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
-		  parse_opt_show_current_patch, RESUME_SHOW_PATCH },
+		OPT_CMDMODE(0, "show-current-patch", &resume,
+			N_("show the patch being applied."),
+			RESUME_SHOW_PATCH),
 		OPT_BOOL(0, "committer-date-is-author-date",
 			&state.committer_date_is_author_date,
 			N_("lie about committer date")),
@@ -2337,12 +2292,12 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 		 *    intend to feed us a patch but wanted to continue
 		 *    unattended.
 		 */
-		if (argc || (resume.mode == RESUME_FALSE && !isatty(0)))
+		if (argc || (resume == RESUME_FALSE && !isatty(0)))
 			die(_("previous rebase directory %s still exists but mbox given."),
 				state.dir);
 
-		if (resume.mode == RESUME_FALSE)
-			resume.mode = RESUME_APPLY;
+		if (resume == RESUME_FALSE)
+			resume = RESUME_APPLY;
 
 		if (state.signoff == SIGNOFF_EXPLICIT)
 			am_append_signoff(&state);
@@ -2356,7 +2311,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 		 * stray directories.
 		 */
 		if (file_exists(state.dir) && !state.rebasing) {
-			if (resume.mode == RESUME_ABORT || resume.mode == RESUME_QUIT) {
+			if (resume == RESUME_ABORT || resume == RESUME_QUIT) {
 				am_destroy(&state);
 				am_state_release(&state);
 				return 0;
@@ -2367,7 +2322,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 				state.dir);
 		}
 
-		if (resume.mode)
+		if (resume)
 			die(_("Resolve operation not in progress, we are not resuming."));
 
 		for (i = 0; i < argc; i++) {
@@ -2385,7 +2340,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 		argv_array_clear(&paths);
 	}
 
-	switch (resume.mode) {
+	switch (resume) {
 	case RESUME_FALSE:
 		am_run(&state, 0);
 		break;
@@ -2406,7 +2361,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 		am_destroy(&state);
 		break;
 	case RESUME_SHOW_PATCH:
-		ret = show_patch(&state, resume.sub_mode);
+		ret = show_patch(&state);
 		break;
 	default:
 		BUG("invalid resume value");
diff --git a/third_party/git/builtin/bisect--helper.c b/third_party/git/builtin/bisect--helper.c
index c1c40b516d..1fbe156e67 100644
--- a/third_party/git/builtin/bisect--helper.c
+++ b/third_party/git/builtin/bisect--helper.c
@@ -52,8 +52,8 @@ static void set_terms(struct bisect_terms *terms, const char *bad,
 	terms->term_bad = xstrdup(bad);
 }
 
-static const char vocab_bad[] = "bad|new";
-static const char vocab_good[] = "good|old";
+static const char *vocab_bad = "bad|new";
+static const char *vocab_good = "good|old";
 
 /*
  * Check whether the string `term` belongs to the set of strings
@@ -169,12 +169,11 @@ static int bisect_reset(const char *commit)
 
 		argv_array_pushl(&argv, "checkout", branch.buf, "--", NULL);
 		if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {
-			error(_("could not check out original"
-				" HEAD '%s'. Try 'git bisect"
-				" reset <commit>'."), branch.buf);
 			strbuf_release(&branch);
 			argv_array_clear(&argv);
-			return -1;
+			return error(_("could not check out original"
+				       " HEAD '%s'. Try 'git bisect"
+				       " reset <commit>'."), branch.buf);
 		}
 		argv_array_clear(&argv);
 	}
@@ -206,31 +205,31 @@ static int bisect_write(const char *state, const char *rev,
 	struct object_id oid;
 	struct commit *commit;
 	FILE *fp = NULL;
-	int res = 0;
+	int retval = 0;
 
 	if (!strcmp(state, terms->term_bad)) {
 		strbuf_addf(&tag, "refs/bisect/%s", state);
 	} else if (one_of(state, terms->term_good, "skip", NULL)) {
 		strbuf_addf(&tag, "refs/bisect/%s-%s", state, rev);
 	} else {
-		res = error(_("Bad bisect_write argument: %s"), state);
+		retval = error(_("Bad bisect_write argument: %s"), state);
 		goto finish;
 	}
 
 	if (get_oid(rev, &oid)) {
-		res = error(_("couldn't get the oid of the rev '%s'"), rev);
+		retval = error(_("couldn't get the oid of the rev '%s'"), rev);
 		goto finish;
 	}
 
 	if (update_ref(NULL, tag.buf, &oid, NULL, 0,
 		       UPDATE_REFS_MSG_ON_ERR)) {
-		res = -1;
+		retval = -1;
 		goto finish;
 	}
 
 	fp = fopen(git_path_bisect_log(), "a");
 	if (!fp) {
-		res = error_errno(_("couldn't open the file '%s'"), git_path_bisect_log());
+		retval = error_errno(_("couldn't open the file '%s'"), git_path_bisect_log());
 		goto finish;
 	}
 
@@ -244,7 +243,7 @@ finish:
 	if (fp)
 		fclose(fp);
 	strbuf_release(&tag);
-	return res;
+	return retval;
 }
 
 static int check_and_set_terms(struct bisect_terms *terms, const char *cmd)
@@ -282,23 +281,35 @@ static int mark_good(const char *refname, const struct object_id *oid,
 	return 1;
 }
 
-static const char need_bad_and_good_revision_warning[] =
+static const char *need_bad_and_good_revision_warning =
 	N_("You need to give me at least one %s and %s revision.\n"
 	   "You can use \"git bisect %s\" and \"git bisect %s\" for that.");
 
-static const char need_bisect_start_warning[] =
+static const char *need_bisect_start_warning =
 	N_("You need to start by \"git bisect start\".\n"
 	   "You then need to give me at least one %s and %s revision.\n"
 	   "You can use \"git bisect %s\" and \"git bisect %s\" for that.");
 
-static int decide_next(const struct bisect_terms *terms,
-		       const char *current_term, int missing_good,
-		       int missing_bad)
+static int bisect_next_check(const struct bisect_terms *terms,
+			     const char *current_term)
 {
+	int missing_good = 1, missing_bad = 1, retval = 0;
+	const char *bad_ref = xstrfmt("refs/bisect/%s", terms->term_bad);
+	const char *good_glob = xstrfmt("%s-*", terms->term_good);
+
+	if (ref_exists(bad_ref))
+		missing_bad = 0;
+
+	for_each_glob_ref_in(mark_good, good_glob, "refs/bisect/",
+			     (void *) &missing_good);
+
 	if (!missing_good && !missing_bad)
-		return 0;
-	if (!current_term)
-		return -1;
+		goto finish;
+
+	if (!current_term) {
+		retval = -1;
+		goto finish;
+	}
 
 	if (missing_good && !missing_bad &&
 	    !strcmp(current_term, terms->term_good)) {
@@ -309,7 +320,7 @@ static int decide_next(const struct bisect_terms *terms,
 		 */
 		warning(_("bisecting only with a %s commit"), terms->term_bad);
 		if (!isatty(0))
-			return 0;
+			goto finish;
 		/*
 		 * TRANSLATORS: Make sure to include [Y] and [n] in your
 		 * translation. The program will only accept English input
@@ -317,35 +328,21 @@ static int decide_next(const struct bisect_terms *terms,
 		 */
 		yesno = git_prompt(_("Are you sure [Y/n]? "), PROMPT_ECHO);
 		if (starts_with(yesno, "N") || starts_with(yesno, "n"))
-			return -1;
-		return 0;
+			retval = -1;
+		goto finish;
+	}
+	if (!is_empty_or_missing_file(git_path_bisect_start())) {
+		retval = error(_(need_bad_and_good_revision_warning),
+			       vocab_bad, vocab_good, vocab_bad, vocab_good);
+	} else {
+		retval = error(_(need_bisect_start_warning),
+			       vocab_good, vocab_bad, vocab_good, vocab_bad);
 	}
 
-	if (!is_empty_or_missing_file(git_path_bisect_start()))
-		return error(_(need_bad_and_good_revision_warning),
-			     vocab_bad, vocab_good, vocab_bad, vocab_good);
-	else
-		return error(_(need_bisect_start_warning),
-			     vocab_good, vocab_bad, vocab_good, vocab_bad);
-}
-
-static int bisect_next_check(const struct bisect_terms *terms,
-			     const char *current_term)
-{
-	int missing_good = 1, missing_bad = 1;
-	char *bad_ref = xstrfmt("refs/bisect/%s", terms->term_bad);
-	char *good_glob = xstrfmt("%s-*", terms->term_good);
-
-	if (ref_exists(bad_ref))
-		missing_bad = 0;
-
-	for_each_glob_ref_in(mark_good, good_glob, "refs/bisect/",
-			     (void *) &missing_good);
-
-	free(good_glob);
-	free(bad_ref);
-
-	return decide_next(terms, current_term, missing_good, missing_bad);
+finish:
+	free((void *) good_glob);
+	free((void *) bad_ref);
+	return retval;
 }
 
 static int get_terms(struct bisect_terms *terms)
@@ -399,7 +396,7 @@ static int bisect_terms(struct bisect_terms *terms, const char *option)
 
 static int bisect_append_log_quoted(const char **argv)
 {
-	int res = 0;
+	int retval = 0;
 	FILE *fp = fopen(git_path_bisect_log(), "a");
 	struct strbuf orig_args = STRBUF_INIT;
 
@@ -407,25 +404,25 @@ static int bisect_append_log_quoted(const char **argv)
 		return -1;
 
 	if (fprintf(fp, "git bisect start") < 1) {
-		res = -1;
+		retval = -1;
 		goto finish;
 	}
 
 	sq_quote_argv(&orig_args, argv);
 	if (fprintf(fp, "%s\n", orig_args.buf) < 1)
-		res = -1;
+		retval = -1;
 
 finish:
 	fclose(fp);
 	strbuf_release(&orig_args);
-	return res;
+	return retval;
 }
 
 static int bisect_start(struct bisect_terms *terms, int no_checkout,
 			const char **argv, int argc)
 {
 	int i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0;
-	int flags, pathspec_pos, res = 0;
+	int flags, pathspec_pos, retval = 0;
 	struct string_list revs = STRING_LIST_INIT_DUP;
 	struct string_list states = STRING_LIST_INIT_DUP;
 	struct strbuf start_head = STRBUF_INIT;
@@ -526,7 +523,7 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,
 			argv_array_pushl(&argv, "checkout", start_head.buf,
 					 "--", NULL);
 			if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {
-				res = error(_("checking out '%s' failed."
+				retval = error(_("checking out '%s' failed."
 						 " Try 'git bisect start "
 						 "<valid-branch>'."),
 					       start_head.buf);
@@ -574,12 +571,12 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,
 
 	if (no_checkout) {
 		if (get_oid(start_head.buf, &oid) < 0) {
-			res = error(_("invalid ref: '%s'"), start_head.buf);
+			retval = error(_("invalid ref: '%s'"), start_head.buf);
 			goto finish;
 		}
 		if (update_ref(NULL, "BISECT_HEAD", &oid, NULL, 0,
 			       UPDATE_REFS_MSG_ON_ERR)) {
-			res = -1;
+			retval = -1;
 			goto finish;
 		}
 	}
@@ -591,26 +588,26 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,
 	for (i = 0; i < states.nr; i++)
 		if (bisect_write(states.items[i].string,
 				 revs.items[i].string, terms, 1)) {
-			res = -1;
+			retval = -1;
 			goto finish;
 		}
 
 	if (must_write_terms && write_terms(terms->term_bad,
 					    terms->term_good)) {
-		res = -1;
+		retval = -1;
 		goto finish;
 	}
 
-	res = bisect_append_log_quoted(argv);
-	if (res)
-		res = -1;
+	retval = bisect_append_log_quoted(argv);
+	if (retval)
+		retval = -1;
 
 finish:
 	string_list_clear(&revs, 0);
 	string_list_clear(&states, 0);
 	strbuf_release(&start_head);
 	strbuf_release(&bisect_names);
-	return res;
+	return retval;
 }
 
 int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
@@ -666,8 +663,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
 
 	switch (cmdmode) {
 	case NEXT_ALL:
-		res = bisect_next_all(the_repository, prefix, no_checkout);
-		break;
+		return bisect_next_all(the_repository, prefix, no_checkout);
 	case WRITE_TERMS:
 		if (argc != 2)
 			return error(_("--write-terms requires two arguments"));
@@ -714,13 +710,5 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
 		return error("BUG: unknown subcommand '%d'", cmdmode);
 	}
 	free_terms(&terms);
-
-	/*
-	 * Handle early success
-	 * From check_merge_bases > check_good_are_ancestors_of_bad > bisect_next_all
-	 */
-	if (res == BISECT_INTERNAL_SUCCESS_MERGE_BASE)
-		res = BISECT_OK;
-
-	return abs(res);
+	return !!res;
 }
diff --git a/third_party/git/builtin/blame.c b/third_party/git/builtin/blame.c
index edd4bf7e3b..7ebd51ae4d 100644
--- a/third_party/git/builtin/blame.c
+++ b/third_party/git/builtin/blame.c
@@ -26,6 +26,7 @@
 #include "progress.h"
 #include "object-store.h"
 #include "blame.h"
+#include "string-list.h"
 #include "refs.h"
 
 static char blame_usage[] = N_("git blame [<options>] [<rev-opts>] [<rev>] [--] <file>");
@@ -319,18 +320,18 @@ static const char *format_time(timestamp_t time, const char *tz_str,
 	return time_buf.buf;
 }
 
-#define OUTPUT_ANNOTATE_COMPAT      (1U<<0)
-#define OUTPUT_LONG_OBJECT_NAME     (1U<<1)
-#define OUTPUT_RAW_TIMESTAMP        (1U<<2)
-#define OUTPUT_PORCELAIN            (1U<<3)
-#define OUTPUT_SHOW_NAME            (1U<<4)
-#define OUTPUT_SHOW_NUMBER          (1U<<5)
-#define OUTPUT_SHOW_SCORE           (1U<<6)
-#define OUTPUT_NO_AUTHOR            (1U<<7)
-#define OUTPUT_SHOW_EMAIL           (1U<<8)
-#define OUTPUT_LINE_PORCELAIN       (1U<<9)
-#define OUTPUT_COLOR_LINE           (1U<<10)
-#define OUTPUT_SHOW_AGE_WITH_COLOR  (1U<<11)
+#define OUTPUT_ANNOTATE_COMPAT	001
+#define OUTPUT_LONG_OBJECT_NAME	002
+#define OUTPUT_RAW_TIMESTAMP	004
+#define OUTPUT_PORCELAIN	010
+#define OUTPUT_SHOW_NAME	020
+#define OUTPUT_SHOW_NUMBER	040
+#define OUTPUT_SHOW_SCORE	0100
+#define OUTPUT_NO_AUTHOR	0200
+#define OUTPUT_SHOW_EMAIL	0400
+#define OUTPUT_LINE_PORCELAIN	01000
+#define OUTPUT_COLOR_LINE	02000
+#define OUTPUT_SHOW_AGE_WITH_COLOR	04000
 
 static void emit_porcelain_details(struct blame_origin *suspect, int repeat)
 {
@@ -459,7 +460,7 @@ static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int
 
 	for (cnt = 0; cnt < ent->num_lines; cnt++) {
 		char ch;
-		int length = (opt & OUTPUT_LONG_OBJECT_NAME) ? the_hash_algo->hexsz : abbrev;
+		int length = (opt & OUTPUT_LONG_OBJECT_NAME) ? GIT_SHA1_HEXSZ : abbrev;
 
 		if (opt & OUTPUT_COLOR_LINE) {
 			if (cnt > 0) {
@@ -861,6 +862,14 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 		OPT_STRING_LIST(0, "ignore-revs-file", &ignore_revs_file_list, N_("file"), N_("Ignore revisions from <file>")),
 		OPT_BIT(0, "color-lines", &output_option, N_("color redundant metadata from previous line differently"), OUTPUT_COLOR_LINE),
 		OPT_BIT(0, "color-by-age", &output_option, N_("color lines by age"), OUTPUT_SHOW_AGE_WITH_COLOR),
+
+		/*
+		 * The following two options are parsed by parse_revision_opt()
+		 * and are only included here to get included in the "-h"
+		 * output:
+		 */
+		{ OPTION_LOWLEVEL_CALLBACK, 0, "indent-heuristic", NULL, NULL, N_("Use an experimental heuristic to improve diffs"), PARSE_OPT_NOARG, NULL, 0, parse_opt_unknown_cb },
+
 		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")),
@@ -876,7 +885,6 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 	struct range_set ranges;
 	unsigned int range_i;
 	long anchor;
-	const int hexsz = the_hash_algo->hexsz;
 
 	setup_default_color_by_age();
 	git_config(git_blame_config, &output_option);
@@ -923,11 +931,11 @@ parse_done:
 	} else if (show_progress < 0)
 		show_progress = isatty(2);
 
-	if (0 < abbrev && abbrev < hexsz)
+	if (0 < abbrev && abbrev < GIT_SHA1_HEXSZ)
 		/* one more abbrev length is needed for the boundary commit */
 		abbrev++;
 	else if (!abbrev)
-		abbrev = hexsz;
+		abbrev = GIT_SHA1_HEXSZ;
 
 	if (revs_file && read_ancestry(revs_file))
 		die_errno("reading graft file '%s' failed", revs_file);
diff --git a/third_party/git/builtin/branch.c b/third_party/git/builtin/branch.c
index d8297f80ff..2ef214632f 100644
--- a/third_party/git/builtin/branch.c
+++ b/third_party/git/builtin/branch.c
@@ -624,7 +624,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		OPT_SET_INT_F(0, "set-upstream", &track, N_("do not use"),
 			BRANCH_TRACK_OVERRIDE, PARSE_OPT_HIDDEN),
 		OPT_STRING('u', "set-upstream-to", &new_upstream, N_("upstream"), N_("change the upstream info")),
-		OPT_BOOL(0, "unset-upstream", &unset_upstream, N_("unset the upstream info")),
+		OPT_BOOL(0, "unset-upstream", &unset_upstream, N_("Unset the upstream info")),
 		OPT__COLOR(&branch_use_color, N_("use colored output")),
 		OPT_SET_INT('r', "remotes",     &filter.kind, N_("act on remote-tracking branches"),
 			FILTER_REFS_REMOTES),
diff --git a/third_party/git/builtin/bundle.c b/third_party/git/builtin/bundle.c
index f049d27a14..1ea4bfdfc1 100644
--- a/third_party/git/builtin/bundle.c
+++ b/third_party/git/builtin/bundle.c
@@ -1,6 +1,4 @@
 #include "builtin.h"
-#include "argv-array.h"
-#include "parse-options.h"
 #include "cache.h"
 #include "bundle.h"
 
@@ -11,184 +9,59 @@
  * bundle supporting "fetch", "pull", and "ls-remote".
  */
 
-static const char * const builtin_bundle_usage[] = {
-  N_("git bundle create [<options>] <file> <git-rev-list args>"),
-  N_("git bundle verify [<options>] <file>"),
-  N_("git bundle list-heads <file> [<refname>...]"),
-  N_("git bundle unbundle <file> [<refname>...]"),
-  NULL
-};
+static const char builtin_bundle_usage[] =
+  "git bundle create <file> <git-rev-list args>\n"
+  "   or: git bundle verify <file>\n"
+  "   or: git bundle list-heads <file> [<refname>...]\n"
+  "   or: git bundle unbundle <file> [<refname>...]";
 
-static const char * const builtin_bundle_create_usage[] = {
-  N_("git bundle create [<options>] <file> <git-rev-list args>"),
-  NULL
-};
-
-static const char * const builtin_bundle_verify_usage[] = {
-  N_("git bundle verify [<options>] <file>"),
-  NULL
-};
-
-static const char * const builtin_bundle_list_heads_usage[] = {
-  N_("git bundle list-heads <file> [<refname>...]"),
-  NULL
-};
-
-static const char * const builtin_bundle_unbundle_usage[] = {
-  N_("git bundle unbundle <file> [<refname>...]"),
-  NULL
-};
-
-static int verbose;
-
-static int parse_options_cmd_bundle(int argc,
-		const char **argv,
-		const char* prefix,
-		const char * const usagestr[],
-		const struct option options[],
-		const char **bundle_file) {
-	int newargc;
-	newargc = parse_options(argc, argv, NULL, options, usagestr,
-			     PARSE_OPT_STOP_AT_NON_OPTION);
-	if (argc < 1)
-		usage_with_options(usagestr, options);
-	*bundle_file = prefix_filename(prefix, argv[0]);
-	return newargc;
-}
-
-static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
-	int all_progress_implied = 0;
-	int progress = isatty(STDERR_FILENO);
-	struct argv_array pack_opts;
-
-	struct option options[] = {
-		OPT_SET_INT('q', "quiet", &progress,
-			    N_("do not show progress meter"), 0),
-		OPT_SET_INT(0, "progress", &progress,
-			    N_("show progress meter"), 1),
-		OPT_SET_INT(0, "all-progress", &progress,
-			    N_("show progress meter during object writing phase"), 2),
-		OPT_BOOL(0, "all-progress-implied",
-			 &all_progress_implied,
-			 N_("similar to --all-progress when progress meter is shown")),
-		OPT_END()
-	};
-	const char* bundle_file;
-
-	argc = parse_options_cmd_bundle(argc, argv, prefix,
-			builtin_bundle_create_usage, options, &bundle_file);
-	/* bundle internals use argv[1] as further parameters */
-
-	argv_array_init(&pack_opts);
-	if (progress == 0)
-		argv_array_push(&pack_opts, "--quiet");
-	else if (progress == 1)
-		argv_array_push(&pack_opts, "--progress");
-	else if (progress == 2)
-		argv_array_push(&pack_opts, "--all-progress");
-	if (progress && all_progress_implied)
-		argv_array_push(&pack_opts, "--all-progress-implied");
-
-	if (!startup_info->have_repository)
-		die(_("Need a repository to create a bundle."));
-	return !!create_bundle(the_repository, bundle_file, argc, argv, &pack_opts);
-}
-
-static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
-	struct bundle_header header;
-	int bundle_fd = -1;
-	int quiet = 0;
-
-	struct option options[] = {
-		OPT_BOOL('q', "quiet", &quiet,
-			    N_("do not show bundle details")),
-		OPT_END()
-	};
-	const char* bundle_file;
-
-	argc = parse_options_cmd_bundle(argc, argv, prefix,
-			builtin_bundle_verify_usage, options, &bundle_file);
-	/* bundle internals use argv[1] as further parameters */
-
-	memset(&header, 0, sizeof(header));
-	if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0)
-		return 1;
-	close(bundle_fd);
-	if (verify_bundle(the_repository, &header, !quiet))
-		return 1;
-	fprintf(stderr, _("%s is okay\n"), bundle_file);
-	return 0;
-}
-
-static int cmd_bundle_list_heads(int argc, const char **argv, const char *prefix) {
-	struct bundle_header header;
-	int bundle_fd = -1;
-
-	struct option options[] = {
-		OPT_END()
-	};
-	const char* bundle_file;
-
-	argc = parse_options_cmd_bundle(argc, argv, prefix,
-			builtin_bundle_list_heads_usage, options, &bundle_file);
-	/* bundle internals use argv[1] as further parameters */
-
-	memset(&header, 0, sizeof(header));
-	if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0)
-		return 1;
-	close(bundle_fd);
-	return !!list_bundle_refs(&header, argc, argv);
-}
-
-static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix) {
+int cmd_bundle(int argc, const char **argv, const char *prefix)
+{
 	struct bundle_header header;
+	const char *cmd, *bundle_file;
 	int bundle_fd = -1;
 
-	struct option options[] = {
-		OPT_END()
-	};
-	const char* bundle_file;
+	if (argc < 3)
+		usage(builtin_bundle_usage);
 
-	argc = parse_options_cmd_bundle(argc, argv, prefix,
-			builtin_bundle_unbundle_usage, options, &bundle_file);
-	/* bundle internals use argv[1] as further parameters */
+	cmd = argv[1];
+	bundle_file = prefix_filename(prefix, argv[2]);
+	argc -= 2;
+	argv += 2;
 
 	memset(&header, 0, sizeof(header));
-	if ((bundle_fd = read_bundle_header(bundle_file, &header)) < 0)
+	if (strcmp(cmd, "create") && (bundle_fd =
+				read_bundle_header(bundle_file, &header)) < 0)
 		return 1;
-	if (!startup_info->have_repository)
-		die(_("Need a repository to unbundle."));
-	return !!unbundle(the_repository, &header, bundle_fd, 0) ||
-		list_bundle_refs(&header, argc, argv);
-}
-
-int cmd_bundle(int argc, const char **argv, const char *prefix)
-{
-	struct option options[] = {
-		OPT__VERBOSE(&verbose, N_("be verbose; must be placed before a subcommand")),
-		OPT_END()
-	};
-	int result;
-
-	argc = parse_options(argc, argv, prefix, options, builtin_bundle_usage,
-		PARSE_OPT_STOP_AT_NON_OPTION);
-
-	packet_trace_identity("bundle");
 
-	if (argc < 2)
-		usage_with_options(builtin_bundle_usage, options);
-
-	else if (!strcmp(argv[0], "create"))
-		result = cmd_bundle_create(argc, argv, prefix);
-	else if (!strcmp(argv[0], "verify"))
-		result = cmd_bundle_verify(argc, argv, prefix);
-	else if (!strcmp(argv[0], "list-heads"))
-		result = cmd_bundle_list_heads(argc, argv, prefix);
-	else if (!strcmp(argv[0], "unbundle"))
-		result = cmd_bundle_unbundle(argc, argv, prefix);
-	else {
-		error(_("Unknown subcommand: %s"), argv[0]);
-		usage_with_options(builtin_bundle_usage, options);
+	if (!strcmp(cmd, "verify")) {
+		close(bundle_fd);
+		if (argc != 1) {
+			usage(builtin_bundle_usage);
+			return 1;
+		}
+		if (verify_bundle(the_repository, &header, 1))
+			return 1;
+		fprintf(stderr, _("%s is okay\n"), bundle_file);
+		return 0;
+	}
+	if (!strcmp(cmd, "list-heads")) {
+		close(bundle_fd);
+		return !!list_bundle_refs(&header, argc, argv);
 	}
-	return result ? 1 : 0;
+	if (!strcmp(cmd, "create")) {
+		if (argc < 2) {
+			usage(builtin_bundle_usage);
+			return 1;
+		}
+		if (!startup_info->have_repository)
+			die(_("Need a repository to create a bundle."));
+		return !!create_bundle(the_repository, bundle_file, argc, argv);
+	} else if (!strcmp(cmd, "unbundle")) {
+		if (!startup_info->have_repository)
+			die(_("Need a repository to unbundle."));
+		return !!unbundle(the_repository, &header, bundle_fd, 0) ||
+			list_bundle_refs(&header, argc, argv);
+	} else
+		usage(builtin_bundle_usage);
 }
diff --git a/third_party/git/builtin/cat-file.c b/third_party/git/builtin/cat-file.c
index 272f9fc6d7..995d47c85a 100644
--- a/third_party/git/builtin/cat-file.c
+++ b/third_party/git/builtin/cat-file.c
@@ -15,7 +15,6 @@
 #include "sha1-array.h"
 #include "packfile.h"
 #include "object-store.h"
-#include "promisor-remote.h"
 
 struct batch_options {
 	int enabled;
@@ -262,7 +261,7 @@ static void expand_atom(struct strbuf *sb, const char *atom, int len,
 			strbuf_addstr(sb, data->rest);
 	} else if (is_atom("deltabase", atom, len)) {
 		if (data->mark_query)
-			data->info.delta_base_oid = &data->delta_base_oid;
+			data->info.delta_base_sha1 = data->delta_base_oid.hash;
 		else
 			strbuf_addstr(sb,
 				      oid_to_hex(&data->delta_base_oid));
@@ -525,8 +524,8 @@ static int batch_objects(struct batch_options *opt)
 	if (opt->all_objects) {
 		struct object_cb_data cb;
 
-		if (has_promisor_remote())
-			warning("This repository uses promisor remotes. Some objects may not be loaded.");
+		if (repository_format_partial_clone)
+			warning("This repository has extensions.partialClone set. Some objects may not be loaded.");
 
 		cb.opt = opt;
 		cb.expand = &data;
diff --git a/third_party/git/builtin/check-ignore.c b/third_party/git/builtin/check-ignore.c
index ea5d0ae3a6..599097304b 100644
--- a/third_party/git/builtin/check-ignore.c
+++ b/third_party/git/builtin/check-ignore.c
@@ -32,19 +32,19 @@ static const struct option check_ignore_options[] = {
 	OPT_END()
 };
 
-static void output_pattern(const char *path, struct path_pattern *pattern)
+static void output_exclude(const char *path, struct exclude *exclude)
 {
-	char *bang  = (pattern && pattern->flags & PATTERN_FLAG_NEGATIVE)  ? "!" : "";
-	char *slash = (pattern && pattern->flags & PATTERN_FLAG_MUSTBEDIR) ? "/" : "";
+	char *bang  = (exclude && exclude->flags & EXC_FLAG_NEGATIVE)  ? "!" : "";
+	char *slash = (exclude && exclude->flags & EXC_FLAG_MUSTBEDIR) ? "/" : "";
 	if (!nul_term_line) {
 		if (!verbose) {
 			write_name_quoted(path, stdout, '\n');
 		} else {
-			if (pattern) {
-				quote_c_style(pattern->pl->src, NULL, stdout, 0);
+			if (exclude) {
+				quote_c_style(exclude->el->src, NULL, stdout, 0);
 				printf(":%d:%s%s%s\t",
-				       pattern->srcpos,
-				       bang, pattern->pattern, slash);
+				       exclude->srcpos,
+				       bang, exclude->pattern, slash);
 			}
 			else {
 				printf("::\t");
@@ -56,11 +56,11 @@ static void output_pattern(const char *path, struct path_pattern *pattern)
 		if (!verbose) {
 			printf("%s%c", path, '\0');
 		} else {
-			if (pattern)
+			if (exclude)
 				printf("%s%c%d%c%s%s%s%c%s%c",
-				       pattern->pl->src, '\0',
-				       pattern->srcpos, '\0',
-				       bang, pattern->pattern, slash, '\0',
+				       exclude->el->src, '\0',
+				       exclude->srcpos, '\0',
+				       bang, exclude->pattern, slash, '\0',
 				       path, '\0');
 			else
 				printf("%c%c%c%s%c", '\0', '\0', '\0', path, '\0');
@@ -74,7 +74,7 @@ static int check_ignore(struct dir_struct *dir,
 	const char *full_path;
 	char *seen;
 	int num_ignored = 0, i;
-	struct path_pattern *pattern;
+	struct exclude *exclude;
 	struct pathspec pathspec;
 
 	if (!argc) {
@@ -103,18 +103,15 @@ static int check_ignore(struct dir_struct *dir,
 	seen = find_pathspecs_matching_against_index(&pathspec, &the_index);
 	for (i = 0; i < pathspec.nr; i++) {
 		full_path = pathspec.items[i].match;
-		pattern = NULL;
+		exclude = NULL;
 		if (!seen[i]) {
 			int dtype = DT_UNKNOWN;
-			pattern = last_matching_pattern(dir, &the_index,
+			exclude = last_exclude_matching(dir, &the_index,
 							full_path, &dtype);
-			if (!verbose && pattern &&
-			    pattern->flags & PATTERN_FLAG_NEGATIVE)
-				pattern = NULL;
 		}
-		if (!quiet && (pattern || show_non_matching))
-			output_pattern(pathspec.items[i].original, pattern);
-		if (pattern)
+		if (!quiet && (exclude || show_non_matching))
+			output_exclude(pathspec.items[i].original, exclude);
+		if (exclude)
 			num_ignored++;
 	}
 	free(seen);
diff --git a/third_party/git/builtin/checkout.c b/third_party/git/builtin/checkout.c
index d6773818b8..6123f732a2 100644
--- a/third_party/git/builtin/checkout.c
+++ b/third_party/git/builtin/checkout.c
@@ -70,8 +70,6 @@ struct checkout_opts {
 	int checkout_worktree;
 	const char *ignore_unmerged_opt;
 	int ignore_unmerged;
-	int pathspec_file_nul;
-	const char *pathspec_from_file;
 
 	const char *new_branch;
 	const char *new_branch_force;
@@ -128,7 +126,6 @@ static int update_some(const struct object_id *oid, struct strbuf *base,
 	if (pos >= 0) {
 		struct cache_entry *old = active_cache[pos];
 		if (ce->ce_mode == old->ce_mode &&
-		    !ce_intent_to_add(old) &&
 		    oideq(&ce->oid, &old->oid)) {
 			old->ce_flags |= CE_UPDATE;
 			discard_cache_entry(ce);
@@ -524,8 +521,6 @@ static int checkout_paths(const struct checkout_opts *opts,
 	/* Now we are committed to check them out */
 	if (opts->checkout_worktree)
 		errs |= checkout_worktree(opts);
-	else
-		remove_marked_cache_entries(&the_index, 1);
 
 	/*
 	 * Allow updating the index when checking out from the index.
@@ -713,11 +708,11 @@ static int merge_working_tree(const struct checkout_opts *opts,
 			 * give up or do a real merge, depending on
 			 * whether the merge flag was used.
 			 */
+			struct tree *result;
 			struct tree *work;
 			struct tree *old_tree;
 			struct merge_options o;
 			struct strbuf sb = STRBUF_INIT;
-			struct strbuf old_commit_shortname = STRBUF_INIT;
 
 			if (!opts->merge)
 				return 1;
@@ -735,6 +730,13 @@ static int merge_working_tree(const struct checkout_opts *opts,
 				      "the following files:\n%s"), sb.buf);
 			strbuf_release(&sb);
 
+			if (repo_index_has_changes(the_repository,
+						   get_commit_tree(old_branch_info->commit),
+						   &sb))
+				warning(_("staged changes in the following files may be lost: %s"),
+					sb.buf);
+			strbuf_release(&sb);
+
 			/* Do more real merge */
 
 			/*
@@ -758,7 +760,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
 			 */
 			init_merge_options(&o, the_repository);
 			o.verbosity = 0;
-			work = write_in_core_index_as_tree(the_repository);
+			work = write_tree_from_memory(&o);
 
 			ret = reset_tree(new_tree,
 					 opts, 1,
@@ -766,25 +768,19 @@ static int merge_working_tree(const struct checkout_opts *opts,
 			if (ret)
 				return ret;
 			o.ancestor = old_branch_info->name;
-			if (old_branch_info->name == NULL) {
-				strbuf_add_unique_abbrev(&old_commit_shortname,
-							 &old_branch_info->commit->object.oid,
-							 DEFAULT_ABBREV);
-				o.ancestor = old_commit_shortname.buf;
-			}
 			o.branch1 = new_branch_info->name;
 			o.branch2 = "local";
 			ret = merge_trees(&o,
 					  new_tree,
 					  work,
-					  old_tree);
+					  old_tree,
+					  &result);
 			if (ret < 0)
 				exit(128);
 			ret = reset_tree(new_tree,
 					 opts, 0,
 					 writeout_error);
 			strbuf_release(&o.obuf);
-			strbuf_release(&old_commit_shortname);
 			if (ret)
 				return ret;
 		}
@@ -865,7 +861,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
 		strbuf_addf(&msg, "checkout: moving from %s to %s",
 			old_desc ? old_desc : "(invalid)", new_branch_info->name);
 	else
-		strbuf_insertstr(&msg, 0, reflog_msg);
+		strbuf_insert(&msg, 0, reflog_msg, strlen(reflog_msg));
 
 	if (!strcmp(new_branch_info->name, "HEAD") && !new_branch_info->path && !opts->force_detach) {
 		/* Nothing to do. */
@@ -1117,43 +1113,12 @@ static void setup_new_branch_info_and_source_tree(
 	}
 }
 
-static const char *parse_remote_branch(const char *arg,
-				       struct object_id *rev,
-				       int could_be_checkout_paths)
-{
-	int num_matches = 0;
-	const char *remote = unique_tracking_name(arg, rev, &num_matches);
-
-	if (remote && could_be_checkout_paths) {
-		die(_("'%s' could be both a local file and a tracking branch.\n"
-			"Please use -- (and optionally --no-guess) to disambiguate"),
-		    arg);
-	}
-
-	if (!remote && num_matches > 1) {
-	    if (advice_checkout_ambiguous_remote_branch_name) {
-		    advise(_("If you meant to check out a remote tracking branch on, e.g. 'origin',\n"
-			     "you can do so by fully qualifying the name with the --track option:\n"
-			     "\n"
-			     "    git checkout --track origin/<name>\n"
-			     "\n"
-			     "If you'd like to always have checkouts of an ambiguous <name> prefer\n"
-			     "one remote, e.g. the 'origin' remote, consider setting\n"
-			     "checkout.defaultRemote=origin in your config."));
-	    }
-
-	    die(_("'%s' matched multiple (%d) remote tracking branches"),
-		arg, num_matches);
-	}
-
-	return remote;
-}
-
 static int parse_branchname_arg(int argc, const char **argv,
 				int dwim_new_local_branch_ok,
 				struct branch_info *new_branch_info,
 				struct checkout_opts *opts,
-				struct object_id *rev)
+				struct object_id *rev,
+				int *dwim_remotes_matched)
 {
 	const char **new_branch = &opts->new_branch;
 	int argcount = 0;
@@ -1258,9 +1223,13 @@ static int parse_branchname_arg(int argc, const char **argv,
 			recover_with_dwim = 0;
 
 		if (recover_with_dwim) {
-			const char *remote = parse_remote_branch(arg, rev,
-								 could_be_checkout_paths);
+			const char *remote = unique_tracking_name(arg, rev,
+								  dwim_remotes_matched);
 			if (remote) {
+				if (could_be_checkout_paths)
+					die(_("'%s' could be both a local file and a tracking branch.\n"
+					      "Please use -- (and optionally --no-guess) to disambiguate"),
+					    arg);
 				*new_branch = arg;
 				arg = remote;
 				/* DWIMmed to create local branch, case (3).(b) */
@@ -1511,8 +1480,6 @@ static struct option *add_checkout_path_options(struct checkout_opts *opts,
 		OPT_BOOL('p', "patch", &opts->patch_mode, N_("select hunks interactively")),
 		OPT_BOOL(0, "ignore-skip-worktree-bits", &opts->ignore_skipworktree,
 			 N_("do not limit pathspecs to sparse entries only")),
-		OPT_PATHSPEC_FROM_FILE(&opts->pathspec_from_file),
-		OPT_PATHSPEC_FILE_NUL(&opts->pathspec_file_nul),
 		OPT_END()
 	};
 	struct option *newopts = parse_options_concat(prevopts, options);
@@ -1525,6 +1492,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 			 const char * const usagestr[])
 {
 	struct branch_info new_branch_info;
+	int dwim_remotes_matched = 0;
 	int parseopt_flags = 0;
 
 	memset(&new_branch_info, 0, sizeof(new_branch_info));
@@ -1632,7 +1600,8 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 			opts->track == BRANCH_TRACK_UNSPECIFIED &&
 			!opts->new_branch;
 		int n = parse_branchname_arg(argc, argv, dwim_ok,
-					     &new_branch_info, opts, &rev);
+					     &new_branch_info, opts, &rev,
+					     &dwim_remotes_matched);
 		argv += n;
 		argc -= n;
 	} else if (!opts->accept_ref && opts->from_treeish) {
@@ -1649,6 +1618,10 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 			die(_("reference is not a tree: %s"), opts->from_treeish);
 	}
 
+	if (opts->accept_pathspec && !opts->empty_pathspec_ok && !argc &&
+	    !opts->patch_mode)	/* patch mode is special */
+		die(_("you must specify path(s) to restore"));
+
 	if (argc) {
 		parse_pathspec(&opts->pathspec, 0,
 			       opts->patch_mode ? PATHSPEC_PREFIX_ORIGIN : 0,
@@ -1668,33 +1641,10 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 		if (opts->force_detach)
 			die(_("git checkout: --detach does not take a path argument '%s'"),
 			    argv[0]);
-	}
 
-	if (opts->pathspec_from_file) {
-		if (opts->pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
-
-		if (opts->force_detach)
-			die(_("--pathspec-from-file is incompatible with --detach"));
-
-		if (opts->patch_mode)
-			die(_("--pathspec-from-file is incompatible with --patch"));
-
-		parse_pathspec_file(&opts->pathspec, 0,
-				    0,
-				    prefix, opts->pathspec_from_file, opts->pathspec_file_nul);
-	} else if (opts->pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
-	}
-
-	if (opts->pathspec.nr) {
 		if (1 < !!opts->writeout_stage + !!opts->force + !!opts->merge)
 			die(_("git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
 			      "checking out of the index."));
-	} else {
-		if (opts->accept_pathspec && !opts->empty_pathspec_ok &&
-		    !opts->patch_mode)	/* patch mode is special */
-			die(_("you must specify path(s) to restore"));
 	}
 
 	if (opts->new_branch) {
@@ -1709,10 +1659,28 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
 	}
 
 	UNLEAK(opts);
-	if (opts->patch_mode || opts->pathspec.nr)
-		return checkout_paths(opts, new_branch_info.name);
-	else
+	if (opts->patch_mode || opts->pathspec.nr) {
+		int ret = checkout_paths(opts, new_branch_info.name);
+		if (ret && dwim_remotes_matched > 1 &&
+		    advice_checkout_ambiguous_remote_branch_name)
+			advise(_("'%s' matched more than one remote tracking branch.\n"
+				 "We found %d remotes with a reference that matched. So we fell back\n"
+				 "on trying to resolve the argument as a path, but failed there too!\n"
+				 "\n"
+				 "If you meant to check out a remote tracking branch on, e.g. 'origin',\n"
+				 "you can do so by fully qualifying the name with the --track option:\n"
+				 "\n"
+				 "    git checkout --track origin/<name>\n"
+				 "\n"
+				 "If you'd like to always have checkouts of an ambiguous <name> prefer\n"
+				 "one remote, e.g. the 'origin' remote, consider setting\n"
+				 "checkout.defaultRemote=origin in your config."),
+			       argv[0],
+			       dwim_remotes_matched);
+		return ret;
+	} else {
 		return checkout_branch(opts, &new_branch_info);
+	}
 }
 
 int cmd_checkout(int argc, const char **argv, const char *prefix)
@@ -1746,15 +1714,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 	opts.checkout_index = -2;    /* default on */
 	opts.checkout_worktree = -2; /* default on */
 
-	if (argc == 3 && !strcmp(argv[1], "-b")) {
-		/*
-		 * User ran 'git checkout -b <branch>' and expects
-		 * the same behavior as 'git switch -c <branch>'.
-		 */
-		opts.switch_branch_doing_nothing_is_ok = 0;
-		opts.only_merge_on_switching_branches = 1;
-	}
-
 	options = parse_options_dup(checkout_options);
 	options = add_common_options(&opts, options);
 	options = add_common_switch_branch_options(&opts, options);
diff --git a/third_party/git/builtin/clean.c b/third_party/git/builtin/clean.c
index 5abf087e7c..d5579da716 100644
--- a/third_party/git/builtin/clean.c
+++ b/third_party/git/builtin/clean.c
@@ -158,8 +158,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
 
 	*dir_gone = 1;
 
-	if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) &&
-	    is_nonbare_repository_dir(path)) {
+	if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) && is_nonbare_repository_dir(path)) {
 		if (!quiet) {
 			quote_path_relative(path->buf, prefix, &quoted);
 			printf(dry_run ?  _(msg_would_skip_git_dir) : _(msg_skip_git_dir),
@@ -649,7 +648,7 @@ static int filter_by_patterns_cmd(void)
 	struct strbuf confirm = STRBUF_INIT;
 	struct strbuf **ignore_list;
 	struct string_list_item *item;
-	struct pattern_list *pl;
+	struct exclude_list *el;
 	int changed = -1, i;
 
 	for (;;) {
@@ -672,7 +671,7 @@ static int filter_by_patterns_cmd(void)
 			break;
 
 		memset(&dir, 0, sizeof(dir));
-		pl = add_pattern_list(&dir, EXC_CMDL, "manual exclude");
+		el = add_exclude_list(&dir, EXC_CMDL, "manual exclude");
 		ignore_list = strbuf_split_max(&confirm, ' ', 0);
 
 		for (i = 0; ignore_list[i]; i++) {
@@ -680,7 +679,7 @@ static int filter_by_patterns_cmd(void)
 			if (!ignore_list[i]->len)
 				continue;
 
-			add_pattern(ignore_list[i]->buf, "", 0, pl, -(i+1));
+			add_exclude(ignore_list[i]->buf, "", 0, el, -(i+1));
 		}
 
 		changed = 0;
@@ -902,7 +901,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	struct pathspec pathspec;
 	struct strbuf buf = STRBUF_INIT;
 	struct string_list exclude_list = STRING_LIST_INIT_NODUP;
-	struct pattern_list *pl;
+	struct exclude_list *el;
 	struct string_list_item *item;
 	const char *qname;
 	struct option options[] = {
@@ -947,19 +946,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 
 	if (force > 1)
 		rm_flags = 0;
-	else
-		dir.flags |= DIR_SKIP_NESTED_GIT;
 
 	dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
 
-	if (argc) {
-		/*
-		 * Remaining args implies pathspecs specified, and we should
-		 * recurse within those.
-		 */
-		remove_directories = 1;
-	}
-
 	if (remove_directories)
 		dir.flags |= DIR_SHOW_IGNORED_TOO | DIR_KEEP_UNTRACKED_CONTENTS;
 
@@ -969,9 +958,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	if (!ignored)
 		setup_standard_excludes(&dir);
 
-	pl = add_pattern_list(&dir, EXC_CMDL, "--exclude option");
+	el = add_exclude_list(&dir, EXC_CMDL, "--exclude option");
 	for (i = 0; i < exclude_list.nr; i++)
-		add_pattern(exclude_list.items[i].string, "", 0, pl, -(i+1));
+		add_exclude(exclude_list.items[i].string, "", 0, el, -(i+1));
 
 	parse_pathspec(&pathspec, 0,
 		       PATHSPEC_PREFER_CWD,
@@ -1018,7 +1007,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	for_each_string_list_item(item, &del_list) {
 		struct stat st;
 
-		strbuf_reset(&abs_path);
 		if (prefix)
 			strbuf_addstr(&abs_path, prefix);
 
@@ -1052,6 +1040,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 				printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
 			}
 		}
+		strbuf_reset(&abs_path);
 	}
 
 	strbuf_release(&abs_path);
diff --git a/third_party/git/builtin/clone.c b/third_party/git/builtin/clone.c
index 1ad26f4d8c..f665b28ccc 100644
--- a/third_party/git/builtin/clone.c
+++ b/third_party/git/builtin/clone.c
@@ -32,6 +32,7 @@
 #include "connected.h"
 #include "packfile.h"
 #include "list-objects-filter-options.h"
+#include "object-store.h"
 
 /*
  * Overall FIXMEs:
@@ -59,7 +60,6 @@ static const char *real_git_dir;
 static char *option_upload_pack = "git-upload-pack";
 static int option_verbosity;
 static int option_progress = -1;
-static int option_sparse_checkout;
 static enum transport_family family;
 static struct string_list option_config = STRING_LIST_INIT_NODUP;
 static struct string_list option_required_reference = STRING_LIST_INIT_NODUP;
@@ -147,8 +147,6 @@ static struct option builtin_clone_options[] = {
 	OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
 	OPT_BOOL(0, "remote-submodules", &option_remote_submodules,
 		    N_("any cloned submodules will use their remote-tracking branch")),
-	OPT_BOOL(0, "sparse", &option_sparse_checkout,
-		    N_("initialize sparse-checkout file to include only files at root")),
 	OPT_END()
 };
 
@@ -673,7 +671,7 @@ static void update_remote_refs(const struct ref *refs,
 			       const char *msg,
 			       struct transport *transport,
 			       int check_connectivity,
-			       int check_refs_are_promisor_objects_only)
+			       int check_refs_only)
 {
 	const struct ref *rm = mapped_refs;
 
@@ -682,8 +680,7 @@ static void update_remote_refs(const struct ref *refs,
 
 		opt.transport = transport;
 		opt.progress = transport->progress;
-		opt.check_refs_are_promisor_objects_only =
-			!!check_refs_are_promisor_objects_only;
+		opt.check_refs_only = !!check_refs_only;
 
 		if (check_connected(iterate_ref_map, &rm, &opt))
 			die(_("remote did not send all necessary objects"));
@@ -737,27 +734,6 @@ static void update_head(const struct ref *our, const struct ref *remote,
 	}
 }
 
-static int git_sparse_checkout_init(const char *repo)
-{
-	struct argv_array argv = ARGV_ARRAY_INIT;
-	int result = 0;
-	argv_array_pushl(&argv, "-C", repo, "sparse-checkout", "init", NULL);
-
-	/*
-	 * We must apply the setting in the current process
-	 * for the later checkout to use the sparse-checkout file.
-	 */
-	core_apply_sparse_checkout = 1;
-
-	if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {
-		error(_("failed to initialize sparse-checkout"));
-		result = 1;
-	}
-
-	argv_array_clear(&argv);
-	return result;
-}
-
 static int checkout(int submodule_progress)
 {
 	struct object_id oid;
@@ -809,12 +785,12 @@ static int checkout(int submodule_progress)
 	if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
 		die(_("unable to write new index file"));
 
-	err |= run_hook_le(NULL, "post-checkout", oid_to_hex(&null_oid),
+	err |= run_hook_le(NULL, "post-checkout", sha1_to_hex(null_sha1),
 			   oid_to_hex(&oid), "1", NULL);
 
 	if (!err && (option_recurse_submodules.nr > 0)) {
 		struct argv_array args = ARGV_ARRAY_INIT;
-		argv_array_pushl(&args, "submodule", "update", "--require-init", "--recursive", NULL);
+		argv_array_pushl(&args, "submodule", "update", "--init", "--recursive", NULL);
 
 		if (option_shallow_submodules == 1)
 			argv_array_push(&args, "--depth=1");
@@ -833,11 +809,6 @@ static int checkout(int submodule_progress)
 			argv_array_push(&args, "--no-fetch");
 		}
 
-		if (option_single_branch >= 0)
-			argv_array_push(&args, option_single_branch ?
-					       "--single-branch" :
-					       "--no-single-branch");
-
 		err = run_command_v_opt(args.argv, RUN_GIT_CMD);
 		argv_array_clear(&args);
 	}
@@ -929,7 +900,7 @@ static void dissociate_from_references(void)
 	free(alternates);
 }
 
-static int path_exists(const char *path)
+static int dir_exists(const char *path)
 {
 	struct stat sb;
 	return !stat(path, &sb);
@@ -957,6 +928,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
 	struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
 
+	fetch_if_missing = 0;
+
 	packet_trace_identity("clone");
 	argc = parse_options(argc, argv, prefix, builtin_clone_options,
 			     builtin_clone_usage, 0);
@@ -1009,7 +982,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		dir = guess_dir_name(repo_name, is_bundle, option_bare);
 	strip_trailing_slashes(dir);
 
-	dest_exists = path_exists(dir);
+	dest_exists = dir_exists(dir);
 	if (dest_exists && !is_empty_dir(dir))
 		die(_("destination path '%s' already exists and is not "
 			"an empty directory."), dir);
@@ -1020,7 +993,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		work_tree = NULL;
 	else {
 		work_tree = getenv("GIT_WORK_TREE");
-		if (work_tree && path_exists(work_tree))
+		if (work_tree && dir_exists(work_tree))
 			die(_("working tree '%s' already exists."), work_tree);
 	}
 
@@ -1048,7 +1021,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	}
 
 	if (real_git_dir) {
-		if (path_exists(real_git_dir))
+		if (dir_exists(real_git_dir))
 			junk_git_dir_flags |= REMOVE_DIR_KEEP_TOPLEVEL;
 		junk_git_dir = real_git_dir;
 	} else {
@@ -1134,9 +1107,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	if (option_required_reference.nr || option_optional_reference.nr)
 		setup_reference();
 
-	if (option_sparse_checkout && git_sparse_checkout_init(dir))
-		return 1;
-
 	remote = remote_get(option_origin);
 
 	strbuf_addf(&default_refspec, "+%s*:%s*", src_ref_prefix,
@@ -1190,11 +1160,13 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 		transport->server_options = &server_options;
 
 	if (filter_options.choice) {
-		const char *spec =
-			expand_list_objects_filter_spec(&filter_options);
+		struct strbuf expanded_filter_spec = STRBUF_INIT;
+		expand_list_objects_filter_spec(&filter_options,
+						&expanded_filter_spec);
 		transport_set_option(transport, TRANS_OPT_LIST_OBJECTS_FILTER,
-				     spec);
+				     expanded_filter_spec.buf);
 		transport_set_option(transport, TRANS_OPT_FROM_PROMISOR, "1");
+		strbuf_release(&expanded_filter_spec);
 	}
 
 	if (transport->smart_options && !deepen && !filter_options.choice)
@@ -1296,6 +1268,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	}
 
 	junk_mode = JUNK_LEAVE_REPO;
+	fetch_if_missing = 1;
 	err = checkout(submodule_progress);
 
 	strbuf_release(&reflog_msg);
diff --git a/third_party/git/builtin/commit-graph.c b/third_party/git/builtin/commit-graph.c
index 4a70b33fb5..38027b83d9 100644
--- a/third_party/git/builtin/commit-graph.c
+++ b/third_party/git/builtin/commit-graph.c
@@ -8,18 +8,25 @@
 #include "object-store.h"
 
 static char const * const builtin_commit_graph_usage[] = {
-	N_("git commit-graph verify [--object-dir <objdir>] [--shallow] [--[no-]progress]"),
-	N_("git commit-graph write [--object-dir <objdir>] [--append|--split] [--reachable|--stdin-packs|--stdin-commits] [--[no-]progress] <split options>"),
+	N_("git commit-graph [--object-dir <objdir>]"),
+	N_("git commit-graph read [--object-dir <objdir>]"),
+	N_("git commit-graph verify [--object-dir <objdir>] [--shallow]"),
+	N_("git commit-graph write [--object-dir <objdir>] [--append|--split] [--reachable|--stdin-packs|--stdin-commits] <split options>"),
 	NULL
 };
 
 static const char * const builtin_commit_graph_verify_usage[] = {
-	N_("git commit-graph verify [--object-dir <objdir>] [--shallow] [--[no-]progress]"),
+	N_("git commit-graph verify [--object-dir <objdir>] [--shallow]"),
+	NULL
+};
+
+static const char * const builtin_commit_graph_read_usage[] = {
+	N_("git commit-graph read [--object-dir <objdir>]"),
 	NULL
 };
 
 static const char * const builtin_commit_graph_write_usage[] = {
-	N_("git commit-graph write [--object-dir <objdir>] [--append|--split] [--reachable|--stdin-packs|--stdin-commits] [--[no-]progress] <split options>"),
+	N_("git commit-graph write [--object-dir <objdir>] [--append|--split] [--reachable|--stdin-packs|--stdin-commits] <split options>"),
 	NULL
 };
 
@@ -31,32 +38,11 @@ static struct opts_commit_graph {
 	int append;
 	int split;
 	int shallow;
-	int progress;
 } opts;
 
-static struct object_directory *find_odb(struct repository *r,
-					 const char *obj_dir)
-{
-	struct object_directory *odb;
-	char *obj_dir_real = real_pathdup(obj_dir, 1);
-
-	prepare_alt_odb(r);
-	for (odb = r->objects->odb; odb; odb = odb->next) {
-		if (!strcmp(obj_dir_real, real_path(odb->path)))
-			break;
-	}
-
-	free(obj_dir_real);
-
-	if (!odb)
-		die(_("could not find object directory matching %s"), obj_dir);
-	return odb;
-}
-
 static int graph_verify(int argc, const char **argv)
 {
 	struct commit_graph *graph = NULL;
-	struct object_directory *odb = NULL;
 	char *graph_name;
 	int open_ok;
 	int fd;
@@ -69,13 +55,9 @@ static int graph_verify(int argc, const char **argv)
 			   N_("The object directory to store the graph")),
 		OPT_BOOL(0, "shallow", &opts.shallow,
 			 N_("if the commit-graph is split, only verify the tip file")),
-		OPT_BOOL(0, "progress", &opts.progress, N_("force progress reporting")),
 		OPT_END(),
 	};
 
-	trace2_cmd_mode("verify");
-
-	opts.progress = isatty(2);
 	argc = parse_options(argc, argv, NULL,
 			     builtin_commit_graph_verify_options,
 			     builtin_commit_graph_verify_usage, 0);
@@ -84,11 +66,8 @@ static int graph_verify(int argc, const char **argv)
 		opts.obj_dir = get_object_directory();
 	if (opts.shallow)
 		flags |= COMMIT_GRAPH_VERIFY_SHALLOW;
-	if (opts.progress)
-		flags |= COMMIT_GRAPH_WRITE_PROGRESS;
 
-	odb = find_odb(the_repository, opts.obj_dir);
-	graph_name = get_commit_graph_filename(odb);
+	graph_name = get_commit_graph_filename(opts.obj_dir);
 	open_ok = open_commit_graph(graph_name, &fd, &st);
 	if (!open_ok && errno != ENOENT)
 		die_errno(_("Could not open commit-graph '%s'"), graph_name);
@@ -96,9 +75,9 @@ static int graph_verify(int argc, const char **argv)
 	FREE_AND_NULL(graph_name);
 
 	if (open_ok)
-		graph = load_commit_graph_one_fd_st(fd, &st, odb);
-	else
-		graph = read_commit_graph_one(the_repository, odb);
+		graph = load_commit_graph_one_fd_st(fd, &st);
+	 else
+		graph = read_commit_graph_one(the_repository, opts.obj_dir);
 
 	/* Return failure if open_ok predicted success */
 	if (!graph)
@@ -108,6 +87,64 @@ static int graph_verify(int argc, const char **argv)
 	return verify_commit_graph(the_repository, graph, flags);
 }
 
+static int graph_read(int argc, const char **argv)
+{
+	struct commit_graph *graph = NULL;
+	char *graph_name;
+	int open_ok;
+	int fd;
+	struct stat st;
+
+	static struct option builtin_commit_graph_read_options[] = {
+		OPT_STRING(0, "object-dir", &opts.obj_dir,
+			N_("dir"),
+			N_("The object directory to store the graph")),
+		OPT_END(),
+	};
+
+	argc = parse_options(argc, argv, NULL,
+			     builtin_commit_graph_read_options,
+			     builtin_commit_graph_read_usage, 0);
+
+	if (!opts.obj_dir)
+		opts.obj_dir = get_object_directory();
+
+	graph_name = get_commit_graph_filename(opts.obj_dir);
+
+	open_ok = open_commit_graph(graph_name, &fd, &st);
+	if (!open_ok)
+		die_errno(_("Could not open commit-graph '%s'"), graph_name);
+
+	graph = load_commit_graph_one_fd_st(fd, &st);
+	if (!graph)
+		return 1;
+
+	FREE_AND_NULL(graph_name);
+
+	printf("header: %08x %d %d %d %d\n",
+		ntohl(*(uint32_t*)graph->data),
+		*(unsigned char*)(graph->data + 4),
+		*(unsigned char*)(graph->data + 5),
+		*(unsigned char*)(graph->data + 6),
+		*(unsigned char*)(graph->data + 7));
+	printf("num_commits: %u\n", graph->num_commits);
+	printf("chunks:");
+
+	if (graph->chunk_oid_fanout)
+		printf(" oid_fanout");
+	if (graph->chunk_oid_lookup)
+		printf(" oid_lookup");
+	if (graph->chunk_commit_data)
+		printf(" commit_metadata");
+	if (graph->chunk_extra_edges)
+		printf(" extra_edges");
+	printf("\n");
+
+	UNLEAK(graph);
+
+	return 0;
+}
+
 extern int read_replace_refs;
 static struct split_commit_graph_opts split_opts;
 
@@ -115,10 +152,9 @@ static int graph_write(int argc, const char **argv)
 {
 	struct string_list *pack_indexes = NULL;
 	struct string_list *commit_hex = NULL;
-	struct object_directory *odb = NULL;
 	struct string_list lines;
 	int result = 0;
-	enum commit_graph_write_flags flags = 0;
+	unsigned int flags = COMMIT_GRAPH_PROGRESS;
 
 	static struct option builtin_commit_graph_write_options[] = {
 		OPT_STRING(0, "object-dir", &opts.obj_dir,
@@ -132,7 +168,6 @@ static int graph_write(int argc, const char **argv)
 			N_("start walk at commits listed by stdin")),
 		OPT_BOOL(0, "append", &opts.append,
 			N_("include all commits already in the commit-graph file")),
-		OPT_BOOL(0, "progress", &opts.progress, N_("force progress reporting")),
 		OPT_BOOL(0, "split", &opts.split,
 			N_("allow writing an incremental commit-graph file")),
 		OPT_INTEGER(0, "max-commits", &split_opts.max_commits,
@@ -144,13 +179,10 @@ static int graph_write(int argc, const char **argv)
 		OPT_END(),
 	};
 
-	opts.progress = isatty(2);
 	split_opts.size_multiple = 2;
 	split_opts.max_commits = 0;
 	split_opts.expire_time = 0;
 
-	trace2_cmd_mode("write");
-
 	argc = parse_options(argc, argv, NULL,
 			     builtin_commit_graph_write_options,
 			     builtin_commit_graph_write_usage, 0);
@@ -160,17 +192,14 @@ static int graph_write(int argc, const char **argv)
 	if (!opts.obj_dir)
 		opts.obj_dir = get_object_directory();
 	if (opts.append)
-		flags |= COMMIT_GRAPH_WRITE_APPEND;
+		flags |= COMMIT_GRAPH_APPEND;
 	if (opts.split)
-		flags |= COMMIT_GRAPH_WRITE_SPLIT;
-	if (opts.progress)
-		flags |= COMMIT_GRAPH_WRITE_PROGRESS;
+		flags |= COMMIT_GRAPH_SPLIT;
 
 	read_replace_refs = 0;
-	odb = find_odb(the_repository, opts.obj_dir);
 
 	if (opts.reachable) {
-		if (write_commit_graph_reachable(odb, flags, &split_opts))
+		if (write_commit_graph_reachable(opts.obj_dir, flags, &split_opts))
 			return 1;
 		return 0;
 	}
@@ -184,15 +213,13 @@ static int graph_write(int argc, const char **argv)
 
 		if (opts.stdin_packs)
 			pack_indexes = &lines;
-		if (opts.stdin_commits) {
+		if (opts.stdin_commits)
 			commit_hex = &lines;
-			flags |= COMMIT_GRAPH_WRITE_CHECK_OIDS;
-		}
 
 		UNLEAK(buf);
 	}
 
-	if (write_commit_graph(odb,
+	if (write_commit_graph(opts.obj_dir,
 			       pack_indexes,
 			       commit_hex,
 			       flags,
@@ -222,9 +249,9 @@ int cmd_commit_graph(int argc, const char **argv, const char *prefix)
 			     builtin_commit_graph_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
 
-	save_commit_buffer = 0;
-
 	if (argc > 0) {
+		if (!strcmp(argv[0], "read"))
+			return graph_read(argc, argv);
 		if (!strcmp(argv[0], "verify"))
 			return graph_verify(argc, argv);
 		if (!strcmp(argv[0], "write"))
diff --git a/third_party/git/builtin/commit.c b/third_party/git/builtin/commit.c
index 7ba33a3bec..ae7aaf6dc6 100644
--- a/third_party/git/builtin/commit.c
+++ b/third_party/git/builtin/commit.c
@@ -107,9 +107,9 @@ static int all, also, interactive, patch_interactive, only, amend, signoff;
 static int edit_flag = -1; /* unspecified */
 static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
 static int config_commit_verbose = -1; /* unspecified */
-static int no_post_rewrite, allow_empty_message, pathspec_file_nul;
+static int no_post_rewrite, allow_empty_message;
 static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;
-static char *sign_commit, *pathspec_from_file;
+static char *sign_commit;
 
 /*
  * The default commit message cleanup mode will remove the lines
@@ -343,31 +343,11 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
 		       PATHSPEC_PREFER_FULL,
 		       prefix, argv);
 
-	if (pathspec_from_file) {
-		if (interactive)
-			die(_("--pathspec-from-file is incompatible with --interactive/--patch"));
-
-		if (all)
-			die(_("--pathspec-from-file with -a does not make sense"));
-
-		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
-
-		parse_pathspec_file(&pathspec, 0,
-				    PATHSPEC_PREFER_FULL,
-				    prefix, pathspec_from_file, pathspec_file_nul);
-	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
-	}
-
-	if (!pathspec.nr && (also || (only && !amend && !allow_empty)))
-		die(_("No paths with --include/--only does not make sense."));
-
 	if (read_cache_preload(&pathspec) < 0)
 		die(_("index file corrupt"));
 
 	if (interactive) {
-		char *old_index_env = NULL, *old_repo_index_file;
+		char *old_index_env = NULL;
 		hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
 
 		refresh_cache_or_die(refresh_flags);
@@ -375,16 +355,12 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
 		if (write_locked_index(&the_index, &index_lock, 0))
 			die(_("unable to create temporary index"));
 
-		old_repo_index_file = the_repository->index_file;
-		the_repository->index_file =
-			(char *)get_lock_file_path(&index_lock);
 		old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT));
-		setenv(INDEX_ENVIRONMENT, the_repository->index_file, 1);
+		setenv(INDEX_ENVIRONMENT, get_lock_file_path(&index_lock), 1);
 
 		if (interactive_add(argc, argv, prefix, patch_interactive) != 0)
 			die(_("interactive add failed"));
 
-		the_repository->index_file = old_repo_index_file;
 		if (old_index_env && *old_index_env)
 			setenv(INDEX_ENVIRONMENT, old_index_env, 1);
 		else
@@ -534,7 +510,7 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int
 	s->nowarn = nowarn;
 	s->is_initial = get_oid(s->reference, &oid) ? 1 : 0;
 	if (!s->is_initial)
-		oidcpy(&s->oid_commit, &oid);
+		hashcpy(s->sha1_commit, oid.hash);
 	s->status_format = status_format;
 	s->ignore_submodule_arg = ignore_submodule_arg;
 
@@ -561,7 +537,7 @@ static void export_one(const char *var, const char *s, const char *e, int hack)
 	struct strbuf buf = STRBUF_INIT;
 	if (hack)
 		strbuf_addch(&buf, hack);
-	strbuf_add(&buf, s, e - s);
+	strbuf_addf(&buf, "%.*s", (int)(e - s), s);
 	setenv(var, buf.buf, 1);
 	strbuf_release(&buf);
 }
@@ -968,7 +944,6 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
 	 */
 	if (!committable && whence != FROM_MERGE && !allow_empty &&
 	    !(amend && is_a_merge(current_head))) {
-		s->hints = advice_status_hints;
 		s->display_comment_prefix = old_display_comment_prefix;
 		run_status(stdout, index_file, prefix, 0, s);
 		if (amend)
@@ -1223,6 +1198,8 @@ static int parse_and_validate_options(int argc, const char *argv[],
 
 	if (also + only + all + interactive > 1)
 		die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
+	if (argc == 0 && (also || (only && !amend && !allow_empty)))
+		die(_("No paths with --include/--only does not make sense."));
 	cleanup_mode = get_cleanup_mode(cleanup_arg, use_editor);
 
 	handle_untracked_files_arg(s);
@@ -1429,7 +1406,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
 
 	s.is_initial = get_oid(s.reference, &oid) ? 1 : 0;
 	if (!s.is_initial)
-		oidcpy(&s.oid_commit, &oid);
+		hashcpy(s.sha1_commit, oid.hash);
 
 	s.ignore_submodule_arg = ignore_submodule_arg;
 	s.status_format = status_format;
@@ -1486,6 +1463,28 @@ static int git_commit_config(const char *k, const char *v, void *cb)
 	return git_status_config(k, v, s);
 }
 
+int run_commit_hook(int editor_is_used, const char *index_file, const char *name, ...)
+{
+	struct argv_array hook_env = ARGV_ARRAY_INIT;
+	va_list args;
+	int ret;
+
+	argv_array_pushf(&hook_env, "GIT_INDEX_FILE=%s", index_file);
+
+	/*
+	 * Let the hook know that no editor will be launched.
+	 */
+	if (!editor_is_used)
+		argv_array_push(&hook_env, "GIT_EDITOR=:");
+
+	va_start(args, name);
+	ret = run_hook_ve(hook_env.argv,name, args);
+	va_end(args);
+	argv_array_clear(&hook_env);
+
+	return ret;
+}
+
 int cmd_commit(int argc, const char **argv, const char *prefix)
 {
 	const char *argv_gc_auto[] = {"gc", "--auto", NULL};
@@ -1536,8 +1535,6 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "amend", &amend, N_("amend previous commit")),
 		OPT_BOOL(0, "no-post-rewrite", &no_post_rewrite, N_("bypass post-rewrite hook")),
 		{ OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, N_("mode"), N_("show untracked files, optional modes: all, normal, no. (Default: all)"), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
-		OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
-		OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
 		/* end commit contents options */
 
 		OPT_HIDDEN_BOOL(0, "allow-empty", &allow_empty,
@@ -1693,7 +1690,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 		      "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))
+	    write_commit_graph_reachable(get_object_directory(), 0, NULL))
 		return 1;
 
 	repo_rerere(the_repository, 0);
diff --git a/third_party/git/builtin/config.c b/third_party/git/builtin/config.c
index ee4aef6a35..98d65bc0ad 100644
--- a/third_party/git/builtin/config.c
+++ b/third_party/git/builtin/config.c
@@ -29,11 +29,10 @@ static int use_worktree_config;
 static struct git_config_source given_config_source;
 static int actions, type;
 static char *default_value;
-static int end_nul;
+static int end_null;
 static int respect_includes_opt = -1;
 static struct config_options config_options;
 static int show_origin;
-static int show_scope;
 
 #define ACTION_GET (1<<0)
 #define ACTION_GET_ALL (1<<1)
@@ -152,11 +151,10 @@ static struct option builtin_config_options[] = {
 	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
 	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
 	OPT_GROUP(N_("Other")),
-	OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),
+	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
 	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
 	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
 	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
-	OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")),
 	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
 	OPT_END(),
 };
@@ -180,34 +178,22 @@ static void check_argc(int argc, int min, int max)
 
 static void show_config_origin(struct strbuf *buf)
 {
-	const char term = end_nul ? '\0' : '\t';
+	const char term = end_null ? '\0' : '\t';
 
 	strbuf_addstr(buf, current_config_origin_type());
 	strbuf_addch(buf, ':');
-	if (end_nul)
+	if (end_null)
 		strbuf_addstr(buf, current_config_name());
 	else
 		quote_c_style(current_config_name(), buf, NULL, 0);
 	strbuf_addch(buf, term);
 }
 
-static void show_config_scope(struct strbuf *buf)
-{
-	const char term = end_nul ? '\0' : '\t';
-	const char *scope = config_scope_name(current_config_scope());
-
-	strbuf_addstr(buf, N_(scope));
-	strbuf_addch(buf, term);
-}
-
 static int show_all_config(const char *key_, const char *value_, void *cb)
 {
-	if (show_origin || show_scope) {
+	if (show_origin) {
 		struct strbuf buf = STRBUF_INIT;
-		if (show_scope)
-			show_config_scope(&buf);
-		if (show_origin)
-			show_config_origin(&buf);
+		show_config_origin(&buf);
 		/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
 		fwrite(buf.buf, 1, buf.len, stdout);
 		strbuf_release(&buf);
@@ -227,8 +213,6 @@ struct strbuf_list {
 
 static int format_config(struct strbuf *buf, const char *key_, const char *value_)
 {
-	if (show_scope)
-		show_config_scope(buf);
 	if (show_origin)
 		show_config_origin(buf);
 	if (show_keys)
@@ -638,7 +622,6 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			!strcmp(given_config_source.file, "-")) {
 		given_config_source.file = NULL;
 		given_config_source.use_stdin = 1;
-		given_config_source.scope = CONFIG_SCOPE_COMMAND;
 	}
 
 	if (use_global_config) {
@@ -654,8 +637,6 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			 */
 			die(_("$HOME not set"));
 
-		given_config_source.scope = CONFIG_SCOPE_GLOBAL;
-
 		if (access_or_warn(user_config, R_OK, 0) &&
 		    xdg_config && !access_or_warn(xdg_config, R_OK, 0)) {
 			given_config_source.file = xdg_config;
@@ -665,13 +646,11 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			free(xdg_config);
 		}
 	}
-	else if (use_system_config) {
+	else if (use_system_config)
 		given_config_source.file = git_etc_gitconfig();
-		given_config_source.scope = CONFIG_SCOPE_SYSTEM;
-	} else if (use_local_config) {
+	else if (use_local_config)
 		given_config_source.file = git_pathdup("config");
-		given_config_source.scope = CONFIG_SCOPE_LOCAL;
-	} else if (use_worktree_config) {
+	else if (use_worktree_config) {
 		struct worktree **worktrees = get_worktrees(0);
 		if (repository_format_worktree_config)
 			given_config_source.file = git_pathdup("config.worktree");
@@ -683,18 +662,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			      "section in \"git help worktree\" for details"));
 		else
 			given_config_source.file = git_pathdup("config");
-		given_config_source.scope = CONFIG_SCOPE_LOCAL;
 		free_worktrees(worktrees);
 	} else if (given_config_source.file) {
 		if (!is_absolute_path(given_config_source.file) && prefix)
 			given_config_source.file =
 				prefix_filename(prefix, given_config_source.file);
-		given_config_source.scope = CONFIG_SCOPE_COMMAND;
-	} else if (given_config_source.blob) {
-		given_config_source.scope = CONFIG_SCOPE_COMMAND;
 	}
 
-
 	if (respect_includes_opt == -1)
 		config_options.respect_includes = !given_config_source.file;
 	else
@@ -704,7 +678,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 		config_options.git_dir = get_git_dir();
 	}
 
-	if (end_nul) {
+	if (end_null) {
 		term = '\0';
 		delim = '\n';
 		key_delim = '\n';
diff --git a/third_party/git/builtin/describe.c b/third_party/git/builtin/describe.c
index 420f4c6401..200154297d 100644
--- a/third_party/git/builtin/describe.c
+++ b/third_party/git/builtin/describe.c
@@ -15,6 +15,7 @@
 #include "argv-array.h"
 #include "run-command.h"
 #include "object-store.h"
+#include "revision.h"
 #include "list-objects.h"
 #include "commit-slab.h"
 
@@ -63,22 +64,19 @@ static const char *prio_names[] = {
 };
 
 static int commit_name_neq(const void *unused_cmp_data,
-			   const struct hashmap_entry *eptr,
-			   const struct hashmap_entry *entry_or_key,
+			   const void *entry,
+			   const void *entry_or_key,
 			   const void *peeled)
 {
-	const struct commit_name *cn1, *cn2;
-
-	cn1 = container_of(eptr, const struct commit_name, entry);
-	cn2 = container_of(entry_or_key, const struct commit_name, entry);
+	const struct commit_name *cn1 = entry;
+	const struct commit_name *cn2 = entry_or_key;
 
 	return !oideq(&cn1->peeled, peeled ? peeled : &cn2->peeled);
 }
 
 static inline struct commit_name *find_commit_name(const struct object_id *peeled)
 {
-	return hashmap_get_entry_from_hash(&names, oidhash(peeled), peeled,
-						struct commit_name, entry);
+	return hashmap_get_from_hash(&names, oidhash(peeled), peeled);
 }
 
 static int replace_name(struct commit_name *e,
@@ -125,8 +123,8 @@ static void add_to_known_names(const char *path,
 		if (!e) {
 			e = xmalloc(sizeof(struct commit_name));
 			oidcpy(&e->peeled, peeled);
-			hashmap_entry_init(&e->entry, oidhash(peeled));
-			hashmap_add(&names, &e->entry);
+			hashmap_entry_init(e, oidhash(peeled));
+			hashmap_add(&names, e);
 			e->path = NULL;
 		}
 		e->tag = tag;
@@ -315,7 +313,7 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
 		 */
 		append_name(n, dst);
 		if (longformat)
-			append_suffix(0, n->tag ? get_tagged_oid(n->tag) : oid, dst);
+			append_suffix(0, n->tag ? &n->tag->tagged->oid : oid, dst);
 		if (suffix)
 			strbuf_addstr(dst, suffix);
 		return;
@@ -332,8 +330,8 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
 		struct commit_name *n;
 
 		init_commit_names(&commit_names);
-		hashmap_for_each_entry(&names, &iter, n,
-					entry /* member name */) {
+		n = hashmap_iter_first(&names, &iter);
+		for (; n; n = hashmap_iter_next(&iter)) {
 			c = lookup_commit_reference_gently(the_repository,
 							   &n->peeled, 1);
 			if (c)
@@ -376,25 +374,11 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
 			if (!(c->object.flags & t->flag_within))
 				t->depth++;
 		}
-		/* Stop if last remaining path already covered by best candidate(s) */
 		if (annotated_cnt && !list) {
-			int best_depth = INT_MAX;
-			unsigned best_within = 0;
-			for (cur_match = 0; cur_match < match_cnt; cur_match++) {
-				struct possible_tag *t = &all_matches[cur_match];
-				if (t->depth < best_depth) {
-					best_depth = t->depth;
-					best_within = t->flag_within;
-				} else if (t->depth == best_depth) {
-					best_within |= t->flag_within;
-				}
-			}
-			if ((c->object.flags & best_within) == best_within) {
-				if (debug)
-					fprintf(stderr, _("finished search at %s\n"),
-						oid_to_hex(&c->object.oid));
-				break;
-			}
+			if (debug)
+				fprintf(stderr, _("finished search at %s\n"),
+					oid_to_hex(&c->object.oid));
+			break;
 		}
 		while (parents) {
 			struct commit *p = parents->item;
diff --git a/third_party/git/builtin/difftool.c b/third_party/git/builtin/difftool.c
index c280e682b2..16eb8b70ea 100644
--- a/third_party/git/builtin/difftool.c
+++ b/third_party/git/builtin/difftool.c
@@ -125,15 +125,12 @@ struct working_tree_entry {
 };
 
 static int working_tree_entry_cmp(const void *unused_cmp_data,
-				  const struct hashmap_entry *eptr,
-				  const struct hashmap_entry *entry_or_key,
+				  const void *entry,
+				  const void *entry_or_key,
 				  const void *unused_keydata)
 {
-	const struct working_tree_entry *a, *b;
-
-	a = container_of(eptr, const struct working_tree_entry, entry);
-	b = container_of(entry_or_key, const struct working_tree_entry, entry);
-
+	const struct working_tree_entry *a = entry;
+	const struct working_tree_entry *b = entry_or_key;
 	return strcmp(a->path, b->path);
 }
 
@@ -148,14 +145,12 @@ struct pair_entry {
 };
 
 static int pair_cmp(const void *unused_cmp_data,
-		    const struct hashmap_entry *eptr,
-		    const struct hashmap_entry *entry_or_key,
+		    const void *entry,
+		    const void *entry_or_key,
 		    const void *unused_keydata)
 {
-	const struct pair_entry *a, *b;
-
-	a = container_of(eptr, const struct pair_entry, entry);
-	b = container_of(entry_or_key, const struct pair_entry, entry);
+	const struct pair_entry *a = entry;
+	const struct pair_entry *b = entry_or_key;
 
 	return strcmp(a->path, b->path);
 }
@@ -166,14 +161,14 @@ static void add_left_or_right(struct hashmap *map, const char *path,
 	struct pair_entry *e, *existing;
 
 	FLEX_ALLOC_STR(e, path, path);
-	hashmap_entry_init(&e->entry, strhash(path));
-	existing = hashmap_get_entry(map, e, entry, NULL);
+	hashmap_entry_init(e, strhash(path));
+	existing = hashmap_get(map, e, NULL);
 	if (existing) {
 		free(e);
 		e = existing;
 	} else {
 		e->left[0] = e->right[0] = '\0';
-		hashmap_add(map, &e->entry);
+		hashmap_add(map, e);
 	}
 	strlcpy(is_right ? e->right : e->left, content, PATH_MAX);
 }
@@ -184,14 +179,12 @@ struct path_entry {
 };
 
 static int path_entry_cmp(const void *unused_cmp_data,
-			  const struct hashmap_entry *eptr,
-			  const struct hashmap_entry *entry_or_key,
+			  const void *entry,
+			  const void *entry_or_key,
 			  const void *key)
 {
-	const struct path_entry *a, *b;
-
-	a = container_of(eptr, const struct path_entry, entry);
-	b = container_of(entry_or_key, const struct path_entry, entry);
+	const struct path_entry *a = entry;
+	const struct path_entry *b = entry_or_key;
 
 	return strcmp(a->path, key ? key : b->path);
 }
@@ -241,8 +234,8 @@ static void changed_files(struct hashmap *result, const char *index_path,
 	while (!strbuf_getline_nul(&buf, fp)) {
 		struct path_entry *entry;
 		FLEX_ALLOC_STR(entry, path, buf.buf);
-		hashmap_entry_init(&entry->entry, strhash(buf.buf));
-		hashmap_add(result, &entry->entry);
+		hashmap_entry_init(entry, strhash(buf.buf));
+		hashmap_add(result, entry);
 	}
 	fclose(fp);
 	if (finish_command(&diff_files))
@@ -468,13 +461,12 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
 
 			/* Avoid duplicate working_tree entries */
 			FLEX_ALLOC_STR(entry, path, dst_path);
-			hashmap_entry_init(&entry->entry, strhash(dst_path));
-			if (hashmap_get(&working_tree_dups, &entry->entry,
-					NULL)) {
+			hashmap_entry_init(entry, strhash(dst_path));
+			if (hashmap_get(&working_tree_dups, entry, NULL)) {
 				free(entry);
 				continue;
 			}
-			hashmap_add(&working_tree_dups, &entry->entry);
+			hashmap_add(&working_tree_dups, entry);
 
 			if (!use_wt_file(workdir, dst_path, &roid)) {
 				if (checkout_path(rmode, &roid, dst_path,
@@ -538,8 +530,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
 	 * temporary file to both the left and right directories to show the
 	 * change in the recorded SHA1 for the submodule.
 	 */
-	hashmap_for_each_entry(&submodules, &iter, entry,
-				entry /* member name */) {
+	hashmap_iter_init(&submodules, &iter);
+	while ((entry = hashmap_iter_next(&iter))) {
 		if (*entry->left) {
 			add_path(&ldir, ldir_len, entry->path);
 			ensure_leading_directories(ldir.buf);
@@ -557,8 +549,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
 	 * shows only the link itself, not the contents of the link target.
 	 * This loop replicates that behavior.
 	 */
-	hashmap_for_each_entry(&symlinks2, &iter, entry,
-				entry /* member name */) {
+	hashmap_iter_init(&symlinks2, &iter);
+	while ((entry = hashmap_iter_next(&iter))) {
 		if (*entry->left) {
 			add_path(&ldir, ldir_len, entry->path);
 			ensure_leading_directories(ldir.buf);
diff --git a/third_party/git/builtin/fast-export.c b/third_party/git/builtin/fast-export.c
index 85868162ee..f541f55d33 100644
--- a/third_party/git/builtin/fast-export.c
+++ b/third_party/git/builtin/fast-export.c
@@ -40,7 +40,6 @@ static int no_data;
 static int full_tree;
 static int reference_excluded_commits;
 static int show_original_ids;
-static int mark_tags;
 static struct string_list extra_refs = STRING_LIST_INIT_NODUP;
 static struct string_list tag_refs = STRING_LIST_INIT_NODUP;
 static struct refspec refspecs = REFSPEC_INIT_FETCH;
@@ -127,15 +126,10 @@ struct anonymized_entry {
 };
 
 static int anonymized_entry_cmp(const void *unused_cmp_data,
-				const struct hashmap_entry *eptr,
-				const struct hashmap_entry *entry_or_key,
+				const void *va, const void *vb,
 				const void *unused_keydata)
 {
-	const struct anonymized_entry *a, *b;
-
-	a = container_of(eptr, const struct anonymized_entry, hash);
-	b = container_of(entry_or_key, const struct anonymized_entry, hash);
-
+	const struct anonymized_entry *a = va, *b = vb;
 	return a->orig_len != b->orig_len ||
 		memcmp(a->orig, b->orig, a->orig_len);
 }
@@ -154,10 +148,10 @@ static const void *anonymize_mem(struct hashmap *map,
 	if (!map->cmpfn)
 		hashmap_init(map, anonymized_entry_cmp, NULL, 0);
 
-	hashmap_entry_init(&key.hash, memhash(orig, *len));
+	hashmap_entry_init(&key, memhash(orig, *len));
 	key.orig = orig;
 	key.orig_len = *len;
-	ret = hashmap_get_entry(map, &key, hash, NULL);
+	ret = hashmap_get(map, &key, NULL);
 
 	if (!ret) {
 		ret = xmalloc(sizeof(*ret));
@@ -166,7 +160,7 @@ static const void *anonymize_mem(struct hashmap *map,
 		ret->orig_len = *len;
 		ret->anon = generate(orig, len);
 		ret->anon_len = *len;
-		hashmap_put(map, &ret->hash);
+		hashmap_put(map, ret);
 	}
 
 	*len = ret->anon_len;
@@ -293,8 +287,7 @@ static void export_blob(const struct object_id *oid)
 		buf = read_object_file(oid, &type, &size);
 		if (!buf)
 			die("could not read blob %s", oid_to_hex(oid));
-		if (check_object_signature(the_repository, oid, buf, size,
-					   type_name(type)) < 0)
+		if (check_object_signature(oid, buf, size, type_name(type)) < 0)
 			die("oid mismatch in blob %s", oid_to_hex(oid));
 		object = parse_object_buffer(the_repository, oid, type,
 					     size, buf, &eaten);
@@ -849,39 +842,25 @@ static void handle_tag(const char *name, struct tag *tag)
 			free(buf);
 			return;
 		case REWRITE:
-			if (tagged->type == OBJ_TAG && !mark_tags) {
-				die(_("Error: Cannot export nested tags unless --mark-tags is specified."));
-			} else if (tagged->type == OBJ_COMMIT) {
-				p = rewrite_commit((struct commit *)tagged);
-				if (!p) {
-					printf("reset %s\nfrom %s\n\n",
-					       name, oid_to_hex(&null_oid));
-					free(buf);
-					return;
-				}
-				tagged_mark = get_object_mark(&p->object);
-			} else {
-				/* tagged->type is either OBJ_BLOB or OBJ_TAG */
-				tagged_mark = get_object_mark(tagged);
+			if (tagged->type != OBJ_COMMIT) {
+				die("tag %s tags unexported %s!",
+				    oid_to_hex(&tag->object.oid),
+				    type_name(tagged->type));
+			}
+			p = rewrite_commit((struct commit *)tagged);
+			if (!p) {
+				printf("reset %s\nfrom %s\n\n",
+				       name, oid_to_hex(&null_oid));
+				free(buf);
+				return;
 			}
+			tagged_mark = get_object_mark(&p->object);
 		}
 	}
 
-	if (tagged->type == OBJ_TAG) {
-		printf("reset %s\nfrom %s\n\n",
-		       name, oid_to_hex(&null_oid));
-	}
-	skip_prefix(name, "refs/tags/", &name);
-	printf("tag %s\n", name);
-	if (mark_tags) {
-		mark_next_object(&tag->object);
-		printf("mark :%"PRIu32"\n", last_idnum);
-	}
-	if (tagged_mark)
-		printf("from :%d\n", tagged_mark);
-	else
-		printf("from %s\n", oid_to_hex(&tagged->oid));
-
+	if (starts_with(name, "refs/tags/"))
+		name += 10;
+	printf("tag %s\nfrom :%d\n", name, tagged_mark);
 	if (show_original_ids)
 		printf("original-oid %s\n", oid_to_hex(&tag->object.oid));
 	printf("%.*s%sdata %d\n%.*s\n",
@@ -1068,16 +1047,11 @@ static void export_marks(char *file)
 		error("Unable to write marks file %s.", file);
 }
 
-static void import_marks(char *input_file, int check_exists)
+static void import_marks(char *input_file)
 {
 	char line[512];
-	FILE *f;
-	struct stat sb;
-
-	if (check_exists && stat(input_file, &sb))
-		return;
+	FILE *f = xfopen(input_file, "r");
 
-	f = xfopen(input_file, "r");
 	while (fgets(line, sizeof(line), f)) {
 		uint32_t mark;
 		char *line_end, *mark_end;
@@ -1141,9 +1115,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 	struct rev_info revs;
 	struct object_array commits = OBJECT_ARRAY_INIT;
 	struct commit *commit;
-	char *export_filename = NULL,
-	     *import_filename = NULL,
-	     *import_filename_if_exists = NULL;
+	char *export_filename = NULL, *import_filename = NULL;
 	uint32_t lastimportid;
 	struct string_list refspecs_list = STRING_LIST_INIT_NODUP;
 	struct string_list paths_of_changed_objects = STRING_LIST_INIT_DUP;
@@ -1163,10 +1135,6 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 			     N_("Dump marks to this file")),
 		OPT_STRING(0, "import-marks", &import_filename, N_("file"),
 			     N_("Import marks from this file")),
-		OPT_STRING(0, "import-marks-if-exists",
-			     &import_filename_if_exists,
-			     N_("file"),
-			     N_("Import marks from this file if it exists")),
 		OPT_BOOL(0, "fake-missing-tagger", &fake_missing_tagger,
 			 N_("Fake a tagger when tags lack one")),
 		OPT_BOOL(0, "full-tree", &full_tree,
@@ -1181,8 +1149,6 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 			 &reference_excluded_commits, N_("Reference parents which are not in fast-export stream by object id")),
 		OPT_BOOL(0, "show-original-ids", &show_original_ids,
 			    N_("Show original object ids of blobs/commits")),
-		OPT_BOOL(0, "mark-tags", &mark_tags,
-			    N_("Label tags with mark ids")),
 
 		OPT_END()
 	};
@@ -1216,12 +1182,8 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 	if (use_done_feature)
 		printf("feature done\n");
 
-	if (import_filename && import_filename_if_exists)
-		die(_("Cannot pass both --import-marks and --import-marks-if-exists"));
 	if (import_filename)
-		import_marks(import_filename, 0);
-	else if (import_filename_if_exists)
-		import_marks(import_filename_if_exists, 1);
+		import_marks(import_filename);
 	lastimportid = last_idnum;
 
 	if (import_filename && revs.prune_data.nr)
diff --git a/third_party/git/builtin/fetch.c b/third_party/git/builtin/fetch.c
index bf6bab80fa..717dd14e89 100644
--- a/third_party/git/builtin/fetch.c
+++ b/third_party/git/builtin/fetch.c
@@ -7,7 +7,6 @@
 #include "refs.h"
 #include "refspec.h"
 #include "object-store.h"
-#include "oidset.h"
 #include "commit.h"
 #include "builtin.h"
 #include "string-list.h"
@@ -24,9 +23,6 @@
 #include "packfile.h"
 #include "list-objects-filter-options.h"
 #include "commit-reach.h"
-#include "branch.h"
-#include "promisor-remote.h"
-#include "commit-graph.h"
 
 #define FORCED_UPDATES_DELAY_WARNING_IN_MS (10 * 1000)
 
@@ -54,13 +50,11 @@ static int fetch_prune_tags_config = -1; /* unspecified */
 static int prune_tags = -1; /* unspecified */
 #define PRUNE_TAGS_BY_DEFAULT 0 /* do we prune tags by default? */
 
-static int all, append, dry_run, force, keep, multiple, update_head_ok;
-static int verbosity, deepen_relative, set_upstream;
+static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity, deepen_relative;
 static int progress = -1;
 static int enable_auto_gc = 1;
 static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen;
-static int max_jobs = -1, submodule_fetch_jobs_config = -1;
-static int fetch_parallel_config = 1;
+static int max_children = 1;
 static enum transport_family family;
 static const char *depth;
 static const char *deepen_since;
@@ -77,7 +71,6 @@ static struct refspec refmap = REFSPEC_INIT_FETCH;
 static struct list_objects_filter_options filter_options;
 static struct string_list server_options = STRING_LIST_INIT_DUP;
 static struct string_list negotiation_tip = STRING_LIST_INIT_NODUP;
-static int fetch_write_commit_graph = -1;
 
 static int git_fetch_config(const char *k, const char *v, void *cb)
 {
@@ -103,20 +96,13 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
 	}
 
 	if (!strcmp(k, "submodule.fetchjobs")) {
-		submodule_fetch_jobs_config = parse_submodule_fetchjobs(k, v);
+		max_children = parse_submodule_fetchjobs(k, v);
 		return 0;
 	} else if (!strcmp(k, "fetch.recursesubmodules")) {
 		recurse_submodules = parse_fetch_recurse_submodules_arg(k, v);
 		return 0;
 	}
 
-	if (!strcmp(k, "fetch.parallel")) {
-		fetch_parallel_config = git_config_int(k, v);
-		if (fetch_parallel_config < 0)
-			die(_("fetch.parallel cannot be negative"));
-		return 0;
-	}
-
 	return git_default_config(k, v, cb);
 }
 
@@ -137,8 +123,6 @@ static struct option builtin_fetch_options[] = {
 	OPT__VERBOSITY(&verbosity),
 	OPT_BOOL(0, "all", &all,
 		 N_("fetch from all remotes")),
-	OPT_BOOL(0, "set-upstream", &set_upstream,
-		 N_("set upstream for git pull/fetch")),
 	OPT_BOOL('a', "append", &append,
 		 N_("append to .git/FETCH_HEAD instead of overwriting")),
 	OPT_STRING(0, "upload-pack", &upload_pack, N_("path"),
@@ -150,7 +134,7 @@ static struct option builtin_fetch_options[] = {
 		    N_("fetch all tags and associated objects"), TAGS_SET),
 	OPT_SET_INT('n', NULL, &tags,
 		    N_("do not fetch all tags (--no-tags)"), TAGS_UNSET),
-	OPT_INTEGER('j', "jobs", &max_jobs,
+	OPT_INTEGER('j', "jobs", &max_children,
 		    N_("number of submodules fetched in parallel")),
 	OPT_BOOL('p', "prune", &prune,
 		 N_("prune remote-tracking branches no longer on remote")),
@@ -199,8 +183,6 @@ static struct option builtin_fetch_options[] = {
 		 N_("run 'gc --auto' after fetching")),
 	OPT_BOOL(0, "show-forced-updates", &fetch_show_forced_updates,
 		 N_("check for forced-updates on all updated branches")),
-	OPT_BOOL(0, "write-commit-graph", &fetch_write_commit_graph,
-		 N_("write the commit-graph after fetching")),
 	OPT_END()
 };
 
@@ -257,31 +239,32 @@ static void add_merge_config(struct ref **head,
 	}
 }
 
-static void create_fetch_oidset(struct ref **head, struct oidset *out)
+static int will_fetch(struct ref **head, const unsigned char *sha1)
 {
 	struct ref *rm = *head;
 	while (rm) {
-		oidset_insert(out, &rm->old_oid);
+		if (hasheq(rm->old_oid.hash, sha1))
+			return 1;
 		rm = rm->next;
 	}
+	return 0;
 }
 
 struct refname_hash_entry {
-	struct hashmap_entry ent;
+	struct hashmap_entry ent; /* must be the first member */
 	struct object_id oid;
 	int ignore;
 	char refname[FLEX_ARRAY];
 };
 
 static int refname_hash_entry_cmp(const void *hashmap_cmp_fn_data,
-				  const struct hashmap_entry *eptr,
-				  const struct hashmap_entry *entry_or_key,
+				  const void *e1_,
+				  const void *e2_,
 				  const void *keydata)
 {
-	const struct refname_hash_entry *e1, *e2;
+	const struct refname_hash_entry *e1 = e1_;
+	const struct refname_hash_entry *e2 = e2_;
 
-	e1 = container_of(eptr, const struct refname_hash_entry, ent);
-	e2 = container_of(entry_or_key, const struct refname_hash_entry, ent);
 	return strcmp(e1->refname, keydata ? keydata : e2->refname);
 }
 
@@ -293,9 +276,9 @@ static struct refname_hash_entry *refname_hash_add(struct hashmap *map,
 	size_t len = strlen(refname);
 
 	FLEX_ALLOC_MEM(ent, refname, refname, len);
-	hashmap_entry_init(&ent->ent, strhash(refname));
+	hashmap_entry_init(ent, strhash(refname));
 	oidcpy(&ent->oid, oid);
-	hashmap_add(map, &ent->ent);
+	hashmap_add(map, ent);
 	return ent;
 }
 
@@ -330,16 +313,13 @@ static void find_non_local_tags(const struct ref *refs,
 {
 	struct hashmap existing_refs;
 	struct hashmap remote_refs;
-	struct oidset fetch_oids = OIDSET_INIT;
 	struct string_list remote_refs_list = STRING_LIST_INIT_NODUP;
 	struct string_list_item *remote_ref_item;
 	const struct ref *ref;
 	struct refname_hash_entry *item = NULL;
-	const int quick_flags = OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT;
 
 	refname_hash_init(&existing_refs);
 	refname_hash_init(&remote_refs);
-	create_fetch_oidset(head, &fetch_oids);
 
 	for_each_ref(add_one_refname, &existing_refs);
 	for (ref = refs; ref; ref = ref->next) {
@@ -354,10 +334,11 @@ static void find_non_local_tags(const struct ref *refs,
 		 */
 		if (ends_with(ref->name, "^{}")) {
 			if (item &&
-			    !has_object_file_with_flags(&ref->old_oid, quick_flags) &&
-			    !oidset_contains(&fetch_oids, &ref->old_oid) &&
-			    !has_object_file_with_flags(&item->oid, quick_flags) &&
-			    !oidset_contains(&fetch_oids, &item->oid))
+			    !has_object_file_with_flags(&ref->old_oid,
+							OBJECT_INFO_QUICK) &&
+			    !will_fetch(head, ref->old_oid.hash) &&
+			    !has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) &&
+			    !will_fetch(head, item->oid.hash))
 				clear_item(item);
 			item = NULL;
 			continue;
@@ -370,8 +351,8 @@ static void find_non_local_tags(const struct ref *refs,
 		 * fetch.
 		 */
 		if (item &&
-		    !has_object_file_with_flags(&item->oid, quick_flags) &&
-		    !oidset_contains(&fetch_oids, &item->oid))
+		    !has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) &&
+		    !will_fetch(head, item->oid.hash))
 			clear_item(item);
 
 		item = NULL;
@@ -384,15 +365,15 @@ static void find_non_local_tags(const struct ref *refs,
 		item = refname_hash_add(&remote_refs, ref->name, &ref->old_oid);
 		string_list_insert(&remote_refs_list, ref->name);
 	}
-	hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent);
+	hashmap_free(&existing_refs, 1);
 
 	/*
 	 * We may have a final lightweight tag that needs to be
 	 * checked to see if it needs fetching.
 	 */
 	if (item &&
-	    !has_object_file_with_flags(&item->oid, quick_flags) &&
-	    !oidset_contains(&fetch_oids, &item->oid))
+	    !has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) &&
+	    !will_fetch(head, item->oid.hash))
 		clear_item(item);
 
 	/*
@@ -402,10 +383,8 @@ static void find_non_local_tags(const struct ref *refs,
 	for_each_string_list_item(remote_ref_item, &remote_refs_list) {
 		const char *refname = remote_ref_item->string;
 		struct ref *rm;
-		unsigned int hash = strhash(refname);
 
-		item = hashmap_get_entry_from_hash(&remote_refs, hash, refname,
-					struct refname_hash_entry, ent);
+		item = hashmap_get_from_hash(&remote_refs, strhash(refname), refname);
 		if (!item)
 			BUG("unseen remote ref?");
 
@@ -419,9 +398,8 @@ static void find_non_local_tags(const struct ref *refs,
 		**tail = rm;
 		*tail = &rm->next;
 	}
-	hashmap_free_entries(&remote_refs, struct refname_hash_entry, ent);
+	hashmap_free(&remote_refs, 1);
 	string_list_clear(&remote_refs_list, 0);
-	oidset_clear(&fetch_oids);
 }
 
 static struct ref *get_ref_map(struct remote *remote,
@@ -538,18 +516,17 @@ static struct ref *get_ref_map(struct remote *remote,
 		if (rm->peer_ref) {
 			const char *refname = rm->peer_ref->name;
 			struct refname_hash_entry *peer_item;
-			unsigned int hash = strhash(refname);
 
-			peer_item = hashmap_get_entry_from_hash(&existing_refs,
-						hash, refname,
-						struct refname_hash_entry, ent);
+			peer_item = hashmap_get_from_hash(&existing_refs,
+							  strhash(refname),
+							  refname);
 			if (peer_item) {
 				struct object_id *old_oid = &peer_item->oid;
 				oidcpy(&rm->peer_ref->old_oid, old_oid);
 			}
 		}
 	}
-	hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent);
+	hashmap_free(&existing_refs, 1);
 
 	return ref_map;
 }
@@ -906,17 +883,8 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
 		url = xstrdup("foreign");
 
 	if (!connectivity_checked) {
-		struct check_connected_options opt = CHECK_CONNECTED_INIT;
-
-		if (filter_options.choice)
-			/*
-			 * Since a filter is specified, objects indirectly
-			 * referenced by refs are allowed to be absent.
-			 */
-			opt.check_refs_are_promisor_objects_only = 1;
-
 		rm = ref_map;
-		if (check_connected(iterate_ref_map, &rm, &opt)) {
+		if (check_connected(iterate_ref_map, &rm, NULL)) {
 			rc = error(_("%s did not send all necessary objects\n"), url);
 			goto abort;
 		}
@@ -966,12 +934,18 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
 				kind = "";
 				what = "";
 			}
-			else if (skip_prefix(rm->name, "refs/heads/", &what))
+			else if (starts_with(rm->name, "refs/heads/")) {
 				kind = "branch";
-			else if (skip_prefix(rm->name, "refs/tags/", &what))
+				what = rm->name + 11;
+			}
+			else if (starts_with(rm->name, "refs/tags/")) {
 				kind = "tag";
-			else if (skip_prefix(rm->name, "refs/remotes/", &what))
+				what = rm->name + 10;
+			}
+			else if (starts_with(rm->name, "refs/remotes/")) {
 				kind = "remote-tracking branch";
+				what = rm->name + 13;
+			}
 			else {
 				kind = "";
 				what = rm->name;
@@ -1080,8 +1054,7 @@ static int check_exist_and_connected(struct ref *ref_map)
 	 * we need all direct targets to exist.
 	 */
 	for (r = rm; r; r = r->next) {
-		if (!has_object_file_with_flags(&r->old_oid,
-						OBJECT_INFO_SKIP_FETCH_OBJECT))
+		if (!has_object_file(&r->old_oid))
 			return -1;
 	}
 
@@ -1092,11 +1065,8 @@ static int check_exist_and_connected(struct ref *ref_map)
 static int fetch_refs(struct transport *transport, struct ref *ref_map)
 {
 	int ret = check_exist_and_connected(ref_map);
-	if (ret) {
-		trace2_region_enter("fetch", "fetch_refs", the_repository);
+	if (ret)
 		ret = transport_fetch_refs(transport, ref_map);
-		trace2_region_leave("fetch", "fetch_refs", the_repository);
-	}
 	if (!ret)
 		/*
 		 * Keep the new pack's ".keep" file around to allow the caller
@@ -1112,14 +1082,11 @@ static int consume_refs(struct transport *transport, struct ref *ref_map)
 {
 	int connectivity_checked = transport->smart_options
 		? transport->smart_options->connectivity_checked : 0;
-	int ret;
-	trace2_region_enter("fetch", "consume_refs", the_repository);
-	ret = store_updated_refs(transport->url,
-				 transport->remote->name,
-				 connectivity_checked,
-				 ref_map);
+	int ret = store_updated_refs(transport->url,
+				     transport->remote->name,
+				     connectivity_checked,
+				     ref_map);
 	transport_unlock_pack(transport);
-	trace2_region_leave("fetch", "consume_refs", the_repository);
 	return ret;
 }
 
@@ -1271,10 +1238,13 @@ static struct transport *prepare_transport(struct remote *remote, int deepen)
 	if (update_shallow)
 		set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes");
 	if (filter_options.choice) {
-		const char *spec =
-			expand_list_objects_filter_spec(&filter_options);
-		set_option(transport, TRANS_OPT_LIST_OBJECTS_FILTER, spec);
+		struct strbuf expanded_filter_spec = STRBUF_INIT;
+		expand_list_objects_filter_spec(&filter_options,
+						&expanded_filter_spec);
+		set_option(transport, TRANS_OPT_LIST_OBJECTS_FILTER,
+			   expanded_filter_spec.buf);
 		set_option(transport, TRANS_OPT_FROM_PROMISOR, "1");
+		strbuf_release(&expanded_filter_spec);
 	}
 	if (negotiation_tip.nr) {
 		if (transport->smart_options)
@@ -1364,11 +1334,9 @@ static int do_fetch(struct transport *transport,
 			argv_array_push(&ref_prefixes, "refs/tags/");
 	}
 
-	if (must_list_refs) {
-		trace2_region_enter("fetch", "remote_refs", the_repository);
+	if (must_list_refs)
 		remote_refs = transport_get_remote_refs(transport, &ref_prefixes);
-		trace2_region_leave("fetch", "remote_refs", the_repository);
-	} else
+	else
 		remote_refs = NULL;
 
 	argv_array_clear(&ref_prefixes);
@@ -1399,51 +1367,6 @@ static int do_fetch(struct transport *transport,
 		retcode = 1;
 		goto cleanup;
 	}
-
-	if (set_upstream) {
-		struct branch *branch = branch_get("HEAD");
-		struct ref *rm;
-		struct ref *source_ref = NULL;
-
-		/*
-		 * We're setting the upstream configuration for the
-		 * current branch. The relevant upstream is the
-		 * fetched branch that is meant to be merged with the
-		 * current one, i.e. the one fetched to FETCH_HEAD.
-		 *
-		 * When there are several such branches, consider the
-		 * request ambiguous and err on the safe side by doing
-		 * nothing and just emit a warning.
-		 */
-		for (rm = ref_map; rm; rm = rm->next) {
-			if (!rm->peer_ref) {
-				if (source_ref) {
-					warning(_("multiple branches detected, incompatible with --set-upstream"));
-					goto skip;
-				} else {
-					source_ref = rm;
-				}
-			}
-		}
-		if (source_ref) {
-			if (!strcmp(source_ref->name, "HEAD") ||
-			    starts_with(source_ref->name, "refs/heads/"))
-				install_branch_config(0,
-						      branch->name,
-						      transport->remote->name,
-						      source_ref->name);
-			else if (starts_with(source_ref->name, "refs/remotes/"))
-				warning(_("not setting upstream for a remote remote-tracking branch"));
-			else if (starts_with(source_ref->name, "refs/tags/"))
-				warning(_("not setting upstream for a remote tag"));
-			else
-				warning(_("unknown branch type"));
-		} else {
-			warning(_("no source branch found.\n"
-				"you need to specify exactly one branch with the --set-upstream option."));
-		}
-	}
- skip:
 	free_refs(ref_map);
 
 	/* if neither --no-tags nor --tags was specified, do automated tag
@@ -1540,62 +1463,7 @@ static void add_options_to_argv(struct argv_array *argv)
 
 }
 
-/* Fetch multiple remotes in parallel */
-
-struct parallel_fetch_state {
-	const char **argv;
-	struct string_list *remotes;
-	int next, result;
-};
-
-static int fetch_next_remote(struct child_process *cp, struct strbuf *out,
-			     void *cb, void **task_cb)
-{
-	struct parallel_fetch_state *state = cb;
-	char *remote;
-
-	if (state->next < 0 || state->next >= state->remotes->nr)
-		return 0;
-
-	remote = state->remotes->items[state->next++].string;
-	*task_cb = remote;
-
-	argv_array_pushv(&cp->args, state->argv);
-	argv_array_push(&cp->args, remote);
-	cp->git_cmd = 1;
-
-	if (verbosity >= 0)
-		printf(_("Fetching %s\n"), remote);
-
-	return 1;
-}
-
-static int fetch_failed_to_start(struct strbuf *out, void *cb, void *task_cb)
-{
-	struct parallel_fetch_state *state = cb;
-	const char *remote = task_cb;
-
-	state->result = error(_("Could not fetch %s"), remote);
-
-	return 0;
-}
-
-static int fetch_finished(int result, struct strbuf *out,
-			  void *cb, void *task_cb)
-{
-	struct parallel_fetch_state *state = cb;
-	const char *remote = task_cb;
-
-	if (result) {
-		strbuf_addf(out, _("could not fetch '%s' (exit code: %d)\n"),
-			    remote, result);
-		state->result = -1;
-	}
-
-	return 0;
-}
-
-static int fetch_multiple(struct string_list *list, int max_children)
+static int fetch_multiple(struct string_list *list)
 {
 	int i, result = 0;
 	struct argv_array argv = ARGV_ARRAY_INIT;
@@ -1606,38 +1474,23 @@ static int fetch_multiple(struct string_list *list, int max_children)
 			return errcode;
 	}
 
-	argv_array_pushl(&argv, "fetch", "--append", "--no-auto-gc",
-			"--no-write-commit-graph", NULL);
+	argv_array_pushl(&argv, "fetch", "--append", "--no-auto-gc", NULL);
 	add_options_to_argv(&argv);
 
-	if (max_children != 1 && list->nr != 1) {
-		struct parallel_fetch_state state = { argv.argv, list, 0, 0 };
-
-		argv_array_push(&argv, "--end-of-options");
-		result = run_processes_parallel_tr2(max_children,
-						    &fetch_next_remote,
-						    &fetch_failed_to_start,
-						    &fetch_finished,
-						    &state,
-						    "fetch", "parallel/fetch");
-
-		if (!result)
-			result = state.result;
-	} else
-		for (i = 0; i < list->nr; i++) {
-			const char *name = list->items[i].string;
-			argv_array_push(&argv, name);
-			if (verbosity >= 0)
-				printf(_("Fetching %s\n"), name);
-			if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {
-				error(_("Could not fetch %s"), name);
-				result = 1;
-			}
-			argv_array_pop(&argv);
+	for (i = 0; i < list->nr; i++) {
+		const char *name = list->items[i].string;
+		argv_array_push(&argv, name);
+		if (verbosity >= 0)
+			printf(_("Fetching %s\n"), name);
+		if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {
+			error(_("Could not fetch %s"), name);
+			result = 1;
 		}
+		argv_array_pop(&argv);
+	}
 
 	argv_array_clear(&argv);
-	return !!result;
+	return result;
 }
 
 /*
@@ -1657,27 +1510,37 @@ static inline void fetch_one_setup_partial(struct remote *remote)
 	 * If no prior partial clone/fetch and the current fetch DID NOT
 	 * request a partial-fetch, do a normal fetch.
 	 */
-	if (!has_promisor_remote() && !filter_options.choice)
+	if (!repository_format_partial_clone && !filter_options.choice)
 		return;
 
 	/*
-	 * If this is a partial-fetch request, we enable partial on
-	 * this repo if not already enabled and remember the given
-	 * filter-spec as the default for subsequent fetches to this
-	 * remote.
+	 * If this is the FIRST partial-fetch request, we enable partial
+	 * on this repo and remember the given filter-spec as the default
+	 * for subsequent fetches to this remote.
 	 */
-	if (filter_options.choice) {
+	if (!repository_format_partial_clone && filter_options.choice) {
 		partial_clone_register(remote->name, &filter_options);
 		return;
 	}
 
 	/*
+	 * We are currently limited to only ONE promisor remote and only
+	 * allow partial-fetches from the promisor remote.
+	 */
+	if (strcmp(remote->name, repository_format_partial_clone)) {
+		if (filter_options.choice)
+			die(_("--filter can only be used with the remote "
+			      "configured in extensions.partialClone"));
+		return;
+	}
+
+	/*
 	 * Do a partial-fetch from the promisor remote using either the
 	 * explicitly given filter-spec or inherit the filter-spec from
 	 * the config.
 	 */
 	if (!filter_options.choice)
-		partial_clone_get_default_filter_spec(&filter_options, remote->name);
+		partial_clone_get_default_filter_spec(&filter_options);
 	return;
 }
 
@@ -1763,13 +1626,14 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 
 	packet_trace_identity("fetch");
 
+	fetch_if_missing = 0;
+
 	/* Record the command line for the reflog */
 	strbuf_addstr(&default_rla, "fetch");
 	for (i = 1; i < argc; i++)
 		strbuf_addf(&default_rla, " %s", argv[i]);
 
-	fetch_config_from_gitmodules(&submodule_fetch_jobs_config,
-				     &recurse_submodules);
+	fetch_config_from_gitmodules(&max_children, &recurse_submodules);
 	git_config(git_fetch_config, NULL);
 
 	argc = parse_options(argc, argv, prefix,
@@ -1797,7 +1661,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 	if (depth || deepen_since || deepen_not.nr)
 		deepen = 1;
 
-	if (filter_options.choice && !has_promisor_remote())
+	if (filter_options.choice && !repository_format_partial_clone)
 		die("--filter can only be used when extensions.partialClone is set");
 
 	if (all) {
@@ -1831,31 +1695,19 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 	}
 
 	if (remote) {
-		if (filter_options.choice || has_promisor_remote())
+		if (filter_options.choice || repository_format_partial_clone)
 			fetch_one_setup_partial(remote);
 		result = fetch_one(remote, argc, argv, prune_tags_ok);
 	} else {
-		int max_children = max_jobs;
-
 		if (filter_options.choice)
 			die(_("--filter can only be used with the remote "
 			      "configured in extensions.partialclone"));
-
-		if (max_children < 0)
-			max_children = fetch_parallel_config;
-
 		/* TODO should this also die if we have a previous partial-clone? */
-		result = fetch_multiple(&list, max_children);
+		result = fetch_multiple(&list);
 	}
 
 	if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) {
 		struct argv_array options = ARGV_ARRAY_INIT;
-		int max_children = max_jobs;
-
-		if (max_children < 0)
-			max_children = submodule_fetch_jobs_config;
-		if (max_children < 0)
-			max_children = fetch_parallel_config;
 
 		add_options_to_argv(&options);
 		result = fetch_populated_submodules(the_repository,
@@ -1870,20 +1722,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 
 	string_list_clear(&list, 0);
 
-	prepare_repo_settings(the_repository);
-	if (fetch_write_commit_graph > 0 ||
-	    (fetch_write_commit_graph < 0 &&
-	     the_repository->settings.fetch_write_commit_graph)) {
-		int commit_graph_flags = COMMIT_GRAPH_WRITE_SPLIT;
-
-		if (progress)
-			commit_graph_flags |= COMMIT_GRAPH_WRITE_PROGRESS;
-
-		write_commit_graph_reachable(the_repository->objects->odb,
-					     commit_graph_flags,
-					     NULL);
-	}
-
 	close_object_store(the_repository->objects);
 
 	if (enable_auto_gc) {
diff --git a/third_party/git/builtin/fmt-merge-msg.c b/third_party/git/builtin/fmt-merge-msg.c
index 736f666f64..a4615587fd 100644
--- a/third_party/git/builtin/fmt-merge-msg.c
+++ b/third_party/git/builtin/fmt-merge-msg.c
@@ -106,7 +106,7 @@ static int handle_line(char *line, struct merge_parents *merge_parents)
 	int i, len = strlen(line);
 	struct origin_data *origin_data;
 	char *src;
-	const char *origin, *tag_name;
+	const char *origin;
 	struct src_data *src_data;
 	struct string_list_item *item;
 	int pulling_head = 0;
@@ -162,13 +162,14 @@ static int handle_line(char *line, struct merge_parents *merge_parents)
 	if (pulling_head) {
 		origin = src;
 		src_data->head_status |= 1;
-	} else if (skip_prefix(line, "branch ", &origin)) {
+	} else if (starts_with(line, "branch ")) {
 		origin_data->is_local_branch = 1;
+		origin = line + 7;
 		string_list_append(&src_data->branch, origin);
 		src_data->head_status |= 2;
-	} else if (skip_prefix(line, "tag ", &tag_name)) {
+	} else if (starts_with(line, "tag ")) {
 		origin = line;
-		string_list_append(&src_data->tag, tag_name);
+		string_list_append(&src_data->tag, origin + 4);
 		src_data->head_status |= 2;
 	} else if (skip_prefix(line, "remote-tracking branch ", &origin)) {
 		string_list_append(&src_data->r_branch, origin);
diff --git a/third_party/git/builtin/fsck.c b/third_party/git/builtin/fsck.c
index 8d13794b14..18403a94fa 100644
--- a/third_party/git/builtin/fsck.c
+++ b/third_party/git/builtin/fsck.c
@@ -50,20 +50,40 @@ static int name_objects;
 #define ERROR_REFS 010
 #define ERROR_COMMIT_GRAPH 020
 
-static const char *describe_object(const struct object_id *oid)
+static const char *describe_object(struct object *obj)
 {
-	return fsck_describe_object(&fsck_walk_options, oid);
+	static struct strbuf bufs[] = {
+		STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
+	};
+	static int b = 0;
+	struct strbuf *buf;
+	char *name = NULL;
+
+	if (name_objects)
+		name = lookup_decoration(fsck_walk_options.object_names, obj);
+
+	buf = bufs + b;
+	b = (b + 1) % ARRAY_SIZE(bufs);
+	strbuf_reset(buf);
+	strbuf_addstr(buf, oid_to_hex(&obj->oid));
+	if (name)
+		strbuf_addf(buf, " (%s)", name);
+
+	return buf->buf;
 }
 
-static const char *printable_type(const struct object_id *oid,
-				  enum object_type type)
+static const char *printable_type(struct object *obj)
 {
 	const char *ret;
 
-	if (type == OBJ_NONE)
-		type = oid_object_info(the_repository, oid, NULL);
+	if (obj->type == OBJ_NONE) {
+		enum object_type type = oid_object_info(the_repository,
+							&obj->oid, NULL);
+		if (type > 0)
+			object_as_type(the_repository, obj, type, 0);
+	}
 
-	ret = type_name(type);
+	ret = type_name(obj->type);
 	if (!ret)
 		ret = _("unknown");
 
@@ -98,32 +118,26 @@ static int objerror(struct object *obj, const char *err)
 	errors_found |= ERROR_OBJECT;
 	/* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */
 	fprintf_ln(stderr, _("error in %s %s: %s"),
-		   printable_type(&obj->oid, obj->type),
-		   describe_object(&obj->oid), err);
+		   printable_type(obj), describe_object(obj), err);
 	return -1;
 }
 
 static int fsck_error_func(struct fsck_options *o,
-			   const struct object_id *oid,
-			   enum object_type object_type,
-			   int msg_type, const char *message)
+	struct object *obj, int type, const char *message)
 {
-	switch (msg_type) {
+	switch (type) {
 	case FSCK_WARN:
 		/* TRANSLATORS: e.g. warning in tree 01bfda: <more explanation> */
 		fprintf_ln(stderr, _("warning in %s %s: %s"),
-			   printable_type(oid, object_type),
-			   describe_object(oid), message);
+			   printable_type(obj), describe_object(obj), message);
 		return 0;
 	case FSCK_ERROR:
 		/* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */
 		fprintf_ln(stderr, _("error in %s %s: %s"),
-			   printable_type(oid, object_type),
-			   describe_object(oid), message);
+			   printable_type(obj), describe_object(obj), message);
 		return 1;
 	default:
-		BUG("%d (FSCK_IGNORE?) should never trigger this callback",
-		    msg_type);
+		BUG("%d (FSCK_IGNORE?) should never trigger this callback", type);
 	}
 }
 
@@ -141,8 +155,7 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt
 	if (!obj) {
 		/* ... these references to parent->fld are safe here */
 		printf_ln(_("broken link from %7s %s"),
-			  printable_type(&parent->oid, parent->type),
-			  describe_object(&parent->oid));
+			  printable_type(parent), describe_object(parent));
 		printf_ln(_("broken link from %7s %s"),
 			  (type == OBJ_ANY ? _("unknown") : type_name(type)),
 			  _("unknown"));
@@ -170,10 +183,10 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt
 		if (parent && !has_object_file(&obj->oid)) {
 			printf_ln(_("broken link from %7s %s\n"
 				    "              to %7s %s"),
-				  printable_type(&parent->oid, parent->type),
-				  describe_object(&parent->oid),
-				  printable_type(&obj->oid, obj->type),
-				  describe_object(&obj->oid));
+				  printable_type(parent),
+				  describe_object(parent),
+				  printable_type(obj),
+				  describe_object(obj));
 			errors_found |= ERROR_REACHABLE;
 		}
 		return 1;
@@ -279,9 +292,8 @@ static void check_reachable_object(struct object *obj)
 			return;
 		if (has_object_pack(&obj->oid))
 			return; /* it is in pack - forget about it */
-		printf_ln(_("missing %s %s"),
-			  printable_type(&obj->oid, obj->type),
-			  describe_object(&obj->oid));
+		printf_ln(_("missing %s %s"), printable_type(obj),
+			  describe_object(obj));
 		errors_found |= ERROR_REACHABLE;
 		return;
 	}
@@ -306,9 +318,8 @@ static void check_unreachable_object(struct object *obj)
 	 * since this is something that is prunable.
 	 */
 	if (show_unreachable) {
-		printf_ln(_("unreachable %s %s"),
-			  printable_type(&obj->oid, obj->type),
-			  describe_object(&obj->oid));
+		printf_ln(_("unreachable %s %s"), printable_type(obj),
+			  describe_object(obj));
 		return;
 	}
 
@@ -326,13 +337,12 @@ static void check_unreachable_object(struct object *obj)
 	 */
 	if (!(obj->flags & USED)) {
 		if (show_dangling)
-			printf_ln(_("dangling %s %s"),
-				  printable_type(&obj->oid, obj->type),
-				  describe_object(&obj->oid));
+			printf_ln(_("dangling %s %s"), printable_type(obj),
+				  describe_object(obj));
 		if (write_lost_and_found) {
 			char *filename = git_pathdup("lost-found/%s/%s",
 				obj->type == OBJ_COMMIT ? "commit" : "other",
-				describe_object(&obj->oid));
+				describe_object(obj));
 			FILE *f;
 
 			if (safe_create_leading_directories_const(filename)) {
@@ -345,7 +355,7 @@ static void check_unreachable_object(struct object *obj)
 				if (stream_blob_to_fd(fileno(f), &obj->oid, NULL, 1))
 					die_errno(_("could not write '%s'"), filename);
 			} else
-				fprintf(f, "%s\n", describe_object(&obj->oid));
+				fprintf(f, "%s\n", describe_object(obj));
 			if (fclose(f))
 				die_errno(_("could not finish '%s'"),
 					  filename);
@@ -364,7 +374,7 @@ static void check_unreachable_object(struct object *obj)
 static void check_object(struct object *obj)
 {
 	if (verbose)
-		fprintf_ln(stderr, _("Checking %s"), describe_object(&obj->oid));
+		fprintf_ln(stderr, _("Checking %s"), describe_object(obj));
 
 	if (obj->flags & REACHABLE)
 		check_reachable_object(obj);
@@ -422,8 +432,7 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
 
 	if (verbose)
 		fprintf_ln(stderr, _("Checking %s %s"),
-			   printable_type(&obj->oid, obj->type),
-			   describe_object(&obj->oid));
+			   printable_type(obj), describe_object(obj));
 
 	if (fsck_walk(obj, NULL, &fsck_obj_options))
 		objerror(obj, _("broken links"));
@@ -436,7 +445,7 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
 
 		if (!commit->parents && show_root)
 			printf_ln(_("root %s"),
-				  describe_object(&commit->object.oid));
+				  describe_object(&commit->object));
 	}
 
 	if (obj->type == OBJ_TAG) {
@@ -444,10 +453,10 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
 
 		if (show_tags && tag->tagged) {
 			printf_ln(_("tagged %s %s (%s) in %s"),
-				  printable_type(&tag->tagged->oid, tag->tagged->type),
-				  describe_object(&tag->tagged->oid),
+				  printable_type(tag->tagged),
+				  describe_object(tag->tagged),
 				  tag->tag,
-				  describe_object(&tag->object.oid));
+				  describe_object(&tag->object));
 		}
 	}
 
@@ -490,10 +499,10 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,
 	if (!is_null_oid(oid)) {
 		obj = lookup_object(the_repository, oid);
 		if (obj && (obj->flags & HAS_OBJ)) {
-			if (timestamp)
-				fsck_put_object_name(&fsck_walk_options, oid,
-						     "%s@{%"PRItime"}",
-						     refname, timestamp);
+			if (timestamp && name_objects)
+				add_decoration(fsck_walk_options.object_names,
+					obj,
+					xstrfmt("%s@{%"PRItime"}", refname, timestamp));
 			obj->flags |= USED;
 			mark_object_reachable(obj);
 		} else if (!is_promisor_object(oid)) {
@@ -557,8 +566,9 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid,
 	}
 	default_refs++;
 	obj->flags |= USED;
-	fsck_put_object_name(&fsck_walk_options,
-			     oid, "%s", refname);
+	if (name_objects)
+		add_decoration(fsck_walk_options.object_names,
+			obj, xstrdup(refname));
 	mark_object_reachable(obj);
 
 	return 0;
@@ -732,7 +742,9 @@ static int fsck_cache_tree(struct cache_tree *it)
 			return 1;
 		}
 		obj->flags |= USED;
-		fsck_put_object_name(&fsck_walk_options, &it->oid, ":");
+		if (name_objects)
+			add_decoration(fsck_walk_options.object_names,
+				obj, xstrdup(":"));
 		mark_object_reachable(obj);
 		if (obj->type != OBJ_TREE)
 			err |= objerror(obj, _("non-tree in cache-tree"));
@@ -818,7 +830,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
 	}
 
 	if (name_objects)
-		fsck_enable_object_names(&fsck_walk_options);
+		fsck_walk_options.object_names =
+			xcalloc(1, sizeof(struct decoration));
 
 	git_config(fsck_config, NULL);
 
@@ -877,8 +890,9 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
 			}
 
 			obj->flags |= USED;
-			fsck_put_object_name(&fsck_walk_options, &oid,
-					     "%s", arg);
+			if (name_objects)
+				add_decoration(fsck_walk_options.object_names,
+					obj, xstrdup(arg));
 			mark_object_reachable(obj);
 			continue;
 		}
@@ -914,8 +928,10 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
 				continue;
 			obj = &blob->object;
 			obj->flags |= USED;
-			fsck_put_object_name(&fsck_walk_options, &obj->oid,
-					     ":%s", active_cache[i]->name);
+			if (name_objects)
+				add_decoration(fsck_walk_options.object_names,
+					obj,
+					xstrfmt(":%s", active_cache[i]->name));
 			mark_object_reachable(obj);
 		}
 		if (active_cache_tree)
diff --git a/third_party/git/builtin/gc.c b/third_party/git/builtin/gc.c
index 8e0b9cf41b..c18efadda5 100644
--- a/third_party/git/builtin/gc.c
+++ b/third_party/git/builtin/gc.c
@@ -27,7 +27,6 @@
 #include "pack-objects.h"
 #include "blob.h"
 #include "tree.h"
-#include "promisor-remote.h"
 
 #define FAILED_RUN "failed to run %s"
 
@@ -42,6 +41,7 @@ static int aggressive_depth = 50;
 static int aggressive_window = 250;
 static int gc_auto_threshold = 6700;
 static int gc_auto_pack_limit = 50;
+static int gc_write_commit_graph;
 static int detach_auto = 1;
 static timestamp_t gc_log_expire_time;
 static const char *gc_log_expire = "1.day.ago";
@@ -148,6 +148,7 @@ static void gc_config(void)
 	git_config_get_int("gc.aggressivedepth", &aggressive_depth);
 	git_config_get_int("gc.auto", &gc_auto_threshold);
 	git_config_get_int("gc.autopacklimit", &gc_auto_pack_limit);
+	git_config_get_bool("gc.writecommitgraph", &gc_write_commit_graph);
 	git_config_get_bool("gc.autodetach", &detach_auto);
 	git_config_get_expiry("gc.pruneexpire", &prune_expire);
 	git_config_get_expiry("gc.worktreepruneexpire", &prune_worktrees_expire);
@@ -458,7 +459,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
 /*
  * Returns 0 if there was no previous error and gc can proceed, 1 if
  * gc should not proceed due to an error in the last run. Prints a
- * message and returns -1 if an error occurred while reading gc.log
+ * message and returns -1 if an error occured while reading gc.log
  */
 static int report_last_gc_error(void)
 {
@@ -601,7 +602,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
 		if (detach_auto) {
 			int ret = report_last_gc_error();
 			if (ret < 0)
-				/* an I/O error occurred, already reported */
+				/* an I/O error occured, already reported */
 				exit(128);
 			if (ret == 1)
 				/* Last gc --auto failed. Skip this one. */
@@ -660,7 +661,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
 			argv_array_push(&prune, prune_expire);
 			if (quiet)
 				argv_array_push(&prune, "--no-progress");
-			if (has_promisor_remote())
+			if (repository_format_partial_clone)
 				argv_array_push(&prune,
 						"--exclude-promisor-objects");
 			if (run_command_v_opt(prune.argv, RUN_GIT_CMD))
@@ -684,11 +685,11 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
 		clean_pack_garbage();
 	}
 
-	prepare_repo_settings(the_repository);
-	if (the_repository->settings.gc_write_commit_graph == 1)
-		write_commit_graph_reachable(the_repository->objects->odb,
-					     !quiet && !daemonized ? COMMIT_GRAPH_WRITE_PROGRESS : 0,
-					     NULL);
+	if (gc_write_commit_graph &&
+	    write_commit_graph_reachable(get_object_directory(),
+					 !quiet && !daemonized ? COMMIT_GRAPH_PROGRESS : 0,
+					 NULL))
+		return 1;
 
 	if (auto_gc && too_many_loose_objects())
 		warning(_("There are too many unreachable loose objects; "
diff --git a/third_party/git/builtin/grep.c b/third_party/git/builtin/grep.c
index 99e2685090..560051784e 100644
--- a/third_party/git/builtin/grep.c
+++ b/third_party/git/builtin/grep.c
@@ -24,7 +24,6 @@
 #include "submodule.h"
 #include "submodule-config.h"
 #include "object-store.h"
-#include "packfile.h"
 
 static char const * const grep_usage[] = {
 	N_("git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]"),
@@ -33,6 +32,7 @@ static char const * const grep_usage[] = {
 
 static int recurse_submodules;
 
+#define GREP_NUM_THREADS_DEFAULT 8
 static int num_threads;
 
 static pthread_t *threads;
@@ -91,11 +91,8 @@ static pthread_cond_t cond_result;
 
 static int skip_first_line;
 
-static void add_work(struct grep_opt *opt, struct grep_source *gs)
+static void add_work(struct grep_opt *opt, const struct grep_source *gs)
 {
-	if (opt->binary != GREP_BINARY_TEXT)
-		grep_source_load_driver(gs, opt->repo->index);
-
 	grep_lock();
 
 	while ((todo_end+1) % ARRAY_SIZE(todo) == todo_done) {
@@ -103,6 +100,9 @@ static void add_work(struct grep_opt *opt, struct grep_source *gs)
 	}
 
 	todo[todo_end].source = *gs;
+	if (opt->binary != GREP_BINARY_TEXT)
+		grep_source_load_driver(&todo[todo_end].source,
+					opt->repo->index);
 	todo[todo_end].done = 0;
 	strbuf_reset(&todo[todo_end].out);
 	todo_end = (todo_end + 1) % ARRAY_SIZE(todo);
@@ -200,12 +200,12 @@ static void start_threads(struct grep_opt *opt)
 	int i;
 
 	pthread_mutex_init(&grep_mutex, NULL);
+	pthread_mutex_init(&grep_read_mutex, NULL);
 	pthread_mutex_init(&grep_attr_mutex, NULL);
 	pthread_cond_init(&cond_add, NULL);
 	pthread_cond_init(&cond_write, NULL);
 	pthread_cond_init(&cond_result, NULL);
 	grep_use_locks = 1;
-	enable_obj_read_lock();
 
 	for (i = 0; i < ARRAY_SIZE(todo); i++) {
 		strbuf_init(&todo[i].out, 0);
@@ -257,12 +257,12 @@ static int wait_all(void)
 	free(threads);
 
 	pthread_mutex_destroy(&grep_mutex);
+	pthread_mutex_destroy(&grep_read_mutex);
 	pthread_mutex_destroy(&grep_attr_mutex);
 	pthread_cond_destroy(&cond_add);
 	pthread_cond_destroy(&cond_write);
 	pthread_cond_destroy(&cond_result);
 	grep_use_locks = 0;
-	disable_obj_read_lock();
 
 	return hit;
 }
@@ -295,6 +295,16 @@ static int grep_cmd_config(const char *var, const char *value, void *cb)
 	return st;
 }
 
+static void *lock_and_read_oid_file(const struct object_id *oid, enum object_type *type, unsigned long *size)
+{
+	void *data;
+
+	grep_read_lock();
+	data = read_object_file(oid, type, size);
+	grep_read_unlock();
+	return data;
+}
+
 static int grep_oid(struct grep_opt *opt, const struct object_id *oid,
 		     const char *filename, int tree_name_len,
 		     const char *path)
@@ -393,32 +403,34 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
 static int grep_submodule(struct grep_opt *opt,
 			  const struct pathspec *pathspec,
 			  const struct object_id *oid,
-			  const char *filename, const char *path, int cached)
+			  const char *filename, const char *path)
 {
 	struct repository subrepo;
 	struct repository *superproject = opt->repo;
-	const struct submodule *sub;
+	const struct submodule *sub = submodule_from_path(superproject,
+							  &null_oid, path);
 	struct grep_opt subopt;
 	int hit;
 
-	sub = submodule_from_path(superproject, &null_oid, path);
+	/*
+	 * NEEDSWORK: submodules functions need to be protected because they
+	 * access the object store via config_from_gitmodules(): the latter
+	 * uses get_oid() which, for now, relies on the global the_repository
+	 * object.
+	 */
+	grep_read_lock();
 
-	if (!is_submodule_active(superproject, path))
+	if (!is_submodule_active(superproject, path)) {
+		grep_read_unlock();
 		return 0;
+	}
 
-	if (repo_submodule_init(&subrepo, superproject, sub))
+	if (repo_submodule_init(&subrepo, superproject, sub)) {
+		grep_read_unlock();
 		return 0;
+	}
 
-	/*
-	 * NEEDSWORK: repo_read_gitmodules() might call
-	 * add_to_alternates_memory() via config_from_gitmodules(). This
-	 * operation causes a race condition with concurrent object readings
-	 * performed by the worker threads. That's why we need obj_read_lock()
-	 * here. It should be removed once it's no longer necessary to add the
-	 * subrepo's odbs to the in-memory alternates list.
-	 */
-	obj_read_lock();
-	repo_read_gitmodules(&subrepo, 0);
+	repo_read_gitmodules(&subrepo);
 
 	/*
 	 * NEEDSWORK: This adds the submodule's object directory to the list of
@@ -431,7 +443,7 @@ static int grep_submodule(struct grep_opt *opt,
 	 * object.
 	 */
 	add_to_alternates_memory(subrepo.objects->odb->path);
-	obj_read_unlock();
+	grep_read_unlock();
 
 	memcpy(&subopt, opt, sizeof(subopt));
 	subopt.repo = &subrepo;
@@ -443,12 +455,14 @@ static int grep_submodule(struct grep_opt *opt,
 		unsigned long size;
 		struct strbuf base = STRBUF_INIT;
 
-		obj_read_lock();
 		object = parse_object_or_die(oid, oid_to_hex(oid));
-		obj_read_unlock();
+
+		grep_read_lock();
 		data = read_object_with_reference(&subrepo,
 						  &object->oid, tree_type,
 						  &size, NULL);
+		grep_read_unlock();
+
 		if (!data)
 			die(_("unable to read tree (%s)"), oid_to_hex(&object->oid));
 
@@ -461,7 +475,7 @@ static int grep_submodule(struct grep_opt *opt,
 		strbuf_release(&base);
 		free(data);
 	} else {
-		hit = grep_cache(&subopt, pathspec, cached);
+		hit = grep_cache(&subopt, pathspec, 1);
 	}
 
 	repo_clear(&subrepo);
@@ -509,8 +523,7 @@ static int grep_cache(struct grep_opt *opt,
 			}
 		} else if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
 			   submodule_path_match(repo->index, pathspec, name.buf, NULL)) {
-			hit |= grep_submodule(opt, pathspec, NULL, ce->name,
-					      ce->name, cached);
+			hit |= grep_submodule(opt, pathspec, NULL, ce->name, ce->name);
 		} else {
 			continue;
 		}
@@ -573,7 +586,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
 			void *data;
 			unsigned long size;
 
-			data = read_object_file(&entry.oid, &type, &size);
+			data = lock_and_read_oid_file(&entry.oid, &type, &size);
 			if (!data)
 				die(_("unable to read tree (%s)"),
 				    oid_to_hex(&entry.oid));
@@ -585,8 +598,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
 			free(data);
 		} else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
 			hit |= grep_submodule(opt, pathspec, &entry.oid,
-					      base->buf, base->buf + tn_len,
-					      1); /* ignored */
+					      base->buf, base->buf + tn_len);
 		}
 
 		strbuf_setlen(base, old_baselen);
@@ -611,9 +623,12 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
 		struct strbuf base;
 		int hit, len;
 
+		grep_read_lock();
 		data = read_object_with_reference(opt->repo,
 						  &obj->oid, tree_type,
 						  &size, NULL);
+		grep_read_unlock();
+
 		if (!data)
 			die(_("unable to read tree (%s)"), oid_to_hex(&obj->oid));
 
@@ -642,18 +657,13 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
 
 	for (i = 0; i < nr; i++) {
 		struct object *real_obj;
-
-		obj_read_lock();
 		real_obj = deref_tag(opt->repo, list->objects[i].item,
 				     NULL, 0);
-		obj_read_unlock();
 
 		/* load the gitmodules file for this rev */
 		if (recurse_submodules) {
 			submodule_free(opt->repo);
-			obj_read_lock();
 			gitmodules_config_oid(&real_obj->oid);
-			obj_read_unlock();
 		}
 		if (grep_object(opt, pathspec, real_obj, list->objects[i].name,
 				list->objects[i].path)) {
@@ -946,9 +956,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 			/* die the same way as if we did it at the beginning */
 			setup_git_directory();
 	}
-	/* Ignore --recurse-submodules if --no-index is given or implied */
-	if (!use_index)
-		recurse_submodules = 0;
 
 	/*
 	 * skip a -- separator; we know it cannot be
@@ -1053,10 +1060,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 	pathspec.recursive = 1;
 	pathspec.recurse_submodules = !!recurse_submodules;
 
-	if (recurse_submodules && untracked)
-		die(_("--untracked not supported with --recurse-submodules"));
-
-	if (show_in_pager) {
+	if (list.nr || cached || show_in_pager) {
 		if (num_threads > 1)
 			warning(_("invalid option combination, ignoring --threads"));
 		num_threads = 1;
@@ -1066,7 +1070,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 	} else if (num_threads < 0)
 		die(_("invalid number of threads specified (%d)"), num_threads);
 	else if (num_threads == 0)
-		num_threads = HAVE_THREADS ? online_cpus() : 1;
+		num_threads = HAVE_THREADS ? GREP_NUM_THREADS_DEFAULT : 1;
 
 	if (num_threads > 1) {
 		if (!HAVE_THREADS)
@@ -1075,17 +1079,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 		    && (opt.pre_context || opt.post_context ||
 			opt.file_break || opt.funcbody))
 			skip_first_line = 1;
-
-		/*
-		 * Pre-read gitmodules (if not read already) and force eager
-		 * initialization of packed_git to prevent racy lazy
-		 * reading/initialization once worker threads are started.
-		 */
-		if (recurse_submodules)
-			repo_read_gitmodules(the_repository, 1);
-		if (startup_info->have_repository)
-			(void)get_packed_git(the_repository);
-
 		start_threads(&opt);
 	} else {
 		/*
@@ -1115,11 +1108,14 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 			strbuf_addf(&buf, "+/%s%s",
 					strcmp("less", pager) ? "" : "*",
 					opt.pattern_list->pattern);
-			string_list_append(&path_list,
-					   strbuf_detach(&buf, NULL));
+			string_list_append(&path_list, buf.buf);
+			strbuf_detach(&buf, NULL);
 		}
 	}
 
+	if (recurse_submodules && (!use_index || untracked))
+		die(_("option not supported with --recurse-submodules"));
+
 	if (!show_in_pager && !opt.status_only)
 		setup_pager();
 
@@ -1149,6 +1145,5 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 		run_pager(&opt, prefix);
 	clear_pathspec(&pathspec);
 	free_grep_patterns(&opt);
-	grep_destroy();
 	return !hit;
 }
diff --git a/third_party/git/builtin/index-pack.c b/third_party/git/builtin/index-pack.c
index d967d188a3..0d55f73b0b 100644
--- a/third_party/git/builtin/index-pack.c
+++ b/third_party/git/builtin/index-pack.c
@@ -14,7 +14,7 @@
 #include "thread-utils.h"
 #include "packfile.h"
 #include "object-store.h"
-#include "promisor-remote.h"
+#include "fetch-object.h"
 
 static const char index_pack_usage[] =
 "git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--verify] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
@@ -757,8 +757,7 @@ static int check_collison(struct object_entry *entry)
 
 	memset(&data, 0, sizeof(data));
 	data.entry = entry;
-	data.st = open_istream(the_repository, &entry->idx.oid, &type, &size,
-			       NULL);
+	data.st = open_istream(&entry->idx.oid, &type, &size, NULL);
 	if (!data.st)
 		return -1;
 	if (size != entry->size || type != entry->type)
@@ -949,7 +948,7 @@ static void resolve_delta(struct object_entry *delta_obj,
 	free(delta_data);
 	if (!result->data)
 		bad_object(delta_obj->idx.offset, _("failed to apply delta"));
-	hash_object_file(the_hash_algo, result->data, result->size,
+	hash_object_file(result->data, result->size,
 			 type_name(delta_obj->real_type), &delta_obj->idx.oid);
 	sha1_object(result->data, NULL, result->size, delta_obj->real_type,
 		    &delta_obj->idx.oid);
@@ -1004,9 +1003,7 @@ static struct base_data *find_unresolved_deltas_1(struct base_data *base,
 
 		if (!compare_and_swap_type(&child->real_type, OBJ_REF_DELTA,
 					   base->obj->real_type))
-			die("REF_DELTA at offset %"PRIuMAX" already resolved (duplicate base %s?)",
-			    (uintmax_t)child->idx.offset,
-			    oid_to_hex(&base->obj->idx.oid));
+			BUG("child->real_type != OBJ_REF_DELTA");
 
 		resolve_delta(child, base, result);
 		if (base->ref_first == base->ref_last && base->ofs_last == -1)
@@ -1355,7 +1352,7 @@ static void fix_unresolved_deltas(struct hashfile *f)
 		sorted_by_pos[i] = &ref_deltas[i];
 	QSORT(sorted_by_pos, nr_ref_deltas, delta_pos_compare);
 
-	if (has_promisor_remote()) {
+	if (repository_format_partial_clone) {
 		/*
 		 * Prefetch the delta bases.
 		 */
@@ -1369,8 +1366,8 @@ static void fix_unresolved_deltas(struct hashfile *f)
 			oid_array_append(&to_fetch, &d->oid);
 		}
 		if (to_fetch.nr)
-			promisor_remote_get_direct(the_repository,
-						   to_fetch.oid, to_fetch.nr);
+			fetch_objects(repository_format_partial_clone,
+				      to_fetch.oid, to_fetch.nr);
 		oid_array_clear(&to_fetch);
 	}
 
@@ -1386,9 +1383,8 @@ static void fix_unresolved_deltas(struct hashfile *f)
 		if (!base_obj->data)
 			continue;
 
-		if (check_object_signature(the_repository, &d->oid,
-					   base_obj->data, base_obj->size,
-					   type_name(type)))
+		if (check_object_signature(&d->oid, base_obj->data,
+				base_obj->size, type_name(type)))
 			die(_("local object %s is corrupt"), oid_to_hex(&d->oid));
 		base_obj->obj = append_obj_to_pack(f, d->oid.hash,
 					base_obj->data, base_obj->size, type);
@@ -1494,11 +1490,11 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
 	}
 
 	if (!from_stdin) {
-		printf("%s\n", hash_to_hex(hash));
+		printf("%s\n", sha1_to_hex(hash));
 	} else {
 		struct strbuf buf = STRBUF_INIT;
 
-		strbuf_addf(&buf, "%s\t%s\n", report, hash_to_hex(hash));
+		strbuf_addf(&buf, "%s\t%s\n", report, sha1_to_hex(hash));
 		write_or_die(1, buf.buf, buf.len);
 		strbuf_release(&buf);
 
diff --git a/third_party/git/builtin/log.c b/third_party/git/builtin/log.c
index 83a4a6188e..44b10b3415 100644
--- a/third_party/git/builtin/log.c
+++ b/third_party/git/builtin/log.c
@@ -37,7 +37,6 @@
 #include "range-diff.h"
 
 #define MAIL_DEFAULT_WRAP 72
-#define COVER_FROM_AUTO_MAX_SUBJECT_LEN 100
 
 /* Set a default date-time format for git log ("log.date" config variable) */
 static const char *default_date_mode = NULL;
@@ -208,7 +207,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
 	if (!rev->show_notes_given && (!rev->pretty_given || w.notes))
 		rev->show_notes = 1;
 	if (rev->show_notes)
-		load_display_notes(&rev->notes_opt);
+		init_display_notes(&rev->notes_opt);
 
 	if ((rev->diffopt.pickaxe_opts & DIFF_PICKAXE_KINDS_MASK) ||
 	    rev->diffopt.filter || rev->diffopt.flags.follow_renames)
@@ -628,7 +627,6 @@ int cmd_show(int argc, const char **argv, const char *prefix)
 			break;
 		case OBJ_TAG: {
 			struct tag *t = (struct tag *)o;
-			struct object_id *oid = get_tagged_oid(t);
 
 			if (rev.shown_one)
 				putchar('\n');
@@ -640,10 +638,10 @@ int cmd_show(int argc, const char **argv, const char *prefix)
 			rev.shown_one = 1;
 			if (ret)
 				break;
-			o = parse_object(the_repository, oid);
+			o = parse_object(the_repository, &t->tagged->oid);
 			if (!o)
 				ret = error(_("could not read object %s"),
-					    oid_to_hex(oid));
+					    oid_to_hex(&t->tagged->oid));
 			objects[i].item = o;
 			i--;
 			break;
@@ -766,56 +764,28 @@ static void add_header(const char *value)
 	item->string[len] = '\0';
 }
 
-enum cover_setting {
-	COVER_UNSET,
-	COVER_OFF,
-	COVER_ON,
-	COVER_AUTO
-};
-
-enum thread_level {
-	THREAD_UNSET,
-	THREAD_SHALLOW,
-	THREAD_DEEP
-};
-
-enum cover_from_description {
-	COVER_FROM_NONE,
-	COVER_FROM_MESSAGE,
-	COVER_FROM_SUBJECT,
-	COVER_FROM_AUTO
-};
-
-static enum thread_level thread;
+#define THREAD_SHALLOW 1
+#define THREAD_DEEP 2
+static int thread;
 static int do_signoff;
 static int base_auto;
 static char *from;
 static const char *signature = git_version_string;
 static const char *signature_file;
-static enum cover_setting config_cover_letter;
+static int config_cover_letter;
 static const char *config_output_directory;
-static enum cover_from_description cover_from_description_mode = COVER_FROM_MESSAGE;
-static int show_notes;
-static struct display_notes_opt notes_opt;
 
-static enum cover_from_description parse_cover_from_description(const char *arg)
-{
-	if (!arg || !strcmp(arg, "default"))
-		return COVER_FROM_MESSAGE;
-	else if (!strcmp(arg, "none"))
-		return COVER_FROM_NONE;
-	else if (!strcmp(arg, "message"))
-		return COVER_FROM_MESSAGE;
-	else if (!strcmp(arg, "subject"))
-		return COVER_FROM_SUBJECT;
-	else if (!strcmp(arg, "auto"))
-		return COVER_FROM_AUTO;
-	else
-		die(_("%s: invalid cover from description mode"), arg);
-}
+enum {
+	COVER_UNSET,
+	COVER_OFF,
+	COVER_ON,
+	COVER_AUTO
+};
 
 static int git_format_config(const char *var, const char *value, void *cb)
 {
+	struct rev_info *rev = cb;
+
 	if (!strcmp(var, "format.headers")) {
 		if (!value)
 			die(_("format.headers without value"));
@@ -865,7 +835,7 @@ static int git_format_config(const char *var, const char *value, void *cb)
 			thread = THREAD_SHALLOW;
 			return 0;
 		}
-		thread = git_config_bool(var, value) ? THREAD_SHALLOW : THREAD_UNSET;
+		thread = git_config_bool(var, value) && THREAD_SHALLOW;
 		return 0;
 	}
 	if (!strcmp(var, "format.signoff")) {
@@ -902,17 +872,19 @@ static int git_format_config(const char *var, const char *value, void *cb)
 		return 0;
 	}
 	if (!strcmp(var, "format.notes")) {
+		struct strbuf buf = STRBUF_INIT;
 		int b = git_parse_maybe_bool(value);
-		if (b < 0)
-			enable_ref_display_notes(&notes_opt, &show_notes, value);
-		else if (b)
-			enable_default_display_notes(&notes_opt, &show_notes);
-		else
-			disable_display_notes(&notes_opt, &show_notes);
-		return 0;
-	}
-	if (!strcmp(var, "format.coverfromdescription")) {
-		cover_from_description_mode = parse_cover_from_description(value);
+		if (!b)
+			return 0;
+		rev->show_notes = 1;
+		if (b < 0) {
+			strbuf_addstr(&buf, value);
+			expand_notes_ref(&buf);
+			string_list_append(&rev->notes_opt.extra_notes_refs,
+					strbuf_detach(&buf, NULL));
+		} else {
+			rev->notes_opt.use_default_notes = 1;
+		}
 		return 0;
 	}
 
@@ -1021,6 +993,20 @@ static void print_signature(FILE *file)
 	putc('\n', file);
 }
 
+static void add_branch_description(struct strbuf *buf, const char *branch_name)
+{
+	struct strbuf desc = STRBUF_INIT;
+	if (!branch_name || !*branch_name)
+		return;
+	read_branch_desc(&desc, branch_name);
+	if (desc.len) {
+		strbuf_addch(buf, '\n');
+		strbuf_addbuf(buf, &desc);
+		strbuf_addch(buf, '\n');
+	}
+	strbuf_release(&desc);
+}
+
 static char *find_branch_name(struct rev_info *rev)
 {
 	int i, positive = -1;
@@ -1067,63 +1053,6 @@ static void show_diffstat(struct rev_info *rev,
 	fprintf(rev->diffopt.file, "\n");
 }
 
-static void prepare_cover_text(struct pretty_print_context *pp,
-			       const char *branch_name,
-			       struct strbuf *sb,
-			       const char *encoding,
-			       int need_8bit_cte)
-{
-	const char *subject = "*** SUBJECT HERE ***";
-	const char *body = "*** BLURB HERE ***";
-	struct strbuf description_sb = STRBUF_INIT;
-	struct strbuf subject_sb = STRBUF_INIT;
-
-	if (cover_from_description_mode == COVER_FROM_NONE)
-		goto do_pp;
-
-	if (branch_name && *branch_name)
-		read_branch_desc(&description_sb, branch_name);
-	if (!description_sb.len)
-		goto do_pp;
-
-	if (cover_from_description_mode == COVER_FROM_SUBJECT ||
-			cover_from_description_mode == COVER_FROM_AUTO)
-		body = format_subject(&subject_sb, description_sb.buf, " ");
-
-	if (cover_from_description_mode == COVER_FROM_MESSAGE ||
-			(cover_from_description_mode == COVER_FROM_AUTO &&
-			 subject_sb.len > COVER_FROM_AUTO_MAX_SUBJECT_LEN))
-		body = description_sb.buf;
-	else
-		subject = subject_sb.buf;
-
-do_pp:
-	pp_title_line(pp, &subject, sb, encoding, need_8bit_cte);
-	pp_remainder(pp, &body, sb, 0);
-
-	strbuf_release(&description_sb);
-	strbuf_release(&subject_sb);
-}
-
-static int get_notes_refs(struct string_list_item *item, void *arg)
-{
-	argv_array_pushf(arg, "--notes=%s", item->string);
-	return 0;
-}
-
-static void get_notes_args(struct argv_array *arg, struct rev_info *rev)
-{
-	if (!rev->show_notes) {
-		argv_array_push(arg, "--no-notes");
-	} else if (rev->notes_opt.use_default_notes > 0 ||
-		   (rev->notes_opt.use_default_notes == -1 &&
-		    !rev->notes_opt.extra_notes_refs.nr)) {
-		argv_array_push(arg, "--notes");
-	} else {
-		for_each_string_list(&rev->notes_opt.extra_notes_refs, get_notes_refs, arg);
-	}
-}
-
 static void make_cover_letter(struct rev_info *rev, int use_stdout,
 			      struct commit *origin,
 			      int nr, struct commit **list,
@@ -1131,6 +1060,8 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
 			      int quiet)
 {
 	const char *committer;
+	const char *body = "*** SUBJECT HERE ***\n\n*** BLURB HERE ***\n";
+	const char *msg;
 	struct shortlog log;
 	struct strbuf sb = STRBUF_INIT;
 	int i;
@@ -1160,12 +1091,15 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
 	if (!branch_name)
 		branch_name = find_branch_name(rev);
 
+	msg = body;
 	pp.fmt = CMIT_FMT_EMAIL;
 	pp.date_mode.type = DATE_RFC2822;
 	pp.rev = rev;
 	pp.print_email_subject = 1;
 	pp_user_info(&pp, NULL, &sb, committer, encoding);
-	prepare_cover_text(&pp, branch_name, &sb, encoding, need_8bit_cte);
+	pp_title_line(&pp, &msg, &sb, encoding, need_8bit_cte);
+	pp_remainder(&pp, &msg, &sb, 0);
+	add_branch_description(&sb, branch_name);
 	fprintf(rev->diffopt.file, "%s\n", sb.buf);
 
 	strbuf_release(&sb);
@@ -1196,16 +1130,13 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
 		 * can be added later if deemed desirable.
 		 */
 		struct diff_options opts;
-		struct argv_array other_arg = ARGV_ARRAY_INIT;
 		diff_setup(&opts);
 		opts.file = rev->diffopt.file;
 		opts.use_color = rev->diffopt.use_color;
 		diff_setup_done(&opts);
 		fprintf_ln(rev->diffopt.file, "%s", rev->rdiff_title);
-		get_notes_args(&other_arg, rev);
 		show_range_diff(rev->rdiff1, rev->rdiff2,
-				rev->creation_factor, 1, &opts, &other_arg);
-		argv_array_clear(&other_arg);
+				rev->creation_factor, 1, &opts);
 	}
 }
 
@@ -1317,9 +1248,9 @@ static int output_directory_callback(const struct option *opt, const char *arg,
 
 static int thread_callback(const struct option *opt, const char *arg, int unset)
 {
-	enum thread_level *thread = (enum thread_level *)opt->value;
+	int *thread = (int *)opt->value;
 	if (unset)
-		*thread = THREAD_UNSET;
+		*thread = 0;
 	else if (!arg || !strcmp(arg, "shallow"))
 		*thread = THREAD_SHALLOW;
 	else if (!strcmp(arg, "deep"))
@@ -1366,7 +1297,7 @@ static int header_callback(const struct option *opt, const char *arg, int unset)
 		string_list_clear(&extra_to, 0);
 		string_list_clear(&extra_cc, 0);
 	} else {
-		add_header(arg);
+	    add_header(arg);
 	}
 	return 0;
 }
@@ -1422,7 +1353,7 @@ static struct commit *get_base_commit(const char *base_commit,
 		base = lookup_commit_reference_by_name(base_commit);
 		if (!base)
 			die(_("unknown commit %s"), base_commit);
-	} else if ((base_commit && !strcmp(base_commit, "auto"))) {
+	} else if ((base_commit && !strcmp(base_commit, "auto")) || base_auto) {
 		struct branch *curr_branch = branch_get(NULL);
 		const char *upstream = branch_get_upstream(curr_branch, NULL);
 		if (upstream) {
@@ -1610,7 +1541,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	int use_patch_format = 0;
 	int quiet = 0;
 	int reroll_count = -1;
-	char *cover_from_description_arg = NULL;
 	char *branch_name = NULL;
 	char *base_commit = NULL;
 	struct base_tree_info bases;
@@ -1647,9 +1577,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		{ OPTION_CALLBACK, 0, "rfc", &rev, NULL,
 			    N_("Use [RFC PATCH] instead of [PATCH]"),
 			    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"),
 			    N_("Use [<prefix>] instead of [PATCH]"),
 			    PARSE_OPT_NONEG, subject_prefix_callback },
@@ -1713,11 +1640,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	extra_to.strdup_strings = 1;
 	extra_cc.strdup_strings = 1;
 	init_log_defaults();
-	init_display_notes(&notes_opt);
-	git_config(git_format_config, NULL);
 	repo_init_revisions(the_repository, &rev, prefix);
-	rev.show_notes = show_notes;
-	memcpy(&rev.notes_opt, &notes_opt, sizeof(notes_opt));
+	git_config(git_format_config, &rev);
 	rev.commit_format = CMIT_FMT_EMAIL;
 	rev.expand_tabs_in_log_default = 0;
 	rev.verbose_header = 1;
@@ -1729,9 +1653,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	s_r_opt.def = "HEAD";
 	s_r_opt.revarg_opt = REVARG_COMMITTISH;
 
-	if (base_auto)
-		base_commit = "auto";
-
 	if (default_attach) {
 		rev.mime_boundary = default_attach;
 		rev.no_inline = 1;
@@ -1747,9 +1668,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 			     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
 			     PARSE_OPT_KEEP_DASHDASH);
 
-	if (cover_from_description_arg)
-		cover_from_description_mode = parse_cover_from_description(cover_from_description_arg);
-
 	if (0 < reroll_count) {
 		struct strbuf sprefix = STRBUF_INIT;
 		strbuf_addf(&sprefix, "%s v%d",
@@ -1836,7 +1754,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		rev.diffopt.flags.binary = 1;
 
 	if (rev.show_notes)
-		load_display_notes(&rev.notes_opt);
+		init_display_notes(&rev.notes_opt);
 
 	if (!output_directory && !use_stdout)
 		output_directory = config_output_directory;
@@ -1847,26 +1765,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		setup_pager();
 
 	if (output_directory) {
-		int saved;
 		if (rev.diffopt.use_color != GIT_COLOR_ALWAYS)
 			rev.diffopt.use_color = GIT_COLOR_NEVER;
 		if (use_stdout)
 			die(_("standard output, or directory, which one?"));
-		/*
-		 * We consider <outdir> as 'outside of gitdir', therefore avoid
-		 * applying adjust_shared_perm in s-c-l-d.
-		 */
-		saved = get_shared_repository();
-		set_shared_repository(0);
-		switch (safe_create_leading_directories_const(output_directory)) {
-		case SCLD_OK:
-		case SCLD_EXISTS:
-			break;
-		default:
-			die(_("could not create leading directories "
-			      "of '%s'"), output_directory);
-		}
-		set_shared_repository(saved);
 		if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
 			die_errno(_("could not create directory '%s'"),
 				  output_directory);
@@ -1995,7 +1897,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	}
 
 	memset(&bases, 0, sizeof(bases));
-	if (base_commit) {
+	if (base_commit || base_auto) {
 		struct commit *base = get_base_commit(base_commit, list, nr);
 		reset_revision_walk();
 		clear_object_flags(UNINTERESTING);
diff --git a/third_party/git/builtin/ls-files.c b/third_party/git/builtin/ls-files.c
index f069a028ce..670e8fb93c 100644
--- a/third_party/git/builtin/ls-files.c
+++ b/third_party/git/builtin/ls-files.c
@@ -492,7 +492,7 @@ static int option_parse_exclude_from(const struct option *opt,
 	BUG_ON_OPT_NEG(unset);
 
 	exc_given = 1;
-	add_patterns_from_file(dir, arg);
+	add_excludes_from_file(dir, arg);
 
 	return 0;
 }
@@ -516,7 +516,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 	int require_work_tree = 0, show_tag = 0, i;
 	const char *max_prefix;
 	struct dir_struct dir;
-	struct pattern_list *pl;
+	struct exclude_list *el;
 	struct string_list exclude_list = STRING_LIST_INIT_NODUP;
 	struct option builtin_ls_files_options[] = {
 		/* Think twice before adding "--nul" synonym to this */
@@ -594,9 +594,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 
 	argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
 			ls_files_usage, 0);
-	pl = add_pattern_list(&dir, EXC_CMDL, "--exclude option");
+	el = add_exclude_list(&dir, EXC_CMDL, "--exclude option");
 	for (i = 0; i < exclude_list.nr; i++) {
-		add_pattern(exclude_list.items[i].string, "", 0, pl, --exclude_args);
+		add_exclude(exclude_list.items[i].string, "", 0, el, --exclude_args);
 	}
 	if (show_tag || show_valid_bit || show_fsmonitor_bit) {
 		tag_cached = "H ";
diff --git a/third_party/git/builtin/merge-recursive.c b/third_party/git/builtin/merge-recursive.c
index a4bfd8fc51..5b910e351e 100644
--- a/third_party/git/builtin/merge-recursive.c
+++ b/third_party/git/builtin/merge-recursive.c
@@ -1,4 +1,3 @@
-#include "cache.h"
 #include "builtin.h"
 #include "commit.h"
 #include "tag.h"
@@ -64,9 +63,6 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
 	if (argc - i != 3) /* "--" "<head>" "<remote>" */
 		die(_("not handling anything other than two heads merge."));
 
-	if (repo_read_index_unmerged(the_repository))
-		die_resolve_conflict("merge");
-
 	o.branch1 = argv[++i];
 	o.branch2 = argv[++i];
 
diff --git a/third_party/git/builtin/merge-tree.c b/third_party/git/builtin/merge-tree.c
index e72714a5a8..97b54caeb9 100644
--- a/third_party/git/builtin/merge-tree.c
+++ b/third_party/git/builtin/merge-tree.c
@@ -180,9 +180,8 @@ static struct merge_list *create_entry(unsigned stage, unsigned mode, const stru
 
 static char *traverse_path(const struct traverse_info *info, const struct name_entry *n)
 {
-	struct strbuf buf = STRBUF_INIT;
-	strbuf_make_traverse_path(&buf, info, n->path, n->pathlen);
-	return strbuf_detach(&buf, NULL);
+	char *path = xmallocz(traverse_path_len(info, n) + the_hash_algo->rawsz);
+	return make_traverse_path(path, info, n);
 }
 
 static void resolve(const struct traverse_info *info, struct name_entry *ours, struct name_entry *result)
diff --git a/third_party/git/builtin/merge.c b/third_party/git/builtin/merge.c
index d127d2225f..e2ccbc44e2 100644
--- a/third_party/git/builtin/merge.c
+++ b/third_party/git/builtin/merge.c
@@ -62,7 +62,6 @@ static int show_diffstat = 1, shortlog_len = -1, squash;
 static int option_commit = -1;
 static int option_edit = -1;
 static int allow_trivial = 1, have_message, verify_signatures;
-static int check_trust_level = 1;
 static int overwrite_ignore = 1;
 static struct strbuf merge_msg = STRBUF_INIT;
 static struct strategy **use_strategies;
@@ -82,7 +81,7 @@ static int show_progress = -1;
 static int default_to_upstream = 1;
 static int signoff;
 static const char *sign_commit;
-static int no_verify;
+static int verify_msg = 1;
 
 static struct strategy all_strategy[] = {
 	{ "recursive",  DEFAULT_TWOHEAD | NO_TRIVIAL },
@@ -288,7 +287,7 @@ static struct option builtin_merge_options[] = {
 	  N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
 	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")),
+	OPT_BOOL(0, "verify", &verify_msg, N_("verify commit-msg hook")),
 	OPT_END()
 };
 
@@ -632,8 +631,6 @@ static int git_merge_config(const char *k, const char *v, void *cb)
 	} else if (!strcmp(k, "commit.gpgsign")) {
 		sign_commit = git_config_bool(k, v) ? "" : NULL;
 		return 0;
-	} else if (!strcmp(k, "gpg.mintrustlevel")) {
-		check_trust_level = 0;
 	}
 
 	status = fmt_merge_msg_config(k, v, cb);
@@ -691,13 +688,16 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
 			      struct commit_list *remoteheads,
 			      struct commit *head)
 {
+	struct lock_file lock = LOCK_INIT;
 	const char *head_arg = "HEAD";
 
-	if (refresh_and_write_cache(REFRESH_QUIET, SKIP_IF_UNCHANGED, 0) < 0)
+	hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
+	refresh_cache(REFRESH_QUIET);
+	if (write_locked_index(&the_index, &lock,
+			       COMMIT_LOCK | SKIP_IF_UNCHANGED))
 		return error(_("Unable to write index."));
 
 	if (!strcmp(strategy, "recursive") || !strcmp(strategy, "subtree")) {
-		struct lock_file lock = LOCK_INIT;
 		int clean, x;
 		struct commit *result;
 		struct commit_list *reversed = NULL;
@@ -816,18 +816,6 @@ static void write_merge_heads(struct commit_list *);
 static void prepare_to_commit(struct commit_list *remoteheads)
 {
 	struct strbuf msg = STRBUF_INIT;
-	const char *index_file = get_index_file();
-
-	if (!no_verify && run_commit_hook(0 < option_edit, index_file, "pre-merge-commit", NULL))
-		abort_commit(remoteheads, NULL);
-	/*
-	 * Re-read the index as pre-merge-commit hook could have updated it,
-	 * and write it out as a tree.  We must do this before we invoke
-	 * the editor and after we invoke run_status above.
-	 */
-	if (find_hook("pre-merge-commit"))
-		discard_cache();
-	read_cache_from(index_file);
 	strbuf_addbuf(&msg, &merge_msg);
 	if (squash)
 		BUG("the control must not reach here under --squash");
@@ -854,7 +842,7 @@ static void prepare_to_commit(struct commit_list *remoteheads)
 			abort_commit(remoteheads, NULL);
 	}
 
-	if (!no_verify && run_commit_hook(0 < option_edit, get_index_file(),
+	if (verify_msg && run_commit_hook(0 < option_edit, get_index_file(),
 					  "commit-msg",
 					  git_path_merge_msg(the_repository), NULL))
 		abort_commit(remoteheads, NULL);
@@ -872,8 +860,12 @@ static int merge_trivial(struct commit *head, struct commit_list *remoteheads)
 {
 	struct object_id result_tree, result_commit;
 	struct commit_list *parents, **pptr = &parents;
+	struct lock_file lock = LOCK_INIT;
 
-	if (refresh_and_write_cache(REFRESH_QUIET, SKIP_IF_UNCHANGED, 0) < 0)
+	hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
+	refresh_cache(REFRESH_QUIET);
+	if (write_locked_index(&the_index, &lock,
+			       COMMIT_LOCK | SKIP_IF_UNCHANGED))
 		return error(_("Unable to write index."));
 
 	write_tree_trivial(&result_tree);
@@ -1400,8 +1392,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 			die(_("Can merge only exactly one commit into empty head"));
 
 		if (verify_signatures)
-			verify_merge_signature(remoteheads->item, verbosity,
-					       check_trust_level);
+			verify_merge_signature(remoteheads->item, verbosity);
 
 		remote_head_oid = &remoteheads->item->object.oid;
 		read_empty(remote_head_oid, 0);
@@ -1424,8 +1415,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 
 	if (verify_signatures) {
 		for (p = remoteheads; p; p = p->next) {
-			verify_merge_signature(p->item, verbosity,
-					       check_trust_level);
+			verify_merge_signature(p->item, verbosity);
 		}
 	}
 
diff --git a/third_party/git/builtin/mktag.c b/third_party/git/builtin/mktag.c
index 4982d3a93e..6fb7dc8578 100644
--- a/third_party/git/builtin/mktag.c
+++ b/third_party/git/builtin/mktag.c
@@ -29,11 +29,8 @@ static int verify_object(const struct object_id *oid, const char *expected_type)
 	const struct object_id *repl = lookup_replace_object(the_repository, oid);
 
 	if (buffer) {
-		if (type == type_from_string(expected_type)) {
-			ret = check_object_signature(the_repository, repl,
-						     buffer, size,
-						     expected_type);
-		}
+		if (type == type_from_string(expected_type))
+			ret = check_object_signature(repl, buffer, size, expected_type);
 		free(buffer);
 	}
 	return ret;
diff --git a/third_party/git/builtin/multi-pack-index.c b/third_party/git/builtin/multi-pack-index.c
index 5bf88cd2a8..b1ea1a6aa1 100644
--- a/third_party/git/builtin/multi-pack-index.c
+++ b/third_party/git/builtin/multi-pack-index.c
@@ -6,25 +6,21 @@
 #include "trace2.h"
 
 static char const * const builtin_multi_pack_index_usage[] = {
-	N_("git multi-pack-index [<options>] (write|verify|expire|repack --batch-size=<size>)"),
+	N_("git multi-pack-index [--object-dir=<dir>] (write|verify|expire|repack --batch-size=<size>)"),
 	NULL
 };
 
 static struct opts_multi_pack_index {
 	const char *object_dir;
 	unsigned long batch_size;
-	int progress;
 } opts;
 
 int cmd_multi_pack_index(int argc, const char **argv,
 			 const char *prefix)
 {
-	unsigned flags = 0;
-
 	static struct option builtin_multi_pack_index_options[] = {
 		OPT_FILENAME(0, "object-dir", &opts.object_dir,
 		  N_("object directory containing set of packfile and pack-index pairs")),
-		OPT_BOOL(0, "progress", &opts.progress, N_("force progress reporting")),
 		OPT_MAGNITUDE(0, "batch-size", &opts.batch_size,
 		  N_("during repack, collect pack-files of smaller size into a batch that is larger than this size")),
 		OPT_END(),
@@ -32,15 +28,12 @@ int cmd_multi_pack_index(int argc, const char **argv,
 
 	git_config(git_default_config, NULL);
 
-	opts.progress = isatty(2);
 	argc = parse_options(argc, argv, prefix,
 			     builtin_multi_pack_index_options,
 			     builtin_multi_pack_index_usage, 0);
 
 	if (!opts.object_dir)
 		opts.object_dir = get_object_directory();
-	if (opts.progress)
-		flags |= MIDX_PROGRESS;
 
 	if (argc == 0)
 		usage_with_options(builtin_multi_pack_index_usage,
@@ -54,17 +47,16 @@ int cmd_multi_pack_index(int argc, const char **argv,
 	trace2_cmd_mode(argv[0]);
 
 	if (!strcmp(argv[0], "repack"))
-		return midx_repack(the_repository, opts.object_dir,
-			(size_t)opts.batch_size, flags);
+		return midx_repack(the_repository, opts.object_dir, (size_t)opts.batch_size);
 	if (opts.batch_size)
 		die(_("--batch-size option is only for 'repack' subcommand"));
 
 	if (!strcmp(argv[0], "write"))
-		return write_midx_file(opts.object_dir, flags);
+		return write_midx_file(opts.object_dir);
 	if (!strcmp(argv[0], "verify"))
-		return verify_midx_file(the_repository, opts.object_dir, flags);
+		return verify_midx_file(the_repository, opts.object_dir);
 	if (!strcmp(argv[0], "expire"))
-		return expire_midx_packs(the_repository, opts.object_dir, flags);
+		return expire_midx_packs(the_repository, opts.object_dir);
 
 	die(_("unrecognized subcommand: %s"), argv[0]);
 }
diff --git a/third_party/git/builtin/name-rev.c b/third_party/git/builtin/name-rev.c
index a9dcd25e46..c785fe16ba 100644
--- a/third_party/git/builtin/name-rev.c
+++ b/third_party/git/builtin/name-rev.c
@@ -6,25 +6,20 @@
 #include "tag.h"
 #include "refs.h"
 #include "parse-options.h"
-#include "prio-queue.h"
 #include "sha1-lookup.h"
 #include "commit-slab.h"
 
-/*
- * One day.  See the 'name a rev shortly after epoch' test in t6120 when
- * changing this value
- */
-#define CUTOFF_DATE_SLOP 86400
+#define CUTOFF_DATE_SLOP 86400 /* one day */
 
-struct rev_name {
-	char *tip_name;
+typedef struct rev_name {
+	const char *tip_name;
 	timestamp_t taggerdate;
 	int generation;
 	int distance;
 	int from_tag;
-};
+} rev_name;
 
-define_commit_slab(commit_rev_name, struct rev_name);
+define_commit_slab(commit_rev_name, struct rev_name *);
 
 static timestamp_t cutoff = TIME_MAX;
 static struct commit_rev_name rev_names;
@@ -32,16 +27,16 @@ static struct commit_rev_name rev_names;
 /* How many generations are maximally preferred over _one_ merge traversal? */
 #define MERGE_TRAVERSAL_WEIGHT 65535
 
-static int is_valid_rev_name(const struct rev_name *name)
+static struct rev_name *get_commit_rev_name(struct commit *commit)
 {
-	return name && (name->generation || name->tip_name);
+	struct rev_name **slot = commit_rev_name_peek(&rev_names, commit);
+
+	return slot ? *slot : NULL;
 }
 
-static struct rev_name *get_commit_rev_name(const struct commit *commit)
+static void set_commit_rev_name(struct commit *commit, struct rev_name *name)
 {
-	struct rev_name *name = commit_rev_name_peek(&rev_names, commit);
-
-	return is_valid_rev_name(name) ? name : NULL;
+	*commit_rev_name_at(&rev_names, commit) = name;
 }
 
 static int is_better_name(struct rev_name *name,
@@ -80,135 +75,68 @@ static int is_better_name(struct rev_name *name,
 	return 0;
 }
 
-static struct rev_name *create_or_update_name(struct commit *commit,
-					      timestamp_t taggerdate,
-					      int generation, int distance,
-					      int from_tag)
-{
-	struct rev_name *name = commit_rev_name_at(&rev_names, commit);
-
-	if (is_valid_rev_name(name)) {
-		if (!is_better_name(name, taggerdate, distance, from_tag))
-			return NULL;
-
-		/*
-		 * This string might still be shared with ancestors
-		 * (generation > 0).  We can release it here regardless,
-		 * because the new name that has just won will be better
-		 * for them as well, so name_rev() will replace these
-		 * stale pointers when it processes the parents.
-		 */
-		if (!name->generation)
-			free(name->tip_name);
-	}
-
-	name->taggerdate = taggerdate;
-	name->generation = generation;
-	name->distance = distance;
-	name->from_tag = from_tag;
-
-	return name;
-}
-
-static char *get_parent_name(const struct rev_name *name, int parent_number)
-{
-	struct strbuf sb = STRBUF_INIT;
-	size_t len;
-
-	strip_suffix(name->tip_name, "^0", &len);
-	if (name->generation > 0) {
-		strbuf_grow(&sb, len +
-			    1 + decimal_width(name->generation) +
-			    1 + decimal_width(parent_number));
-		strbuf_addf(&sb, "%.*s~%d^%d", (int)len, name->tip_name,
-			    name->generation, parent_number);
-	} else {
-		strbuf_grow(&sb, len +
-			    1 + decimal_width(parent_number));
-		strbuf_addf(&sb, "%.*s^%d", (int)len, name->tip_name,
-			    parent_number);
-	}
-	return strbuf_detach(&sb, NULL);
-}
-
-static void name_rev(struct commit *start_commit,
+static void name_rev(struct commit *commit,
 		const char *tip_name, timestamp_t taggerdate,
-		int from_tag, int deref)
+		int generation, int distance, int from_tag,
+		int deref)
 {
-	struct prio_queue queue;
-	struct commit *commit;
-	struct commit **parents_to_queue = NULL;
-	size_t parents_to_queue_nr, parents_to_queue_alloc = 0;
-	struct rev_name *start_name;
-
-	parse_commit(start_commit);
-	if (start_commit->date < cutoff)
-		return;
+	struct rev_name *name = get_commit_rev_name(commit);
+	struct commit_list *parents;
+	int parent_number = 1;
+	char *to_free = NULL;
 
-	start_name = create_or_update_name(start_commit, taggerdate, 0, 0,
-					   from_tag);
-	if (!start_name)
-		return;
-	if (deref)
-		start_name->tip_name = xstrfmt("%s^0", tip_name);
-	else
-		start_name->tip_name = xstrdup(tip_name);
+	parse_commit(commit);
 
-	memset(&queue, 0, sizeof(queue)); /* Use the prio_queue as LIFO */
-	prio_queue_put(&queue, start_commit);
-
-	while ((commit = prio_queue_get(&queue))) {
-		struct rev_name *name = get_commit_rev_name(commit);
-		struct commit_list *parents;
-		int parent_number = 1;
-
-		parents_to_queue_nr = 0;
+	if (commit->date < cutoff)
+		return;
 
-		for (parents = commit->parents;
-				parents;
-				parents = parents->next, parent_number++) {
-			struct commit *parent = parents->item;
-			struct rev_name *parent_name;
-			int generation, distance;
+	if (deref) {
+		tip_name = to_free = xstrfmt("%s^0", tip_name);
 
-			parse_commit(parent);
-			if (parent->date < cutoff)
-				continue;
+		if (generation)
+			die("generation: %d, but deref?", generation);
+	}
 
-			if (parent_number > 1) {
-				generation = 0;
-				distance = name->distance + MERGE_TRAVERSAL_WEIGHT;
-			} else {
-				generation = name->generation + 1;
-				distance = name->distance + 1;
-			}
+	if (name == NULL) {
+		name = xmalloc(sizeof(rev_name));
+		set_commit_rev_name(commit, name);
+		goto copy_data;
+	} else if (is_better_name(name, taggerdate, distance, from_tag)) {
+copy_data:
+		name->tip_name = tip_name;
+		name->taggerdate = taggerdate;
+		name->generation = generation;
+		name->distance = distance;
+		name->from_tag = from_tag;
+	} else {
+		free(to_free);
+		return;
+	}
 
-			parent_name = create_or_update_name(parent, taggerdate,
-							    generation,
-							    distance, from_tag);
-			if (parent_name) {
-				if (parent_number > 1)
-					parent_name->tip_name =
-						get_parent_name(name,
-								parent_number);
-				else
-					parent_name->tip_name = name->tip_name;
-				ALLOC_GROW(parents_to_queue,
-					   parents_to_queue_nr + 1,
-					   parents_to_queue_alloc);
-				parents_to_queue[parents_to_queue_nr] = parent;
-				parents_to_queue_nr++;
-			}
+	for (parents = commit->parents;
+			parents;
+			parents = parents->next, parent_number++) {
+		if (parent_number > 1) {
+			size_t len;
+			char *new_name;
+
+			strip_suffix(tip_name, "^0", &len);
+			if (generation > 0)
+				new_name = xstrfmt("%.*s~%d^%d", (int)len, tip_name,
+						   generation, parent_number);
+			else
+				new_name = xstrfmt("%.*s^%d", (int)len, tip_name,
+						   parent_number);
+
+			name_rev(parents->item, new_name, taggerdate, 0,
+				 distance + MERGE_TRAVERSAL_WEIGHT,
+				 from_tag, 0);
+		} else {
+			name_rev(parents->item, tip_name, taggerdate,
+				 generation + 1, distance + 1,
+				 from_tag, 0);
 		}
-
-		/* The first parent must come out first from the prio_queue */
-		while (parents_to_queue_nr)
-			prio_queue_put(&queue,
-				       parents_to_queue[--parents_to_queue_nr]);
 	}
-
-	clear_prio_queue(&queue);
-	free(parents_to_queue);
 }
 
 static int subpath_matches(const char *path, const char *filter)
@@ -229,10 +157,10 @@ static const char *name_ref_abbrev(const char *refname, int shorten_unambiguous)
 {
 	if (shorten_unambiguous)
 		refname = shorten_unambiguous_ref(refname, 0);
-	else if (skip_prefix(refname, "refs/heads/", &refname))
-		; /* refname already advanced */
-	else
-		skip_prefix(refname, "refs/", &refname);
+	else if (starts_with(refname, "refs/heads/"))
+		refname = refname + 11;
+	else if (starts_with(refname, "refs/"))
+		refname = refname + 5;
 	return refname;
 }
 
@@ -247,10 +175,6 @@ static struct tip_table {
 	struct tip_table_entry {
 		struct object_id oid;
 		const char *refname;
-		struct commit *commit;
-		timestamp_t taggerdate;
-		unsigned int from_tag:1;
-		unsigned int deref:1;
 	} *table;
 	int nr;
 	int alloc;
@@ -258,18 +182,13 @@ static struct tip_table {
 } tip_table;
 
 static void add_to_tip_table(const struct object_id *oid, const char *refname,
-			     int shorten_unambiguous, struct commit *commit,
-			     timestamp_t taggerdate, int from_tag, int deref)
+			     int shorten_unambiguous)
 {
 	refname = name_ref_abbrev(refname, shorten_unambiguous);
 
 	ALLOC_GROW(tip_table.table, tip_table.nr + 1, tip_table.alloc);
 	oidcpy(&tip_table.table[tip_table.nr].oid, oid);
 	tip_table.table[tip_table.nr].refname = xstrdup(refname);
-	tip_table.table[tip_table.nr].commit = commit;
-	tip_table.table[tip_table.nr].taggerdate = taggerdate;
-	tip_table.table[tip_table.nr].from_tag = from_tag;
-	tip_table.table[tip_table.nr].deref = deref;
 	tip_table.nr++;
 	tip_table.sorted = 0;
 }
@@ -280,30 +199,12 @@ static int tipcmp(const void *a_, const void *b_)
 	return oidcmp(&a->oid, &b->oid);
 }
 
-static int cmp_by_tag_and_age(const void *a_, const void *b_)
-{
-	const struct tip_table_entry *a = a_, *b = b_;
-	int cmp;
-
-	/* Prefer tags. */
-	cmp = b->from_tag - a->from_tag;
-	if (cmp)
-		return cmp;
-
-	/* Older is better. */
-	if (a->taggerdate < b->taggerdate)
-		return -1;
-	return a->taggerdate != b->taggerdate;
-}
-
 static int name_ref(const char *path, const struct object_id *oid, int flags, void *cb_data)
 {
 	struct object *o = parse_object(the_repository, oid);
 	struct name_ref_data *data = cb_data;
 	int can_abbreviate_output = data->tags_only && data->name_only;
 	int deref = 0;
-	int from_tag = 0;
-	struct commit *commit = NULL;
 	timestamp_t taggerdate = TIME_MAX;
 
 	if (data->tags_only && !starts_with(path, "refs/tags/"))
@@ -352,6 +253,8 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo
 			return 0;
 	}
 
+	add_to_tip_table(oid, path, can_abbreviate_output);
+
 	while (o && o->type == OBJ_TAG) {
 		struct tag *t = (struct tag *) o;
 		if (!t->tagged)
@@ -361,33 +264,16 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo
 		taggerdate = t->date;
 	}
 	if (o && o->type == OBJ_COMMIT) {
-		commit = (struct commit *)o;
-		from_tag = starts_with(path, "refs/tags/");
-		if (taggerdate == TIME_MAX)
-			taggerdate = commit->date;
-	}
+		struct commit *commit = (struct commit *)o;
+		int from_tag = starts_with(path, "refs/tags/");
 
-	add_to_tip_table(oid, path, can_abbreviate_output, commit, taggerdate,
+		if (taggerdate == TIME_MAX)
+			taggerdate = ((struct commit *)o)->date;
+		path = name_ref_abbrev(path, can_abbreviate_output);
+		name_rev(commit, xstrdup(path), taggerdate, 0, 0,
 			 from_tag, deref);
-	return 0;
-}
-
-static void name_tips(void)
-{
-	int i;
-
-	/*
-	 * Try to set better names first, so that worse ones spread
-	 * less.
-	 */
-	QSORT(tip_table.table, tip_table.nr, cmp_by_tag_and_age);
-	for (i = 0; i < tip_table.nr; i++) {
-		struct tip_table_entry *e = &tip_table.table[i];
-		if (e->commit) {
-			name_rev(e->commit, e->refname, e->taggerdate,
-				 e->from_tag, e->deref);
-		}
 	}
+	return 0;
 }
 
 static const unsigned char *nth_tip_table_ent(size_t ix, void *table_)
@@ -419,11 +305,11 @@ static const char *get_exact_ref_match(const struct object *o)
 static const char *get_rev_name(const struct object *o, struct strbuf *buf)
 {
 	struct rev_name *n;
-	const struct commit *c;
+	struct commit *c;
 
 	if (o->type != OBJ_COMMIT)
 		return get_exact_ref_match(o);
-	c = (const struct commit *) o;
+	c = (struct commit *) o;
 	n = get_commit_rev_name(c);
 	if (!n)
 		return NULL;
@@ -431,10 +317,11 @@ static const char *get_rev_name(const struct object *o, struct strbuf *buf)
 	if (!n->generation)
 		return n->tip_name;
 	else {
+		int len = strlen(n->tip_name);
+		if (len > 2 && !strcmp(n->tip_name + len - 2, "^0"))
+			len -= 2;
 		strbuf_reset(buf);
-		strbuf_addstr(buf, n->tip_name);
-		strbuf_strip_suffix(buf, "^0");
-		strbuf_addf(buf, "~%d", n->generation);
+		strbuf_addf(buf, "%.*s~%d", len, n->tip_name, n->generation);
 		return buf->buf;
 	}
 }
@@ -594,15 +481,9 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
 		add_object_array(object, *argv, &revs);
 	}
 
-	if (cutoff) {
-		/* check for undeflow */
-		if (cutoff > TIME_MIN + CUTOFF_DATE_SLOP)
-			cutoff = cutoff - CUTOFF_DATE_SLOP;
-		else
-			cutoff = TIME_MIN;
-	}
+	if (cutoff)
+		cutoff = cutoff - CUTOFF_DATE_SLOP;
 	for_each_ref(name_ref, &data);
-	name_tips();
 
 	if (transform_stdin) {
 		char buffer[2048];
diff --git a/third_party/git/builtin/notes.c b/third_party/git/builtin/notes.c
index 35e468ea2d..02e97f55c5 100644
--- a/third_party/git/builtin/notes.c
+++ b/third_party/git/builtin/notes.c
@@ -513,7 +513,7 @@ static int copy(int argc, const char **argv, const char *prefix)
 		}
 	}
 
-	if (argc < 1) {
+	if (argc < 2) {
 		error(_("too few parameters"));
 		usage_with_options(git_notes_copy_usage, options);
 	}
@@ -622,7 +622,7 @@ static int append_edit(int argc, const char **argv, const char *prefix)
 
 		strbuf_grow(&d.buf, size + 1);
 		if (d.buf.len && prev_buf && size)
-			strbuf_insertstr(&d.buf, 0, "\n");
+			strbuf_insert(&d.buf, 0, "\n", 1);
 		if (prev_buf && size)
 			strbuf_insert(&d.buf, 0, prev_buf, size);
 		free(prev_buf);
@@ -745,7 +745,7 @@ static int merge_commit(struct notes_merge_options *o)
 	memset(&pretty_ctx, 0, sizeof(pretty_ctx));
 	format_commit_message(partial, "%s", &msg, &pretty_ctx);
 	strbuf_trim(&msg);
-	strbuf_insertstr(&msg, 0, "notes: ");
+	strbuf_insert(&msg, 0, "notes: ", 7);
 	update_ref(msg.buf, o->local_ref, &oid,
 		   is_null_oid(&parent_oid) ? NULL : &parent_oid,
 		   0, UPDATE_REFS_DIE_ON_ERR);
diff --git a/third_party/git/builtin/pack-objects.c b/third_party/git/builtin/pack-objects.c
index 02aa6ee480..76ce906946 100644
--- a/third_party/git/builtin/pack-objects.c
+++ b/third_party/git/builtin/pack-objects.c
@@ -92,11 +92,10 @@ static struct progress *progress_state;
 
 static struct packed_git *reuse_packfile;
 static uint32_t reuse_packfile_objects;
-static struct bitmap *reuse_packfile_bitmap;
+static off_t reuse_packfile_offset;
 
 static int use_bitmap_index_default = 1;
 static int use_bitmap_index = -1;
-static int allow_pack_reuse = 1;
 static enum {
 	WRITE_BITMAP_FALSE = 0,
 	WRITE_BITMAP_QUIET,
@@ -164,7 +163,7 @@ static void *get_delta(struct object_entry *entry)
 	delta_buf = diff_delta(base_buf, base_size,
 			       buf, size, &delta_size, 0);
 	/*
-	 * We successfully computed this delta once but dropped it for
+	 * We succesfully computed this delta once but dropped it for
 	 * memory reasons. Something is very wrong if this time we
 	 * recompute and create a different delta.
 	 */
@@ -304,8 +303,7 @@ static unsigned long write_no_reuse_object(struct hashfile *f, struct object_ent
 	if (!usable_delta) {
 		if (oe_type(entry) == OBJ_BLOB &&
 		    oe_size_greater_than(&to_pack, entry, big_file_threshold) &&
-		    (st = open_istream(the_repository, &entry->idx.oid, &type,
-				       &size, NULL)) != NULL)
+		    (st = open_istream(&entry->idx.oid, &type, &size, NULL)) != NULL)
 			buf = NULL;
 		else {
 			buf = read_object_file(&entry->idx.oid, &type, &size);
@@ -612,12 +610,12 @@ static int mark_tagged(const char *path, const struct object_id *oid, int flag,
 		       void *cb_data)
 {
 	struct object_id peeled;
-	struct object_entry *entry = packlist_find(&to_pack, oid);
+	struct object_entry *entry = packlist_find(&to_pack, oid, NULL);
 
 	if (entry)
 		entry->tagged = 1;
 	if (!peel_ref(path, &peeled)) {
-		entry = packlist_find(&to_pack, &peeled);
+		entry = packlist_find(&to_pack, &peeled, NULL);
 		if (entry)
 			entry->tagged = 1;
 	}
@@ -786,186 +784,57 @@ static struct object_entry **compute_write_order(void)
 	return wo;
 }
 
-
-/*
- * A reused set of objects. All objects in a chunk have the same
- * relative position in the original packfile and the generated
- * packfile.
- */
-
-static struct reused_chunk {
-	/* The offset of the first object of this chunk in the original
-	 * packfile. */
-	off_t original;
-	/* The offset of the first object of this chunk in the generated
-	 * packfile minus "original". */
-	off_t difference;
-} *reused_chunks;
-static int reused_chunks_nr;
-static int reused_chunks_alloc;
-
-static void record_reused_object(off_t where, off_t offset)
+static off_t write_reused_pack(struct hashfile *f)
 {
-	if (reused_chunks_nr && reused_chunks[reused_chunks_nr-1].difference == offset)
-		return;
+	unsigned char buffer[8192];
+	off_t to_write, total;
+	int fd;
 
-	ALLOC_GROW(reused_chunks, reused_chunks_nr + 1,
-		   reused_chunks_alloc);
-	reused_chunks[reused_chunks_nr].original = where;
-	reused_chunks[reused_chunks_nr].difference = offset;
-	reused_chunks_nr++;
-}
+	if (!is_pack_valid(reuse_packfile))
+		die(_("packfile is invalid: %s"), reuse_packfile->pack_name);
 
-/*
- * Binary search to find the chunk that "where" is in. Note
- * that we're not looking for an exact match, just the first
- * chunk that contains it (which implicitly ends at the start
- * of the next chunk.
- */
-static off_t find_reused_offset(off_t where)
-{
-	int lo = 0, hi = reused_chunks_nr;
-	while (lo < hi) {
-		int mi = lo + ((hi - lo) / 2);
-		if (where == reused_chunks[mi].original)
-			return reused_chunks[mi].difference;
-		if (where < reused_chunks[mi].original)
-			hi = mi;
-		else
-			lo = mi + 1;
-	}
+	fd = git_open(reuse_packfile->pack_name);
+	if (fd < 0)
+		die_errno(_("unable to open packfile for reuse: %s"),
+			  reuse_packfile->pack_name);
 
-	/*
-	 * The first chunk starts at zero, so we can't have gone below
-	 * there.
-	 */
-	assert(lo);
-	return reused_chunks[lo-1].difference;
-}
+	if (lseek(fd, sizeof(struct pack_header), SEEK_SET) == -1)
+		die_errno(_("unable to seek in reused packfile"));
 
-static void write_reused_pack_one(size_t pos, struct hashfile *out,
-				  struct pack_window **w_curs)
-{
-	off_t offset, next, cur;
-	enum object_type type;
-	unsigned long size;
+	if (reuse_packfile_offset < 0)
+		reuse_packfile_offset = reuse_packfile->pack_size - the_hash_algo->rawsz;
 
-	offset = reuse_packfile->revindex[pos].offset;
-	next = reuse_packfile->revindex[pos + 1].offset;
+	total = to_write = reuse_packfile_offset - sizeof(struct pack_header);
 
-	record_reused_object(offset, offset - hashfile_total(out));
+	while (to_write) {
+		int read_pack = xread(fd, buffer, sizeof(buffer));
 
-	cur = offset;
-	type = unpack_object_header(reuse_packfile, w_curs, &cur, &size);
-	assert(type >= 0);
+		if (read_pack <= 0)
+			die_errno(_("unable to read from reused packfile"));
 
-	if (type == OBJ_OFS_DELTA) {
-		off_t base_offset;
-		off_t fixup;
-
-		unsigned char header[MAX_PACK_OBJECT_HEADER];
-		unsigned len;
-
-		base_offset = get_delta_base(reuse_packfile, w_curs, &cur, type, offset);
-		assert(base_offset != 0);
-
-		/* Convert to REF_DELTA if we must... */
-		if (!allow_ofs_delta) {
-			int base_pos = find_revindex_position(reuse_packfile, base_offset);
-			struct object_id base_oid;
-
-			nth_packed_object_id(&base_oid, reuse_packfile,
-					     reuse_packfile->revindex[base_pos].nr);
-
-			len = encode_in_pack_object_header(header, sizeof(header),
-							   OBJ_REF_DELTA, size);
-			hashwrite(out, header, len);
-			hashwrite(out, base_oid.hash, 20);
-			copy_pack_data(out, reuse_packfile, w_curs, cur, next - cur);
-			return;
-		}
-
-		/* Otherwise see if we need to rewrite the offset... */
-		fixup = find_reused_offset(offset) -
-			find_reused_offset(base_offset);
-		if (fixup) {
-			unsigned char ofs_header[10];
-			unsigned i, ofs_len;
-			off_t ofs = offset - base_offset - fixup;
-
-			len = encode_in_pack_object_header(header, sizeof(header),
-							   OBJ_OFS_DELTA, size);
+		if (read_pack > to_write)
+			read_pack = to_write;
 
-			i = sizeof(ofs_header) - 1;
-			ofs_header[i] = ofs & 127;
-			while (ofs >>= 7)
-				ofs_header[--i] = 128 | (--ofs & 127);
-
-			ofs_len = sizeof(ofs_header) - i;
-
-			hashwrite(out, header, len);
-			hashwrite(out, ofs_header + sizeof(ofs_header) - ofs_len, ofs_len);
-			copy_pack_data(out, reuse_packfile, w_curs, cur, next - cur);
-			return;
-		}
-
-		/* ...otherwise we have no fixup, and can write it verbatim */
-	}
-
-	copy_pack_data(out, reuse_packfile, w_curs, offset, next - offset);
-}
-
-static size_t write_reused_pack_verbatim(struct hashfile *out,
-					 struct pack_window **w_curs)
-{
-	size_t pos = 0;
-
-	while (pos < reuse_packfile_bitmap->word_alloc &&
-			reuse_packfile_bitmap->words[pos] == (eword_t)~0)
-		pos++;
-
-	if (pos) {
-		off_t to_write;
-
-		written = (pos * BITS_IN_EWORD);
-		to_write = reuse_packfile->revindex[written].offset
-			- sizeof(struct pack_header);
-
-		/* We're recording one chunk, not one object. */
-		record_reused_object(sizeof(struct pack_header), 0);
-		hashflush(out);
-		copy_pack_data(out, reuse_packfile, w_curs,
-			sizeof(struct pack_header), to_write);
+		hashwrite(f, buffer, read_pack);
+		to_write -= read_pack;
 
+		/*
+		 * We don't know the actual number of objects written,
+		 * only how many bytes written, how many bytes total, and
+		 * how many objects total. So we can fake it by pretending all
+		 * objects we are writing are the same size. This gives us a
+		 * smooth progress meter, and at the end it matches the true
+		 * answer.
+		 */
+		written = reuse_packfile_objects *
+				(((double)(total - to_write)) / total);
 		display_progress(progress_state, written);
 	}
-	return pos;
-}
-
-static void write_reused_pack(struct hashfile *f)
-{
-	size_t i = 0;
-	uint32_t offset;
-	struct pack_window *w_curs = NULL;
-
-	if (allow_ofs_delta)
-		i = write_reused_pack_verbatim(f, &w_curs);
-
-	for (; i < reuse_packfile_bitmap->word_alloc; ++i) {
-		eword_t word = reuse_packfile_bitmap->words[i];
-		size_t pos = (i * BITS_IN_EWORD);
-
-		for (offset = 0; offset < BITS_IN_EWORD; ++offset) {
-			if ((word >> offset) == 0)
-				break;
-
-			offset += ewah_bit_ctz64(word >> offset);
-			write_reused_pack_one(pos + offset, f, &w_curs);
-			display_progress(progress_state, ++written);
-		}
-	}
 
-	unuse_pack(&w_curs);
+	close(fd);
+	written = reuse_packfile_objects;
+	display_progress(progress_state, written);
+	return reuse_packfile_offset - sizeof(struct pack_header);
 }
 
 static const char no_split_warning[] = N_(
@@ -998,9 +867,11 @@ static void write_pack_file(void)
 		offset = write_pack_header(f, nr_remaining);
 
 		if (reuse_packfile) {
+			off_t packfile_size;
 			assert(pack_to_stdout);
-			write_reused_pack(f);
-			offset = hashfile_total(f);
+
+			packfile_size = write_reused_pack(f);
+			offset += packfile_size;
 		}
 
 		nr_written = 0;
@@ -1125,15 +996,12 @@ static int no_try_delta(const char *path)
  * few lines later when we want to add the new entry.
  */
 static int have_duplicate_entry(const struct object_id *oid,
-				int exclude)
+				int exclude,
+				uint32_t *index_pos)
 {
 	struct object_entry *entry;
 
-	if (reuse_packfile_bitmap &&
-	    bitmap_walk_contains(bitmap_git, reuse_packfile_bitmap, oid))
-		return 1;
-
-	entry = packlist_find(&to_pack, oid);
+	entry = packlist_find(&to_pack, oid, index_pos);
 	if (!entry)
 		return 0;
 
@@ -1273,12 +1141,13 @@ static void create_object_entry(const struct object_id *oid,
 				uint32_t hash,
 				int exclude,
 				int no_try_delta,
+				uint32_t index_pos,
 				struct packed_git *found_pack,
 				off_t found_offset)
 {
 	struct object_entry *entry;
 
-	entry = packlist_alloc(&to_pack, oid);
+	entry = packlist_alloc(&to_pack, oid->hash, index_pos);
 	entry->hash = hash;
 	oe_set_type(entry, type);
 	if (exclude)
@@ -1302,10 +1171,11 @@ static int add_object_entry(const struct object_id *oid, enum object_type type,
 {
 	struct packed_git *found_pack = NULL;
 	off_t found_offset = 0;
+	uint32_t index_pos;
 
 	display_progress(progress_state, ++nr_seen);
 
-	if (have_duplicate_entry(oid, exclude))
+	if (have_duplicate_entry(oid, exclude, &index_pos))
 		return 0;
 
 	if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset)) {
@@ -1320,7 +1190,7 @@ static int add_object_entry(const struct object_id *oid, enum object_type type,
 
 	create_object_entry(oid, type, pack_name_hash(name),
 			    exclude, name && no_try_delta(name),
-			    found_pack, found_offset);
+			    index_pos, found_pack, found_offset);
 	return 1;
 }
 
@@ -1329,15 +1199,17 @@ static int add_object_entry_from_bitmap(const struct object_id *oid,
 					int flags, uint32_t name_hash,
 					struct packed_git *pack, off_t offset)
 {
+	uint32_t index_pos;
+
 	display_progress(progress_state, ++nr_seen);
 
-	if (have_duplicate_entry(oid, 0))
+	if (have_duplicate_entry(oid, 0, &index_pos))
 		return 0;
 
 	if (!want_object_in_pack(oid, 0, &pack, &offset))
 		return 0;
 
-	create_object_entry(oid, type, name_hash, 0, 0, pack, offset);
+	create_object_entry(oid, type, name_hash, 0, 0, index_pos, pack, offset);
 	return 1;
 }
 
@@ -1619,17 +1491,23 @@ static void cleanup_preferred_base(void)
  * deltify other objects against, in order to avoid
  * circular deltas.
  */
-static int can_reuse_delta(const struct object_id *base_oid,
+static int can_reuse_delta(const unsigned char *base_sha1,
 			   struct object_entry *delta,
 			   struct object_entry **base_out)
 {
 	struct object_entry *base;
+	struct object_id base_oid;
+
+	if (!base_sha1)
+		return 0;
+
+	oidread(&base_oid, base_sha1);
 
 	/*
 	 * First see if we're already sending the base (or it's explicitly in
 	 * our "excluded" list).
 	 */
-	base = packlist_find(&to_pack, base_oid);
+	base = packlist_find(&to_pack, &base_oid, NULL);
 	if (base) {
 		if (!in_same_island(&delta->idx.oid, &base->idx.oid))
 			return 0;
@@ -1642,9 +1520,9 @@ static int can_reuse_delta(const struct object_id *base_oid,
 	 * even if it was buried too deep in history to make it into the
 	 * packing list.
 	 */
-	if (thin && bitmap_has_oid_in_uninteresting(bitmap_git, base_oid)) {
+	if (thin && bitmap_has_oid_in_uninteresting(bitmap_git, &base_oid)) {
 		if (use_delta_islands) {
-			if (!in_same_island(&delta->idx.oid, base_oid))
+			if (!in_same_island(&delta->idx.oid, &base_oid))
 				return 0;
 		}
 		*base_out = NULL;
@@ -1661,8 +1539,7 @@ static void check_object(struct object_entry *entry)
 	if (IN_PACK(entry)) {
 		struct packed_git *p = IN_PACK(entry);
 		struct pack_window *w_curs = NULL;
-		int have_base = 0;
-		struct object_id base_ref;
+		const unsigned char *base_ref = NULL;
 		struct object_entry *base_entry;
 		unsigned long used, used_0;
 		unsigned long avail;
@@ -1703,13 +1580,9 @@ static void check_object(struct object_entry *entry)
 			unuse_pack(&w_curs);
 			return;
 		case OBJ_REF_DELTA:
-			if (reuse_delta && !entry->preferred_base) {
-				oidread(&base_ref,
-					use_pack(p, &w_curs,
-						 entry->in_pack_offset + used,
-						 NULL));
-				have_base = 1;
-			}
+			if (reuse_delta && !entry->preferred_base)
+				base_ref = use_pack(p, &w_curs,
+						entry->in_pack_offset + used, NULL);
 			entry->in_pack_header_size = used + the_hash_algo->rawsz;
 			break;
 		case OBJ_OFS_DELTA:
@@ -1739,15 +1612,13 @@ static void check_object(struct object_entry *entry)
 				revidx = find_pack_revindex(p, ofs);
 				if (!revidx)
 					goto give_up;
-				if (!nth_packed_object_id(&base_ref, p, revidx->nr))
-					have_base = 1;
+				base_ref = nth_packed_object_sha1(p, revidx->nr);
 			}
 			entry->in_pack_header_size = used + used_0;
 			break;
 		}
 
-		if (have_base &&
-		    can_reuse_delta(&base_ref, entry, &base_entry)) {
+		if (can_reuse_delta(base_ref, entry, &base_entry)) {
 			oe_set_type(entry, entry->in_pack_type);
 			SET_SIZE(entry, in_pack_size); /* delta size */
 			SET_DELTA_SIZE(entry, in_pack_size);
@@ -1757,7 +1628,7 @@ static void check_object(struct object_entry *entry)
 				entry->delta_sibling_idx = base_entry->delta_child_idx;
 				SET_DELTA_CHILD(base_entry, entry);
 			} else {
-				SET_DELTA_EXT(entry, &base_ref);
+				SET_DELTA_EXT(entry, base_ref);
 			}
 
 			unuse_pack(&w_curs);
@@ -2471,6 +2342,15 @@ static void find_deltas(struct object_entry **list, unsigned *list_size,
 	free(array);
 }
 
+static void try_to_free_from_threads(size_t size)
+{
+	packing_data_lock(&to_pack);
+	release_pack_memory(size);
+	packing_data_unlock(&to_pack);
+}
+
+static try_to_free_t old_try_to_free_routine;
+
 /*
  * The main object list is split into smaller lists, each is handed to
  * one worker.
@@ -2511,10 +2391,12 @@ static void init_threaded_search(void)
 	pthread_mutex_init(&cache_mutex, NULL);
 	pthread_mutex_init(&progress_mutex, NULL);
 	pthread_cond_init(&progress_cond, NULL);
+	old_try_to_free_routine = set_try_to_free_routine(try_to_free_from_threads);
 }
 
 static void cleanup_threaded_search(void)
 {
+	set_try_to_free_routine(old_try_to_free_routine);
 	pthread_cond_destroy(&progress_cond);
 	pthread_mutex_destroy(&cache_mutex);
 	pthread_mutex_destroy(&progress_mutex);
@@ -2686,13 +2568,6 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
 	free(p);
 }
 
-static int obj_is_packed(const struct object_id *oid)
-{
-	return packlist_find(&to_pack, oid) ||
-		(reuse_packfile_bitmap &&
-		 bitmap_walk_contains(bitmap_git, reuse_packfile_bitmap, oid));
-}
-
 static void add_tag_chain(const struct object_id *oid)
 {
 	struct tag *tag;
@@ -2704,7 +2579,7 @@ static void add_tag_chain(const struct object_id *oid)
 	 * it was included via bitmaps, we would not have parsed it
 	 * previously).
 	 */
-	if (obj_is_packed(oid))
+	if (packlist_find(&to_pack, oid, NULL))
 		return;
 
 	tag = lookup_tag(the_repository, oid);
@@ -2728,7 +2603,7 @@ static int add_ref_tag(const char *path, const struct object_id *oid, int flag,
 
 	if (starts_with(path, "refs/tags/") && /* is a tag? */
 	    !peel_ref(path, &peeled)    && /* peelable? */
-	    obj_is_packed(&peeled)) /* object packed? */
+	    packlist_find(&to_pack, &peeled, NULL))      /* object packed? */
 		add_tag_chain(oid);
 	return 0;
 }
@@ -2796,7 +2671,6 @@ static void prepare_pack(int window, int depth)
 
 	if (nr_deltas && n > 1) {
 		unsigned nr_done = 0;
-
 		if (progress)
 			progress_state = start_progress(_("Compressing objects"),
 							nr_deltas);
@@ -2841,8 +2715,8 @@ static int git_pack_config(const char *k, const char *v, void *cb)
 		use_bitmap_index_default = git_config_bool(k, v);
 		return 0;
 	}
-	if (!strcmp(k, "pack.allowpackreuse")) {
-		allow_pack_reuse = git_config_bool(k, v);
+	if (!strcmp(k, "pack.usesparse")) {
+		sparse = git_config_bool(k, v);
 		return 0;
 	}
 	if (!strcmp(k, "pack.threads")) {
@@ -2929,7 +2803,7 @@ static void show_object(struct object *obj, const char *name, void *data)
 		for (p = strchr(name, '/'); p; p = strchr(p + 1, '/'))
 			depth++;
 
-		ent = packlist_find(&to_pack, &obj->oid);
+		ent = packlist_find(&to_pack, &obj->oid, NULL);
 		if (ent && depth > oe_tree_depth(&to_pack, ent))
 			oe_set_tree_depth(&to_pack, ent, depth);
 	}
@@ -3055,7 +2929,7 @@ static void add_objects_in_unpacked_packs(void)
 			   in_pack.alloc);
 
 		for (i = 0; i < p->num_objects; i++) {
-			nth_packed_object_id(&oid, p, i);
+			nth_packed_object_oid(&oid, p, i);
 			o = lookup_unknown_object(&oid);
 			if (!(o->flags & OBJECT_ADDED))
 				mark_in_pack_object(o, p, &in_pack);
@@ -3159,8 +3033,8 @@ static void loosen_unused_packed_objects(void)
 			die(_("cannot open pack index"));
 
 		for (i = 0; i < p->num_objects; i++) {
-			nth_packed_object_id(&oid, p, i);
-			if (!packlist_find(&to_pack, &oid) &&
+			nth_packed_object_oid(&oid, p, i);
+			if (!packlist_find(&to_pack, &oid, NULL) &&
 			    !has_sha1_pack_kept_or_nonlocal(&oid) &&
 			    !loosened_object_can_be_discarded(&oid, p->mtime))
 				if (force_object_loose(&oid, p->mtime))
@@ -3176,8 +3050,8 @@ static void loosen_unused_packed_objects(void)
  */
 static int pack_options_allow_reuse(void)
 {
-	return allow_pack_reuse &&
-	       pack_to_stdout &&
+	return pack_to_stdout &&
+	       allow_ofs_delta &&
 	       !ignore_packed_keep_on_disk &&
 	       !ignore_packed_keep_in_core &&
 	       (!local || !have_non_local_packs) &&
@@ -3186,7 +3060,7 @@ static int pack_options_allow_reuse(void)
 
 static int get_object_list_from_bitmap(struct rev_info *revs)
 {
-	if (!(bitmap_git = prepare_bitmap_walk(revs, &filter_options)))
+	if (!(bitmap_git = prepare_bitmap_walk(revs)))
 		return -1;
 
 	if (pack_options_allow_reuse() &&
@@ -3194,14 +3068,13 @@ static int get_object_list_from_bitmap(struct rev_info *revs)
 			bitmap_git,
 			&reuse_packfile,
 			&reuse_packfile_objects,
-			&reuse_packfile_bitmap)) {
+			&reuse_packfile_offset)) {
 		assert(reuse_packfile_objects);
 		nr_result += reuse_packfile_objects;
 		display_progress(progress_state, nr_result);
 	}
 
-	traverse_bitmap_commit_list(bitmap_git, revs,
-				    &add_object_entry_from_bitmap);
+	traverse_bitmap_commit_list(bitmap_git, &add_object_entry_from_bitmap);
 	return 0;
 }
 
@@ -3470,10 +3343,6 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 	read_replace_refs = 0;
 
 	sparse = git_env_bool("GIT_TEST_PACK_SPARSE", 0);
-	prepare_repo_settings(the_repository);
-	if (!sparse && the_repository->settings.pack_use_sparse != -1)
-		sparse = the_repository->settings.pack_use_sparse;
-
 	reset_pack_idx_option(&pack_idx_opts);
 	git_config(git_pack_config, NULL);
 
@@ -3565,6 +3434,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 	if (filter_options.choice) {
 		if (!pack_to_stdout)
 			die(_("cannot use --filter without --stdout"));
+		use_bitmap_index = 0;
 	}
 
 	/*
@@ -3655,9 +3525,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 	if (progress)
 		fprintf_ln(stderr,
 			   _("Total %"PRIu32" (delta %"PRIu32"),"
-			     " reused %"PRIu32" (delta %"PRIu32"),"
-			     " pack-reused %"PRIu32),
-			   written, written_delta, reused, reused_delta,
-			   reuse_packfile_objects);
+			     " reused %"PRIu32" (delta %"PRIu32")"),
+			   written, written_delta, reused, reused_delta);
 	return 0;
 }
diff --git a/third_party/git/builtin/patch-id.c b/third_party/git/builtin/patch-id.c
index 822ffff51f..bd28b80b2d 100644
--- a/third_party/git/builtin/patch-id.c
+++ b/third_party/git/builtin/patch-id.c
@@ -1,12 +1,16 @@
-#include "cache.h"
 #include "builtin.h"
 #include "config.h"
 #include "diff.h"
 
 static void flush_current_id(int patchlen, struct object_id *id, struct object_id *result)
 {
-	if (patchlen)
-		printf("%s %s\n", oid_to_hex(result), oid_to_hex(id));
+	char name[50];
+
+	if (!patchlen)
+		return;
+
+	memcpy(name, oid_to_hex(id), GIT_SHA1_HEXSZ + 1);
+	printf("%s %s\n", oid_to_hex(result), name);
 }
 
 static int remove_space(char *line)
@@ -56,9 +60,9 @@ static int get_one_patchid(struct object_id *next_oid, struct object_id *result,
 {
 	int patchlen = 0, found_next = 0;
 	int before = -1, after = -1;
-	git_hash_ctx ctx;
+	git_SHA_CTX ctx;
 
-	the_hash_algo->init_fn(&ctx);
+	git_SHA1_Init(&ctx);
 	oidclr(result);
 
 	while (strbuf_getwholeline(line_buf, stdin, '\n') != EOF) {
@@ -118,7 +122,7 @@ static int get_one_patchid(struct object_id *next_oid, struct object_id *result,
 		/* Compute the sha without whitespace */
 		len = remove_space(line);
 		patchlen += len;
-		the_hash_algo->update_fn(&ctx, line, len);
+		git_SHA1_Update(&ctx, line, len);
 	}
 
 	if (!found_next)
diff --git a/third_party/git/builtin/pull.c b/third_party/git/builtin/pull.c
index 3e624d1e00..f1eaf6e6ed 100644
--- a/third_party/git/builtin/pull.c
+++ b/third_party/git/builtin/pull.c
@@ -15,7 +15,6 @@
 #include "sha1-array.h"
 #include "remote.h"
 #include "dir.h"
-#include "rebase.h"
 #include "refs.h"
 #include "refspec.h"
 #include "revision.h"
@@ -27,6 +26,15 @@
 #include "commit-reach.h"
 #include "sequencer.h"
 
+enum rebase_type {
+	REBASE_INVALID = -1,
+	REBASE_FALSE = 0,
+	REBASE_TRUE,
+	REBASE_PRESERVE,
+	REBASE_MERGES,
+	REBASE_INTERACTIVE
+};
+
 /**
  * Parses the value of --rebase. If value is a false value, returns
  * REBASE_FALSE. If value is a true value, returns REBASE_TRUE. If value is
@@ -37,9 +45,22 @@
 static enum rebase_type parse_config_rebase(const char *key, const char *value,
 		int fatal)
 {
-	enum rebase_type v = rebase_parse_value(value);
-	if (v != REBASE_INVALID)
-		return v;
+	int v = git_parse_maybe_bool(value);
+
+	if (!v)
+		return REBASE_FALSE;
+	else if (v > 0)
+		return REBASE_TRUE;
+	else if (!strcmp(value, "preserve") || !strcmp(value, "p"))
+		return REBASE_PRESERVE;
+	else if (!strcmp(value, "merges") || !strcmp(value, "m"))
+		return REBASE_MERGES;
+	else if (!strcmp(value, "interactive") || !strcmp(value, "i"))
+		return REBASE_INTERACTIVE;
+	/*
+	 * Please update _git_config() in git-completion.bash when you
+	 * add new rebase modes.
+	 */
 
 	if (fatal)
 		die(_("Invalid value for %s: %s"), key, value);
@@ -86,7 +107,6 @@ static char *opt_ff;
 static char *opt_verify_signatures;
 static int opt_autostash = -1;
 static int config_autostash;
-static int check_trust_level = 1;
 static struct argv_array opt_strategies = ARGV_ARRAY_INIT;
 static struct argv_array opt_strategy_opts = ARGV_ARRAY_INIT;
 static char *opt_gpg_sign;
@@ -109,7 +129,6 @@ static char *opt_refmap;
 static char *opt_ipv4;
 static char *opt_ipv6;
 static int opt_show_forced_updates = -1;
-static char *set_upstream;
 
 static struct option pull_options[] = {
 	/* Shared options */
@@ -224,9 +243,6 @@ static struct option pull_options[] = {
 		PARSE_OPT_NOARG),
 	OPT_BOOL(0, "show-forced-updates", &opt_show_forced_updates,
 		 N_("check for forced-updates on all updated branches")),
-	OPT_PASSTHRU(0, "set-upstream", &set_upstream, NULL,
-		N_("set upstream for git pull/fetch"),
-		PARSE_OPT_NOARG),
 
 	OPT_END()
 };
@@ -335,8 +351,6 @@ static enum rebase_type config_get_rebase(void)
  */
 static int git_pull_config(const char *var, const char *value, void *cb)
 {
-	int status;
-
 	if (!strcmp(var, "rebase.autostash")) {
 		config_autostash = git_config_bool(var, value);
 		return 0;
@@ -344,14 +358,7 @@ static int git_pull_config(const char *var, const char *value, void *cb)
 		recurse_submodules = git_config_bool(var, value) ?
 			RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF;
 		return 0;
-	} else if (!strcmp(var, "gpg.mintrustlevel")) {
-		check_trust_level = 0;
 	}
-
-	status = git_gpg_config(var, value, cb);
-	if (status)
-		return status;
-
 	return git_default_config(var, value, cb);
 }
 
@@ -549,8 +556,6 @@ static int run_fetch(const char *repo, const char **refspecs)
 		argv_array_push(&args, "--show-forced-updates");
 	else if (opt_show_forced_updates == 0)
 		argv_array_push(&args, "--no-show-forced-updates");
-	if (set_upstream)
-		argv_array_push(&args, set_upstream);
 
 	if (repo) {
 		argv_array_push(&args, repo);
@@ -576,8 +581,7 @@ static int pull_into_void(const struct object_id *merge_head,
 			die(_("unable to access commit %s"),
 			    oid_to_hex(merge_head));
 
-		verify_merge_signature(commit, opt_verbosity,
-				       check_trust_level);
+		verify_merge_signature(commit, opt_verbosity);
 	}
 
 	/*
diff --git a/third_party/git/builtin/push.c b/third_party/git/builtin/push.c
index 6dbf0f0bb7..021dd3b1e4 100644
--- a/third_party/git/builtin/push.c
+++ b/third_party/git/builtin/push.c
@@ -64,7 +64,6 @@ static struct string_list push_options_config = STRING_LIST_INIT_DUP;
 static const char *map_refspec(const char *ref,
 			       struct remote *remote, struct ref *local_refs)
 {
-	const char *branch_name;
 	struct ref *matched = NULL;
 
 	/* Does "ref" uniquely name our ref? */
@@ -85,8 +84,8 @@ static const char *map_refspec(const char *ref,
 	}
 
 	if (push_default == PUSH_DEFAULT_UPSTREAM &&
-	    skip_prefix(matched->name, "refs/heads/", &branch_name)) {
-		struct branch *branch = branch_get(branch_name);
+	    starts_with(matched->name, "refs/heads/")) {
+		struct branch *branch = branch_get(matched->name + 11);
 		if (branch->merge_nr == 1 && branch->merge[0]->src) {
 			struct strbuf buf = STRBUF_INIT;
 			strbuf_addf(&buf, "%s:%s",
@@ -144,8 +143,8 @@ static int push_url_of_remote(struct remote *remote, const char ***url_p)
 	return remote->url_nr;
 }
 
-static NORETURN void die_push_simple(struct branch *branch,
-				     struct remote *remote)
+static NORETURN int die_push_simple(struct branch *branch,
+				    struct remote *remote)
 {
 	/*
 	 * There's no point in using shorten_unambiguous_ref here,
@@ -358,10 +357,8 @@ static int push_with_options(struct transport *transport, struct refspec *rs,
 
 	if (verbosity > 0)
 		fprintf(stderr, _("Pushing to %s\n"), transport->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);
@@ -388,14 +385,30 @@ static int push_with_options(struct transport *transport, struct refspec *rs,
 }
 
 static int do_push(const char *repo, int flags,
-		   const struct string_list *push_options,
-		   struct remote *remote)
+		   const struct string_list *push_options)
 {
 	int i, errs;
+	struct remote *remote = pushremote_get(repo);
 	const char **url;
 	int url_nr;
 	struct refspec *push_refspec = &rs;
 
+	if (!remote) {
+		if (repo)
+			die(_("bad repository '%s'"), repo);
+		die(_("No configured push destination.\n"
+		    "Either specify the URL from the command-line or configure a remote repository using\n"
+		    "\n"
+		    "    git remote add <name> <url>\n"
+		    "\n"
+		    "and then push using the remote name\n"
+		    "\n"
+		    "    git push <name>\n"));
+	}
+
+	if (remote->mirror)
+		flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
+
 	if (push_options->nr)
 		flags |= TRANSPORT_PUSH_OPTIONS;
 
@@ -535,7 +548,6 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 	struct string_list push_options_cmdline = STRING_LIST_INIT_DUP;
 	struct string_list *push_options;
 	const struct string_list_item *item;
-	struct remote *remote;
 
 	struct option options[] = {
 		OPT__VERBOSITY(&verbosity),
@@ -590,6 +602,20 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 		die(_("--delete is incompatible with --all, --mirror and --tags"));
 	if (deleterefs && argc < 2)
 		die(_("--delete doesn't make sense without any refs"));
+	if (flags & TRANSPORT_PUSH_ALL) {
+		if (tags)
+			die(_("--all and --tags are incompatible"));
+		if (argc >= 2)
+			die(_("--all can't be combined with refspecs"));
+	}
+	if (flags & TRANSPORT_PUSH_MIRROR) {
+		if (tags)
+			die(_("--mirror and --tags are incompatible"));
+		if (argc >= 2)
+			die(_("--mirror can't be combined with refspecs"));
+	}
+	if ((flags & TRANSPORT_PUSH_ALL) && (flags & TRANSPORT_PUSH_MIRROR))
+		die(_("--all and --mirror are incompatible"));
 
 	if (recurse_submodules == RECURSE_SUBMODULES_CHECK)
 		flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK;
@@ -606,43 +632,11 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 		set_refspecs(argv + 1, argc - 1, repo);
 	}
 
-	remote = pushremote_get(repo);
-	if (!remote) {
-		if (repo)
-			die(_("bad repository '%s'"), repo);
-		die(_("No configured push destination.\n"
-		    "Either specify the URL from the command-line or configure a remote repository using\n"
-		    "\n"
-		    "    git remote add <name> <url>\n"
-		    "\n"
-		    "and then push using the remote name\n"
-		    "\n"
-		    "    git push <name>\n"));
-	}
-
-	if (remote->mirror)
-		flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
-
-	if (flags & TRANSPORT_PUSH_ALL) {
-		if (tags)
-			die(_("--all and --tags are incompatible"));
-		if (argc >= 2)
-			die(_("--all can't be combined with refspecs"));
-	}
-	if (flags & TRANSPORT_PUSH_MIRROR) {
-		if (tags)
-			die(_("--mirror and --tags are incompatible"));
-		if (argc >= 2)
-			die(_("--mirror can't be combined with refspecs"));
-	}
-	if ((flags & TRANSPORT_PUSH_ALL) && (flags & TRANSPORT_PUSH_MIRROR))
-		die(_("--all and --mirror are incompatible"));
-
 	for_each_string_list_item(item, push_options)
 		if (strchr(item->string, '\n'))
 			die(_("push options must not have new line characters"));
 
-	rc = do_push(repo, flags, push_options, remote);
+	rc = do_push(repo, flags, push_options);
 	string_list_clear(&push_options_cmdline, 0);
 	string_list_clear(&push_options_config, 0);
 	if (rc == -1)
diff --git a/third_party/git/builtin/range-diff.c b/third_party/git/builtin/range-diff.c
index d8a4670629..9202e75544 100644
--- a/third_party/git/builtin/range-diff.c
+++ b/third_party/git/builtin/range-diff.c
@@ -15,16 +15,12 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix)
 {
 	int creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT;
 	struct diff_options diffopt = { NULL };
-	struct argv_array other_arg = ARGV_ARRAY_INIT;
 	int simple_color = -1;
 	struct option range_diff_options[] = {
 		OPT_INTEGER(0, "creation-factor", &creation_factor,
 			    N_("Percentage by which creation is weighted")),
 		OPT_BOOL(0, "no-dual-color", &simple_color,
 			    N_("use simple diff colors")),
-		OPT_PASSTHRU_ARGV(0, "notes", &other_arg,
-				  N_("notes"), N_("passed to 'git log'"),
-				  PARSE_OPT_OPTARG),
 		OPT_END()
 	};
 	struct option *options;
@@ -82,9 +78,8 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix)
 	FREE_AND_NULL(options);
 
 	res = show_range_diff(range1.buf, range2.buf, creation_factor,
-			      simple_color < 1, &diffopt, &other_arg);
+			      simple_color < 1, &diffopt);
 
-	argv_array_clear(&other_arg);
 	strbuf_release(&range1);
 	strbuf_release(&range2);
 
diff --git a/third_party/git/builtin/read-tree.c b/third_party/git/builtin/read-tree.c
index af7424b94c..ca5e655d2f 100644
--- a/third_party/git/builtin/read-tree.c
+++ b/third_party/git/builtin/read-tree.c
@@ -185,7 +185,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
 
 	if (opts.reset || opts.merge || opts.prefix) {
 		if (read_cache_unmerged() && (opts.prefix || opts.merge))
-			die(_("You need to resolve your current index first"));
+			die("You need to resolve your current index first");
 		stage = opts.merge = 1;
 	}
 	resolve_undo_clear();
diff --git a/third_party/git/builtin/rebase.c b/third_party/git/builtin/rebase.c
index bff53d5d16..670096c065 100644
--- a/third_party/git/builtin/rebase.c
+++ b/third_party/git/builtin/rebase.c
@@ -29,8 +29,8 @@
 #include "rebase-interactive.h"
 
 static char const * const builtin_rebase_usage[] = {
-	N_("git rebase [-i] [options] [--exec <cmd>] "
-		"[--onto <newbase> | --keep-base] [<upstream> [<branch>]]"),
+	N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
+		"[<upstream>] [<branch>]"),
 	N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
 		"--root [<branch>]"),
 	N_("git rebase --continue | --abort | --skip | --edit-todo"),
@@ -44,22 +44,14 @@ static GIT_PATH_FUNC(merge_dir, "rebase-merge")
 
 enum rebase_type {
 	REBASE_UNSPECIFIED = -1,
-	REBASE_APPLY,
+	REBASE_AM,
 	REBASE_MERGE,
+	REBASE_INTERACTIVE,
 	REBASE_PRESERVE_MERGES
 };
 
-enum empty_type {
-	EMPTY_UNSPECIFIED = -1,
-	EMPTY_DROP,
-	EMPTY_KEEP,
-	EMPTY_ASK
-};
-
 struct rebase_options {
 	enum rebase_type type;
-	enum empty_type empty;
-	const char *default_backend;
 	const char *state_dir;
 	struct commit *upstream;
 	const char *upstream_name;
@@ -70,7 +62,7 @@ struct rebase_options {
 	const char *onto_name;
 	const char *revisions;
 	const char *switch_to;
-	int root, root_with_onto;
+	int root;
 	struct object_id *squash_onto;
 	struct commit *restrict_revision;
 	int dont_finish_rebase;
@@ -85,6 +77,7 @@ struct rebase_options {
 	const char *action;
 	int signoff;
 	int allow_rerere_autoupdate;
+	int keep_empty;
 	int autosquash;
 	char *gpg_sign_opt;
 	int autostash;
@@ -99,8 +92,6 @@ struct rebase_options {
 
 #define REBASE_OPTIONS_INIT {			  	\
 		.type = REBASE_UNSPECIFIED,	  	\
-		.empty = EMPTY_UNSPECIFIED,	  	\
-		.default_backend = "merge",	  	\
 		.flags = REBASE_NO_QUIET, 		\
 		.git_am_opts = ARGV_ARRAY_INIT,		\
 		.git_format_patch_opt = STRBUF_INIT	\
@@ -119,9 +110,6 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 		replay.allow_rerere_auto = opts->allow_rerere_autoupdate;
 	replay.allow_empty = 1;
 	replay.allow_empty_message = opts->allow_empty_message;
-	replay.drop_redundant_commits = (opts->empty == EMPTY_DROP);
-	replay.keep_redundant_commits = (opts->empty == EMPTY_KEEP);
-	replay.quiet = !(opts->flags & REBASE_NO_QUIET);
 	replay.verbose = opts->flags & REBASE_VERBOSE;
 	replay.reschedule_failed_exec = opts->reschedule_failed_exec;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
@@ -129,11 +117,6 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
 	if (opts->strategy_opts)
 		parse_strategy_opts(&replay, opts->strategy_opts);
 
-	if (opts->squash_onto) {
-		oidcpy(&replay.squash_onto, opts->squash_onto);
-		replay.have_squash_onto = 1;
-	}
-
 	return replay;
 }
 
@@ -258,17 +241,21 @@ static int edit_todo_file(unsigned flags)
 }
 
 static int get_revision_ranges(struct commit *upstream, struct commit *onto,
-			       struct object_id *orig_head, const char **head_hash,
+			       const char **head_hash,
 			       char **revisions, char **shortrevisions)
 {
 	struct commit *base_rev = upstream ? upstream : onto;
 	const char *shorthead;
+	struct object_id orig_head;
 
-	*head_hash = find_unique_abbrev(orig_head, GIT_MAX_HEXSZ);
+	if (get_oid("HEAD", &orig_head))
+		return error(_("no HEAD?"));
+
+	*head_hash = find_unique_abbrev(&orig_head, GIT_MAX_HEXSZ);
 	*revisions = xstrfmt("%s...%s", oid_to_hex(&base_rev->object.oid),
 						   *head_hash);
 
-	shorthead = find_unique_abbrev(orig_head, DEFAULT_ABBREV);
+	shorthead = find_unique_abbrev(&orig_head, DEFAULT_ABBREV);
 
 	if (upstream) {
 		const char *shortrev;
@@ -322,8 +309,12 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
 	struct replay_opts replay = get_replay_opts(opts);
 	struct string_list commands = STRING_LIST_INIT_DUP;
 
-	if (get_revision_ranges(opts->upstream, opts->onto, &opts->orig_head,
-				&head_hash, &revisions, &shortrevisions))
+	if (prepare_branch_to_be_rebased(the_repository, &replay,
+					 opts->switch_to))
+		return -1;
+
+	if (get_revision_ranges(opts->upstream, opts->onto, &head_hash,
+				&revisions, &shortrevisions))
 		return -1;
 
 	if (init_basic_state(&replay,
@@ -341,8 +332,8 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
 
 	argv_array_pushl(&make_script_args, "", revisions, NULL);
 	if (opts->restrict_revision)
-		argv_array_pushf(&make_script_args, "^%s",
-				 oid_to_hex(&opts->restrict_revision->object.oid));
+		argv_array_push(&make_script_args,
+				oid_to_hex(&opts->restrict_revision->object.oid));
 
 	ret = sequencer_make_script(the_repository, &todo_list.buf,
 				    make_script_args.argc, make_script_args.argv,
@@ -371,7 +362,7 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
 	return ret;
 }
 
-static int run_sequencer_rebase(struct rebase_options *opts,
+static int run_rebase_interactive(struct rebase_options *opts,
 				  enum action command)
 {
 	unsigned flags = 0;
@@ -379,10 +370,10 @@ static int run_sequencer_rebase(struct rebase_options *opts,
 
 	git_config_get_bool("rebase.abbreviatecommands", &abbreviate_commands);
 
+	flags |= opts->keep_empty ? TODO_LIST_KEEP_EMPTY : 0;
 	flags |= abbreviate_commands ? TODO_LIST_ABBREVIATE_CMDS : 0;
 	flags |= opts->rebase_merges ? TODO_LIST_REBASE_MERGES : 0;
 	flags |= opts->rebase_cousins > 0 ? TODO_LIST_REBASE_COUSINS : 0;
-	flags |= opts->root_with_onto ? TODO_LIST_ROOT_WITH_ONTO : 0;
 	flags |= command == ACTION_SHORTEN_OIDS ? TODO_LIST_SHORTEN_IDS : 0;
 
 	switch (command) {
@@ -442,21 +433,6 @@ static int run_sequencer_rebase(struct rebase_options *opts,
 	return ret;
 }
 
-static int parse_opt_keep_empty(const struct option *opt, const char *arg,
-				int unset)
-{
-	struct rebase_options *opts = opt->value;
-
-	BUG_ON_OPT_ARG(arg);
-
-	/*
-	 * If we ever want to remap --keep-empty to --empty=keep, insert:
-	 * 	opts->empty = unset ? EMPTY_UNSPECIFIED : EMPTY_KEEP;
-	 */
-	opts->type = REBASE_MERGE;
-	return 0;
-}
-
 static const char * const builtin_rebase_interactive_usage[] = {
 	N_("git rebase--interactive [<options>]"),
 	NULL
@@ -470,13 +446,9 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 	struct option options[] = {
 		OPT_NEGBIT(0, "ff", &opts.flags, N_("allow fast-forward"),
 			   REBASE_FORCE),
-		{ OPTION_CALLBACK, 'k', "keep-empty", &options, NULL,
-			N_("(DEPRECATED) keep empty commits"),
-			PARSE_OPT_NOARG | PARSE_OPT_HIDDEN,
-			parse_opt_keep_empty },
-		OPT_BOOL_F(0, "allow-empty-message", &opts.allow_empty_message,
-			   N_("allow commits with empty messages"),
-			   PARSE_OPT_HIDDEN),
+		OPT_BOOL(0, "keep-empty", &opts.keep_empty, N_("keep empty commits")),
+		OPT_BOOL(0, "allow-empty-message", &opts.allow_empty_message,
+			 N_("allow commits with empty messages")),
 		OPT_BOOL(0, "rebase-merges", &opts.rebase_merges, N_("rebase merge commits")),
 		OPT_BOOL(0, "rebase-cousins", &opts.rebase_cousins,
 			 N_("keep original branch points of cousins")),
@@ -546,26 +518,28 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
 		warning(_("--[no-]rebase-cousins has no effect without "
 			  "--rebase-merges"));
 
-	return !!run_sequencer_rebase(&opts, command);
+	return !!run_rebase_interactive(&opts, command);
 }
 
-static int is_merge(struct rebase_options *opts)
+static int is_interactive(struct rebase_options *opts)
 {
-	return opts->type == REBASE_MERGE ||
+	return opts->type == REBASE_INTERACTIVE ||
 		opts->type == REBASE_PRESERVE_MERGES;
 }
 
-static void imply_merge(struct rebase_options *opts, const char *option)
+static void imply_interactive(struct rebase_options *opts, const char *option)
 {
 	switch (opts->type) {
-	case REBASE_APPLY:
+	case REBASE_AM:
 		die(_("%s requires an interactive rebase"), option);
 		break;
-	case REBASE_MERGE:
+	case REBASE_INTERACTIVE:
 	case REBASE_PRESERVE_MERGES:
 		break;
+	case REBASE_MERGE:
+		/* we now implement --merge via --interactive */
 	default:
-		opts->type = REBASE_MERGE; /* implied */
+		opts->type = REBASE_INTERACTIVE; /* implied */
 		break;
 	}
 }
@@ -691,8 +665,8 @@ static int rebase_write_basic_state(struct rebase_options *opts)
 		   opts->onto ? oid_to_hex(&opts->onto->object.oid) : "");
 	write_file(state_dir_path("orig-head", opts), "%s",
 		   oid_to_hex(&opts->orig_head));
-	if (!(opts->flags & REBASE_NO_QUIET))
-		write_file(state_dir_path("quiet", opts), "%s", "");
+	write_file(state_dir_path("quiet", opts), "%s",
+		   opts->flags & REBASE_NO_QUIET ? "" : "t");
 	if (opts->flags & REBASE_VERBOSE)
 		write_file(state_dir_path("verbose", opts), "%s", "");
 	if (opts->strategy)
@@ -710,7 +684,7 @@ static int rebase_write_basic_state(struct rebase_options *opts)
 		write_file(state_dir_path("gpg_sign_opt", opts), "%s",
 			   opts->gpg_sign_opt);
 	if (opts->signoff)
-		write_file(state_dir_path("signoff", opts), "--signoff");
+		write_file(state_dir_path("strategy", opts), "--signoff");
 
 	return 0;
 }
@@ -774,7 +748,7 @@ static int finish_rebase(struct rebase_options *opts)
 	 * user should see them.
 	 */
 	run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
-	if (opts->type == REBASE_MERGE) {
+	if (opts->type == REBASE_INTERACTIVE) {
 		struct replay_opts replay = REPLAY_OPTS_INIT;
 
 		replay.action = REPLAY_INTERACTIVE_REBASE;
@@ -1037,8 +1011,7 @@ static int run_am(struct rebase_options *opts)
 	argv_array_pushl(&format_patch.args, "format-patch", "-k", "--stdout",
 			 "--full-index", "--cherry-pick", "--right-only",
 			 "--src-prefix=a/", "--dst-prefix=b/", "--no-renames",
-			 "--no-cover-letter", "--pretty=mboxrd", "--topo-order",
-			 "--no-base", NULL);
+			 "--no-cover-letter", "--pretty=mboxrd", "--topo-order", NULL);
 	if (opts->git_format_patch_opt.len)
 		argv_array_split(&format_patch.args,
 				 opts->git_format_patch_opt.buf);
@@ -1107,8 +1080,8 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action)
 	int status;
 	const char *backend, *backend_func;
 
-	if (opts->type == REBASE_MERGE) {
-		/* Run sequencer-based rebase */
+	if (opts->type == REBASE_INTERACTIVE) {
+		/* Run builtin interactive rebase */
 		setenv("GIT_CHERRY_PICK_HELP", resolvemsg, 1);
 		if (!(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) {
 			setenv("GIT_SEQUENCE_EDITOR", ":", 1);
@@ -1121,11 +1094,11 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action)
 			opts->gpg_sign_opt = tmp;
 		}
 
-		status = run_sequencer_rebase(opts, action);
+		status = run_rebase_interactive(opts, action);
 		goto finished_rebase;
 	}
 
-	if (opts->type == REBASE_APPLY) {
+	if (opts->type == REBASE_AM) {
 		status = run_am(opts);
 		goto finished_rebase;
 	}
@@ -1145,6 +1118,8 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action)
 	add_var(&script_snippet, "revisions", opts->revisions);
 	add_var(&script_snippet, "restrict_revision", opts->restrict_revision ?
 		oid_to_hex(&opts->restrict_revision->object.oid) : NULL);
+	add_var(&script_snippet, "GIT_QUIET",
+		opts->flags & REBASE_NO_QUIET ? "" : "t");
 	sq_quote_argv_pretty(&buf, opts->git_am_opts.argv);
 	add_var(&script_snippet, "git_am_opt", buf.buf);
 	strbuf_release(&buf);
@@ -1162,6 +1137,7 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action)
 		opts->allow_rerere_autoupdate ?
 			opts->allow_rerere_autoupdate == RERERE_AUTOUPDATE ?
 			"--rerere-autoupdate" : "--no-rerere-autoupdate" : "");
+	add_var(&script_snippet, "keep_empty", opts->keep_empty ? "yes" : "");
 	add_var(&script_snippet, "autosquash", opts->autosquash ? "t" : "");
 	add_var(&script_snippet, "gpg_sign_opt", opts->gpg_sign_opt);
 	add_var(&script_snippet, "cmd", opts->cmd);
@@ -1179,7 +1155,7 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action)
 	add_var(&script_snippet, "git_format_patch_opt",
 		opts->git_format_patch_opt.buf);
 
-	if (is_merge(opts) &&
+	if (is_interactive(opts) &&
 	    !(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) {
 		strbuf_addstr(&script_snippet,
 			      "GIT_SEQUENCE_EDITOR=:; export GIT_SEQUENCE_EDITOR; ");
@@ -1204,8 +1180,8 @@ static int run_specific_rebase(struct rebase_options *opts, enum action action)
 finished_rebase:
 	if (opts->dont_finish_rebase)
 		; /* do nothing */
-	else if (opts->type == REBASE_MERGE)
-		; /* merge backend cleans up after itself */
+	else if (opts->type == REBASE_INTERACTIVE)
+		; /* interactive rebase cleans up after itself */
 	else if (status == 0) {
 		if (!file_exists(state_dir_path("stopped-sha", opts)))
 			finish_rebase(opts);
@@ -1263,10 +1239,6 @@ static int rebase_config(const char *var, const char *value, void *data)
 		return 0;
 	}
 
-	if (!strcmp(var, "rebase.backend")) {
-		return git_config_string(&opts->default_backend, var, value);
-	}
-
 	return git_default_config(var, value, data);
 }
 
@@ -1288,60 +1260,28 @@ static int is_linear_history(struct commit *from, struct commit *to)
 	return 1;
 }
 
-static int can_fast_forward(struct commit *onto, struct commit *upstream,
-			    struct commit *restrict_revision,
-			    struct object_id *head_oid, struct object_id *merge_base)
+static int can_fast_forward(struct commit *onto, struct object_id *head_oid,
+			    struct object_id *merge_base)
 {
 	struct commit *head = lookup_commit(the_repository, head_oid);
-	struct commit_list *merge_bases = NULL;
-	int res = 0;
+	struct commit_list *merge_bases;
+	int res;
 
 	if (!head)
-		goto done;
+		return 0;
 
 	merge_bases = get_merge_bases(onto, head);
-	if (!merge_bases || merge_bases->next) {
+	if (merge_bases && !merge_bases->next) {
+		oidcpy(merge_base, &merge_bases->item->object.oid);
+		res = oideq(merge_base, &onto->object.oid);
+	} else {
 		oidcpy(merge_base, &null_oid);
-		goto done;
+		res = 0;
 	}
-
-	oidcpy(merge_base, &merge_bases->item->object.oid);
-	if (!oideq(merge_base, &onto->object.oid))
-		goto done;
-
-	if (restrict_revision && !oideq(&restrict_revision->object.oid, merge_base))
-		goto done;
-
-	if (!upstream)
-		goto done;
-
-	free_commit_list(merge_bases);
-	merge_bases = get_merge_bases(upstream, head);
-	if (!merge_bases || merge_bases->next)
-		goto done;
-
-	if (!oideq(&onto->object.oid, &merge_bases->item->object.oid))
-		goto done;
-
-	res = 1;
-
-done:
 	free_commit_list(merge_bases);
 	return res && is_linear_history(onto, head);
 }
 
-static int parse_opt_am(const struct option *opt, const char *arg, int unset)
-{
-	struct rebase_options *opts = opt->value;
-
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-
-	opts->type = REBASE_APPLY;
-
-	return 0;
-}
-
 /* -i followed by -m is still -i */
 static int parse_opt_merge(const struct option *opt, const char *arg, int unset)
 {
@@ -1350,7 +1290,7 @@ static int parse_opt_merge(const struct option *opt, const char *arg, int unset)
 	BUG_ON_OPT_NEG(unset);
 	BUG_ON_OPT_ARG(arg);
 
-	if (!is_merge(opts))
+	if (!is_interactive(opts))
 		opts->type = REBASE_MERGE;
 
 	return 0;
@@ -1365,35 +1305,12 @@ static int parse_opt_interactive(const struct option *opt, const char *arg,
 	BUG_ON_OPT_NEG(unset);
 	BUG_ON_OPT_ARG(arg);
 
-	opts->type = REBASE_MERGE;
+	opts->type = REBASE_INTERACTIVE;
 	opts->flags |= REBASE_INTERACTIVE_EXPLICIT;
 
 	return 0;
 }
 
-static enum empty_type parse_empty_value(const char *value)
-{
-	if (!strcasecmp(value, "drop"))
-		return EMPTY_DROP;
-	else if (!strcasecmp(value, "keep"))
-		return EMPTY_KEEP;
-	else if (!strcasecmp(value, "ask"))
-		return EMPTY_ASK;
-
-	die(_("unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and \"ask\"."), value);
-}
-
-static int parse_opt_empty(const struct option *opt, const char *arg, int unset)
-{
-	struct rebase_options *options = opt->value;
-	enum empty_type value = parse_empty_value(arg);
-
-	BUG_ON_OPT_NEG(unset);
-
-	options->empty = value;
-	return 0;
-}
-
 static void NORETURN error_on_missing_default_upstream(void)
 {
 	struct branch *current_branch = branch_get(NULL);
@@ -1429,14 +1346,14 @@ static void set_reflog_action(struct rebase_options *options)
 	const char *env;
 	struct strbuf buf = STRBUF_INIT;
 
-	if (!is_merge(options))
+	if (!is_interactive(options))
 		return;
 
 	env = getenv(GIT_REFLOG_ACTION_ENVIRONMENT);
 	if (env && strcmp("rebase", env))
 		return; /* only override it if it is "rebase" */
 
-	strbuf_addf(&buf, "rebase (%s)", options->action);
+	strbuf_addf(&buf, "rebase -i (%s)", options->action);
 	setenv(GIT_REFLOG_ACTION_ENVIRONMENT, buf.buf, 1);
 	strbuf_release(&buf);
 }
@@ -1459,7 +1376,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	struct rebase_options options = REBASE_OPTIONS_INIT;
 	const char *branch_name;
 	int ret, flags, total_argc, in_progress = 0;
-	int keep_base = 0;
 	int ok_to_skip_pre_rebase = 0;
 	struct strbuf msg = STRBUF_INIT;
 	struct strbuf revisions = STRBUF_INIT;
@@ -1474,18 +1390,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	struct object_id squash_onto;
 	char *squash_onto_name = NULL;
 	int reschedule_failed_exec = -1;
-	int allow_preemptive_ff = 1;
 	struct option builtin_rebase_options[] = {
 		OPT_STRING(0, "onto", &options.onto_name,
 			   N_("revision"),
 			   N_("rebase onto given branch instead of upstream")),
-		OPT_BOOL(0, "keep-base", &keep_base,
-			 N_("use the merge-base of upstream and branch as the current base")),
 		OPT_BOOL(0, "no-verify", &ok_to_skip_pre_rebase,
 			 N_("allow pre-rebase hook to run")),
 		OPT_NEGBIT('q', "quiet", &options.flags,
 			   N_("be quiet. implies --no-stat"),
-			   REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT),
+			   REBASE_NO_QUIET| REBASE_VERBOSE | REBASE_DIFFSTAT),
 		OPT_BIT('v', "verbose", &options.flags,
 			N_("display a diffstat of what changed upstream"),
 			REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT),
@@ -1526,10 +1439,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		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,
-			N_("use apply strategies to rebase"),
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG,
-			parse_opt_am },
 		{ OPTION_CALLBACK, 'm', "merge", &options, NULL,
 			N_("use merging strategies to rebase"),
 			PARSE_OPT_NOARG | PARSE_OPT_NONEG,
@@ -1538,18 +1447,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			N_("let the user edit the list of commits to rebase"),
 			PARSE_OPT_NOARG | PARSE_OPT_NONEG,
 			parse_opt_interactive },
-		OPT_SET_INT_F('p', "preserve-merges", &options.type,
-			      N_("(DEPRECATED) try to recreate merges instead of "
-				 "ignoring them"),
-			      REBASE_PRESERVE_MERGES, PARSE_OPT_HIDDEN),
+		OPT_SET_INT('p', "preserve-merges", &options.type,
+			    N_("(DEPRECATED) try to recreate merges instead of "
+			       "ignoring them"), REBASE_PRESERVE_MERGES),
 		OPT_RERERE_AUTOUPDATE(&options.allow_rerere_autoupdate),
-		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,
-			N_("(DEPRECATED) keep empty commits"),
-			PARSE_OPT_NOARG | PARSE_OPT_HIDDEN,
-			parse_opt_keep_empty },
+		OPT_BOOL('k', "keep-empty", &options.keep_empty,
+			 N_("preserve empty commits during rebase")),
 		OPT_BOOL(0, "autosquash", &options.autosquash,
 			 N_("move commits that begin with "
 			    "squash!/fixup! under -i")),
@@ -1561,10 +1464,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		OPT_STRING_LIST('x', "exec", &exec, N_("exec"),
 				N_("add exec lines after each commit of the "
 				   "editable list")),
-		OPT_BOOL_F(0, "allow-empty-message",
-			   &options.allow_empty_message,
-			   N_("allow rebasing commits with empty messages"),
-			   PARSE_OPT_HIDDEN),
+		OPT_BOOL(0, "allow-empty-message",
+			 &options.allow_empty_message,
+			 N_("allow rebasing commits with empty messages")),
 		{OPTION_STRING, 'r', "rebase-merges", &rebase_merges,
 			N_("mode"),
 			N_("try to rebase merges instead of skipping them"),
@@ -1604,7 +1506,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		die(_("It looks like 'git am' is in progress. Cannot rebase."));
 
 	if (is_directory(apply_dir())) {
-		options.type = REBASE_APPLY;
+		options.type = REBASE_AM;
 		options.state_dir = apply_dir();
 	} else if (is_directory(merge_dir())) {
 		strbuf_reset(&buf);
@@ -1616,7 +1518,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			strbuf_reset(&buf);
 			strbuf_addf(&buf, "%s/interactive", merge_dir());
 			if(file_exists(buf.buf)) {
-				options.type = REBASE_MERGE;
+				options.type = REBASE_INTERACTIVE;
 				options.flags |= REBASE_INTERACTIVE_EXPLICIT;
 			} else
 				options.type = REBASE_MERGE;
@@ -1645,23 +1547,16 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		warning(_("git rebase --preserve-merges is deprecated. "
 			  "Use --rebase-merges instead."));
 
-	if (keep_base) {
-		if (options.onto_name)
-			die(_("cannot combine '--keep-base' with '--onto'"));
-		if (options.root)
-			die(_("cannot combine '--keep-base' with '--root'"));
-	}
-
 	if (action != ACTION_NONE && !in_progress)
 		die(_("No rebase in progress?"));
 	setenv(GIT_REFLOG_ACTION_ENVIRONMENT, "rebase", 0);
 
-	if (action == ACTION_EDIT_TODO && !is_merge(&options))
+	if (action == ACTION_EDIT_TODO && !is_interactive(&options))
 		die(_("The --edit-todo action can only be used during "
 		      "interactive rebase."));
 
 	if (trace2_is_enabled()) {
-		if (is_merge(&options))
+		if (is_interactive(&options))
 			trace2_cmd_mode("interactive");
 		else if (exec.nr)
 			trace2_cmd_mode("interactive-exec");
@@ -1737,7 +1632,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		goto cleanup;
 	}
 	case ACTION_QUIT: {
-		if (options.type == REBASE_MERGE) {
+		if (options.type == REBASE_INTERACTIVE) {
 			struct replay_opts replay = REPLAY_OPTS_INIT;
 
 			replay.action = REPLAY_INTERACTIVE_REBASE;
@@ -1786,20 +1681,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		    state_dir_base, cmd_live_rebase, buf.buf);
 	}
 
-	if ((options.flags & REBASE_INTERACTIVE_EXPLICIT) ||
-	    (action != ACTION_NONE) ||
-	    (exec.nr > 0) ||
-	    options.autosquash) {
-		allow_preemptive_ff = 0;
-	}
-
 	for (i = 0; i < options.git_am_opts.argc; i++) {
 		const char *option = options.git_am_opts.argv[i], *p;
 		if (!strcmp(option, "--committer-date-is-author-date") ||
 		    !strcmp(option, "--ignore-date") ||
 		    !strcmp(option, "--whitespace=fix") ||
 		    !strcmp(option, "--whitespace=strip"))
-			allow_preemptive_ff = 0;
+			options.flags |= REBASE_FORCE;
 		else if (skip_prefix(option, "-C", &p)) {
 			while (*p)
 				if (!isdigit(*(p++)))
@@ -1819,8 +1707,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	if (!(options.flags & REBASE_NO_QUIET))
 		argv_array_push(&options.git_am_opts, "-q");
 
-	if (options.empty != EMPTY_UNSPECIFIED)
-		imply_merge(&options, "--empty");
+	if (options.keep_empty)
+		imply_interactive(&options, "--keep-empty");
 
 	if (gpg_sign) {
 		free(options.gpg_sign_opt);
@@ -1830,7 +1718,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	if (exec.nr) {
 		int i;
 
-		imply_merge(&options, "--exec");
+		imply_interactive(&options, "--exec");
 
 		strbuf_reset(&buf);
 		for (i = 0; i < exec.nr; i++)
@@ -1846,7 +1734,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		else if (strcmp("no-rebase-cousins", rebase_merges))
 			die(_("Unknown mode: %s"), rebase_merges);
 		options.rebase_merges = 1;
-		imply_merge(&options, "--rebase-merges");
+		imply_interactive(&options, "--rebase-merges");
 	}
 
 	if (strategy_options.nr) {
@@ -1865,9 +1753,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	if (options.strategy) {
 		options.strategy = xstrdup(options.strategy);
 		switch (options.type) {
-		case REBASE_APPLY:
+		case REBASE_AM:
 			die(_("--strategy requires --merge or --interactive"));
 		case REBASE_MERGE:
+		case REBASE_INTERACTIVE:
 		case REBASE_PRESERVE_MERGES:
 			/* compatible */
 			break;
@@ -1880,65 +1769,47 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	}
 
 	if (options.type == REBASE_MERGE)
-		imply_merge(&options, "--merge");
+		imply_interactive(&options, "--merge");
 
 	if (options.root && !options.onto_name)
-		imply_merge(&options, "--root without --onto");
+		imply_interactive(&options, "--root without --onto");
 
 	if (isatty(2) && options.flags & REBASE_NO_QUIET)
 		strbuf_addstr(&options.git_format_patch_opt, " --progress");
 
-	if (options.git_am_opts.argc || options.type == REBASE_APPLY) {
-		/* all am options except -q are compatible only with --apply */
-		for (i = options.git_am_opts.argc - 1; i >= 0; i--)
-			if (strcmp(options.git_am_opts.argv[i], "-q"))
-				break;
-
-		if (i >= 0) {
-			if (is_merge(&options))
-				die(_("cannot combine apply options with "
-				      "merge options"));
-			else
-				options.type = REBASE_APPLY;
-		}
-	}
-
-	if (options.type == REBASE_UNSPECIFIED) {
-		if (!strcmp(options.default_backend, "merge"))
-			imply_merge(&options, "--merge");
-		else if (!strcmp(options.default_backend, "apply"))
-			options.type = REBASE_APPLY;
-		else
-			die(_("Unknown rebase backend: %s"),
-			    options.default_backend);
-	}
-
 	switch (options.type) {
 	case REBASE_MERGE:
+	case REBASE_INTERACTIVE:
 	case REBASE_PRESERVE_MERGES:
 		options.state_dir = merge_dir();
 		break;
-	case REBASE_APPLY:
+	case REBASE_AM:
 		options.state_dir = apply_dir();
 		break;
 	default:
-		BUG("options.type was just set above; should be unreachable.");
+		/* the default rebase backend is `--am` */
+		options.type = REBASE_AM;
+		options.state_dir = apply_dir();
+		break;
 	}
 
-	if (options.empty == EMPTY_UNSPECIFIED) {
-		if (options.flags & REBASE_INTERACTIVE_EXPLICIT)
-			options.empty = EMPTY_ASK;
-		else if (exec.nr > 0)
-			options.empty = EMPTY_KEEP;
-		else
-			options.empty = EMPTY_DROP;
-	}
-	if (reschedule_failed_exec > 0 && !is_merge(&options))
+	if (reschedule_failed_exec > 0 && !is_interactive(&options))
 		die(_("--reschedule-failed-exec requires "
 		      "--exec or --interactive"));
 	if (reschedule_failed_exec >= 0)
 		options.reschedule_failed_exec = reschedule_failed_exec;
 
+	if (options.git_am_opts.argc) {
+		/* all am options except -q are compatible only with --am */
+		for (i = options.git_am_opts.argc - 1; i >= 0; i--)
+			if (strcmp(options.git_am_opts.argv[i], "-q"))
+				break;
+
+		if (is_interactive(&options) && i >= 0)
+			die(_("cannot combine am options with either "
+			      "interactive or merge options"));
+	}
+
 	if (options.signoff) {
 		if (options.type == REBASE_PRESERVE_MERGES)
 			die("cannot combine '--signoff' with "
@@ -1962,6 +1833,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			      "'--reschedule-failed-exec'"));
 	}
 
+	if (options.rebase_merges) {
+		if (strategy_options.nr)
+			die(_("cannot combine '--rebase-merges' with "
+			      "'--strategy-option'"));
+		if (options.strategy)
+			die(_("cannot combine '--rebase-merges' with "
+			      "'--strategy'"));
+	}
+
 	if (!options.root) {
 		if (argc < 1) {
 			struct branch *branch;
@@ -1992,9 +1872,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 			options.squash_onto = &squash_onto;
 			options.onto_name = squash_onto_name =
 				xstrdup(oid_to_hex(&squash_onto));
-		} else
-			options.root_with_onto = 1;
-
+		}
 		options.upstream_name = NULL;
 		options.upstream = NULL;
 		if (argc > 1)
@@ -2004,22 +1882,12 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 	}
 
 	/* Make sure the branch to rebase onto is valid. */
-	if (keep_base) {
-		strbuf_reset(&buf);
-		strbuf_addstr(&buf, options.upstream_name);
-		strbuf_addstr(&buf, "...");
-		options.onto_name = xstrdup(buf.buf);
-	} else if (!options.onto_name)
+	if (!options.onto_name)
 		options.onto_name = options.upstream_name;
 	if (strstr(options.onto_name, "...")) {
-		if (get_oid_mb(options.onto_name, &merge_base) < 0) {
-			if (keep_base)
-				die(_("'%s': need exactly one merge base with branch"),
-				    options.upstream_name);
-			else
-				die(_("'%s': need exactly one merge base"),
-				    options.onto_name);
-		}
+		if (get_oid_mb(options.onto_name, &merge_base) < 0)
+			die(_("'%s': need exactly one merge base"),
+			    options.onto_name);
 		options.onto = lookup_commit_or_die(&merge_base,
 						    options.onto_name);
 	} else {
@@ -2044,11 +1912,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		/* Is it a local branch? */
 		strbuf_reset(&buf);
 		strbuf_addf(&buf, "refs/heads/%s", branch_name);
-		if (!read_ref(buf.buf, &options.orig_head)) {
-			die_if_checked_out(buf.buf, 1);
+		if (!read_ref(buf.buf, &options.orig_head))
 			options.head_name = xstrdup(buf.buf);
 		/* If not is it a valid ref (branch or commit)? */
-		} else if (!get_oid(branch_name, &options.orig_head))
+		else if (!get_oid(branch_name, &options.orig_head))
 			options.head_name = NULL;
 		else
 			die(_("fatal: no such branch/commit '%s'"),
@@ -2101,6 +1968,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 				state_dir_path("autostash", &options);
 			struct child_process stash = CHILD_PROCESS_INIT;
 			struct object_id oid;
+			struct commit *head =
+				lookup_commit_reference(the_repository,
+							&options.orig_head);
 
 			argv_array_pushl(&stash.args,
 					 "stash", "create", "autostash", NULL);
@@ -2121,9 +1991,17 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 				    options.state_dir);
 			write_file(autostash, "%s", oid_to_hex(&oid));
 			printf(_("Created autostash: %s\n"), buf.buf);
-			if (reset_head(NULL, "reset --hard",
+			if (reset_head(&head->object.oid, "reset --hard",
 				       NULL, RESET_HEAD_HARD, NULL, NULL) < 0)
 				die(_("could not reset --hard"));
+			printf(_("HEAD is now at %s"),
+			       find_unique_abbrev(&head->object.oid,
+						  DEFAULT_ABBREV));
+			strbuf_reset(&buf);
+			pp_commit_easy(CMIT_FMT_ONELINE, head, &buf);
+			if (buf.len > 0)
+				printf(" %s", buf.buf);
+			putchar('\n');
 
 			if (discard_index(the_repository->index) < 0 ||
 				repo_read_index(the_repository) < 0)
@@ -2144,25 +2022,31 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 
 	/*
 	 * Check if we are already based on onto with linear history,
-	 * in which case we could fast-forward without replacing the commits
-	 * with new commits recreated by replaying their changes.
-	 *
-	 * Note that can_fast_forward() initializes merge_base, so we have to
-	 * call it before checking allow_preemptive_ff.
+	 * but this should be done only when upstream and onto are the same
+	 * and if this is not an interactive rebase.
 	 */
-	if (can_fast_forward(options.onto, options.upstream, options.restrict_revision,
-		    &options.orig_head, &merge_base) &&
-	    allow_preemptive_ff) {
+	if (can_fast_forward(options.onto, &options.orig_head, &merge_base) &&
+	    !is_interactive(&options) && !options.restrict_revision &&
+	    options.upstream &&
+	    !oidcmp(&options.upstream->object.oid, &options.onto->object.oid)) {
 		int flag;
 
 		if (!(options.flags & REBASE_FORCE)) {
 			/* Lazily switch to the target branch if needed... */
 			if (options.switch_to) {
+				struct object_id oid;
+
+				if (get_oid(options.switch_to, &oid) < 0) {
+					ret = !!error(_("could not parse '%s'"),
+						      options.switch_to);
+					goto cleanup;
+				}
+
 				strbuf_reset(&buf);
 				strbuf_addf(&buf, "%s: checkout %s",
 					    getenv(GIT_REFLOG_ACTION_ENVIRONMENT),
 					    options.switch_to);
-				if (reset_head(&options.orig_head, "checkout",
+				if (reset_head(&oid, "checkout",
 					       options.head_name,
 					       RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
 					       NULL, buf.buf) < 0) {
@@ -2227,7 +2111,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 		diff_flush(&opts);
 	}
 
-	if (is_merge(&options))
+	if (is_interactive(&options))
 		goto run_rebase;
 
 	/* Detach HEAD and reset the tree */
diff --git a/third_party/git/builtin/receive-pack.c b/third_party/git/builtin/receive-pack.c
index 2cc18bbffd..dcf385511f 100644
--- a/third_party/git/builtin/receive-pack.c
+++ b/third_party/git/builtin/receive-pack.c
@@ -27,7 +27,6 @@
 #include "object-store.h"
 #include "protocol.h"
 #include "commit-reach.h"
-#include "worktree.h"
 
 static const char * const receive_pack_usage[] = {
 	N_("git receive-pack <git-dir>"),
@@ -418,22 +417,24 @@ static int copy_to_sideband(int in, int out, void *arg)
 	return 0;
 }
 
-static void hmac(unsigned char *out,
+#define HMAC_BLOCK_SIZE 64
+
+static void hmac_sha1(unsigned char *out,
 		      const char *key_in, size_t key_len,
 		      const char *text, size_t text_len)
 {
-	unsigned char key[GIT_MAX_BLKSZ];
-	unsigned char k_ipad[GIT_MAX_BLKSZ];
-	unsigned char k_opad[GIT_MAX_BLKSZ];
+	unsigned char key[HMAC_BLOCK_SIZE];
+	unsigned char k_ipad[HMAC_BLOCK_SIZE];
+	unsigned char k_opad[HMAC_BLOCK_SIZE];
 	int i;
-	git_hash_ctx ctx;
+	git_SHA_CTX ctx;
 
 	/* RFC 2104 2. (1) */
-	memset(key, '\0', GIT_MAX_BLKSZ);
-	if (the_hash_algo->blksz < key_len) {
-		the_hash_algo->init_fn(&ctx);
-		the_hash_algo->update_fn(&ctx, key_in, key_len);
-		the_hash_algo->final_fn(key, &ctx);
+	memset(key, '\0', HMAC_BLOCK_SIZE);
+	if (HMAC_BLOCK_SIZE < key_len) {
+		git_SHA1_Init(&ctx);
+		git_SHA1_Update(&ctx, key_in, key_len);
+		git_SHA1_Final(key, &ctx);
 	} else {
 		memcpy(key, key_in, key_len);
 	}
@@ -445,29 +446,29 @@ static void hmac(unsigned char *out,
 	}
 
 	/* RFC 2104 2. (3) & (4) */
-	the_hash_algo->init_fn(&ctx);
-	the_hash_algo->update_fn(&ctx, k_ipad, sizeof(k_ipad));
-	the_hash_algo->update_fn(&ctx, text, text_len);
-	the_hash_algo->final_fn(out, &ctx);
+	git_SHA1_Init(&ctx);
+	git_SHA1_Update(&ctx, k_ipad, sizeof(k_ipad));
+	git_SHA1_Update(&ctx, text, text_len);
+	git_SHA1_Final(out, &ctx);
 
 	/* RFC 2104 2. (6) & (7) */
-	the_hash_algo->init_fn(&ctx);
-	the_hash_algo->update_fn(&ctx, k_opad, sizeof(k_opad));
-	the_hash_algo->update_fn(&ctx, out, the_hash_algo->rawsz);
-	the_hash_algo->final_fn(out, &ctx);
+	git_SHA1_Init(&ctx);
+	git_SHA1_Update(&ctx, k_opad, sizeof(k_opad));
+	git_SHA1_Update(&ctx, out, GIT_SHA1_RAWSZ);
+	git_SHA1_Final(out, &ctx);
 }
 
 static char *prepare_push_cert_nonce(const char *path, timestamp_t stamp)
 {
 	struct strbuf buf = STRBUF_INIT;
-	unsigned char hash[GIT_MAX_RAWSZ];
+	unsigned char sha1[GIT_SHA1_RAWSZ];
 
 	strbuf_addf(&buf, "%s:%"PRItime, path, stamp);
-	hmac(hash, buf.buf, buf.len, cert_nonce_seed, strlen(cert_nonce_seed));
+	hmac_sha1(sha1, buf.buf, buf.len, cert_nonce_seed, strlen(cert_nonce_seed));
 	strbuf_release(&buf);
 
 	/* RFC 2104 5. HMAC-SHA1-80 */
-	strbuf_addf(&buf, "%"PRItime"-%.*s", stamp, (int)the_hash_algo->hexsz, hash_to_hex(hash));
+	strbuf_addf(&buf, "%"PRItime"-%.*s", stamp, GIT_SHA1_HEXSZ, sha1_to_hex(sha1));
 	return strbuf_detach(&buf, NULL);
 }
 
@@ -817,6 +818,16 @@ static int run_update_hook(struct command *cmd)
 	return finish_command(&proc);
 }
 
+static int is_ref_checked_out(const char *ref)
+{
+	if (is_bare_repository())
+		return 0;
+
+	if (!head_name)
+		return 0;
+	return !strcmp(head_name, ref);
+}
+
 static char *refuse_unconfigured_deny_msg =
 	N_("By default, updating the current branch in a non-bare repository\n"
 	   "is denied, because it will make the index and work tree inconsistent\n"
@@ -959,7 +970,7 @@ static const char *push_to_deploy(unsigned char *sha1,
 	if (run_command(&child))
 		return "Working directory has staged changes";
 
-	read_tree[3] = hash_to_hex(sha1);
+	read_tree[3] = sha1_to_hex(sha1);
 	child_process_init(&child);
 	child.argv = read_tree;
 	child.env = env->argv;
@@ -976,38 +987,28 @@ static const char *push_to_deploy(unsigned char *sha1,
 
 static const char *push_to_checkout_hook = "push-to-checkout";
 
-static const char *push_to_checkout(unsigned char *hash,
+static const char *push_to_checkout(unsigned char *sha1,
 				    struct argv_array *env,
 				    const char *work_tree)
 {
 	argv_array_pushf(env, "GIT_WORK_TREE=%s", absolute_path(work_tree));
 	if (run_hook_le(env->argv, push_to_checkout_hook,
-			hash_to_hex(hash), NULL))
+			sha1_to_hex(sha1), NULL))
 		return "push-to-checkout hook declined";
 	else
 		return NULL;
 }
 
-static const char *update_worktree(unsigned char *sha1, const struct worktree *worktree)
+static const char *update_worktree(unsigned char *sha1)
 {
-	const char *retval, *work_tree, *git_dir = NULL;
+	const char *retval;
+	const char *work_tree = git_work_tree_cfg ? git_work_tree_cfg : "..";
 	struct argv_array env = ARGV_ARRAY_INIT;
 
-	if (worktree && worktree->path)
-		work_tree = worktree->path;
-	else if (git_work_tree_cfg)
-		work_tree = git_work_tree_cfg;
-	else
-		work_tree = "..";
-
 	if (is_bare_repository())
 		return "denyCurrentBranch = updateInstead needs a worktree";
-	if (worktree)
-		git_dir = get_worktree_git_dir(worktree);
-	if (!git_dir)
-		git_dir = get_git_dir();
 
-	argv_array_pushf(&env, "GIT_DIR=%s", absolute_path(git_dir));
+	argv_array_pushf(&env, "GIT_DIR=%s", absolute_path(get_git_dir()));
 
 	if (!find_hook(push_to_checkout_hook))
 		retval = push_to_deploy(sha1, &env, work_tree);
@@ -1027,7 +1028,6 @@ static const char *update(struct command *cmd, struct shallow_info *si)
 	struct object_id *old_oid = &cmd->old_oid;
 	struct object_id *new_oid = &cmd->new_oid;
 	int do_update_worktree = 0;
-	const struct worktree *worktree = is_bare_repository() ? NULL : find_shared_symref("HEAD", name);
 
 	/* only refs/... are allowed */
 	if (!starts_with(name, "refs/") || check_refname_format(name + 5, 0)) {
@@ -1039,7 +1039,7 @@ static const char *update(struct command *cmd, struct shallow_info *si)
 	free(namespaced_name);
 	namespaced_name = strbuf_detach(&namespaced_name_buf, NULL);
 
-	if (worktree) {
+	if (is_ref_checked_out(namespaced_name)) {
 		switch (deny_current_branch) {
 		case DENY_IGNORE:
 			break;
@@ -1071,7 +1071,7 @@ static const char *update(struct command *cmd, struct shallow_info *si)
 			return "deletion prohibited";
 		}
 
-		if (worktree || (head_name && !strcmp(namespaced_name, head_name))) {
+		if (head_name && !strcmp(namespaced_name, head_name)) {
 			switch (deny_delete_current) {
 			case DENY_IGNORE:
 				break;
@@ -1120,7 +1120,7 @@ static const char *update(struct command *cmd, struct shallow_info *si)
 	}
 
 	if (do_update_worktree) {
-		ret = update_worktree(new_oid->hash, find_shared_symref("HEAD", name));
+		ret = update_worktree(new_oid->hash);
 		if (ret)
 			return ret;
 	}
diff --git a/third_party/git/builtin/reflog.c b/third_party/git/builtin/reflog.c
index 81dfd563c0..4d3430900d 100644
--- a/third_party/git/builtin/reflog.c
+++ b/third_party/git/builtin/reflog.c
@@ -560,16 +560,15 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
 
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
-
 		if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n"))
 			flags |= EXPIRE_REFLOGS_DRY_RUN;
-		else if (skip_prefix(arg, "--expire=", &arg)) {
-			if (parse_expiry_date(arg, &cb.cmd.expire_total))
+		else if (starts_with(arg, "--expire=")) {
+			if (parse_expiry_date(arg + 9, &cb.cmd.expire_total))
 				die(_("'%s' is not a valid timestamp"), arg);
 			explicit_expiry |= EXPIRE_TOTAL;
 		}
-		else if (skip_prefix(arg, "--expire-unreachable=", &arg)) {
-			if (parse_expiry_date(arg, &cb.cmd.expire_unreachable))
+		else if (starts_with(arg, "--expire-unreachable=")) {
+			if (parse_expiry_date(arg + 21, &cb.cmd.expire_unreachable))
 				die(_("'%s' is not a valid timestamp"), arg);
 			explicit_expiry |= EXPIRE_UNREACH;
 		}
diff --git a/third_party/git/builtin/remote.c b/third_party/git/builtin/remote.c
index 555d4c896c..5591cef775 100644
--- a/third_party/git/builtin/remote.c
+++ b/third_party/git/builtin/remote.c
@@ -6,7 +6,6 @@
 #include "string-list.h"
 #include "strbuf.h"
 #include "run-command.h"
-#include "rebase.h"
 #include "refs.h"
 #include "refspec.h"
 #include "object-store.h"
@@ -249,8 +248,9 @@ static int add(int argc, const char **argv)
 struct branch_info {
 	char *remote_name;
 	struct string_list merge;
-	enum rebase_type rebase;
-	char *push_remote_name;
+	enum {
+		NO_REBASE, NORMAL_REBASE, INTERACTIVE_REBASE, REBASE_MERGES
+	} rebase;
 };
 
 static struct string_list branch_list = STRING_LIST_INIT_NODUP;
@@ -264,69 +264,59 @@ static const char *abbrev_ref(const char *name, const char *prefix)
 
 static int config_read_branches(const char *key, const char *value, void *cb)
 {
-	const char *orig_key = key;
-	char *name;
-	struct string_list_item *item;
-	struct branch_info *info;
-	enum { REMOTE, MERGE, REBASE, PUSH_REMOTE } type;
-	size_t key_len;
+	if (starts_with(key, "branch.")) {
+		const char *orig_key = key;
+		char *name;
+		struct string_list_item *item;
+		struct branch_info *info;
+		enum { REMOTE, MERGE, REBASE } type;
+		size_t key_len;
+
+		key += 7;
+		if (strip_suffix(key, ".remote", &key_len)) {
+			name = xmemdupz(key, key_len);
+			type = REMOTE;
+		} else if (strip_suffix(key, ".merge", &key_len)) {
+			name = xmemdupz(key, key_len);
+			type = MERGE;
+		} else if (strip_suffix(key, ".rebase", &key_len)) {
+			name = xmemdupz(key, key_len);
+			type = REBASE;
+		} else
+			return 0;
 
-	if (!starts_with(key, "branch."))
-		return 0;
+		item = string_list_insert(&branch_list, name);
 
-	key += strlen("branch.");
-	if (strip_suffix(key, ".remote", &key_len))
-		type = REMOTE;
-	else if (strip_suffix(key, ".merge", &key_len))
-		type = MERGE;
-	else if (strip_suffix(key, ".rebase", &key_len))
-		type = REBASE;
-	else if (strip_suffix(key, ".pushremote", &key_len))
-		type = PUSH_REMOTE;
-	else
-		return 0;
-	name = xmemdupz(key, key_len);
-
-	item = string_list_insert(&branch_list, name);
-
-	if (!item->util)
-		item->util = xcalloc(1, sizeof(struct branch_info));
-	info = item->util;
-	switch (type) {
-	case REMOTE:
-		if (info->remote_name)
-			warning(_("more than one %s"), orig_key);
-		info->remote_name = xstrdup(value);
-		break;
-	case MERGE: {
-		char *space = strchr(value, ' ');
-		value = abbrev_branch(value);
-		while (space) {
-			char *merge;
-			merge = xstrndup(value, space - value);
-			string_list_append(&info->merge, merge);
-			value = abbrev_branch(space + 1);
-			space = strchr(value, ' ');
+		if (!item->util)
+			item->util = xcalloc(1, sizeof(struct branch_info));
+		info = item->util;
+		if (type == REMOTE) {
+			if (info->remote_name)
+				warning(_("more than one %s"), orig_key);
+			info->remote_name = xstrdup(value);
+		} else if (type == MERGE) {
+			char *space = strchr(value, ' ');
+			value = abbrev_branch(value);
+			while (space) {
+				char *merge;
+				merge = xstrndup(value, space - value);
+				string_list_append(&info->merge, merge);
+				value = abbrev_branch(space + 1);
+				space = strchr(value, ' ');
+			}
+			string_list_append(&info->merge, xstrdup(value));
+		} else {
+			int v = git_parse_maybe_bool(value);
+			if (v >= 0)
+				info->rebase = v;
+			else if (!strcmp(value, "preserve"))
+				info->rebase = NORMAL_REBASE;
+			else if (!strcmp(value, "merges"))
+				info->rebase = REBASE_MERGES;
+			else if (!strcmp(value, "interactive"))
+				info->rebase = INTERACTIVE_REBASE;
 		}
-		string_list_append(&info->merge, xstrdup(value));
-		break;
-	}
-	case REBASE:
-		/*
-		 * Consider invalid values as false and check the
-		 * truth value with >= REBASE_TRUE.
-		 */
-		info->rebase = rebase_parse_value(value);
-		break;
-	case PUSH_REMOTE:
-		if (info->push_remote_name)
-			warning(_("more than one %s"), orig_key);
-		info->push_remote_name = xstrdup(value);
-		break;
-	default:
-		BUG("unexpected type=%d", type);
 	}
-
 	return 0;
 }
 
@@ -615,56 +605,6 @@ static int migrate_file(struct remote *remote)
 	return 0;
 }
 
-struct push_default_info
-{
-	const char *old_name;
-	enum config_scope scope;
-	struct strbuf origin;
-	int linenr;
-};
-
-static int config_read_push_default(const char *key, const char *value,
-	void *cb)
-{
-	struct push_default_info* info = cb;
-	if (strcmp(key, "remote.pushdefault") ||
-	    !value || strcmp(value, info->old_name))
-		return 0;
-
-	info->scope = current_config_scope();
-	strbuf_reset(&info->origin);
-	strbuf_addstr(&info->origin, current_config_name());
-	info->linenr = current_config_line();
-
-	return 0;
-}
-
-static void handle_push_default(const char* old_name, const char* new_name)
-{
-	struct push_default_info push_default = {
-		old_name, CONFIG_SCOPE_UNKNOWN, STRBUF_INIT, -1 };
-	git_config(config_read_push_default, &push_default);
-	if (push_default.scope >= CONFIG_SCOPE_COMMAND)
-		; /* pass */
-	else if (push_default.scope >= CONFIG_SCOPE_LOCAL) {
-		int result = git_config_set_gently("remote.pushDefault",
-						   new_name);
-		if (new_name && result && result != CONFIG_NOTHING_SET)
-			die(_("could not set '%s'"), "remote.pushDefault");
-		else if (!new_name && result && result != CONFIG_NOTHING_SET)
-			die(_("could not unset '%s'"), "remote.pushDefault");
-	} else if (push_default.scope >= CONFIG_SCOPE_SYSTEM) {
-		/* warn */
-		warning(_("The %s configuration remote.pushDefault in:\n"
-			  "\t%s:%d\n"
-			  "now names the non-existent remote '%s'"),
-			config_scope_name(push_default.scope),
-			push_default.origin.buf, push_default.linenr,
-			old_name);
-	}
-}
-
-
 static int mv(int argc, const char **argv)
 {
 	struct option options[] = {
@@ -740,11 +680,6 @@ static int mv(int argc, const char **argv)
 			strbuf_addf(&buf, "branch.%s.remote", item->string);
 			git_config_set(buf.buf, rename.new_name);
 		}
-		if (info->push_remote_name && !strcmp(info->push_remote_name, rename.old_name)) {
-			strbuf_reset(&buf);
-			strbuf_addf(&buf, "branch.%s.pushremote", item->string);
-			git_config_set(buf.buf, rename.new_name);
-		}
 	}
 
 	if (!refspec_updated)
@@ -758,8 +693,9 @@ static int mv(int argc, const char **argv)
 	for (i = 0; i < remote_branches.nr; i++) {
 		struct string_list_item *item = remote_branches.items + i;
 		int flag = 0;
+		struct object_id oid;
 
-		read_ref_full(item->string, RESOLVE_REF_READING, NULL, &flag);
+		read_ref_full(item->string, RESOLVE_REF_READING, &oid, &flag);
 		if (!(flag & REF_ISSYMREF))
 			continue;
 		if (delete_ref(NULL, item->string, NULL, REF_NO_DEREF))
@@ -800,9 +736,6 @@ static int mv(int argc, const char **argv)
 			die(_("creating '%s' failed"), buf.buf);
 	}
 	string_list_clear(&remote_branches, 1);
-
-	handle_push_default(rename.old_name, rename.new_name);
-
 	return 0;
 }
 
@@ -849,13 +782,6 @@ static int rm(int argc, const char **argv)
 					die(_("could not unset '%s'"), buf.buf);
 			}
 		}
-		if (info->push_remote_name && !strcmp(info->push_remote_name, remote->name)) {
-			strbuf_reset(&buf);
-			strbuf_addf(&buf, "branch.%s.pushremote", item->string);
-			result = git_config_set_gently(buf.buf, NULL);
-			if (result && result != CONFIG_NOTHING_SET)
-				die(_("could not unset '%s'"), buf.buf);
-		}
 	}
 
 	/*
@@ -888,8 +814,6 @@ static int rm(int argc, const char **argv)
 		strbuf_addf(&buf, "remote.%s", remote->name);
 		if (git_config_rename_section(buf.buf, NULL) < 1)
 			return error(_("Could not remove config section '%s'"), buf.buf);
-
-		handle_push_default(remote->name, NULL);
 	}
 
 	return result;
@@ -1020,7 +944,7 @@ static int add_local_to_show_info(struct string_list_item *branch_item, void *cb
 		return 0;
 	if ((n = strlen(branch_item->string)) > show_info->width)
 		show_info->width = n;
-	if (branch_info->rebase >= REBASE_TRUE)
+	if (branch_info->rebase)
 		show_info->any_rebase = 1;
 
 	item = string_list_insert(show_info->list, branch_item->string);
@@ -1037,16 +961,16 @@ static int show_local_info_item(struct string_list_item *item, void *cb_data)
 	int width = show_info->width + 4;
 	int i;
 
-	if (branch_info->rebase >= REBASE_TRUE && branch_info->merge.nr > 1) {
+	if (branch_info->rebase && branch_info->merge.nr > 1) {
 		error(_("invalid branch.%s.merge; cannot rebase onto > 1 branch"),
 			item->string);
 		return 0;
 	}
 
 	printf("    %-*s ", show_info->width, item->string);
-	if (branch_info->rebase >= REBASE_TRUE) {
+	if (branch_info->rebase) {
 		const char *msg;
-		if (branch_info->rebase == REBASE_INTERACTIVE)
+		if (branch_info->rebase == INTERACTIVE_REBASE)
 			msg = _("rebases interactively onto remote %s");
 		else if (branch_info->rebase == REBASE_MERGES)
 			msg = _("rebases interactively (with merges) onto "
diff --git a/third_party/git/builtin/repack.c b/third_party/git/builtin/repack.c
index 0781763b06..632c0c0a79 100644
--- a/third_party/git/builtin/repack.c
+++ b/third_party/git/builtin/repack.c
@@ -11,7 +11,6 @@
 #include "midx.h"
 #include "packfile.h"
 #include "object-store.h"
-#include "promisor-remote.h"
 
 static int delta_base_offset = 1;
 static int pack_kept_objects = -1;
@@ -191,7 +190,7 @@ static int write_oid(const struct object_id *oid, struct packed_git *pack,
 			die(_("could not start pack-objects to repack promisor objects"));
 	}
 
-	xwrite(cmd->in, oid_to_hex(oid), the_hash_algo->hexsz);
+	xwrite(cmd->in, oid_to_hex(oid), GIT_SHA1_HEXSZ);
 	xwrite(cmd->in, "\n", 1);
 	return 0;
 }
@@ -233,13 +232,6 @@ static void repack_promisor_objects(const struct pack_objects_args *args,
 		/*
 		 * pack-objects creates the .pack and .idx files, but not the
 		 * .promisor file. Create the .promisor file, which is empty.
-		 *
-		 * NEEDSWORK: fetch-pack sometimes generates non-empty
-		 * .promisor files containing the ref names and associated
-		 * hashes at the point of generation of the corresponding
-		 * packfile, but this would not preserve their contents. Maybe
-		 * concatenate the contents of all .promisor files instead of
-		 * just creating a new empty file.
 		 */
 		promisor_name = mkpathdup("%s-%s.promisor", packtmp,
 					  line.buf);
@@ -369,7 +361,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 	argv_array_push(&cmd.args, "--all");
 	argv_array_push(&cmd.args, "--reflog");
 	argv_array_push(&cmd.args, "--indexed-objects");
-	if (has_promisor_remote())
+	if (repository_format_partial_clone)
 		argv_array_push(&cmd.args, "--exclude-promisor-objects");
 	if (write_bitmaps > 0)
 		argv_array_push(&cmd.args, "--write-bitmap-index");
@@ -569,7 +561,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 	remove_temporary_files();
 
 	if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX, 0))
-		write_midx_file(get_object_directory(), 0);
+		write_midx_file(get_object_directory());
 
 	string_list_clear(&names, 0);
 	string_list_clear(&rollback, 0);
diff --git a/third_party/git/builtin/replace.c b/third_party/git/builtin/replace.c
index b36d17a657..644b21ca8d 100644
--- a/third_party/git/builtin/replace.c
+++ b/third_party/git/builtin/replace.c
@@ -272,7 +272,7 @@ static int import_object(struct object_id *oid, enum object_type type,
 			return error(_("unable to spawn mktree"));
 		}
 
-		if (strbuf_read(&result, cmd.out, the_hash_algo->hexsz + 1) < 0) {
+		if (strbuf_read(&result, cmd.out, 41) < 0) {
 			error_errno(_("unable to read from mktree"));
 			close(fd);
 			close(cmd.out);
@@ -358,15 +358,14 @@ static int replace_parents(struct strbuf *buf, int argc, const char **argv)
 	struct strbuf new_parents = STRBUF_INIT;
 	const char *parent_start, *parent_end;
 	int i;
-	const unsigned hexsz = the_hash_algo->hexsz;
 
 	/* find existing parents */
 	parent_start = buf->buf;
-	parent_start += hexsz + 6; /* "tree " + "hex sha1" + "\n" */
+	parent_start += GIT_SHA1_HEXSZ + 6; /* "tree " + "hex sha1" + "\n" */
 	parent_end = parent_start;
 
 	while (starts_with(parent_end, "parent "))
-		parent_end += hexsz + 8; /* "parent " + "hex sha1" + "\n" */
+		parent_end += 48; /* "parent " + "hex sha1" + "\n" */
 
 	/* prepare new parents */
 	for (i = 0; i < argc; i++) {
@@ -409,8 +408,7 @@ static int check_one_mergetag(struct commit *commit,
 	struct tag *tag;
 	int i;
 
-	hash_object_file(the_hash_algo, extra->value, extra->len,
-			 type_name(OBJ_TAG), &tag_oid);
+	hash_object_file(extra->value, extra->len, type_name(OBJ_TAG), &tag_oid);
 	tag = lookup_tag(the_repository, &tag_oid);
 	if (!tag)
 		return error(_("bad mergetag in commit '%s'"), ref);
@@ -423,7 +421,7 @@ static int check_one_mergetag(struct commit *commit,
 		if (get_oid(mergetag_data->argv[i], &oid) < 0)
 			return error(_("not a valid object name: '%s'"),
 				     mergetag_data->argv[i]);
-		if (oideq(get_tagged_oid(tag), &oid))
+		if (oideq(&tag->tagged->oid, &oid))
 			return 0; /* found */
 	}
 
diff --git a/third_party/git/builtin/reset.c b/third_party/git/builtin/reset.c
index 18228c312e..fdd572168b 100644
--- a/third_party/git/builtin/reset.c
+++ b/third_party/git/builtin/reset.c
@@ -30,9 +30,8 @@
 
 static const char * const git_reset_usage[] = {
 	N_("git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"),
-	N_("git reset [-q] [<tree-ish>] [--] <pathspec>..."),
-	N_("git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<tree-ish>]"),
-	N_("git reset --patch [<tree-ish>] [--] [<pathspec>...]"),
+	N_("git reset [-q] [<tree-ish>] [--] <paths>..."),
+	N_("git reset --patch [<tree-ish>] [--] [<paths>...]"),
 	NULL
 };
 
@@ -285,8 +284,8 @@ static int git_reset_config(const char *var, const char *value, void *cb)
 int cmd_reset(int argc, const char **argv, const char *prefix)
 {
 	int reset_type = NONE, update_ref_status = 0, quiet = 0;
-	int patch_mode = 0, pathspec_file_nul = 0, unborn;
-	const char *rev, *pathspec_from_file = NULL;
+	int patch_mode = 0, unborn;
+	const char *rev;
 	struct object_id oid;
 	struct pathspec pathspec;
 	int intent_to_add = 0;
@@ -307,8 +306,6 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
 		OPT_BOOL('N', "intent-to-add", &intent_to_add,
 				N_("record only the fact that removed paths will be added later")),
-		OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
-		OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
 		OPT_END()
 	};
 
@@ -319,25 +316,11 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 						PARSE_OPT_KEEP_DASHDASH);
 	parse_args(&pathspec, argv, prefix, patch_mode, &rev);
 
-	if (pathspec_from_file) {
-		if (patch_mode)
-			die(_("--pathspec-from-file is incompatible with --patch"));
-
-		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
-
-		parse_pathspec_file(&pathspec, 0,
-				    PATHSPEC_PREFER_FULL,
-				    prefix, pathspec_from_file, pathspec_file_nul);
-	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
-	}
-
 	unborn = !strcmp(rev, "HEAD") && get_oid("HEAD", &oid);
 	if (unborn) {
 		/* reset on unborn branch: treat as reset to empty tree */
 		oidcpy(&oid, the_hash_algo->empty_tree);
-	} else if (!pathspec.nr && !patch_mode) {
+	} else if (!pathspec.nr) {
 		struct commit *commit;
 		if (get_oid_committish(rev, &oid))
 			die(_("Failed to resolve '%s' as a valid revision."), rev);
diff --git a/third_party/git/builtin/rev-list.c b/third_party/git/builtin/rev-list.c
index f520111eda..301ccb970b 100644
--- a/third_party/git/builtin/rev-list.c
+++ b/third_party/git/builtin/rev-list.c
@@ -18,6 +18,7 @@
 #include "reflog-walk.h"
 #include "oidset.h"
 #include "packfile.h"
+#include "object-store.h"
 
 static const char rev_list_usage[] =
 "git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
@@ -253,26 +254,11 @@ static int finish_object(struct object *obj, const char *name, void *cb_data)
 static void show_object(struct object *obj, const char *name, void *cb_data)
 {
 	struct rev_list_info *info = cb_data;
-	struct rev_info *revs = info->revs;
-
 	if (finish_object(obj, name, cb_data))
 		return;
 	display_progress(progress, ++progress_counter);
 	if (info->flags & REV_LIST_QUIET)
 		return;
-
-	if (revs->count) {
-		/*
-		 * The object count is always accumulated in the .count_right
-		 * field for traversal that is not a left-right traversal,
-		 * and cmd_rev_list() made sure that a .count request that
-		 * wants to count non-commit objects, which is handled by
-		 * the show_object() callback, does not ask for .left_right.
-		 */
-		revs->count_right++;
-		return;
-	}
-
 	if (arg_show_object_names)
 		show_object_with_name(stdout, obj, name);
 	else
@@ -379,79 +365,6 @@ static inline int parse_missing_action_value(const char *value)
 	return 0;
 }
 
-static int try_bitmap_count(struct rev_info *revs,
-			    struct list_objects_filter_options *filter)
-{
-	uint32_t commit_count = 0,
-		 tag_count = 0,
-		 tree_count = 0,
-		 blob_count = 0;
-	int max_count;
-	struct bitmap_index *bitmap_git;
-
-	/* This function only handles counting, not general traversal. */
-	if (!revs->count)
-		return -1;
-
-	/*
-	 * A bitmap result can't know left/right, etc, because we don't
-	 * actually traverse.
-	 */
-	if (revs->left_right || revs->cherry_mark)
-		return -1;
-
-	/*
-	 * If we're counting reachable objects, we can't handle a max count of
-	 * commits to traverse, since we don't know which objects go with which
-	 * commit.
-	 */
-	if (revs->max_count >= 0 &&
-	    (revs->tag_objects || revs->tree_objects || revs->blob_objects))
-		return -1;
-
-	/*
-	 * This must be saved before doing any walking, since the revision
-	 * machinery will count it down to zero while traversing.
-	 */
-	max_count = revs->max_count;
-
-	bitmap_git = prepare_bitmap_walk(revs, filter);
-	if (!bitmap_git)
-		return -1;
-
-	count_bitmap_commit_list(bitmap_git, &commit_count,
-				 revs->tree_objects ? &tree_count : NULL,
-				 revs->blob_objects ? &blob_count : NULL,
-				 revs->tag_objects ? &tag_count : NULL);
-	if (max_count >= 0 && max_count < commit_count)
-		commit_count = max_count;
-
-	printf("%d\n", commit_count + tree_count + blob_count + tag_count);
-	free_bitmap_index(bitmap_git);
-	return 0;
-}
-
-static int try_bitmap_traversal(struct rev_info *revs,
-				struct list_objects_filter_options *filter)
-{
-	struct bitmap_index *bitmap_git;
-
-	/*
-	 * We can't use a bitmap result with a traversal limit, since the set
-	 * of commits we'd get would be essentially random.
-	 */
-	if (revs->max_count >= 0)
-		return -1;
-
-	bitmap_git = prepare_bitmap_walk(revs, filter);
-	if (!bitmap_git)
-		return -1;
-
-	traverse_bitmap_commit_list(bitmap_git, revs, &show_object_fast);
-	free_bitmap_index(bitmap_git);
-	return 0;
-}
-
 int cmd_rev_list(int argc, const char **argv, const char *prefix)
 {
 	struct rev_info revs;
@@ -558,6 +471,10 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 			parse_list_objects_filter(&filter_options, arg);
 			if (filter_options.choice && !revs.blob_objects)
 				die(_("object filtering requires --objects"));
+			if (filter_options.choice == LOFC_SPARSE_OID &&
+			    !filter_options.sparse_oid_value)
+				die(_("invalid sparse value '%s'"),
+				    filter_options.filter_spec);
 			continue;
 		}
 		if (!strcmp(arg, ("--no-" CL_ARG__FILTER))) {
@@ -609,10 +526,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 	if (revs.show_notes)
 		die(_("rev-list does not support display of notes"));
 
-	if (revs.count &&
-	    (revs.tag_objects || revs.tree_objects || revs.blob_objects) &&
-	    (revs.left_right || revs.cherry_mark))
-		die(_("marked counting is incompatible with --objects"));
+	if (filter_options.choice && use_bitmap_index)
+		die(_("cannot combine --use-bitmap-index with object filtering"));
 
 	save_commit_buffer = (revs.verbose_header ||
 			      revs.grep_filter.pattern_list ||
@@ -623,11 +538,28 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 	if (show_progress)
 		progress = start_delayed_progress(show_progress, 0);
 
-	if (use_bitmap_index) {
-		if (!try_bitmap_count(&revs, &filter_options))
-			return 0;
-		if (!try_bitmap_traversal(&revs, &filter_options))
-			return 0;
+	if (use_bitmap_index && !revs.prune) {
+		if (revs.count && !revs.left_right && !revs.cherry_mark) {
+			uint32_t commit_count;
+			int max_count = revs.max_count;
+			struct bitmap_index *bitmap_git;
+			if ((bitmap_git = prepare_bitmap_walk(&revs))) {
+				count_bitmap_commit_list(bitmap_git, &commit_count, NULL, NULL, NULL);
+				if (max_count >= 0 && max_count < commit_count)
+					commit_count = max_count;
+				printf("%d\n", commit_count);
+				free_bitmap_index(bitmap_git);
+				return 0;
+			}
+		} else if (revs.max_count < 0 &&
+			   revs.tag_objects && revs.tree_objects && revs.blob_objects) {
+			struct bitmap_index *bitmap_git;
+			if ((bitmap_git = prepare_bitmap_walk(&revs))) {
+				traverse_bitmap_commit_list(bitmap_git, &show_object_fast);
+				free_bitmap_index(bitmap_git);
+				return 0;
+			}
+		}
 	}
 
 	if (prepare_revision_walk(&revs))
diff --git a/third_party/git/builtin/rev-parse.c b/third_party/git/builtin/rev-parse.c
index 7a00da8203..f8bbe6d47e 100644
--- a/third_party/git/builtin/rev-parse.c
+++ b/third_party/git/builtin/rev-parse.c
@@ -593,7 +593,6 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 	const char *name = NULL;
 	struct object_context unused;
 	struct strbuf buf = STRBUF_INIT;
-	const int hexsz = the_hash_algo->hexsz;
 
 	if (argc > 1 && !strcmp("--parseopt", argv[1]))
 		return cmd_parseopt(argc - 1, argv + 1, prefix);
@@ -731,8 +730,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 				abbrev = strtoul(arg, NULL, 10);
 				if (abbrev < MINIMUM_ABBREV)
 					abbrev = MINIMUM_ABBREV;
-				else if (hexsz <= abbrev)
-					abbrev = hexsz;
+				else if (40 <= abbrev)
+					abbrev = 40;
 				continue;
 			}
 			if (!strcmp(arg, "--sq")) {
@@ -803,8 +802,6 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 				const char *work_tree = get_git_work_tree();
 				if (work_tree)
 					puts(work_tree);
-				else
-					die("this operation must be run in a work tree");
 				continue;
 			}
 			if (!strcmp(arg, "--show-superproject-working-tree")) {
@@ -921,17 +918,6 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 				show_datestring("--min-age=", arg);
 				continue;
 			}
-			if (opt_with_value(arg, "--show-object-format", &arg)) {
-				const char *val = arg ? arg : "storage";
-
-				if (strcmp(val, "storage") &&
-				    strcmp(val, "input") &&
-				    strcmp(val, "output"))
-					die("unknown mode for --show-object-format: %s",
-					    arg);
-				puts(the_hash_algo->name);
-				continue;
-			}
 			if (show_flag(arg) && verify)
 				die_no_single_rev(quiet);
 			continue;
diff --git a/third_party/git/builtin/rm.c b/third_party/git/builtin/rm.c
index 4858631e0f..19ce95a901 100644
--- a/third_party/git/builtin/rm.c
+++ b/third_party/git/builtin/rm.c
@@ -235,8 +235,7 @@ static int check_local_mod(struct object_id *head, int index_only)
 }
 
 static int show_only = 0, force = 0, index_only = 0, recursive = 0, quiet = 0;
-static int ignore_unmatch = 0, pathspec_file_nul;
-static char *pathspec_from_file;
+static int ignore_unmatch = 0;
 
 static struct option builtin_rm_options[] = {
 	OPT__DRY_RUN(&show_only, N_("dry run")),
@@ -246,8 +245,6 @@ static struct option builtin_rm_options[] = {
 	OPT_BOOL('r', NULL,             &recursive,  N_("allow recursive removal")),
 	OPT_BOOL( 0 , "ignore-unmatch", &ignore_unmatch,
 				N_("exit with a zero status even if nothing matched")),
-	OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
-	OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
 	OPT_END(),
 };
 
@@ -262,24 +259,8 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 
 	argc = parse_options(argc, argv, prefix, builtin_rm_options,
 			     builtin_rm_usage, 0);
-
-	parse_pathspec(&pathspec, 0,
-		       PATHSPEC_PREFER_CWD,
-		       prefix, argv);
-
-	if (pathspec_from_file) {
-		if (pathspec.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
-
-		parse_pathspec_file(&pathspec, 0,
-				    PATHSPEC_PREFER_CWD,
-				    prefix, pathspec_from_file, pathspec_file_nul);
-	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
-	}
-
-	if (!pathspec.nr)
-		die(_("No pathspec was given. Which files should I remove?"));
+	if (!argc)
+		usage_with_options(builtin_rm_usage, builtin_rm_options);
 
 	if (!index_only)
 		setup_work_tree();
@@ -289,6 +270,9 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 	if (read_cache() < 0)
 		die(_("index file corrupt"));
 
+	parse_pathspec(&pathspec, 0,
+		       PATHSPEC_PREFER_CWD,
+		       prefix, argv);
 	refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, &pathspec, NULL, NULL);
 
 	seen = xcalloc(pathspec.nr, 1);
diff --git a/third_party/git/builtin/show-branch.c b/third_party/git/builtin/show-branch.c
index 8c90cbb18f..35d7f51c23 100644
--- a/third_party/git/builtin/show-branch.c
+++ b/third_party/git/builtin/show-branch.c
@@ -536,7 +536,7 @@ static void append_one_rev(const char *av)
 		append_ref(av, &revkey, 0);
 		return;
 	}
-	if (strpbrk(av, "*?[")) {
+	if (strchr(av, '*') || strchr(av, '?') || strchr(av, '[')) {
 		/* glob style match */
 		int saved_matches = ref_name_cnt;
 
diff --git a/third_party/git/builtin/show-index.c b/third_party/git/builtin/show-index.c
index 0826f6a5a2..a6e678809e 100644
--- a/third_party/git/builtin/show-index.c
+++ b/third_party/git/builtin/show-index.c
@@ -11,7 +11,6 @@ int cmd_show_index(int argc, const char **argv, const char *prefix)
 	unsigned nr;
 	unsigned int version;
 	static unsigned int top_index[256];
-	const unsigned hashsz = the_hash_algo->rawsz;
 
 	if (argc != 1)
 		usage(show_index_usage);
@@ -37,23 +36,23 @@ int cmd_show_index(int argc, const char **argv, const char *prefix)
 	}
 	if (version == 1) {
 		for (i = 0; i < nr; i++) {
-			unsigned int offset, entry[(GIT_MAX_RAWSZ + 4) / sizeof(unsigned int)];
+			unsigned int offset, entry[6];
 
-			if (fread(entry, 4 + hashsz, 1, stdin) != 1)
+			if (fread(entry, 4 + 20, 1, stdin) != 1)
 				die("unable to read entry %u/%u", i, nr);
 			offset = ntohl(entry[0]);
-			printf("%u %s\n", offset, hash_to_hex((void *)(entry+1)));
+			printf("%u %s\n", offset, sha1_to_hex((void *)(entry+1)));
 		}
 	} else {
 		unsigned off64_nr = 0;
 		struct {
-			struct object_id oid;
+			unsigned char sha1[20];
 			uint32_t crc;
 			uint32_t off;
 		} *entries;
 		ALLOC_ARRAY(entries, nr);
 		for (i = 0; i < nr; i++)
-			if (fread(entries[i].oid.hash, hashsz, 1, stdin) != 1)
+			if (fread(entries[i].sha1, 20, 1, stdin) != 1)
 				die("unable to read sha1 %u/%u", i, nr);
 		for (i = 0; i < nr; i++)
 			if (fread(&entries[i].crc, 4, 1, stdin) != 1)
@@ -78,7 +77,7 @@ int cmd_show_index(int argc, const char **argv, const char *prefix)
 			}
 			printf("%" PRIuMAX " %s (%08"PRIx32")\n",
 			       (uintmax_t) offset,
-			       oid_to_hex(&entries[i].oid),
+			       sha1_to_hex(entries[i].sha1),
 			       ntohl(entries[i].crc));
 		}
 		free(entries);
diff --git a/third_party/git/builtin/sparse-checkout.c b/third_party/git/builtin/sparse-checkout.c
deleted file mode 100644
index 740da4b6d5..0000000000
--- a/third_party/git/builtin/sparse-checkout.c
+++ /dev/null
@@ -1,631 +0,0 @@
-#include "builtin.h"
-#include "config.h"
-#include "dir.h"
-#include "parse-options.h"
-#include "pathspec.h"
-#include "repository.h"
-#include "run-command.h"
-#include "strbuf.h"
-#include "string-list.h"
-#include "cache.h"
-#include "cache-tree.h"
-#include "lockfile.h"
-#include "resolve-undo.h"
-#include "unpack-trees.h"
-#include "wt-status.h"
-#include "quote.h"
-
-static const char *empty_base = "";
-
-static char const * const builtin_sparse_checkout_usage[] = {
-	N_("git sparse-checkout (init|list|set|add|disable) <options>"),
-	NULL
-};
-
-static char *get_sparse_checkout_filename(void)
-{
-	return git_pathdup("info/sparse-checkout");
-}
-
-static void write_patterns_to_file(FILE *fp, struct pattern_list *pl)
-{
-	int i;
-
-	for (i = 0; i < pl->nr; i++) {
-		struct path_pattern *p = pl->patterns[i];
-
-		if (p->flags & PATTERN_FLAG_NEGATIVE)
-			fprintf(fp, "!");
-
-		fprintf(fp, "%s", p->pattern);
-
-		if (p->flags & PATTERN_FLAG_MUSTBEDIR)
-			fprintf(fp, "/");
-
-		fprintf(fp, "\n");
-	}
-}
-
-static int sparse_checkout_list(int argc, const char **argv)
-{
-	struct pattern_list pl;
-	char *sparse_filename;
-	int res;
-
-	memset(&pl, 0, sizeof(pl));
-
-	pl.use_cone_patterns = core_sparse_checkout_cone;
-
-	sparse_filename = get_sparse_checkout_filename();
-	res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL);
-	free(sparse_filename);
-
-	if (res < 0) {
-		warning(_("this worktree is not sparse (sparse-checkout file may not exist)"));
-		return 0;
-	}
-
-	if (pl.use_cone_patterns) {
-		int i;
-		struct pattern_entry *pe;
-		struct hashmap_iter iter;
-		struct string_list sl = STRING_LIST_INIT_DUP;
-
-		hashmap_for_each_entry(&pl.recursive_hashmap, &iter, pe, ent) {
-			/* pe->pattern starts with "/", skip it */
-			string_list_insert(&sl, pe->pattern + 1);
-		}
-
-		string_list_sort(&sl);
-
-		for (i = 0; i < sl.nr; i++) {
-			quote_c_style(sl.items[i].string, NULL, stdout, 0);
-			printf("\n");
-		}
-
-		return 0;
-	}
-
-	write_patterns_to_file(stdout, &pl);
-	clear_pattern_list(&pl);
-
-	return 0;
-}
-
-static int update_working_directory(struct pattern_list *pl)
-{
-	int result = 0;
-	struct unpack_trees_options o;
-	struct lock_file lock_file = LOCK_INIT;
-	struct object_id oid;
-	struct tree *tree;
-	struct tree_desc t;
-	struct repository *r = the_repository;
-
-	if (repo_read_index_unmerged(r))
-		die(_("you need to resolve your current index first"));
-
-	if (get_oid("HEAD", &oid))
-		return 0;
-
-	tree = parse_tree_indirect(&oid);
-	parse_tree(tree);
-	init_tree_desc(&t, tree->buffer, tree->size);
-
-	memset(&o, 0, sizeof(o));
-	o.verbose_update = isatty(2);
-	o.merge = 1;
-	o.update = 1;
-	o.fn = oneway_merge;
-	o.head_idx = -1;
-	o.src_index = r->index;
-	o.dst_index = r->index;
-	o.skip_sparse_checkout = 0;
-	o.pl = pl;
-	o.keep_pattern_list = !!pl;
-
-	resolve_undo_clear_index(r->index);
-	setup_work_tree();
-
-	cache_tree_free(&r->index->cache_tree);
-
-	repo_hold_locked_index(r, &lock_file, LOCK_DIE_ON_ERROR);
-
-	core_apply_sparse_checkout = 1;
-	result = unpack_trees(1, &t, &o);
-
-	if (!result) {
-		prime_cache_tree(r, r->index, tree);
-		write_locked_index(r->index, &lock_file, COMMIT_LOCK);
-	} else
-		rollback_lock_file(&lock_file);
-
-	return result;
-}
-
-static char *escaped_pattern(char *pattern)
-{
-	char *p = pattern;
-	struct strbuf final = STRBUF_INIT;
-
-	while (*p) {
-		if (is_glob_special(*p))
-			strbuf_addch(&final, '\\');
-
-		strbuf_addch(&final, *p);
-		p++;
-	}
-
-	return strbuf_detach(&final, NULL);
-}
-
-static void write_cone_to_file(FILE *fp, struct pattern_list *pl)
-{
-	int i;
-	struct pattern_entry *pe;
-	struct hashmap_iter iter;
-	struct string_list sl = STRING_LIST_INIT_DUP;
-	struct strbuf parent_pattern = STRBUF_INIT;
-
-	hashmap_for_each_entry(&pl->parent_hashmap, &iter, pe, ent) {
-		if (hashmap_get_entry(&pl->recursive_hashmap, pe, ent, NULL))
-			continue;
-
-		if (!hashmap_contains_parent(&pl->recursive_hashmap,
-					     pe->pattern,
-					     &parent_pattern))
-			string_list_insert(&sl, pe->pattern);
-	}
-
-	string_list_sort(&sl);
-	string_list_remove_duplicates(&sl, 0);
-
-	fprintf(fp, "/*\n!/*/\n");
-
-	for (i = 0; i < sl.nr; i++) {
-		char *pattern = escaped_pattern(sl.items[i].string);
-
-		if (strlen(pattern))
-			fprintf(fp, "%s/\n!%s/*/\n", pattern, pattern);
-		free(pattern);
-	}
-
-	string_list_clear(&sl, 0);
-
-	hashmap_for_each_entry(&pl->recursive_hashmap, &iter, pe, ent) {
-		if (!hashmap_contains_parent(&pl->recursive_hashmap,
-					     pe->pattern,
-					     &parent_pattern))
-			string_list_insert(&sl, pe->pattern);
-	}
-
-	strbuf_release(&parent_pattern);
-
-	string_list_sort(&sl);
-	string_list_remove_duplicates(&sl, 0);
-
-	for (i = 0; i < sl.nr; i++) {
-		char *pattern = escaped_pattern(sl.items[i].string);
-		fprintf(fp, "%s/\n", pattern);
-		free(pattern);
-	}
-}
-
-static int write_patterns_and_update(struct pattern_list *pl)
-{
-	char *sparse_filename;
-	FILE *fp;
-	int fd;
-	struct lock_file lk = LOCK_INIT;
-	int result;
-
-	sparse_filename = get_sparse_checkout_filename();
-
-	if (safe_create_leading_directories(sparse_filename))
-		die(_("failed to create directory for sparse-checkout file"));
-
-	fd = hold_lock_file_for_update(&lk, sparse_filename,
-				      LOCK_DIE_ON_ERROR);
-
-	result = update_working_directory(pl);
-	if (result) {
-		rollback_lock_file(&lk);
-		free(sparse_filename);
-		clear_pattern_list(pl);
-		update_working_directory(NULL);
-		return result;
-	}
-
-	fp = xfdopen(fd, "w");
-
-	if (core_sparse_checkout_cone)
-		write_cone_to_file(fp, pl);
-	else
-		write_patterns_to_file(fp, pl);
-
-	fflush(fp);
-	commit_lock_file(&lk);
-
-	free(sparse_filename);
-	clear_pattern_list(pl);
-
-	return 0;
-}
-
-enum sparse_checkout_mode {
-	MODE_NO_PATTERNS = 0,
-	MODE_ALL_PATTERNS = 1,
-	MODE_CONE_PATTERNS = 2,
-};
-
-static int set_config(enum sparse_checkout_mode mode)
-{
-	const char *config_path;
-
-	if (git_config_set_gently("extensions.worktreeConfig", "true")) {
-		error(_("failed to set extensions.worktreeConfig setting"));
-		return 1;
-	}
-
-	config_path = git_path("config.worktree");
-	git_config_set_in_file_gently(config_path,
-				      "core.sparseCheckout",
-				      mode ? "true" : NULL);
-
-	git_config_set_in_file_gently(config_path,
-				      "core.sparseCheckoutCone",
-				      mode == MODE_CONE_PATTERNS ? "true" : NULL);
-
-	return 0;
-}
-
-static char const * const builtin_sparse_checkout_init_usage[] = {
-	N_("git sparse-checkout init [--cone]"),
-	NULL
-};
-
-static struct sparse_checkout_init_opts {
-	int cone_mode;
-} init_opts;
-
-static int sparse_checkout_init(int argc, const char **argv)
-{
-	struct pattern_list pl;
-	char *sparse_filename;
-	int res;
-	struct object_id oid;
-	int mode;
-	struct strbuf pattern = STRBUF_INIT;
-
-	static struct option builtin_sparse_checkout_init_options[] = {
-		OPT_BOOL(0, "cone", &init_opts.cone_mode,
-			 N_("initialize the sparse-checkout in cone mode")),
-		OPT_END(),
-	};
-
-	repo_read_index(the_repository);
-	require_clean_work_tree(the_repository,
-				N_("initialize sparse-checkout"), NULL, 1, 0);
-
-	argc = parse_options(argc, argv, NULL,
-			     builtin_sparse_checkout_init_options,
-			     builtin_sparse_checkout_init_usage, 0);
-
-	if (init_opts.cone_mode) {
-		mode = MODE_CONE_PATTERNS;
-		core_sparse_checkout_cone = 1;
-	} else
-		mode = MODE_ALL_PATTERNS;
-
-	if (set_config(mode))
-		return 1;
-
-	memset(&pl, 0, sizeof(pl));
-
-	sparse_filename = get_sparse_checkout_filename();
-	res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL);
-
-	/* If we already have a sparse-checkout file, use it. */
-	if (res >= 0) {
-		free(sparse_filename);
-		core_apply_sparse_checkout = 1;
-		return update_working_directory(NULL);
-	}
-
-	if (get_oid("HEAD", &oid)) {
-		FILE *fp;
-
-		/* assume we are in a fresh repo, but update the sparse-checkout file */
-		fp = xfopen(sparse_filename, "w");
-		if (!fp)
-			die(_("failed to open '%s'"), sparse_filename);
-
-		free(sparse_filename);
-		fprintf(fp, "/*\n!/*/\n");
-		fclose(fp);
-		return 0;
-	}
-
-	strbuf_addstr(&pattern, "/*");
-	add_pattern(strbuf_detach(&pattern, NULL), empty_base, 0, &pl, 0);
-	strbuf_addstr(&pattern, "!/*/");
-	add_pattern(strbuf_detach(&pattern, NULL), empty_base, 0, &pl, 0);
-
-	return write_patterns_and_update(&pl);
-}
-
-static void insert_recursive_pattern(struct pattern_list *pl, struct strbuf *path)
-{
-	struct pattern_entry *e = xmalloc(sizeof(*e));
-	e->patternlen = path->len;
-	e->pattern = strbuf_detach(path, NULL);
-	hashmap_entry_init(&e->ent,
-			   ignore_case ?
-			   strihash(e->pattern) :
-			   strhash(e->pattern));
-
-	hashmap_add(&pl->recursive_hashmap, &e->ent);
-
-	while (e->patternlen) {
-		char *slash = strrchr(e->pattern, '/');
-		char *oldpattern = e->pattern;
-		size_t newlen;
-
-		if (slash == e->pattern)
-			break;
-
-		newlen = slash - e->pattern;
-		e = xmalloc(sizeof(struct pattern_entry));
-		e->patternlen = newlen;
-		e->pattern = xstrndup(oldpattern, newlen);
-		hashmap_entry_init(&e->ent,
-				   ignore_case ?
-				   strihash(e->pattern) :
-				   strhash(e->pattern));
-
-		if (!hashmap_get_entry(&pl->parent_hashmap, e, ent, NULL))
-			hashmap_add(&pl->parent_hashmap, &e->ent);
-	}
-}
-
-static void strbuf_to_cone_pattern(struct strbuf *line, struct pattern_list *pl)
-{
-	strbuf_trim(line);
-
-	strbuf_trim_trailing_dir_sep(line);
-
-	if (strbuf_normalize_path(line))
-		die(_("could not normalize path %s"), line->buf);
-
-	if (!line->len)
-		return;
-
-	if (line->buf[0] != '/')
-		strbuf_insertstr(line, 0, "/");
-
-	insert_recursive_pattern(pl, line);
-}
-
-static char const * const builtin_sparse_checkout_set_usage[] = {
-	N_("git sparse-checkout (set|add) (--stdin | <patterns>)"),
-	NULL
-};
-
-static struct sparse_checkout_set_opts {
-	int use_stdin;
-} set_opts;
-
-static void add_patterns_from_input(struct pattern_list *pl,
-				    int argc, const char **argv)
-{
-	int i;
-	if (core_sparse_checkout_cone) {
-		struct strbuf line = STRBUF_INIT;
-
-		hashmap_init(&pl->recursive_hashmap, pl_hashmap_cmp, NULL, 0);
-		hashmap_init(&pl->parent_hashmap, pl_hashmap_cmp, NULL, 0);
-		pl->use_cone_patterns = 1;
-
-		if (set_opts.use_stdin) {
-			struct strbuf unquoted = STRBUF_INIT;
-			while (!strbuf_getline(&line, stdin)) {
-				if (line.buf[0] == '"') {
-					strbuf_reset(&unquoted);
-					if (unquote_c_style(&unquoted, line.buf, NULL))
-						die(_("unable to unquote C-style string '%s'"),
-						line.buf);
-
-					strbuf_swap(&unquoted, &line);
-				}
-
-				strbuf_to_cone_pattern(&line, pl);
-			}
-
-			strbuf_release(&unquoted);
-		} else {
-			for (i = 0; i < argc; i++) {
-				strbuf_setlen(&line, 0);
-				strbuf_addstr(&line, argv[i]);
-				strbuf_to_cone_pattern(&line, pl);
-			}
-		}
-	} else {
-		if (set_opts.use_stdin) {
-			struct strbuf line = STRBUF_INIT;
-
-			while (!strbuf_getline(&line, stdin)) {
-				size_t len;
-				char *buf = strbuf_detach(&line, &len);
-				add_pattern(buf, empty_base, 0, pl, 0);
-			}
-		} else {
-			for (i = 0; i < argc; i++)
-				add_pattern(argv[i], empty_base, 0, pl, 0);
-		}
-	}
-}
-
-enum modify_type {
-	REPLACE,
-	ADD,
-};
-
-static void add_patterns_cone_mode(int argc, const char **argv,
-				   struct pattern_list *pl)
-{
-	struct strbuf buffer = STRBUF_INIT;
-	struct pattern_entry *pe;
-	struct hashmap_iter iter;
-	struct pattern_list existing;
-	char *sparse_filename = get_sparse_checkout_filename();
-
-	add_patterns_from_input(pl, argc, argv);
-
-	memset(&existing, 0, sizeof(existing));
-	existing.use_cone_patterns = core_sparse_checkout_cone;
-
-	if (add_patterns_from_file_to_list(sparse_filename, "", 0,
-					   &existing, NULL))
-		die(_("unable to load existing sparse-checkout patterns"));
-	free(sparse_filename);
-
-	hashmap_for_each_entry(&existing.recursive_hashmap, &iter, pe, ent) {
-		if (!hashmap_contains_parent(&pl->recursive_hashmap,
-					pe->pattern, &buffer) ||
-		    !hashmap_contains_parent(&pl->parent_hashmap,
-					pe->pattern, &buffer)) {
-			strbuf_reset(&buffer);
-			strbuf_addstr(&buffer, pe->pattern);
-			insert_recursive_pattern(pl, &buffer);
-		}
-	}
-
-	clear_pattern_list(&existing);
-	strbuf_release(&buffer);
-}
-
-static void add_patterns_literal(int argc, const char **argv,
-				 struct pattern_list *pl)
-{
-	char *sparse_filename = get_sparse_checkout_filename();
-	if (add_patterns_from_file_to_list(sparse_filename, "", 0,
-					   pl, NULL))
-		die(_("unable to load existing sparse-checkout patterns"));
-	free(sparse_filename);
-	add_patterns_from_input(pl, argc, argv);
-}
-
-static int modify_pattern_list(int argc, const char **argv, enum modify_type m)
-{
-	int result;
-	int changed_config = 0;
-	struct pattern_list pl;
-	memset(&pl, 0, sizeof(pl));
-
-	switch (m) {
-	case ADD:
-		if (core_sparse_checkout_cone)
-			add_patterns_cone_mode(argc, argv, &pl);
-		else
-			add_patterns_literal(argc, argv, &pl);
-		break;
-
-	case REPLACE:
-		add_patterns_from_input(&pl, argc, argv);
-		break;
-	}
-
-	if (!core_apply_sparse_checkout) {
-		set_config(MODE_ALL_PATTERNS);
-		core_apply_sparse_checkout = 1;
-		changed_config = 1;
-	}
-
-	result = write_patterns_and_update(&pl);
-
-	if (result && changed_config)
-		set_config(MODE_NO_PATTERNS);
-
-	clear_pattern_list(&pl);
-	return result;
-}
-
-static int sparse_checkout_set(int argc, const char **argv, const char *prefix,
-			       enum modify_type m)
-{
-	static struct option builtin_sparse_checkout_set_options[] = {
-		OPT_BOOL(0, "stdin", &set_opts.use_stdin,
-			 N_("read patterns from standard in")),
-		OPT_END(),
-	};
-
-	repo_read_index(the_repository);
-	require_clean_work_tree(the_repository,
-				N_("set sparse-checkout patterns"), NULL, 1, 0);
-
-	argc = parse_options(argc, argv, prefix,
-			     builtin_sparse_checkout_set_options,
-			     builtin_sparse_checkout_set_usage,
-			     PARSE_OPT_KEEP_UNKNOWN);
-
-	return modify_pattern_list(argc, argv, m);
-}
-
-static int sparse_checkout_disable(int argc, const char **argv)
-{
-	struct pattern_list pl;
-	struct strbuf match_all = STRBUF_INIT;
-
-	repo_read_index(the_repository);
-	require_clean_work_tree(the_repository,
-				N_("disable sparse-checkout"), NULL, 1, 0);
-
-	memset(&pl, 0, sizeof(pl));
-	hashmap_init(&pl.recursive_hashmap, pl_hashmap_cmp, NULL, 0);
-	hashmap_init(&pl.parent_hashmap, pl_hashmap_cmp, NULL, 0);
-	pl.use_cone_patterns = 0;
-	core_apply_sparse_checkout = 1;
-
-	strbuf_addstr(&match_all, "/*");
-	add_pattern(strbuf_detach(&match_all, NULL), empty_base, 0, &pl, 0);
-
-	if (update_working_directory(&pl))
-		die(_("error while refreshing working directory"));
-
-	clear_pattern_list(&pl);
-	return set_config(MODE_NO_PATTERNS);
-}
-
-int cmd_sparse_checkout(int argc, const char **argv, const char *prefix)
-{
-	static struct option builtin_sparse_checkout_options[] = {
-		OPT_END(),
-	};
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage_with_options(builtin_sparse_checkout_usage,
-				   builtin_sparse_checkout_options);
-
-	argc = parse_options(argc, argv, prefix,
-			     builtin_sparse_checkout_options,
-			     builtin_sparse_checkout_usage,
-			     PARSE_OPT_STOP_AT_NON_OPTION);
-
-	git_config(git_default_config, NULL);
-
-	if (argc > 0) {
-		if (!strcmp(argv[0], "list"))
-			return sparse_checkout_list(argc, argv);
-		if (!strcmp(argv[0], "init"))
-			return sparse_checkout_init(argc, argv);
-		if (!strcmp(argv[0], "set"))
-			return sparse_checkout_set(argc, argv, prefix, REPLACE);
-		if (!strcmp(argv[0], "add"))
-			return sparse_checkout_set(argc, argv, prefix, ADD);
-		if (!strcmp(argv[0], "disable"))
-			return sparse_checkout_disable(argc, argv);
-	}
-
-	usage_with_options(builtin_sparse_checkout_usage,
-			   builtin_sparse_checkout_options);
-}
diff --git a/third_party/git/builtin/stash.c b/third_party/git/builtin/stash.c
index 78af6ce564..b5a301f24d 100644
--- a/third_party/git/builtin/stash.c
+++ b/third_party/git/builtin/stash.c
@@ -27,7 +27,6 @@ static const char * const git_stash_usage[] = {
 	N_("git stash clear"),
 	N_("git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
 	   "          [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"
-	   "          [--pathspec-from-file=<file> [--pathspec-file-nul]]\n"
 	   "          [--] [<pathspec>...]]"),
 	N_("git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
 	   "          [-u|--include-untracked] [-a|--all] [<message>]"),
@@ -397,7 +396,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
 	const struct object_id *bases[1];
 
 	read_cache_preload(NULL);
-	if (refresh_and_write_cache(REFRESH_QUIET, 0, 0))
+	if (refresh_cache(REFRESH_QUIET))
 		return -1;
 
 	if (write_cache_as_tree(&c_tree, 0, NULL))
@@ -428,8 +427,6 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
 				return error(_("could not save index tree"));
 
 			reset_head();
-			discard_cache();
-			read_cache();
 		}
 	}
 
@@ -484,12 +481,13 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
 		if (ret)
 			return -1;
 
-		/* read back the result of update_index() back from the disk */
 		discard_cache();
-		read_cache();
 	}
 
-	if (!quiet) {
+	if (quiet) {
+		if (refresh_cache(REFRESH_QUIET))
+			warning("could not refresh index");
+	} else {
 		struct child_process cp = CHILD_PROCESS_INIT;
 
 		/*
@@ -499,10 +497,6 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
 		 */
 		cp.git_cmd = 1;
 		cp.dir = prefix;
-		argv_array_pushf(&cp.env_array, GIT_WORK_TREE_ENVIRONMENT"=%s",
-				 absolute_path(get_git_work_tree()));
-		argv_array_pushf(&cp.env_array, GIT_DIR_ENVIRONMENT"=%s",
-				 absolute_path(get_git_dir()));
 		argv_array_push(&cp.args, "status");
 		run_command(&cp);
 	}
@@ -999,9 +993,9 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
 {
 	int ret = 0;
 	struct child_process cp_read_tree = CHILD_PROCESS_INIT;
+	struct child_process cp_add_i = CHILD_PROCESS_INIT;
 	struct child_process cp_diff_tree = CHILD_PROCESS_INIT;
 	struct index_state istate = { NULL };
-	char *old_index_env = NULL, *old_repo_index_file;
 
 	remove_path(stash_index_path.buf);
 
@@ -1015,19 +1009,16 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
 	}
 
 	/* Find out what the user wants. */
-	old_repo_index_file = the_repository->index_file;
-	the_repository->index_file = stash_index_path.buf;
-	old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT));
-	setenv(INDEX_ENVIRONMENT, the_repository->index_file, 1);
-
-	ret = run_add_interactive(NULL, "--patch=stash", ps);
-
-	the_repository->index_file = old_repo_index_file;
-	if (old_index_env && *old_index_env)
-		setenv(INDEX_ENVIRONMENT, old_index_env, 1);
-	else
-		unsetenv(INDEX_ENVIRONMENT);
-	FREE_AND_NULL(old_index_env);
+	cp_add_i.git_cmd = 1;
+	argv_array_pushl(&cp_add_i.args, "add--interactive", "--patch=stash",
+			 "--", NULL);
+	add_pathspecs(&cp_add_i.args, ps);
+	argv_array_pushf(&cp_add_i.env_array, "GIT_INDEX_FILE=%s",
+			 stash_index_path.buf);
+	if (run_command(&cp_add_i)) {
+		ret = -1;
+		goto done;
+	}
 
 	/* State of the working tree. */
 	if (write_index_as_tree(&info->w_tree, &istate, stash_index_path.buf, 0,
@@ -1091,9 +1082,8 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps
 	}
 
 	cp_upd_index.git_cmd = 1;
-	argv_array_pushl(&cp_upd_index.args, "update-index",
-			 "--ignore-skip-worktree-entries",
-			 "-z", "--add", "--remove", "--stdin", NULL);
+	argv_array_pushl(&cp_upd_index.args, "update-index", "-z", "--add",
+			 "--remove", "--stdin", NULL);
 	argv_array_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s",
 			 stash_index_path.buf);
 
@@ -1139,10 +1129,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
 	prepare_fallback_ident("git stash", "git@stash");
 
 	read_cache_preload(NULL);
-	if (refresh_and_write_cache(REFRESH_QUIET, 0, 0) < 0) {
-		ret = -1;
-		goto done;
-	}
+	refresh_cache(REFRESH_QUIET);
 
 	if (get_oid("HEAD", &info->b_commit)) {
 		if (!quiet)
@@ -1303,7 +1290,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
 		free(ps_matched);
 	}
 
-	if (refresh_and_write_cache(REFRESH_QUIET, 0, 0)) {
+	if (refresh_cache(REFRESH_QUIET)) {
 		ret = -1;
 		goto done;
 	}
@@ -1396,7 +1383,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
 			struct child_process cp = CHILD_PROCESS_INIT;
 			cp.git_cmd = 1;
 			argv_array_pushl(&cp.args, "reset", "--hard", "-q",
-					 "--no-recurse-submodules", NULL);
+					 NULL);
 			if (run_command(&cp)) {
 				ret = -1;
 				goto done;
@@ -1452,17 +1439,13 @@ done:
 	return ret;
 }
 
-static int push_stash(int argc, const char **argv, const char *prefix,
-		      int push_assumed)
+static int push_stash(int argc, const char **argv, const char *prefix)
 {
-	int force_assume = 0;
 	int keep_index = -1;
 	int patch_mode = 0;
 	int include_untracked = 0;
 	int quiet = 0;
-	int pathspec_file_nul = 0;
 	const char *stash_msg = NULL;
-	const char *pathspec_from_file = NULL;
 	struct pathspec ps;
 	struct option options[] = {
 		OPT_BOOL('k', "keep-index", &keep_index,
@@ -1476,45 +1459,16 @@ static int push_stash(int argc, const char **argv, const char *prefix,
 			    N_("include ignore files"), 2),
 		OPT_STRING('m', "message", &stash_msg, N_("message"),
 			   N_("stash message")),
-		OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
-		OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
 		OPT_END()
 	};
 
-	if (argc) {
-		force_assume = !strcmp(argv[0], "-p");
+	if (argc)
 		argc = parse_options(argc, argv, prefix, options,
 				     git_stash_push_usage,
-				     PARSE_OPT_KEEP_DASHDASH);
-	}
-
-	if (argc) {
-		if (!strcmp(argv[0], "--")) {
-			argc--;
-			argv++;
-		} else if (push_assumed && !force_assume) {
-			die("subcommand wasn't specified; 'push' can't be assumed due to unexpected token '%s'",
-			    argv[0]);
-		}
-	}
+				     0);
 
 	parse_pathspec(&ps, 0, PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
 		       prefix, argv);
-
-	if (pathspec_from_file) {
-		if (patch_mode)
-			die(_("--pathspec-from-file is incompatible with --patch"));
-
-		if (ps.nr)
-			die(_("--pathspec-from-file is incompatible with pathspec arguments"));
-
-		parse_pathspec_file(&ps, 0,
-				    PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
-				    prefix, pathspec_from_file, pathspec_file_nul);
-	} else if (pathspec_file_nul) {
-		die(_("--pathspec-file-nul requires --pathspec-from-file"));
-	}
-
 	return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
 			     include_untracked);
 }
@@ -1584,6 +1538,7 @@ static int use_builtin_stash(void)
 
 int cmd_stash(int argc, const char **argv, const char *prefix)
 {
+	int i = -1;
 	pid_t pid = getpid();
 	const char *index_file;
 	struct argv_array args = ARGV_ARRAY_INIT;
@@ -1616,7 +1571,7 @@ int cmd_stash(int argc, const char **argv, const char *prefix)
 		    (uintmax_t)pid);
 
 	if (!argc)
-		return !!push_stash(0, NULL, prefix, 0);
+		return !!push_stash(0, NULL, prefix);
 	else if (!strcmp(argv[0], "apply"))
 		return !!apply_stash(argc, argv, prefix);
 	else if (!strcmp(argv[0], "clear"))
@@ -1636,15 +1591,45 @@ int cmd_stash(int argc, const char **argv, const char *prefix)
 	else if (!strcmp(argv[0], "create"))
 		return !!create_stash(argc, argv, prefix);
 	else if (!strcmp(argv[0], "push"))
-		return !!push_stash(argc, argv, prefix, 0);
+		return !!push_stash(argc, argv, prefix);
 	else if (!strcmp(argv[0], "save"))
 		return !!save_stash(argc, argv, prefix);
 	else if (*argv[0] != '-')
 		usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv[0]),
 			      git_stash_usage, options);
 
-	/* Assume 'stash push' */
+	if (strcmp(argv[0], "-p")) {
+		while (++i < argc && strcmp(argv[i], "--")) {
+			/*
+			 * `akpqu` is a string which contains all short options,
+			 * except `-m` which is verified separately.
+			 */
+			if ((strlen(argv[i]) == 2) && *argv[i] == '-' &&
+			    strchr("akpqu", argv[i][1]))
+				continue;
+
+			if (!strcmp(argv[i], "--all") ||
+			    !strcmp(argv[i], "--keep-index") ||
+			    !strcmp(argv[i], "--no-keep-index") ||
+			    !strcmp(argv[i], "--patch") ||
+			    !strcmp(argv[i], "--quiet") ||
+			    !strcmp(argv[i], "--include-untracked"))
+				continue;
+
+			/*
+			 * `-m` and `--message=` are verified separately because
+			 * they need to be immediately followed by a string
+			 * (i.e.`-m"foobar"` or `--message="foobar"`).
+			 */
+			if (starts_with(argv[i], "-m") ||
+			    starts_with(argv[i], "--message="))
+				continue;
+
+			usage_with_options(git_stash_usage, options);
+		}
+	}
+
 	argv_array_push(&args, "push");
 	argv_array_pushv(&args, argv);
-	return !!push_stash(args.argc, args.argv, prefix, 1);
+	return !!push_stash(args.argc, args.argv, prefix);
 }
diff --git a/third_party/git/builtin/submodule--helper.c b/third_party/git/builtin/submodule--helper.c
index 86a608eec1..909e77e802 100644
--- a/third_party/git/builtin/submodule--helper.c
+++ b/third_party/git/builtin/submodule--helper.c
@@ -19,8 +19,6 @@
 #include "diffcore.h"
 #include "diff.h"
 #include "object-store.h"
-#include "dir.h"
-#include "advice.h"
 
 #define OPT_QUIET (1 << 0)
 #define OPT_CACHED (1 << 1)
@@ -426,7 +424,7 @@ static int module_list(int argc, const char **argv, const char *prefix)
 		const struct cache_entry *ce = list.entries[i];
 
 		if (ce_stage(ce))
-			printf("%06o %s U\t", ce->ce_mode, oid_to_hex(&null_oid));
+			printf("%06o %s U\t", ce->ce_mode, sha1_to_hex(null_sha1));
 		else
 			printf("%06o %s %d\t", ce->ce_mode,
 			       oid_to_hex(&ce->oid), ce_stage(ce));
@@ -782,8 +780,6 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
 	struct argv_array diff_files_args = ARGV_ARRAY_INIT;
 	struct rev_info rev;
 	int diff_files_result;
-	struct strbuf buf = STRBUF_INIT;
-	const char *git_dir;
 
 	if (!submodule_from_path(the_repository, &null_oid, path))
 		die(_("no submodule mapping found in .gitmodules for path '%s'"),
@@ -796,26 +792,17 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
 		goto cleanup;
 	}
 
-	strbuf_addf(&buf, "%s/.git", path);
-	git_dir = read_gitfile(buf.buf);
-	if (!git_dir)
-		git_dir = buf.buf;
-
-	if (!is_submodule_active(the_repository, path) ||
-	    !is_git_directory(git_dir)) {
+	if (!is_submodule_active(the_repository, path)) {
 		print_status(flags, '-', path, ce_oid, displaypath);
-		strbuf_release(&buf);
 		goto cleanup;
 	}
-	strbuf_release(&buf);
 
 	argv_array_pushl(&diff_files_args, "diff-files",
 			 "--ignore-submodules=dirty", "--quiet", "--",
 			 path, NULL);
 
 	git_config(git_diff_basic_config, NULL);
-
-	repo_init_revisions(the_repository, &rev, NULL);
+	repo_init_revisions(the_repository, &rev, prefix);
 	rev.abbrev = 0;
 	diff_files_args.argc = setup_revisions(diff_files_args.argc,
 					       diff_files_args.argv,
@@ -1235,7 +1222,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix)
 
 static int clone_submodule(const char *path, const char *gitdir, const char *url,
 			   const char *depth, struct string_list *reference, int dissociate,
-			   int quiet, int progress, int single_branch)
+			   int quiet, int progress)
 {
 	struct child_process cp = CHILD_PROCESS_INIT;
 
@@ -1257,10 +1244,6 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url
 		argv_array_push(&cp.args, "--dissociate");
 	if (gitdir && *gitdir)
 		argv_array_pushl(&cp.args, "--separate-git-dir", gitdir, NULL);
-	if (single_branch >= 0)
-		argv_array_push(&cp.args, single_branch ?
-					  "--single-branch" :
-					  "--no-single-branch");
 
 	argv_array_push(&cp.args, "--");
 	argv_array_push(&cp.args, url);
@@ -1285,13 +1268,6 @@ struct submodule_alternate_setup {
 #define SUBMODULE_ALTERNATE_SETUP_INIT { NULL, \
 	SUBMODULE_ALTERNATE_ERROR_IGNORE, NULL }
 
-static const char alternate_error_advice[] = N_(
-"An alternate computed from a superproject's alternate is invalid.\n"
-"To allow Git to clone without an alternate in such a case, set\n"
-"submodule.alternateErrorStrategy to 'info' or, equivalently, clone with\n"
-"'--reference-if-able' instead of '--reference'."
-);
-
 static int add_possible_reference_from_superproject(
 		struct object_directory *odb, void *sas_cb)
 {
@@ -1323,8 +1299,6 @@ static int add_possible_reference_from_superproject(
 		} else {
 			switch (sas->error_mode) {
 			case SUBMODULE_ALTERNATE_ERROR_DIE:
-				if (advice_submodule_alternate_error_strategy_die)
-					advise(_(alternate_error_advice));
 				die(_("submodule '%s' cannot add alternate: %s"),
 				    sas->submodule_name, err.buf);
 			case SUBMODULE_ALTERNATE_ERROR_INFO:
@@ -1385,9 +1359,8 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 	char *p, *path = NULL, *sm_gitdir;
 	struct strbuf sb = STRBUF_INIT;
 	struct string_list reference = STRING_LIST_INIT_NODUP;
-	int dissociate = 0, require_init = 0;
+	int dissociate = 0;
 	char *sm_alternate = NULL, *error_strategy = NULL;
-	int single_branch = -1;
 
 	struct option module_clone_options[] = {
 		OPT_STRING(0, "prefix", &prefix,
@@ -1413,17 +1386,12 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		OPT__QUIET(&quiet, "Suppress output for cloning a submodule"),
 		OPT_BOOL(0, "progress", &progress,
 			   N_("force cloning progress")),
-		OPT_BOOL(0, "require-init", &require_init,
-			   N_("disallow cloning into non-empty directory")),
-		OPT_BOOL(0, "single-branch", &single_branch,
-			 N_("clone only one branch, HEAD or --branch")),
 		OPT_END()
 	};
 
 	const char *const git_submodule_helper_usage[] = {
 		N_("git submodule--helper clone [--prefix=<path>] [--quiet] "
 		   "[--reference <repository>] [--name <name>] [--depth <depth>] "
-		   "[--single-branch] "
 		   "--url <url> --path <path>"),
 		NULL
 	};
@@ -1445,10 +1413,6 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 	} else
 		path = xstrdup(path);
 
-	if (validate_submodule_git_dir(sm_gitdir, name) < 0)
-		die(_("refusing to create/use '%s' in another submodule's "
-			"git dir"), sm_gitdir);
-
 	if (!file_exists(sm_gitdir)) {
 		if (safe_create_leading_directories_const(sm_gitdir) < 0)
 			die(_("could not create directory '%s'"), sm_gitdir);
@@ -1456,12 +1420,10 @@ static int module_clone(int argc, const char **argv, const char *prefix)
 		prepare_possible_alternates(name, &reference);
 
 		if (clone_submodule(path, sm_gitdir, url, depth, &reference, dissociate,
-				    quiet, progress, single_branch))
+				    quiet, progress))
 			die(_("clone of '%s' into submodule path '%s' failed"),
 			    url, path);
 	} else {
-		if (require_init && !access(path, X_OK) && !is_empty_dir(path))
-			die(_("directory not empty: '%s'"), path);
 		if (safe_create_leading_directories_const(path) < 0)
 			die(_("could not create directory '%s'"), path);
 		strbuf_addf(&sb, "%s/index", sm_gitdir);
@@ -1516,8 +1478,6 @@ static void determine_submodule_update_strategy(struct repository *r,
 			die(_("Invalid update mode '%s' configured for submodule path '%s'"),
 				val, path);
 	} else if (sub->update_strategy.type != SM_UPDATE_UNSPECIFIED) {
-		if (sub->update_strategy.type == SM_UPDATE_COMMAND)
-			BUG("how did we read update = !command from .gitmodules?");
 		out->type = sub->update_strategy.type;
 		out->command = sub->update_strategy.command;
 	} else
@@ -1576,11 +1536,9 @@ struct submodule_update_clone {
 	int recommend_shallow;
 	struct string_list references;
 	int dissociate;
-	unsigned require_init;
 	const char *depth;
 	const char *recursive_prefix;
 	const char *prefix;
-	int single_branch;
 
 	/* to be consumed by git-submodule.sh */
 	struct update_clone_data *update_clone;
@@ -1595,14 +1553,10 @@ struct submodule_update_clone {
 
 	int max_jobs;
 };
-#define SUBMODULE_UPDATE_CLONE_INIT { \
-	.list = MODULE_LIST_INIT, \
-	.update = SUBMODULE_UPDATE_STRATEGY_INIT, \
-	.recommend_shallow = -1, \
-	.references = STRING_LIST_INIT_DUP, \
-	.single_branch = -1, \
-	.max_jobs = 1, \
-}
+#define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \
+	SUBMODULE_UPDATE_STRATEGY_INIT, 0, 0, -1, STRING_LIST_INIT_DUP, 0, \
+	NULL, NULL, NULL, \
+	NULL, 0, 0, 0, NULL, 0, 0, 1}
 
 
 static void next_submodule_warn_missing(struct submodule_update_clone *suc,
@@ -1727,8 +1681,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 		argv_array_pushl(&child->args, "--prefix", suc->prefix, NULL);
 	if (suc->recommend_shallow && sub->recommend_shallow == 1)
 		argv_array_push(&child->args, "--depth=1");
-	if (suc->require_init)
-		argv_array_push(&child->args, "--require-init");
 	argv_array_pushl(&child->args, "--path", sub->path, NULL);
 	argv_array_pushl(&child->args, "--name", sub->name, NULL);
 	argv_array_pushl(&child->args, "--url", url, NULL);
@@ -1741,10 +1693,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
 		argv_array_push(&child->args, "--dissociate");
 	if (suc->depth)
 		argv_array_push(&child->args, suc->depth);
-	if (suc->single_branch >= 0)
-		argv_array_push(&child->args, suc->single_branch ?
-					      "--single-branch" :
-					      "--no-single-branch");
 
 cleanup:
 	strbuf_reset(&displaypath_sb);
@@ -1922,15 +1870,11 @@ static int update_clone(int argc, const char **argv, const char *prefix)
 		OPT__QUIET(&suc.quiet, N_("don't print cloning progress")),
 		OPT_BOOL(0, "progress", &suc.progress,
 			    N_("force cloning progress")),
-		OPT_BOOL(0, "require-init", &suc.require_init,
-			   N_("disallow cloning into non-empty directory")),
-		OPT_BOOL(0, "single-branch", &suc.single_branch,
-			 N_("clone only one branch, HEAD or --branch")),
 		OPT_END()
 	};
 
 	const char *const git_submodule_helper_usage[] = {
-		N_("git submodule--helper update-clone [--prefix=<path>] [<path>...]"),
+		N_("git submodule--helper update_clone [--prefix=<path>] [<path>...]"),
 		NULL
 	};
 	suc.prefix = prefix;
diff --git a/third_party/git/builtin/unpack-objects.c b/third_party/git/builtin/unpack-objects.c
index dd4a75e030..a87a4bfd2c 100644
--- a/third_party/git/builtin/unpack-objects.c
+++ b/third_party/git/builtin/unpack-objects.c
@@ -24,7 +24,6 @@ static off_t consumed_bytes;
 static off_t max_input_size;
 static git_hash_ctx ctx;
 static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
-static struct progress *progress;
 
 /*
  * When running under --strict mode, objects whose reachability are
@@ -93,7 +92,6 @@ static void use(int bytes)
 	consumed_bytes += bytes;
 	if (max_input_size && consumed_bytes > max_input_size)
 		die(_("pack exceeds maximum allowed size"));
-	display_throughput(progress, consumed_bytes);
 }
 
 static void *get_data(unsigned long size)
@@ -265,8 +263,7 @@ static void write_object(unsigned nr, enum object_type type,
 	} else {
 		struct object *obj;
 		int eaten;
-		hash_object_file(the_hash_algo, buf, size, type_name(type),
-				 &obj_list[nr].oid);
+		hash_object_file(buf, size, type_name(type), &obj_list[nr].oid);
 		added_object(nr, type, buf, size);
 		obj = parse_object_buffer(the_repository, &obj_list[nr].oid,
 					  type, size, buf,
@@ -487,6 +484,7 @@ static void unpack_one(unsigned nr)
 static void unpack_all(void)
 {
 	int i;
+	struct progress *progress = NULL;
 	struct pack_header *hdr = fill(sizeof(struct pack_header));
 
 	nr_objects = ntohl(hdr->hdr_entries);
diff --git a/third_party/git/builtin/update-index.c b/third_party/git/builtin/update-index.c
index d527b8f106..dff2f4b837 100644
--- a/third_party/git/builtin/update-index.c
+++ b/third_party/git/builtin/update-index.c
@@ -35,7 +35,6 @@ static int verbose;
 static int mark_valid_only;
 static int mark_skip_worktree_only;
 static int mark_fsmonitor_only;
-static int ignore_skip_worktree_entries;
 #define MARK_FLAG 1
 #define UNMARK_FLAG 2
 static struct strbuf mtime_dir = STRBUF_INIT;
@@ -382,8 +381,7 @@ static int process_path(const char *path, struct stat *st, int stat_errno)
 		 * so updating it does not make sense.
 		 * On the other hand, removing it from index should work
 		 */
-		if (!ignore_skip_worktree_entries && allow_remove &&
-		    remove_file_from_cache(path))
+		if (allow_remove && remove_file_from_cache(path))
 			return error("%s: cannot remove from the index", path);
 		return 0;
 	}
@@ -968,7 +966,6 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
 	struct parse_opt_ctx_t ctx;
 	strbuf_getline_fn getline_fn;
 	int parseopt_state = PARSE_OPT_UNKNOWN;
-	struct repository *r = the_repository;
 	struct option options[] = {
 		OPT_BIT('q', NULL, &refresh_args.flags,
 			N_("continue refresh even when index needs update"),
@@ -1016,8 +1013,6 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
 		{OPTION_SET_INT, 0, "no-skip-worktree", &mark_skip_worktree_only, NULL,
 			N_("clear skip-worktree bit"),
 			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
-		OPT_BOOL(0, "ignore-skip-worktree-entries", &ignore_skip_worktree_entries,
-			 N_("do not touch index-only entries")),
 		OPT_SET_INT(0, "info-only", &info_only,
 			N_("add to index only; do not add content to object database"), 1),
 		OPT_SET_INT(0, "force-remove", &force_remove,
@@ -1185,12 +1180,11 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
 		remove_split_index(&the_index);
 	}
 
-	prepare_repo_settings(r);
 	switch (untracked_cache) {
 	case UC_UNSPECIFIED:
 		break;
 	case UC_DISABLE:
-		if (r->settings.core_untracked_cache == UNTRACKED_CACHE_WRITE)
+		if (git_config_get_untracked_cache() == 1)
 			warning(_("core.untrackedCache is set to true; "
 				  "remove or change it, if you really want to "
 				  "disable the untracked cache"));
@@ -1202,7 +1196,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
 		return !test_if_untracked_cache_is_supported();
 	case UC_ENABLE:
 	case UC_FORCE:
-		if (r->settings.core_untracked_cache == UNTRACKED_CACHE_REMOVE)
+		if (git_config_get_untracked_cache() == 0)
 			warning(_("core.untrackedCache is set to false; "
 				  "remove or change it, if you really want to "
 				  "enable the untracked cache"));
diff --git a/third_party/git/builtin/worktree.c b/third_party/git/builtin/worktree.c
index 24f22800f3..a5bb02b207 100644
--- a/third_party/git/builtin/worktree.c
+++ b/third_party/git/builtin/worktree.c
@@ -10,6 +10,7 @@
 #include "run-command.h"
 #include "sigchain.h"
 #include "submodule.h"
+#include "refs.h"
 #include "utf8.h"
 #include "worktree.h"
 
@@ -234,7 +235,14 @@ static void validate_worktree_add(const char *path, const struct add_opts *opts)
 		die(_("'%s' already exists"), path);
 
 	worktrees = get_worktrees(0);
-	wt = find_worktree_by_path(worktrees, path);
+	/*
+	 * find_worktree()'s suffix matching may undesirably find the main
+	 * rather than a linked worktree (for instance, when the basenames
+	 * of the main worktree and the one being created are the same).
+	 * We're only interested in linked worktrees, so skip the main
+	 * worktree with +1.
+	 */
+	wt = find_worktree(worktrees + 1, NULL, path);
 	if (!wt)
 		goto done;
 
@@ -342,7 +350,7 @@ static int add_worktree(const char *path, const char *refname,
 	 */
 	strbuf_reset(&sb);
 	strbuf_addf(&sb, "%s/HEAD", sb_repo.buf);
-	write_file(sb.buf, "%s", oid_to_hex(&null_oid));
+	write_file(sb.buf, "%s", sha1_to_hex(null_sha1));
 	strbuf_reset(&sb);
 	strbuf_addf(&sb, "%s/commondir", sb_repo.buf);
 	write_file(sb.buf, "../..");
@@ -369,7 +377,7 @@ static int add_worktree(const char *path, const char *refname,
 	if (opts->checkout) {
 		cp.argv = NULL;
 		argv_array_clear(&cp.args);
-		argv_array_pushl(&cp.args, "reset", "--hard", "--no-recurse-submodules", NULL);
+		argv_array_pushl(&cp.args, "reset", "--hard", NULL);
 		if (opts->quiet)
 			argv_array_push(&cp.args, "--quiet");
 		cp.env = child_env.argv;
@@ -872,7 +880,7 @@ static void check_clean_worktree(struct worktree *wt,
 			  original_path);
 	ret = xread(cp.out, buf, sizeof(buf));
 	if (ret)
-		die(_("'%s' contains modified or untracked files, use --force to delete it"),
+		die(_("'%s' is dirty, use --force to delete it"),
 		    original_path);
 	close(cp.out);
 	ret = finish_command(&cp);