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.c623
-rw-r--r--third_party/git/builtin/am.c2437
-rw-r--r--third_party/git/builtin/annotate.c22
-rw-r--r--third_party/git/builtin/apply.c34
-rw-r--r--third_party/git/builtin/archive.c112
-rw-r--r--third_party/git/builtin/bisect--helper.c981
-rw-r--r--third_party/git/builtin/blame.c1204
-rw-r--r--third_party/git/builtin/branch.c853
-rw-r--r--third_party/git/builtin/bugreport.c194
-rw-r--r--third_party/git/builtin/bundle.c197
-rw-r--r--third_party/git/builtin/cat-file.c721
-rw-r--r--third_party/git/builtin/check-attr.c189
-rw-r--r--third_party/git/builtin/check-ignore.c196
-rw-r--r--third_party/git/builtin/check-mailmap.c67
-rw-r--r--third_party/git/builtin/check-ref-format.c91
-rw-r--r--third_party/git/builtin/checkout-index.c262
-rw-r--r--third_party/git/builtin/checkout.c1868
-rw-r--r--third_party/git/builtin/clean.c1073
-rw-r--r--third_party/git/builtin/clone.c1337
-rw-r--r--third_party/git/builtin/column.c59
-rw-r--r--third_party/git/builtin/commit-graph.c342
-rw-r--r--third_party/git/builtin/commit-tree.c152
-rw-r--r--third_party/git/builtin/commit.c1724
-rw-r--r--third_party/git/builtin/config.c919
-rw-r--r--third_party/git/builtin/count-objects.c172
-rw-r--r--third_party/git/builtin/credential-cache--daemon.c318
-rw-r--r--third_party/git/builtin/credential-cache.c157
-rw-r--r--third_party/git/builtin/credential-store.c195
-rw-r--r--third_party/git/builtin/credential.c31
-rw-r--r--third_party/git/builtin/describe.c681
-rw-r--r--third_party/git/builtin/diff-files.c82
-rw-r--r--third_party/git/builtin/diff-index.c62
-rw-r--r--third_party/git/builtin/diff-tree.c205
-rw-r--r--third_party/git/builtin/diff.c577
-rw-r--r--third_party/git/builtin/difftool.c772
-rw-r--r--third_party/git/builtin/env--helper.c100
-rw-r--r--third_party/git/builtin/fast-export.c1312
-rw-r--r--third_party/git/builtin/fast-import.c3634
-rw-r--r--third_party/git/builtin/fetch-pack.c271
-rw-r--r--third_party/git/builtin/fetch.c1943
-rw-r--r--third_party/git/builtin/fmt-merge-msg.c65
-rw-r--r--third_party/git/builtin/for-each-ref.c87
-rw-r--r--third_party/git/builtin/fsck.c961
-rw-r--r--third_party/git/builtin/gc.c1038
-rw-r--r--third_party/git/builtin/get-tar-commit-id.c52
-rw-r--r--third_party/git/builtin/grep.c1175
-rw-r--r--third_party/git/builtin/hash-object.c162
-rw-r--r--third_party/git/builtin/help.c623
-rw-r--r--third_party/git/builtin/index-pack.c1908
-rw-r--r--third_party/git/builtin/init-db.c705
-rw-r--r--third_party/git/builtin/interpret-trailers.c140
-rw-r--r--third_party/git/builtin/log.c2336
-rw-r--r--third_party/git/builtin/ls-files.c693
-rw-r--r--third_party/git/builtin/ls-remote.c154
-rw-r--r--third_party/git/builtin/ls-tree.c190
-rw-r--r--third_party/git/builtin/mailinfo.c65
-rw-r--r--third_party/git/builtin/mailsplit.c369
-rw-r--r--third_party/git/builtin/merge-base.c188
-rw-r--r--third_party/git/builtin/merge-file.c118
-rw-r--r--third_party/git/builtin/merge-index.c111
-rw-r--r--third_party/git/builtin/merge-ours.c33
-rw-r--r--third_party/git/builtin/merge-recursive.c92
-rw-r--r--third_party/git/builtin/merge-tree.c390
-rw-r--r--third_party/git/builtin/merge.c1715
-rw-r--r--third_party/git/builtin/mktag.c179
-rw-r--r--third_party/git/builtin/mktree.c193
-rw-r--r--third_party/git/builtin/multi-pack-index.c70
-rw-r--r--third_party/git/builtin/mv.c307
-rw-r--r--third_party/git/builtin/name-rev.c636
-rw-r--r--third_party/git/builtin/notes.c1039
-rw-r--r--third_party/git/builtin/pack-objects.c3772
-rw-r--r--third_party/git/builtin/pack-redundant.c653
-rw-r--r--third_party/git/builtin/pack-refs.c24
-rw-r--r--third_party/git/builtin/patch-id.c180
-rw-r--r--third_party/git/builtin/prune-packed.c31
-rw-r--r--third_party/git/builtin/prune.c189
-rw-r--r--third_party/git/builtin/pull.c1051
-rw-r--r--third_party/git/builtin/push.c639
-rw-r--r--third_party/git/builtin/range-diff.c92
-rw-r--r--third_party/git/builtin/read-tree.c270
-rw-r--r--third_party/git/builtin/rebase.c2105
-rw-r--r--third_party/git/builtin/receive-pack.c2547
-rw-r--r--third_party/git/builtin/reflog.c789
-rw-r--r--third_party/git/builtin/remote-ext.c202
-rw-r--r--third_party/git/builtin/remote-fd.c82
-rw-r--r--third_party/git/builtin/remote.c1723
-rw-r--r--third_party/git/builtin/repack.c580
-rw-r--r--third_party/git/builtin/replace.c624
-rw-r--r--third_party/git/builtin/rerere.c120
-rw-r--r--third_party/git/builtin/reset.c454
-rw-r--r--third_party/git/builtin/rev-list.c694
-rw-r--r--third_party/git/builtin/rev-parse.c984
-rw-r--r--third_party/git/builtin/revert.c247
-rw-r--r--third_party/git/builtin/rm.c409
-rw-r--r--third_party/git/builtin/send-pack.c328
-rw-r--r--third_party/git/builtin/shortlog.c538
-rw-r--r--third_party/git/builtin/show-branch.c954
-rw-r--r--third_party/git/builtin/show-index.c106
-rw-r--r--third_party/git/builtin/show-ref.c226
-rw-r--r--third_party/git/builtin/sparse-checkout.c663
-rw-r--r--third_party/git/builtin/stash.c1612
-rw-r--r--third_party/git/builtin/stripspace.c65
-rw-r--r--third_party/git/builtin/submodule--helper.c2800
-rw-r--r--third_party/git/builtin/symbolic-ref.c78
-rw-r--r--third_party/git/builtin/tag.c594
-rw-r--r--third_party/git/builtin/unpack-file.c38
-rw-r--r--third_party/git/builtin/unpack-objects.c599
-rw-r--r--third_party/git/builtin/update-index.c1245
-rw-r--r--third_party/git/builtin/update-ref.c560
-rw-r--r--third_party/git/builtin/update-server-info.c26
-rw-r--r--third_party/git/builtin/upload-archive.c133
-rw-r--r--third_party/git/builtin/upload-pack.c74
-rw-r--r--third_party/git/builtin/var.c94
-rw-r--r--third_party/git/builtin/verify-commit.c90
-rw-r--r--third_party/git/builtin/verify-pack.c90
-rw-r--r--third_party/git/builtin/verify-tag.c77
-rw-r--r--third_party/git/builtin/worktree.c1088
-rw-r--r--third_party/git/builtin/write-tree.c57
118 files changed, 0 insertions, 72559 deletions
diff --git a/third_party/git/builtin/add.c b/third_party/git/builtin/add.c
deleted file mode 100644
index a825887c503d..000000000000
--- a/third_party/git/builtin/add.c
+++ /dev/null
@@ -1,623 +0,0 @@
-/*
- * "git add" builtin command
- *
- * Copyright (C) 2006 Linus Torvalds
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "config.h"
-#include "builtin.h"
-#include "lockfile.h"
-#include "dir.h"
-#include "pathspec.h"
-#include "exec-cmd.h"
-#include "cache-tree.h"
-#include "run-command.h"
-#include "parse-options.h"
-#include "diff.h"
-#include "diffcore.h"
-#include "revision.h"
-#include "bulk-checkin.h"
-#include "strvec.h"
-#include "submodule.h"
-#include "add-interactive.h"
-
-static const char * const builtin_add_usage[] = {
-	N_("git add [<options>] [--] <pathspec>..."),
-	NULL
-};
-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;
-	int add_errors;
-};
-
-static void chmod_pathspec(struct pathspec *pathspec, char flip)
-{
-	int i;
-
-	for (i = 0; i < active_nr; i++) {
-		struct cache_entry *ce = active_cache[i];
-
-		if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
-			continue;
-
-		if (chmod_cache_entry(ce, flip) < 0)
-			fprintf(stderr, "cannot chmod %cx '%s'\n", flip, ce->name);
-	}
-}
-
-static int fix_unmerged_status(struct diff_filepair *p,
-			       struct update_callback_data *data)
-{
-	if (p->status != DIFF_STATUS_UNMERGED)
-		return p->status;
-	if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode)
-		/*
-		 * This is not an explicit add request, and the
-		 * path is missing from the working tree (deleted)
-		 */
-		return DIFF_STATUS_DELETED;
-	else
-		/*
-		 * Either an explicit add request, or path exists
-		 * in the working tree.  An attempt to explicitly
-		 * add a path that does not exist in the working tree
-		 * will be caught as an error by the caller immediately.
-		 */
-		return DIFF_STATUS_MODIFIED;
-}
-
-static void update_callback(struct diff_queue_struct *q,
-			    struct diff_options *opt, void *cbdata)
-{
-	int i;
-	struct update_callback_data *data = cbdata;
-
-	for (i = 0; i < q->nr; i++) {
-		struct diff_filepair *p = q->queue[i];
-		const char *path = p->one->path;
-		switch (fix_unmerged_status(p, data)) {
-		default:
-			die(_("unexpected diff status %c"), p->status);
-		case DIFF_STATUS_MODIFIED:
-		case DIFF_STATUS_TYPE_CHANGED:
-			if (add_file_to_index(&the_index, path,	data->flags)) {
-				if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
-					die(_("updating files failed"));
-				data->add_errors++;
-			}
-			break;
-		case DIFF_STATUS_DELETED:
-			if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
-				break;
-			if (!(data->flags & ADD_CACHE_PRETEND))
-				remove_file_from_index(&the_index, path);
-			if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))
-				printf(_("remove '%s'\n"), path);
-			break;
-		}
-	}
-}
-
-int add_files_to_cache(const char *prefix,
-		       const struct pathspec *pathspec, int flags)
-{
-	struct update_callback_data data;
-	struct rev_info rev;
-
-	memset(&data, 0, sizeof(data));
-	data.flags = flags;
-
-	repo_init_revisions(the_repository, &rev, prefix);
-	setup_revisions(0, NULL, &rev, NULL);
-	if (pathspec)
-		copy_pathspec(&rev.prune_data, pathspec);
-	rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
-	rev.diffopt.format_callback = update_callback;
-	rev.diffopt.format_callback_data = &data;
-	rev.diffopt.flags.override_submodule_config = 1;
-	rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
-	run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
-	clear_pathspec(&rev.prune_data);
-	return !!data.add_errors;
-}
-
-static int renormalize_tracked_files(const struct pathspec *pathspec, int flags)
-{
-	int i, retval = 0;
-
-	for (i = 0; i < active_nr; i++) {
-		struct cache_entry *ce = active_cache[i];
-
-		if (ce_stage(ce))
-			continue; /* do not touch unmerged paths */
-		if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode))
-			continue; /* do not touch non blobs */
-		if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
-			continue;
-		retval |= add_file_to_cache(ce->name, flags | ADD_CACHE_RENORMALIZE);
-	}
-
-	return retval;
-}
-
-static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec, int prefix)
-{
-	char *seen;
-	int i;
-	struct dir_entry **src, **dst;
-
-	seen = xcalloc(pathspec->nr, 1);
-
-	src = dst = dir->entries;
-	i = dir->nr;
-	while (--i >= 0) {
-		struct dir_entry *entry = *src++;
-		if (dir_path_match(&the_index, entry, pathspec, prefix, seen))
-			*dst++ = entry;
-	}
-	dir->nr = dst - dir->entries;
-	add_pathspec_matches_against_index(pathspec, &the_index, seen);
-	return seen;
-}
-
-static void refresh(int verbose, const struct pathspec *pathspec)
-{
-	char *seen;
-	int i;
-
-	seen = xcalloc(pathspec->nr, 1);
-	refresh_index(&the_index, verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET,
-		      pathspec, seen, _("Unstaged changes after refreshing the index:"));
-	for (i = 0; i < pathspec->nr; i++) {
-		if (!seen[i])
-			die(_("pathspec '%s' did not match any files"),
-			    pathspec->items[i].match);
-	}
-	free(seen);
-}
-
-int run_add_interactive(const char *revision, const char *patch_mode,
-			const struct pathspec *pathspec)
-{
-	int status, i;
-	struct strvec argv = STRVEC_INIT;
-	int use_builtin_add_i =
-		git_env_bool("GIT_TEST_ADD_I_USE_BUILTIN", -1);
-
-	if (use_builtin_add_i < 0) {
-		int experimental;
-		if (!git_config_get_bool("add.interactive.usebuiltin",
-					 &use_builtin_add_i))
-			; /* ok */
-		else if (!git_config_get_bool("feature.experimental", &experimental) &&
-			 experimental)
-			use_builtin_add_i = 1;
-	}
-
-	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);
-	}
-
-	strvec_push(&argv, "add--interactive");
-	if (patch_mode)
-		strvec_push(&argv, patch_mode);
-	if (revision)
-		strvec_push(&argv, revision);
-	strvec_push(&argv, "--");
-	for (i = 0; i < pathspec->nr; i++)
-		/* pass original pathspec, to be re-parsed */
-		strvec_push(&argv, pathspec->items[i].original);
-
-	status = run_command_v_opt(argv.v, RUN_GIT_CMD);
-	strvec_clear(&argv);
-	return status;
-}
-
-int interactive_add(const char **argv, const char *prefix, int patch)
-{
-	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 ? "--patch" : NULL,
-				   &pathspec);
-}
-
-static int edit_patch(int argc, const char **argv, const char *prefix)
-{
-	char *file = git_pathdup("ADD_EDIT.patch");
-	const char *apply_argv[] = { "apply", "--recount", "--cached",
-		NULL, NULL };
-	struct child_process child = CHILD_PROCESS_INIT;
-	struct rev_info rev;
-	int out;
-	struct stat st;
-
-	apply_argv[3] = file;
-
-	git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
-
-	if (read_cache() < 0)
-		die(_("Could not read the index"));
-
-	repo_init_revisions(the_repository, &rev, prefix);
-	rev.diffopt.context = 7;
-
-	argc = setup_revisions(argc, argv, &rev, NULL);
-	rev.diffopt.output_format = DIFF_FORMAT_PATCH;
-	rev.diffopt.use_color = 0;
-	rev.diffopt.flags.ignore_dirty_submodules = 1;
-	out = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
-	if (out < 0)
-		die(_("Could not open '%s' for writing."), file);
-	rev.diffopt.file = xfdopen(out, "w");
-	rev.diffopt.close_file = 1;
-	if (run_diff_files(&rev, 0))
-		die(_("Could not write patch"));
-
-	if (launch_editor(file, NULL, NULL))
-		die(_("editing patch failed"));
-
-	if (stat(file, &st))
-		die_errno(_("Could not stat '%s'"), file);
-	if (!st.st_size)
-		die(_("Empty patch. Aborted."));
-
-	child.git_cmd = 1;
-	child.argv = apply_argv;
-	if (run_command(&child))
-		die(_("Could not apply '%s'"), file);
-
-	unlink(file);
-	free(file);
-	return 0;
-}
-
-static const char ignore_error[] =
-N_("The following paths are ignored by one of your .gitignore files:\n");
-
-static int verbose, show_only, ignored_too, refresh_only;
-static int ignore_add_errors, intent_to_add, ignore_missing;
-static int warn_on_embedded_repo = 1;
-
-#define ADDREMOVE_DEFAULT 1
-static int addremove = ADDREMOVE_DEFAULT;
-static int addremove_explicit = -1; /* unspecified */
-
-static char *chmod_arg;
-
-static int ignore_removal_cb(const struct option *opt, const char *arg, int unset)
-{
-	/* if we are told to ignore, we are not adding removals */
-	*(int *)opt->value = !unset ? 0 : 1;
-	return 0;
-}
-
-static struct option builtin_add_options[] = {
-	OPT__DRY_RUN(&show_only, N_("dry run")),
-	OPT__VERBOSE(&verbose, N_("be verbose")),
-	OPT_GROUP(""),
-	OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
-	OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
-	OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
-	OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files"), 0),
-	OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
-	OPT_BOOL(0, "renormalize", &add_renormalize, N_("renormalize EOL of tracked files (implies -u)")),
-	OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
-	OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
-	OPT_CALLBACK_F(0, "ignore-removal", &addremove_explicit,
-	  NULL /* takes no arguments */,
-	  N_("ignore paths removed in the working tree (same as --no-all)"),
-	  PARSE_OPT_NOARG, ignore_removal_cb),
-	OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
-	OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
-	OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
-	OPT_STRING(0, "chmod", &chmod_arg, "(+|-)x",
-		   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(),
-};
-
-static int add_config(const char *var, const char *value, void *cb)
-{
-	if (!strcmp(var, "add.ignoreerrors") ||
-	    !strcmp(var, "add.ignore-errors")) {
-		ignore_add_errors = git_config_bool(var, value);
-		return 0;
-	}
-
-	return git_default_config(var, value, cb);
-}
-
-static const char embedded_advice[] = N_(
-"You've added another git repository inside your current repository.\n"
-"Clones of the outer repository will not contain the contents of\n"
-"the embedded repository and will not know how to obtain it.\n"
-"If you meant to add a submodule, use:\n"
-"\n"
-"	git submodule add <url> %s\n"
-"\n"
-"If you added this path by mistake, you can remove it from the\n"
-"index with:\n"
-"\n"
-"	git rm --cached %s\n"
-"\n"
-"See \"git help submodule\" for more information."
-);
-
-static void check_embedded_repo(const char *path)
-{
-	struct strbuf name = STRBUF_INIT;
-
-	if (!warn_on_embedded_repo)
-		return;
-	if (!ends_with(path, "/"))
-		return;
-
-	/* Drop trailing slash for aesthetics */
-	strbuf_addstr(&name, path);
-	strbuf_strip_suffix(&name, "/");
-
-	warning(_("adding embedded git repository: %s"), name.buf);
-	if (advice_add_embedded_repo) {
-		advise(embedded_advice, name.buf, name.buf);
-		/* there may be multiple entries; advise only once */
-		advice_add_embedded_repo = 0;
-	}
-
-	strbuf_release(&name);
-}
-
-static int add_files(struct dir_struct *dir, int flags)
-{
-	int i, exit_status = 0;
-
-	if (dir->ignored_nr) {
-		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\""));
-		exit_status = 1;
-	}
-
-	for (i = 0; i < dir->nr; i++) {
-		if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
-			if (!ignore_add_errors)
-				die(_("adding files failed"));
-			exit_status = 1;
-		} else {
-			check_embedded_repo(dir->entries[i]->name);
-		}
-	}
-	return exit_status;
-}
-
-int cmd_add(int argc, const char **argv, const char *prefix)
-{
-	int exit_status = 0;
-	struct pathspec pathspec;
-	struct dir_struct dir;
-	int flags;
-	int add_new_files;
-	int require_pathspec;
-	char *seen = NULL;
-	struct lock_file lock_file = LOCK_INIT;
-
-	git_config(add_config, NULL);
-
-	argc = parse_options(argc, argv, prefix, builtin_add_options,
-			  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"));
-		exit(interactive_add(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"));
-		return(edit_patch(argc, argv, prefix));
-	}
-	argc--;
-	argv++;
-
-	if (0 <= addremove_explicit)
-		addremove = addremove_explicit;
-	else if (take_worktree_changes && ADDREMOVE_DEFAULT)
-		addremove = 0; /* "-u" was given but not "-A" */
-
-	if (addremove && take_worktree_changes)
-		die(_("-A and -u are mutually incompatible"));
-
-	if (!show_only && ignore_missing)
-		die(_("Option --ignore-missing can only be used together with --dry-run"));
-
-	if (chmod_arg && ((chmod_arg[0] != '-' && chmod_arg[0] != '+') ||
-			  chmod_arg[1] != 'x' || chmod_arg[2]))
-		die(_("--chmod param '%s' must be either -x or +x"), chmod_arg);
-
-	add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize;
-	require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
-
-	hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
-
-	/*
-	 * Check the "pathspec '%s' did not match any files" block
-	 * below before enabling new magic.
-	 */
-	parse_pathspec(&pathspec, PATHSPEC_ATTR,
-		       PATHSPEC_PREFER_FULL |
-		       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"));
-
-	die_in_unpopulated_submodule(&the_index, prefix);
-	die_path_inside_submodule(&the_index, &pathspec);
-
-	dir_init(&dir);
-	if (add_new_files) {
-		int baselen;
-
-		/* Set up the default git porcelain excludes */
-		if (!ignored_too) {
-			dir.flags |= DIR_COLLECT_IGNORED;
-			setup_standard_excludes(&dir);
-		}
-
-		/* This picks up the paths that are not tracked */
-		baselen = fill_directory(&dir, &the_index, &pathspec);
-		if (pathspec.nr)
-			seen = prune_directory(&dir, &pathspec, baselen);
-	}
-
-	if (refresh_only) {
-		refresh(verbose, &pathspec);
-		goto finish;
-	}
-
-	if (pathspec.nr) {
-		int i;
-
-		if (!seen)
-			seen = find_pathspecs_matching_against_index(&pathspec, &the_index);
-
-		/*
-		 * file_exists() assumes exact match
-		 */
-		GUARD_PATHSPEC(&pathspec,
-			       PATHSPEC_FROMTOP |
-			       PATHSPEC_LITERAL |
-			       PATHSPEC_GLOB |
-			       PATHSPEC_ICASE |
-			       PATHSPEC_EXCLUDE);
-
-		for (i = 0; i < pathspec.nr; i++) {
-			const char *path = pathspec.items[i].match;
-			if (pathspec.items[i].magic & PATHSPEC_EXCLUDE)
-				continue;
-			if (!seen[i] && path[0] &&
-			    ((pathspec.items[i].magic &
-			      (PATHSPEC_GLOB | PATHSPEC_ICASE)) ||
-			     !file_exists(path))) {
-				if (ignore_missing) {
-					int dtype = DT_UNKNOWN;
-					if (is_excluded(&dir, &the_index, path, &dtype))
-						dir_add_ignored(&dir, &the_index,
-								path, pathspec.items[i].len);
-				} else
-					die(_("pathspec '%s' did not match any files"),
-					    pathspec.items[i].original);
-			}
-		}
-		free(seen);
-	}
-
-	plug_bulk_checkin();
-
-	if (add_renormalize)
-		exit_status |= renormalize_tracked_files(&pathspec, flags);
-	else
-		exit_status |= add_files_to_cache(prefix, &pathspec, flags);
-
-	if (add_new_files)
-		exit_status |= add_files(&dir, flags);
-
-	if (chmod_arg && pathspec.nr)
-		chmod_pathspec(&pathspec, chmod_arg[0]);
-	unplug_bulk_checkin();
-
-finish:
-	if (write_locked_index(&the_index, &lock_file,
-			       COMMIT_LOCK | SKIP_IF_UNCHANGED))
-		die(_("Unable to write new index file"));
-
-	dir_clear(&dir);
-	UNLEAK(pathspec);
-	return exit_status;
-}
diff --git a/third_party/git/builtin/am.c b/third_party/git/builtin/am.c
deleted file mode 100644
index 4949535a7f1f..000000000000
--- a/third_party/git/builtin/am.c
+++ /dev/null
@@ -1,2437 +0,0 @@
-/*
- * Builtin "git am"
- *
- * Based on git-am.sh by Junio C Hamano.
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "config.h"
-#include "builtin.h"
-#include "exec-cmd.h"
-#include "parse-options.h"
-#include "dir.h"
-#include "run-command.h"
-#include "quote.h"
-#include "tempfile.h"
-#include "lockfile.h"
-#include "cache-tree.h"
-#include "refs.h"
-#include "commit.h"
-#include "diff.h"
-#include "diffcore.h"
-#include "unpack-trees.h"
-#include "branch.h"
-#include "sequencer.h"
-#include "revision.h"
-#include "merge-recursive.h"
-#include "log-tree.h"
-#include "notes-utils.h"
-#include "rerere.h"
-#include "prompt.h"
-#include "mailinfo.h"
-#include "apply.h"
-#include "string-list.h"
-#include "packfile.h"
-#include "repository.h"
-
-/**
- * Returns the length of the first line of msg.
- */
-static int linelen(const char *msg)
-{
-	return strchrnul(msg, '\n') - msg;
-}
-
-/**
- * Returns true if `str` consists of only whitespace, false otherwise.
- */
-static int str_isspace(const char *str)
-{
-	for (; *str; str++)
-		if (!isspace(*str))
-			return 0;
-
-	return 1;
-}
-
-enum patch_format {
-	PATCH_FORMAT_UNKNOWN = 0,
-	PATCH_FORMAT_MBOX,
-	PATCH_FORMAT_STGIT,
-	PATCH_FORMAT_STGIT_SERIES,
-	PATCH_FORMAT_HG,
-	PATCH_FORMAT_MBOXRD
-};
-
-enum keep_type {
-	KEEP_FALSE = 0,
-	KEEP_TRUE,      /* pass -k flag to git-mailinfo */
-	KEEP_NON_PATCH  /* pass -b flag to git-mailinfo */
-};
-
-enum scissors_type {
-	SCISSORS_UNSET = -1,
-	SCISSORS_FALSE = 0,  /* pass --no-scissors to git-mailinfo */
-	SCISSORS_TRUE        /* pass --scissors to git-mailinfo */
-};
-
-enum signoff_type {
-	SIGNOFF_FALSE = 0,
-	SIGNOFF_TRUE = 1,
-	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;
-
-	/* current and last patch numbers, 1-indexed */
-	int cur;
-	int last;
-
-	/* commit metadata and message */
-	char *author_name;
-	char *author_email;
-	char *author_date;
-	char *committer_name;
-	char *committer_email;
-	char *msg;
-	size_t msg_len;
-
-	/* when --rebasing, records the original commit the patch came from */
-	struct object_id orig_commit;
-
-	/* number of digits in patch filename */
-	int prec;
-
-	/* various operating modes and command line options */
-	int interactive;
-	int threeway;
-	int quiet;
-	int signoff; /* enum signoff_type */
-	int utf8;
-	int keep; /* enum keep_type */
-	int message_id;
-	int scissors; /* enum scissors_type */
-	struct strvec git_apply_opts;
-	const char *resolvemsg;
-	int committer_date_is_author_date;
-	int ignore_date;
-	int allow_rerere_autoupdate;
-	const char *sign_commit;
-	int rebasing;
-};
-
-/**
- * Initializes am_state with the default values.
- */
-static void am_state_init(struct am_state *state)
-{
-	const char *committer;
-	struct ident_split id;
-	int gpgsign;
-
-	memset(state, 0, sizeof(*state));
-
-	state->dir = git_pathdup("rebase-apply");
-
-	state->prec = 4;
-
-	git_config_get_bool("am.threeway", &state->threeway);
-
-	state->utf8 = 1;
-
-	git_config_get_bool("am.messageid", &state->message_id);
-
-	state->scissors = SCISSORS_UNSET;
-
-	strvec_init(&state->git_apply_opts);
-
-	if (!git_config_get_bool("commit.gpgsign", &gpgsign))
-		state->sign_commit = gpgsign ? "" : NULL;
-
-	committer = git_committer_info(IDENT_STRICT);
-	if (split_ident_line(&id, committer, strlen(committer)) < 0)
-		die(_("invalid committer: %s"), committer);
-	state->committer_name =
-		xmemdupz(id.name_begin, id.name_end - id.name_begin);
-	state->committer_email =
-		xmemdupz(id.mail_begin, id.mail_end - id.mail_begin);
-}
-
-/**
- * Releases memory allocated by an am_state.
- */
-static void am_state_release(struct am_state *state)
-{
-	free(state->dir);
-	free(state->author_name);
-	free(state->author_email);
-	free(state->author_date);
-	free(state->committer_name);
-	free(state->committer_email);
-	free(state->msg);
-	strvec_clear(&state->git_apply_opts);
-}
-
-/**
- * Returns path relative to the am_state directory.
- */
-static inline const char *am_path(const struct am_state *state, const char *path)
-{
-	return mkpath("%s/%s", state->dir, path);
-}
-
-/**
- * For convenience to call write_file()
- */
-static void write_state_text(const struct am_state *state,
-			     const char *name, const char *string)
-{
-	write_file(am_path(state, name), "%s", string);
-}
-
-static void write_state_count(const struct am_state *state,
-			      const char *name, int value)
-{
-	write_file(am_path(state, name), "%d", value);
-}
-
-static void write_state_bool(const struct am_state *state,
-			     const char *name, int value)
-{
-	write_state_text(state, name, value ? "t" : "f");
-}
-
-/**
- * If state->quiet is false, calls fprintf(fp, fmt, ...), and appends a newline
- * at the end.
- */
-static void say(const struct am_state *state, FILE *fp, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	if (!state->quiet) {
-		vfprintf(fp, fmt, ap);
-		putc('\n', fp);
-	}
-	va_end(ap);
-}
-
-/**
- * Returns 1 if there is an am session in progress, 0 otherwise.
- */
-static int am_in_progress(const struct am_state *state)
-{
-	struct stat st;
-
-	if (lstat(state->dir, &st) < 0 || !S_ISDIR(st.st_mode))
-		return 0;
-	if (lstat(am_path(state, "last"), &st) || !S_ISREG(st.st_mode))
-		return 0;
-	if (lstat(am_path(state, "next"), &st) || !S_ISREG(st.st_mode))
-		return 0;
-	return 1;
-}
-
-/**
- * Reads the contents of `file` in the `state` directory into `sb`. Returns the
- * number of bytes read on success, -1 if the file does not exist. If `trim` is
- * set, trailing whitespace will be removed.
- */
-static int read_state_file(struct strbuf *sb, const struct am_state *state,
-			const char *file, int trim)
-{
-	strbuf_reset(sb);
-
-	if (strbuf_read_file(sb, am_path(state, file), 0) >= 0) {
-		if (trim)
-			strbuf_trim(sb);
-
-		return sb->len;
-	}
-
-	if (errno == ENOENT)
-		return -1;
-
-	die_errno(_("could not read '%s'"), am_path(state, file));
-}
-
-/**
- * Reads and parses the state directory's "author-script" file, and sets
- * state->author_name, state->author_email and state->author_date accordingly.
- * Returns 0 on success, -1 if the file could not be parsed.
- *
- * The author script is of the format:
- *
- *	GIT_AUTHOR_NAME='$author_name'
- *	GIT_AUTHOR_EMAIL='$author_email'
- *	GIT_AUTHOR_DATE='$author_date'
- *
- * where $author_name, $author_email and $author_date are quoted. We are strict
- * with our parsing, as the file was meant to be eval'd in the old git-am.sh
- * script, and thus if the file differs from what this function expects, it is
- * better to bail out than to do something that the user does not expect.
- */
-static int read_am_author_script(struct am_state *state)
-{
-	const char *filename = am_path(state, "author-script");
-
-	assert(!state->author_name);
-	assert(!state->author_email);
-	assert(!state->author_date);
-
-	return read_author_script(filename, &state->author_name,
-				  &state->author_email, &state->author_date, 1);
-}
-
-/**
- * Saves state->author_name, state->author_email and state->author_date in the
- * state directory's "author-script" file.
- */
-static void write_author_script(const struct am_state *state)
-{
-	struct strbuf sb = STRBUF_INIT;
-
-	strbuf_addstr(&sb, "GIT_AUTHOR_NAME=");
-	sq_quote_buf(&sb, state->author_name);
-	strbuf_addch(&sb, '\n');
-
-	strbuf_addstr(&sb, "GIT_AUTHOR_EMAIL=");
-	sq_quote_buf(&sb, state->author_email);
-	strbuf_addch(&sb, '\n');
-
-	strbuf_addstr(&sb, "GIT_AUTHOR_DATE=");
-	sq_quote_buf(&sb, state->author_date);
-	strbuf_addch(&sb, '\n');
-
-	write_state_text(state, "author-script", sb.buf);
-
-	strbuf_release(&sb);
-}
-
-/**
- * Reads the commit message from the state directory's "final-commit" file,
- * setting state->msg to its contents and state->msg_len to the length of its
- * contents in bytes.
- *
- * Returns 0 on success, -1 if the file does not exist.
- */
-static int read_commit_msg(struct am_state *state)
-{
-	struct strbuf sb = STRBUF_INIT;
-
-	assert(!state->msg);
-
-	if (read_state_file(&sb, state, "final-commit", 0) < 0) {
-		strbuf_release(&sb);
-		return -1;
-	}
-
-	state->msg = strbuf_detach(&sb, &state->msg_len);
-	return 0;
-}
-
-/**
- * Saves state->msg in the state directory's "final-commit" file.
- */
-static void write_commit_msg(const struct am_state *state)
-{
-	const char *filename = am_path(state, "final-commit");
-	write_file_buf(filename, state->msg, state->msg_len);
-}
-
-/**
- * Loads state from disk.
- */
-static void am_load(struct am_state *state)
-{
-	struct strbuf sb = STRBUF_INIT;
-
-	if (read_state_file(&sb, state, "next", 1) < 0)
-		BUG("state file 'next' does not exist");
-	state->cur = strtol(sb.buf, NULL, 10);
-
-	if (read_state_file(&sb, state, "last", 1) < 0)
-		BUG("state file 'last' does not exist");
-	state->last = strtol(sb.buf, NULL, 10);
-
-	if (read_am_author_script(state) < 0)
-		die(_("could not parse author script"));
-
-	read_commit_msg(state);
-
-	if (read_state_file(&sb, state, "original-commit", 1) < 0)
-		oidclr(&state->orig_commit);
-	else if (get_oid_hex(sb.buf, &state->orig_commit) < 0)
-		die(_("could not parse %s"), am_path(state, "original-commit"));
-
-	read_state_file(&sb, state, "threeway", 1);
-	state->threeway = !strcmp(sb.buf, "t");
-
-	read_state_file(&sb, state, "quiet", 1);
-	state->quiet = !strcmp(sb.buf, "t");
-
-	read_state_file(&sb, state, "sign", 1);
-	state->signoff = !strcmp(sb.buf, "t");
-
-	read_state_file(&sb, state, "utf8", 1);
-	state->utf8 = !strcmp(sb.buf, "t");
-
-	if (file_exists(am_path(state, "rerere-autoupdate"))) {
-		read_state_file(&sb, state, "rerere-autoupdate", 1);
-		state->allow_rerere_autoupdate = strcmp(sb.buf, "t") ?
-			RERERE_NOAUTOUPDATE : RERERE_AUTOUPDATE;
-	} else {
-		state->allow_rerere_autoupdate = 0;
-	}
-
-	read_state_file(&sb, state, "keep", 1);
-	if (!strcmp(sb.buf, "t"))
-		state->keep = KEEP_TRUE;
-	else if (!strcmp(sb.buf, "b"))
-		state->keep = KEEP_NON_PATCH;
-	else
-		state->keep = KEEP_FALSE;
-
-	read_state_file(&sb, state, "messageid", 1);
-	state->message_id = !strcmp(sb.buf, "t");
-
-	read_state_file(&sb, state, "scissors", 1);
-	if (!strcmp(sb.buf, "t"))
-		state->scissors = SCISSORS_TRUE;
-	else if (!strcmp(sb.buf, "f"))
-		state->scissors = SCISSORS_FALSE;
-	else
-		state->scissors = SCISSORS_UNSET;
-
-	read_state_file(&sb, state, "apply-opt", 1);
-	strvec_clear(&state->git_apply_opts);
-	if (sq_dequote_to_strvec(sb.buf, &state->git_apply_opts) < 0)
-		die(_("could not parse %s"), am_path(state, "apply-opt"));
-
-	state->rebasing = !!file_exists(am_path(state, "rebasing"));
-
-	strbuf_release(&sb);
-}
-
-/**
- * Removes the am_state directory, forcefully terminating the current am
- * session.
- */
-static void am_destroy(const struct am_state *state)
-{
-	struct strbuf sb = STRBUF_INIT;
-
-	strbuf_addstr(&sb, state->dir);
-	remove_dir_recursively(&sb, 0);
-	strbuf_release(&sb);
-}
-
-/**
- * Runs applypatch-msg hook. Returns its exit code.
- */
-static int run_applypatch_msg_hook(struct am_state *state)
-{
-	int ret;
-
-	assert(state->msg);
-	ret = run_hook_le(NULL, "applypatch-msg", am_path(state, "final-commit"), NULL);
-
-	if (!ret) {
-		FREE_AND_NULL(state->msg);
-		if (read_commit_msg(state) < 0)
-			die(_("'%s' was deleted by the applypatch-msg hook"),
-				am_path(state, "final-commit"));
-	}
-
-	return ret;
-}
-
-/**
- * Runs post-rewrite hook. Returns it exit code.
- */
-static int run_post_rewrite_hook(const struct am_state *state)
-{
-	struct child_process cp = CHILD_PROCESS_INIT;
-	const char *hook = find_hook("post-rewrite");
-	int ret;
-
-	if (!hook)
-		return 0;
-
-	strvec_push(&cp.args, hook);
-	strvec_push(&cp.args, "rebase");
-
-	cp.in = xopen(am_path(state, "rewritten"), O_RDONLY);
-	cp.stdout_to_stderr = 1;
-	cp.trace2_hook_name = "post-rewrite";
-
-	ret = run_command(&cp);
-
-	close(cp.in);
-	return ret;
-}
-
-/**
- * Reads the state directory's "rewritten" file, and copies notes from the old
- * commits listed in the file to their rewritten commits.
- *
- * Returns 0 on success, -1 on failure.
- */
-static int copy_notes_for_rebase(const struct am_state *state)
-{
-	struct notes_rewrite_cfg *c;
-	struct strbuf sb = STRBUF_INIT;
-	const char *invalid_line = _("Malformed input line: '%s'.");
-	const char *msg = "Notes added by 'git rebase'";
-	FILE *fp;
-	int ret = 0;
-
-	assert(state->rebasing);
-
-	c = init_copy_notes_for_rewrite("rebase");
-	if (!c)
-		return 0;
-
-	fp = xfopen(am_path(state, "rewritten"), "r");
-
-	while (!strbuf_getline_lf(&sb, fp)) {
-		struct object_id from_obj, to_obj;
-		const char *p;
-
-		if (sb.len != the_hash_algo->hexsz * 2 + 1) {
-			ret = error(invalid_line, sb.buf);
-			goto finish;
-		}
-
-		if (parse_oid_hex(sb.buf, &from_obj, &p)) {
-			ret = error(invalid_line, sb.buf);
-			goto finish;
-		}
-
-		if (*p != ' ') {
-			ret = error(invalid_line, sb.buf);
-			goto finish;
-		}
-
-		if (get_oid_hex(p + 1, &to_obj)) {
-			ret = error(invalid_line, sb.buf);
-			goto finish;
-		}
-
-		if (copy_note_for_rewrite(c, &from_obj, &to_obj))
-			ret = error(_("Failed to copy notes from '%s' to '%s'"),
-					oid_to_hex(&from_obj), oid_to_hex(&to_obj));
-	}
-
-finish:
-	finish_copy_notes_for_rewrite(the_repository, c, msg);
-	fclose(fp);
-	strbuf_release(&sb);
-	return ret;
-}
-
-/**
- * Determines if the file looks like a piece of RFC2822 mail by grabbing all
- * non-indented lines and checking if they look like they begin with valid
- * header field names.
- *
- * Returns 1 if the file looks like a piece of mail, 0 otherwise.
- */
-static int is_mail(FILE *fp)
-{
-	const char *header_regex = "^[!-9;-~]+:";
-	struct strbuf sb = STRBUF_INIT;
-	regex_t regex;
-	int ret = 1;
-
-	if (fseek(fp, 0L, SEEK_SET))
-		die_errno(_("fseek failed"));
-
-	if (regcomp(&regex, header_regex, REG_NOSUB | REG_EXTENDED))
-		die("invalid pattern: %s", header_regex);
-
-	while (!strbuf_getline(&sb, fp)) {
-		if (!sb.len)
-			break; /* End of header */
-
-		/* Ignore indented folded lines */
-		if (*sb.buf == '\t' || *sb.buf == ' ')
-			continue;
-
-		/* It's a header if it matches header_regex */
-		if (regexec(&regex, sb.buf, 0, NULL, 0)) {
-			ret = 0;
-			goto done;
-		}
-	}
-
-done:
-	regfree(&regex);
-	strbuf_release(&sb);
-	return ret;
-}
-
-/**
- * Attempts to detect the patch_format of the patches contained in `paths`,
- * returning the PATCH_FORMAT_* enum value. Returns PATCH_FORMAT_UNKNOWN if
- * detection fails.
- */
-static int detect_patch_format(const char **paths)
-{
-	enum patch_format ret = PATCH_FORMAT_UNKNOWN;
-	struct strbuf l1 = STRBUF_INIT;
-	struct strbuf l2 = STRBUF_INIT;
-	struct strbuf l3 = STRBUF_INIT;
-	FILE *fp;
-
-	/*
-	 * We default to mbox format if input is from stdin and for directories
-	 */
-	if (!*paths || !strcmp(*paths, "-") || is_directory(*paths))
-		return PATCH_FORMAT_MBOX;
-
-	/*
-	 * Otherwise, check the first few lines of the first patch, starting
-	 * from the first non-blank line, to try to detect its format.
-	 */
-
-	fp = xfopen(*paths, "r");
-
-	while (!strbuf_getline(&l1, fp)) {
-		if (l1.len)
-			break;
-	}
-
-	if (starts_with(l1.buf, "From ") || starts_with(l1.buf, "From: ")) {
-		ret = PATCH_FORMAT_MBOX;
-		goto done;
-	}
-
-	if (starts_with(l1.buf, "# This series applies on GIT commit")) {
-		ret = PATCH_FORMAT_STGIT_SERIES;
-		goto done;
-	}
-
-	if (!strcmp(l1.buf, "# HG changeset patch")) {
-		ret = PATCH_FORMAT_HG;
-		goto done;
-	}
-
-	strbuf_getline(&l2, fp);
-	strbuf_getline(&l3, fp);
-
-	/*
-	 * If the second line is empty and the third is a From, Author or Date
-	 * entry, this is likely an StGit patch.
-	 */
-	if (l1.len && !l2.len &&
-		(starts_with(l3.buf, "From:") ||
-		 starts_with(l3.buf, "Author:") ||
-		 starts_with(l3.buf, "Date:"))) {
-		ret = PATCH_FORMAT_STGIT;
-		goto done;
-	}
-
-	if (l1.len && is_mail(fp)) {
-		ret = PATCH_FORMAT_MBOX;
-		goto done;
-	}
-
-done:
-	fclose(fp);
-	strbuf_release(&l1);
-	strbuf_release(&l2);
-	strbuf_release(&l3);
-	return ret;
-}
-
-/**
- * Splits out individual email patches from `paths`, where each path is either
- * a mbox file or a Maildir. Returns 0 on success, -1 on failure.
- */
-static int split_mail_mbox(struct am_state *state, const char **paths,
-				int keep_cr, int mboxrd)
-{
-	struct child_process cp = CHILD_PROCESS_INIT;
-	struct strbuf last = STRBUF_INIT;
-	int ret;
-
-	cp.git_cmd = 1;
-	strvec_push(&cp.args, "mailsplit");
-	strvec_pushf(&cp.args, "-d%d", state->prec);
-	strvec_pushf(&cp.args, "-o%s", state->dir);
-	strvec_push(&cp.args, "-b");
-	if (keep_cr)
-		strvec_push(&cp.args, "--keep-cr");
-	if (mboxrd)
-		strvec_push(&cp.args, "--mboxrd");
-	strvec_push(&cp.args, "--");
-	strvec_pushv(&cp.args, paths);
-
-	ret = capture_command(&cp, &last, 8);
-	if (ret)
-		goto exit;
-
-	state->cur = 1;
-	state->last = strtol(last.buf, NULL, 10);
-
-exit:
-	strbuf_release(&last);
-	return ret ? -1 : 0;
-}
-
-/**
- * Callback signature for split_mail_conv(). The foreign patch should be
- * read from `in`, and the converted patch (in RFC2822 mail format) should be
- * written to `out`. Return 0 on success, or -1 on failure.
- */
-typedef int (*mail_conv_fn)(FILE *out, FILE *in, int keep_cr);
-
-/**
- * Calls `fn` for each file in `paths` to convert the foreign patch to the
- * RFC2822 mail format suitable for parsing with git-mailinfo.
- *
- * Returns 0 on success, -1 on failure.
- */
-static int split_mail_conv(mail_conv_fn fn, struct am_state *state,
-			const char **paths, int keep_cr)
-{
-	static const char *stdin_only[] = {"-", NULL};
-	int i;
-
-	if (!*paths)
-		paths = stdin_only;
-
-	for (i = 0; *paths; paths++, i++) {
-		FILE *in, *out;
-		const char *mail;
-		int ret;
-
-		if (!strcmp(*paths, "-"))
-			in = stdin;
-		else
-			in = fopen(*paths, "r");
-
-		if (!in)
-			return error_errno(_("could not open '%s' for reading"),
-					   *paths);
-
-		mail = mkpath("%s/%0*d", state->dir, state->prec, i + 1);
-
-		out = fopen(mail, "w");
-		if (!out) {
-			if (in != stdin)
-				fclose(in);
-			return error_errno(_("could not open '%s' for writing"),
-					   mail);
-		}
-
-		ret = fn(out, in, keep_cr);
-
-		fclose(out);
-		if (in != stdin)
-			fclose(in);
-
-		if (ret)
-			return error(_("could not parse patch '%s'"), *paths);
-	}
-
-	state->cur = 1;
-	state->last = i;
-	return 0;
-}
-
-/**
- * A split_mail_conv() callback that converts an StGit patch to an RFC2822
- * message suitable for parsing with git-mailinfo.
- */
-static int stgit_patch_to_mail(FILE *out, FILE *in, int keep_cr)
-{
-	struct strbuf sb = STRBUF_INIT;
-	int subject_printed = 0;
-
-	while (!strbuf_getline_lf(&sb, in)) {
-		const char *str;
-
-		if (str_isspace(sb.buf))
-			continue;
-		else if (skip_prefix(sb.buf, "Author:", &str))
-			fprintf(out, "From:%s\n", str);
-		else if (starts_with(sb.buf, "From") || starts_with(sb.buf, "Date"))
-			fprintf(out, "%s\n", sb.buf);
-		else if (!subject_printed) {
-			fprintf(out, "Subject: %s\n", sb.buf);
-			subject_printed = 1;
-		} else {
-			fprintf(out, "\n%s\n", sb.buf);
-			break;
-		}
-	}
-
-	strbuf_reset(&sb);
-	while (strbuf_fread(&sb, 8192, in) > 0) {
-		fwrite(sb.buf, 1, sb.len, out);
-		strbuf_reset(&sb);
-	}
-
-	strbuf_release(&sb);
-	return 0;
-}
-
-/**
- * This function only supports a single StGit series file in `paths`.
- *
- * Given an StGit series file, converts the StGit patches in the series into
- * RFC2822 messages suitable for parsing with git-mailinfo, and queues them in
- * the state directory.
- *
- * Returns 0 on success, -1 on failure.
- */
-static int split_mail_stgit_series(struct am_state *state, const char **paths,
-					int keep_cr)
-{
-	const char *series_dir;
-	char *series_dir_buf;
-	FILE *fp;
-	struct strvec patches = STRVEC_INIT;
-	struct strbuf sb = STRBUF_INIT;
-	int ret;
-
-	if (!paths[0] || paths[1])
-		return error(_("Only one StGIT patch series can be applied at once"));
-
-	series_dir_buf = xstrdup(*paths);
-	series_dir = dirname(series_dir_buf);
-
-	fp = fopen(*paths, "r");
-	if (!fp)
-		return error_errno(_("could not open '%s' for reading"), *paths);
-
-	while (!strbuf_getline_lf(&sb, fp)) {
-		if (*sb.buf == '#')
-			continue; /* skip comment lines */
-
-		strvec_push(&patches, mkpath("%s/%s", series_dir, sb.buf));
-	}
-
-	fclose(fp);
-	strbuf_release(&sb);
-	free(series_dir_buf);
-
-	ret = split_mail_conv(stgit_patch_to_mail, state, patches.v, keep_cr);
-
-	strvec_clear(&patches);
-	return ret;
-}
-
-/**
- * A split_patches_conv() callback that converts a mercurial patch to a RFC2822
- * message suitable for parsing with git-mailinfo.
- */
-static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr)
-{
-	struct strbuf sb = STRBUF_INIT;
-	int rc = 0;
-
-	while (!strbuf_getline_lf(&sb, in)) {
-		const char *str;
-
-		if (skip_prefix(sb.buf, "# User ", &str))
-			fprintf(out, "From: %s\n", str);
-		else if (skip_prefix(sb.buf, "# Date ", &str)) {
-			timestamp_t timestamp;
-			long tz, tz2;
-			char *end;
-
-			errno = 0;
-			timestamp = parse_timestamp(str, &end, 10);
-			if (errno) {
-				rc = error(_("invalid timestamp"));
-				goto exit;
-			}
-
-			if (!skip_prefix(end, " ", &str)) {
-				rc = error(_("invalid Date line"));
-				goto exit;
-			}
-
-			errno = 0;
-			tz = strtol(str, &end, 10);
-			if (errno) {
-				rc = error(_("invalid timezone offset"));
-				goto exit;
-			}
-
-			if (*end) {
-				rc = error(_("invalid Date line"));
-				goto exit;
-			}
-
-			/*
-			 * mercurial's timezone is in seconds west of UTC,
-			 * however git's timezone is in hours + minutes east of
-			 * UTC. Convert it.
-			 */
-			tz2 = labs(tz) / 3600 * 100 + labs(tz) % 3600 / 60;
-			if (tz > 0)
-				tz2 = -tz2;
-
-			fprintf(out, "Date: %s\n", show_date(timestamp, tz2, DATE_MODE(RFC2822)));
-		} else if (starts_with(sb.buf, "# ")) {
-			continue;
-		} else {
-			fprintf(out, "\n%s\n", sb.buf);
-			break;
-		}
-	}
-
-	strbuf_reset(&sb);
-	while (strbuf_fread(&sb, 8192, in) > 0) {
-		fwrite(sb.buf, 1, sb.len, out);
-		strbuf_reset(&sb);
-	}
-exit:
-	strbuf_release(&sb);
-	return rc;
-}
-
-/**
- * Splits a list of files/directories into individual email patches. Each path
- * in `paths` must be a file/directory that is formatted according to
- * `patch_format`.
- *
- * Once split out, the individual email patches will be stored in the state
- * directory, with each patch's filename being its index, padded to state->prec
- * digits.
- *
- * state->cur will be set to the index of the first mail, and state->last will
- * be set to the index of the last mail.
- *
- * Set keep_cr to 0 to convert all lines ending with \r\n to end with \n, 1
- * to disable this behavior, -1 to use the default configured setting.
- *
- * Returns 0 on success, -1 on failure.
- */
-static int split_mail(struct am_state *state, enum patch_format patch_format,
-			const char **paths, int keep_cr)
-{
-	if (keep_cr < 0) {
-		keep_cr = 0;
-		git_config_get_bool("am.keepcr", &keep_cr);
-	}
-
-	switch (patch_format) {
-	case PATCH_FORMAT_MBOX:
-		return split_mail_mbox(state, paths, keep_cr, 0);
-	case PATCH_FORMAT_STGIT:
-		return split_mail_conv(stgit_patch_to_mail, state, paths, keep_cr);
-	case PATCH_FORMAT_STGIT_SERIES:
-		return split_mail_stgit_series(state, paths, keep_cr);
-	case PATCH_FORMAT_HG:
-		return split_mail_conv(hg_patch_to_mail, state, paths, keep_cr);
-	case PATCH_FORMAT_MBOXRD:
-		return split_mail_mbox(state, paths, keep_cr, 1);
-	default:
-		BUG("invalid patch_format");
-	}
-	return -1;
-}
-
-/**
- * Setup a new am session for applying patches
- */
-static void am_setup(struct am_state *state, enum patch_format patch_format,
-			const char **paths, int keep_cr)
-{
-	struct object_id curr_head;
-	const char *str;
-	struct strbuf sb = STRBUF_INIT;
-
-	if (!patch_format)
-		patch_format = detect_patch_format(paths);
-
-	if (!patch_format) {
-		fprintf_ln(stderr, _("Patch format detection failed."));
-		exit(128);
-	}
-
-	if (mkdir(state->dir, 0777) < 0 && errno != EEXIST)
-		die_errno(_("failed to create directory '%s'"), state->dir);
-	delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
-
-	if (split_mail(state, patch_format, paths, keep_cr) < 0) {
-		am_destroy(state);
-		die(_("Failed to split patches."));
-	}
-
-	if (state->rebasing)
-		state->threeway = 1;
-
-	write_state_bool(state, "threeway", state->threeway);
-	write_state_bool(state, "quiet", state->quiet);
-	write_state_bool(state, "sign", state->signoff);
-	write_state_bool(state, "utf8", state->utf8);
-
-	if (state->allow_rerere_autoupdate)
-		write_state_bool(state, "rerere-autoupdate",
-			 state->allow_rerere_autoupdate == RERERE_AUTOUPDATE);
-
-	switch (state->keep) {
-	case KEEP_FALSE:
-		str = "f";
-		break;
-	case KEEP_TRUE:
-		str = "t";
-		break;
-	case KEEP_NON_PATCH:
-		str = "b";
-		break;
-	default:
-		BUG("invalid value for state->keep");
-	}
-
-	write_state_text(state, "keep", str);
-	write_state_bool(state, "messageid", state->message_id);
-
-	switch (state->scissors) {
-	case SCISSORS_UNSET:
-		str = "";
-		break;
-	case SCISSORS_FALSE:
-		str = "f";
-		break;
-	case SCISSORS_TRUE:
-		str = "t";
-		break;
-	default:
-		BUG("invalid value for state->scissors");
-	}
-	write_state_text(state, "scissors", str);
-
-	sq_quote_argv(&sb, state->git_apply_opts.v);
-	write_state_text(state, "apply-opt", sb.buf);
-
-	if (state->rebasing)
-		write_state_text(state, "rebasing", "");
-	else
-		write_state_text(state, "applying", "");
-
-	if (!get_oid("HEAD", &curr_head)) {
-		write_state_text(state, "abort-safety", oid_to_hex(&curr_head));
-		if (!state->rebasing)
-			update_ref("am", "ORIG_HEAD", &curr_head, NULL, 0,
-				   UPDATE_REFS_DIE_ON_ERR);
-	} else {
-		write_state_text(state, "abort-safety", "");
-		if (!state->rebasing)
-			delete_ref(NULL, "ORIG_HEAD", NULL, 0);
-	}
-
-	/*
-	 * NOTE: Since the "next" and "last" files determine if an am_state
-	 * session is in progress, they should be written last.
-	 */
-
-	write_state_count(state, "next", state->cur);
-	write_state_count(state, "last", state->last);
-
-	strbuf_release(&sb);
-}
-
-/**
- * Increments the patch pointer, and cleans am_state for the application of the
- * next patch.
- */
-static void am_next(struct am_state *state)
-{
-	struct object_id head;
-
-	FREE_AND_NULL(state->author_name);
-	FREE_AND_NULL(state->author_email);
-	FREE_AND_NULL(state->author_date);
-	FREE_AND_NULL(state->msg);
-	state->msg_len = 0;
-
-	unlink(am_path(state, "author-script"));
-	unlink(am_path(state, "final-commit"));
-
-	oidclr(&state->orig_commit);
-	unlink(am_path(state, "original-commit"));
-	delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
-
-	if (!get_oid("HEAD", &head))
-		write_state_text(state, "abort-safety", oid_to_hex(&head));
-	else
-		write_state_text(state, "abort-safety", "");
-
-	state->cur++;
-	write_state_count(state, "next", state->cur);
-}
-
-/**
- * Returns the filename of the current patch email.
- */
-static const char *msgnum(const struct am_state *state)
-{
-	static struct strbuf sb = STRBUF_INIT;
-
-	strbuf_reset(&sb);
-	strbuf_addf(&sb, "%0*d", state->prec, state->cur);
-
-	return sb.buf;
-}
-
-/**
- * Dies with a user-friendly message on how to proceed after resolving the
- * problem. This message can be overridden with state->resolvemsg.
- */
-static void NORETURN die_user_resolve(const struct am_state *state)
-{
-	if (state->resolvemsg) {
-		printf_ln("%s", state->resolvemsg);
-	} else {
-		const char *cmdline = state->interactive ? "git am -i" : "git am";
-
-		printf_ln(_("When you have resolved this problem, run \"%s --continue\"."), cmdline);
-		printf_ln(_("If you prefer to skip this patch, run \"%s --skip\" instead."), cmdline);
-		printf_ln(_("To restore the original branch and stop patching, run \"%s --abort\"."), cmdline);
-	}
-
-	exit(128);
-}
-
-/**
- * Appends signoff to the "msg" field of the am_state.
- */
-static void am_append_signoff(struct am_state *state)
-{
-	struct strbuf sb = STRBUF_INIT;
-
-	strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len);
-	append_signoff(&sb, 0, 0);
-	state->msg = strbuf_detach(&sb, &state->msg_len);
-}
-
-/**
- * Parses `mail` using git-mailinfo, extracting its patch and authorship info.
- * state->msg will be set to the patch message. state->author_name,
- * state->author_email and state->author_date will be set to the patch author's
- * name, email and date respectively. The patch body will be written to the
- * state directory's "patch" file.
- *
- * Returns 1 if the patch should be skipped, 0 otherwise.
- */
-static int parse_mail(struct am_state *state, const char *mail)
-{
-	FILE *fp;
-	struct strbuf sb = STRBUF_INIT;
-	struct strbuf msg = STRBUF_INIT;
-	struct strbuf author_name = STRBUF_INIT;
-	struct strbuf author_date = STRBUF_INIT;
-	struct strbuf author_email = STRBUF_INIT;
-	int ret = 0;
-	struct mailinfo mi;
-
-	setup_mailinfo(&mi);
-
-	if (state->utf8)
-		mi.metainfo_charset = get_commit_output_encoding();
-	else
-		mi.metainfo_charset = NULL;
-
-	switch (state->keep) {
-	case KEEP_FALSE:
-		break;
-	case KEEP_TRUE:
-		mi.keep_subject = 1;
-		break;
-	case KEEP_NON_PATCH:
-		mi.keep_non_patch_brackets_in_subject = 1;
-		break;
-	default:
-		BUG("invalid value for state->keep");
-	}
-
-	if (state->message_id)
-		mi.add_message_id = 1;
-
-	switch (state->scissors) {
-	case SCISSORS_UNSET:
-		break;
-	case SCISSORS_FALSE:
-		mi.use_scissors = 0;
-		break;
-	case SCISSORS_TRUE:
-		mi.use_scissors = 1;
-		break;
-	default:
-		BUG("invalid value for state->scissors");
-	}
-
-	mi.input = xfopen(mail, "r");
-	mi.output = xfopen(am_path(state, "info"), "w");
-	if (mailinfo(&mi, am_path(state, "msg"), am_path(state, "patch")))
-		die("could not parse patch");
-
-	fclose(mi.input);
-	fclose(mi.output);
-
-	if (mi.format_flowed)
-		warning(_("Patch sent with format=flowed; "
-			  "space at the end of lines might be lost."));
-
-	/* Extract message and author information */
-	fp = xfopen(am_path(state, "info"), "r");
-	while (!strbuf_getline_lf(&sb, fp)) {
-		const char *x;
-
-		if (skip_prefix(sb.buf, "Subject: ", &x)) {
-			if (msg.len)
-				strbuf_addch(&msg, '\n');
-			strbuf_addstr(&msg, x);
-		} else if (skip_prefix(sb.buf, "Author: ", &x))
-			strbuf_addstr(&author_name, x);
-		else if (skip_prefix(sb.buf, "Email: ", &x))
-			strbuf_addstr(&author_email, x);
-		else if (skip_prefix(sb.buf, "Date: ", &x))
-			strbuf_addstr(&author_date, x);
-	}
-	fclose(fp);
-
-	/* Skip pine's internal folder data */
-	if (!strcmp(author_name.buf, "Mail System Internal Data")) {
-		ret = 1;
-		goto finish;
-	}
-
-	if (is_empty_or_missing_file(am_path(state, "patch"))) {
-		printf_ln(_("Patch is empty."));
-		die_user_resolve(state);
-	}
-
-	strbuf_addstr(&msg, "\n\n");
-	strbuf_addbuf(&msg, &mi.log_message);
-	strbuf_stripspace(&msg, 0);
-
-	assert(!state->author_name);
-	state->author_name = strbuf_detach(&author_name, NULL);
-
-	assert(!state->author_email);
-	state->author_email = strbuf_detach(&author_email, NULL);
-
-	assert(!state->author_date);
-	state->author_date = strbuf_detach(&author_date, NULL);
-
-	assert(!state->msg);
-	state->msg = strbuf_detach(&msg, &state->msg_len);
-
-finish:
-	strbuf_release(&msg);
-	strbuf_release(&author_date);
-	strbuf_release(&author_email);
-	strbuf_release(&author_name);
-	strbuf_release(&sb);
-	clear_mailinfo(&mi);
-	return ret;
-}
-
-/**
- * Sets commit_id to the commit hash where the mail was generated from.
- * Returns 0 on success, -1 on failure.
- */
-static int get_mail_commit_oid(struct object_id *commit_id, const char *mail)
-{
-	struct strbuf sb = STRBUF_INIT;
-	FILE *fp = xfopen(mail, "r");
-	const char *x;
-	int ret = 0;
-
-	if (strbuf_getline_lf(&sb, fp) ||
-	    !skip_prefix(sb.buf, "From ", &x) ||
-	    get_oid_hex(x, commit_id) < 0)
-		ret = -1;
-
-	strbuf_release(&sb);
-	fclose(fp);
-	return ret;
-}
-
-/**
- * Sets state->msg, state->author_name, state->author_email, state->author_date
- * to the commit's respective info.
- */
-static void get_commit_info(struct am_state *state, struct commit *commit)
-{
-	const char *buffer, *ident_line, *msg;
-	size_t ident_len;
-	struct ident_split id;
-
-	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);
-
-	assert(!state->author_name);
-	if (id.name_begin)
-		state->author_name =
-			xmemdupz(id.name_begin, id.name_end - id.name_begin);
-	else
-		state->author_name = xstrdup("");
-
-	assert(!state->author_email);
-	if (id.mail_begin)
-		state->author_email =
-			xmemdupz(id.mail_begin, id.mail_end - id.mail_begin);
-	else
-		state->author_email = xstrdup("");
-
-	assert(!state->author_date);
-	state->author_date = xstrdup(show_ident_date(&id, DATE_MODE(NORMAL)));
-
-	assert(!state->msg);
-	msg = strstr(buffer, "\n\n");
-	if (!msg)
-		die(_("unable to parse commit %s"), oid_to_hex(&commit->object.oid));
-	state->msg = xstrdup(msg + 2);
-	state->msg_len = strlen(state->msg);
-	unuse_commit_buffer(commit, buffer);
-}
-
-/**
- * Writes `commit` as a patch to the state directory's "patch" file.
- */
-static void write_commit_patch(const struct am_state *state, struct commit *commit)
-{
-	struct rev_info rev_info;
-	FILE *fp;
-
-	fp = xfopen(am_path(state, "patch"), "w");
-	repo_init_revisions(the_repository, &rev_info, NULL);
-	rev_info.diff = 1;
-	rev_info.abbrev = 0;
-	rev_info.disable_stdin = 1;
-	rev_info.show_root_diff = 1;
-	rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;
-	rev_info.no_commit_id = 1;
-	rev_info.diffopt.flags.binary = 1;
-	rev_info.diffopt.flags.full_index = 1;
-	rev_info.diffopt.use_color = 0;
-	rev_info.diffopt.file = fp;
-	rev_info.diffopt.close_file = 1;
-	add_pending_object(&rev_info, &commit->object, "");
-	diff_setup_done(&rev_info.diffopt);
-	log_tree_commit(&rev_info, commit);
-}
-
-/**
- * Writes the diff of the index against HEAD as a patch to the state
- * directory's "patch" file.
- */
-static void write_index_patch(const struct am_state *state)
-{
-	struct tree *tree;
-	struct object_id head;
-	struct rev_info rev_info;
-	FILE *fp;
-
-	if (!get_oid("HEAD", &head)) {
-		struct commit *commit = lookup_commit_or_die(&head, "HEAD");
-		tree = get_commit_tree(commit);
-	} else
-		tree = lookup_tree(the_repository,
-				   the_repository->hash_algo->empty_tree);
-
-	fp = xfopen(am_path(state, "patch"), "w");
-	repo_init_revisions(the_repository, &rev_info, NULL);
-	rev_info.diff = 1;
-	rev_info.disable_stdin = 1;
-	rev_info.no_commit_id = 1;
-	rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;
-	rev_info.diffopt.use_color = 0;
-	rev_info.diffopt.file = fp;
-	rev_info.diffopt.close_file = 1;
-	add_pending_object(&rev_info, &tree->object, "");
-	diff_setup_done(&rev_info.diffopt);
-	run_diff_index(&rev_info, 1);
-}
-
-/**
- * Like parse_mail(), but parses the mail by looking up its commit ID
- * directly. This is used in --rebasing mode to bypass git-mailinfo's munging
- * of patches.
- *
- * state->orig_commit will be set to the original commit ID.
- *
- * Will always return 0 as the patch should never be skipped.
- */
-static int parse_mail_rebase(struct am_state *state, const char *mail)
-{
-	struct commit *commit;
-	struct object_id commit_oid;
-
-	if (get_mail_commit_oid(&commit_oid, mail) < 0)
-		die(_("could not parse %s"), mail);
-
-	commit = lookup_commit_or_die(&commit_oid, mail);
-
-	get_commit_info(state, commit);
-
-	write_commit_patch(state, commit);
-
-	oidcpy(&state->orig_commit, &commit_oid);
-	write_state_text(state, "original-commit", oid_to_hex(&commit_oid));
-	update_ref("am", "REBASE_HEAD", &commit_oid,
-		   NULL, REF_NO_DEREF, UPDATE_REFS_DIE_ON_ERR);
-
-	return 0;
-}
-
-/**
- * Applies current patch with git-apply. Returns 0 on success, -1 otherwise. If
- * `index_file` is not NULL, the patch will be applied to that index.
- */
-static int run_apply(const struct am_state *state, const char *index_file)
-{
-	struct strvec apply_paths = STRVEC_INIT;
-	struct strvec apply_opts = STRVEC_INIT;
-	struct apply_state apply_state;
-	int res, opts_left;
-	int force_apply = 0;
-	int options = 0;
-
-	if (init_apply_state(&apply_state, the_repository, NULL))
-		BUG("init_apply_state() failed");
-
-	strvec_push(&apply_opts, "apply");
-	strvec_pushv(&apply_opts, state->git_apply_opts.v);
-
-	opts_left = apply_parse_options(apply_opts.nr, apply_opts.v,
-					&apply_state, &force_apply, &options,
-					NULL);
-
-	if (opts_left != 0)
-		die("unknown option passed through to git apply");
-
-	if (index_file) {
-		apply_state.index_file = index_file;
-		apply_state.cached = 1;
-	} else
-		apply_state.check_index = 1;
-
-	/*
-	 * If we are allowed to fall back on 3-way merge, don't give false
-	 * errors during the initial attempt.
-	 */
-	if (state->threeway && !index_file)
-		apply_state.apply_verbosity = verbosity_silent;
-
-	if (check_apply_state(&apply_state, force_apply))
-		BUG("check_apply_state() failed");
-
-	strvec_push(&apply_paths, am_path(state, "patch"));
-
-	res = apply_all_patches(&apply_state, apply_paths.nr, apply_paths.v, options);
-
-	strvec_clear(&apply_paths);
-	strvec_clear(&apply_opts);
-	clear_apply_state(&apply_state);
-
-	if (res)
-		return res;
-
-	if (index_file) {
-		/* Reload index as apply_all_patches() will have modified it. */
-		discard_cache();
-		read_cache_from(index_file);
-	}
-
-	return 0;
-}
-
-/**
- * Builds an index that contains just the blobs needed for a 3way merge.
- */
-static int build_fake_ancestor(const struct am_state *state, const char *index_file)
-{
-	struct child_process cp = CHILD_PROCESS_INIT;
-
-	cp.git_cmd = 1;
-	strvec_push(&cp.args, "apply");
-	strvec_pushv(&cp.args, state->git_apply_opts.v);
-	strvec_pushf(&cp.args, "--build-fake-ancestor=%s", index_file);
-	strvec_push(&cp.args, am_path(state, "patch"));
-
-	if (run_command(&cp))
-		return -1;
-
-	return 0;
-}
-
-/**
- * Attempt a threeway merge, using index_path as the temporary index.
- */
-static int fall_back_threeway(const struct am_state *state, const char *index_path)
-{
-	struct object_id orig_tree, their_tree, our_tree;
-	const struct object_id *bases[1] = { &orig_tree };
-	struct merge_options o;
-	struct commit *result;
-	char *their_tree_name;
-
-	if (get_oid("HEAD", &our_tree) < 0)
-		oidcpy(&our_tree, the_hash_algo->empty_tree);
-
-	if (build_fake_ancestor(state, index_path))
-		return error("could not build fake ancestor");
-
-	discard_cache();
-	read_cache_from(index_path);
-
-	if (write_index_as_tree(&orig_tree, &the_index, index_path, 0, NULL))
-		return error(_("Repository lacks necessary blobs to fall back on 3-way merge."));
-
-	say(state, stdout, _("Using index info to reconstruct a base tree..."));
-
-	if (!state->quiet) {
-		/*
-		 * List paths that needed 3-way fallback, so that the user can
-		 * review them with extra care to spot mismerges.
-		 */
-		struct rev_info rev_info;
-
-		repo_init_revisions(the_repository, &rev_info, NULL);
-		rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS;
-		rev_info.diffopt.filter |= diff_filter_bit('A');
-		rev_info.diffopt.filter |= diff_filter_bit('M');
-		add_pending_oid(&rev_info, "HEAD", &our_tree, 0);
-		diff_setup_done(&rev_info.diffopt);
-		run_diff_index(&rev_info, 1);
-	}
-
-	if (run_apply(state, index_path))
-		return error(_("Did you hand edit your patch?\n"
-				"It does not apply to blobs recorded in its index."));
-
-	if (write_index_as_tree(&their_tree, &the_index, index_path, 0, NULL))
-		return error("could not write tree");
-
-	say(state, stdout, _("Falling back to patching base and 3-way merge..."));
-
-	discard_cache();
-	read_cache();
-
-	/*
-	 * This is not so wrong. Depending on which base we picked, orig_tree
-	 * may be wildly different from ours, but their_tree has the same set of
-	 * wildly different changes in parts the patch did not touch, so
-	 * recursive ends up canceling them, saying that we reverted all those
-	 * changes.
-	 */
-
-	init_merge_options(&o, the_repository);
-
-	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;
-
-	if (state->quiet)
-		o.verbosity = 0;
-
-	if (merge_recursive_generic(&o, &our_tree, &their_tree, 1, bases, &result)) {
-		repo_rerere(the_repository, state->allow_rerere_autoupdate);
-		free(their_tree_name);
-		return error(_("Failed to merge in the changes."));
-	}
-
-	free(their_tree_name);
-	return 0;
-}
-
-/**
- * Commits the current index with state->msg as the commit message and
- * state->author_name, state->author_email and state->author_date as the author
- * information.
- */
-static void do_commit(const struct am_state *state)
-{
-	struct object_id tree, parent, commit;
-	const struct object_id *old_oid;
-	struct commit_list *parents = NULL;
-	const char *reflog_msg, *author, *committer = NULL;
-	struct strbuf sb = STRBUF_INIT;
-
-	if (run_hook_le(NULL, "pre-applypatch", NULL))
-		exit(1);
-
-	if (write_cache_as_tree(&tree, 0, NULL))
-		die(_("git write-tree failed to write a tree"));
-
-	if (!get_oid_commit("HEAD", &parent)) {
-		old_oid = &parent;
-		commit_list_insert(lookup_commit(the_repository, &parent),
-				   &parents);
-	} else {
-		old_oid = NULL;
-		say(state, stderr, _("applying to an empty history"));
-	}
-
-	author = fmt_ident(state->author_name, state->author_email,
-		WANT_AUTHOR_IDENT,
-			state->ignore_date ? NULL : state->author_date,
-			IDENT_STRICT);
-
-	if (state->committer_date_is_author_date)
-		committer = fmt_ident(state->committer_name,
-				      state->committer_email, WANT_COMMITTER_IDENT,
-				      state->ignore_date ? NULL
-							 : state->author_date,
-				      IDENT_STRICT);
-
-	if (commit_tree_extended(state->msg, state->msg_len, &tree, parents,
-				 &commit, author, committer, state->sign_commit,
-				 NULL))
-		die(_("failed to write commit object"));
-
-	reflog_msg = getenv("GIT_REFLOG_ACTION");
-	if (!reflog_msg)
-		reflog_msg = "am";
-
-	strbuf_addf(&sb, "%s: %.*s", reflog_msg, linelen(state->msg),
-			state->msg);
-
-	update_ref(sb.buf, "HEAD", &commit, old_oid, 0,
-		   UPDATE_REFS_DIE_ON_ERR);
-
-	if (state->rebasing) {
-		FILE *fp = xfopen(am_path(state, "rewritten"), "a");
-
-		assert(!is_null_oid(&state->orig_commit));
-		fprintf(fp, "%s ", oid_to_hex(&state->orig_commit));
-		fprintf(fp, "%s\n", oid_to_hex(&commit));
-		fclose(fp);
-	}
-
-	run_hook_le(NULL, "post-applypatch", NULL);
-
-	strbuf_release(&sb);
-}
-
-/**
- * Validates the am_state for resuming -- the "msg" and authorship fields must
- * be filled up.
- */
-static void validate_resume_state(const struct am_state *state)
-{
-	if (!state->msg)
-		die(_("cannot resume: %s does not exist."),
-			am_path(state, "final-commit"));
-
-	if (!state->author_name || !state->author_email || !state->author_date)
-		die(_("cannot resume: %s does not exist."),
-			am_path(state, "author-script"));
-}
-
-/**
- * Interactively prompt the user on whether the current patch should be
- * applied.
- *
- * Returns 0 if the user chooses to apply the patch, 1 if the user chooses to
- * skip it.
- */
-static int do_interactive(struct am_state *state)
-{
-	assert(state->msg);
-
-	for (;;) {
-		char reply[64];
-
-		puts(_("Commit Body is:"));
-		puts("--------------------------");
-		printf("%s", state->msg);
-		puts("--------------------------");
-
-		/*
-		 * TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
-		 * in your translation. The program will only accept English
-		 * input at this point.
-		 */
-		printf(_("Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: "));
-		if (!fgets(reply, sizeof(reply), stdin))
-			die("unable to read from stdin; aborting");
-
-		if (*reply == 'y' || *reply == 'Y') {
-			return 0;
-		} else if (*reply == 'a' || *reply == 'A') {
-			state->interactive = 0;
-			return 0;
-		} else if (*reply == 'n' || *reply == 'N') {
-			return 1;
-		} else if (*reply == 'e' || *reply == 'E') {
-			struct strbuf msg = STRBUF_INIT;
-
-			if (!launch_editor(am_path(state, "final-commit"), &msg, NULL)) {
-				free(state->msg);
-				state->msg = strbuf_detach(&msg, &state->msg_len);
-			}
-			strbuf_release(&msg);
-		} else if (*reply == 'v' || *reply == 'V') {
-			const char *pager = git_pager(1);
-			struct child_process cp = CHILD_PROCESS_INIT;
-
-			if (!pager)
-				pager = "cat";
-			prepare_pager_args(&cp, pager);
-			strvec_push(&cp.args, am_path(state, "patch"));
-			run_command(&cp);
-		}
-	}
-}
-
-/**
- * Applies all queued mail.
- *
- * If `resume` is true, we are "resuming". The "msg" and authorship fields, as
- * well as the state directory's "patch" file is used as-is for applying the
- * patch and committing it.
- */
-static void am_run(struct am_state *state, int resume)
-{
-	struct strbuf sb = STRBUF_INIT;
-
-	unlink(am_path(state, "dirtyindex"));
-
-	if (refresh_and_write_cache(REFRESH_QUIET, 0, 0) < 0)
-		die(_("unable to write index file"));
-
-	if (repo_index_has_changes(the_repository, NULL, &sb)) {
-		write_state_bool(state, "dirtyindex", 1);
-		die(_("Dirty index: cannot apply patches (dirty: %s)"), sb.buf);
-	}
-
-	strbuf_release(&sb);
-
-	while (state->cur <= state->last) {
-		const char *mail = am_path(state, msgnum(state));
-		int apply_status;
-
-		reset_ident_date();
-
-		if (!file_exists(mail))
-			goto next;
-
-		if (resume) {
-			validate_resume_state(state);
-		} else {
-			int skip;
-
-			if (state->rebasing)
-				skip = parse_mail_rebase(state, mail);
-			else
-				skip = parse_mail(state, mail);
-
-			if (skip)
-				goto next; /* mail should be skipped */
-
-			if (state->signoff)
-				am_append_signoff(state);
-
-			write_author_script(state);
-			write_commit_msg(state);
-		}
-
-		if (state->interactive && do_interactive(state))
-			goto next;
-
-		if (run_applypatch_msg_hook(state))
-			exit(1);
-
-		say(state, stdout, _("Applying: %.*s"), linelen(state->msg), state->msg);
-
-		apply_status = run_apply(state, NULL);
-
-		if (apply_status && state->threeway) {
-			struct strbuf sb = STRBUF_INIT;
-
-			strbuf_addstr(&sb, am_path(state, "patch-merge-index"));
-			apply_status = fall_back_threeway(state, sb.buf);
-			strbuf_release(&sb);
-
-			/*
-			 * Applying the patch to an earlier tree and merging
-			 * the result may have produced the same tree as ours.
-			 */
-			if (!apply_status &&
-			    !repo_index_has_changes(the_repository, NULL, NULL)) {
-				say(state, stdout, _("No changes -- Patch already applied."));
-				goto next;
-			}
-		}
-
-		if (apply_status) {
-			printf_ln(_("Patch failed at %s %.*s"), msgnum(state),
-				linelen(state->msg), state->msg);
-
-			if (advice_amworkdir)
-				advise(_("Use 'git am --show-current-patch=diff' to see the failed patch"));
-
-			die_user_resolve(state);
-		}
-
-		do_commit(state);
-
-next:
-		am_next(state);
-
-		if (resume)
-			am_load(state);
-		resume = 0;
-	}
-
-	if (!is_empty_or_missing_file(am_path(state, "rewritten"))) {
-		assert(state->rebasing);
-		copy_notes_for_rebase(state);
-		run_post_rewrite_hook(state);
-	}
-
-	/*
-	 * In rebasing mode, it's up to the caller to take care of
-	 * housekeeping.
-	 */
-	if (!state->rebasing) {
-		am_destroy(state);
-		close_object_store(the_repository->objects);
-		run_auto_maintenance(state->quiet);
-	}
-}
-
-/**
- * Resume the current am session after patch application failure. The user did
- * all the hard work, and we do not have to do any patch application. Just
- * trust and commit what the user has in the index and working tree.
- */
-static void am_resolve(struct am_state *state)
-{
-	validate_resume_state(state);
-
-	say(state, stdout, _("Applying: %.*s"), linelen(state->msg), state->msg);
-
-	if (!repo_index_has_changes(the_repository, NULL, NULL)) {
-		printf_ln(_("No changes - did you forget to use 'git add'?\n"
-			"If there is nothing left to stage, chances are that something else\n"
-			"already introduced the same changes; you might want to skip this patch."));
-		die_user_resolve(state);
-	}
-
-	if (unmerged_cache()) {
-		printf_ln(_("You still have unmerged paths in your index.\n"
-			"You should 'git add' each file with resolved conflicts to mark them as such.\n"
-			"You might run `git rm` on a file to accept \"deleted by them\" for it."));
-		die_user_resolve(state);
-	}
-
-	if (state->interactive) {
-		write_index_patch(state);
-		if (do_interactive(state))
-			goto next;
-	}
-
-	repo_rerere(the_repository, 0);
-
-	do_commit(state);
-
-next:
-	am_next(state);
-	am_load(state);
-	am_run(state, 0);
-}
-
-/**
- * Performs a checkout fast-forward from `head` to `remote`. If `reset` is
- * true, any unmerged entries will be discarded. Returns 0 on success, -1 on
- * failure.
- */
-static int fast_forward_to(struct tree *head, struct tree *remote, int reset)
-{
-	struct lock_file lock_file = LOCK_INIT;
-	struct unpack_trees_options opts;
-	struct tree_desc t[2];
-
-	if (parse_tree(head) || parse_tree(remote))
-		return -1;
-
-	hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
-
-	refresh_cache(REFRESH_QUIET);
-
-	memset(&opts, 0, sizeof(opts));
-	opts.head_idx = 1;
-	opts.src_index = &the_index;
-	opts.dst_index = &the_index;
-	opts.update = 1;
-	opts.merge = 1;
-	opts.reset = reset;
-	opts.fn = twoway_merge;
-	init_tree_desc(&t[0], head->buffer, head->size);
-	init_tree_desc(&t[1], remote->buffer, remote->size);
-
-	if (unpack_trees(2, t, &opts)) {
-		rollback_lock_file(&lock_file);
-		return -1;
-	}
-
-	if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
-		die(_("unable to write new index file"));
-
-	return 0;
-}
-
-/**
- * Merges a tree into the index. The index's stat info will take precedence
- * over the merged tree's. Returns 0 on success, -1 on failure.
- */
-static int merge_tree(struct tree *tree)
-{
-	struct lock_file lock_file = LOCK_INIT;
-	struct unpack_trees_options opts;
-	struct tree_desc t[1];
-
-	if (parse_tree(tree))
-		return -1;
-
-	hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
-
-	memset(&opts, 0, sizeof(opts));
-	opts.head_idx = 1;
-	opts.src_index = &the_index;
-	opts.dst_index = &the_index;
-	opts.merge = 1;
-	opts.fn = oneway_merge;
-	init_tree_desc(&t[0], tree->buffer, tree->size);
-
-	if (unpack_trees(1, t, &opts)) {
-		rollback_lock_file(&lock_file);
-		return -1;
-	}
-
-	if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
-		die(_("unable to write new index file"));
-
-	return 0;
-}
-
-/**
- * Clean the index without touching entries that are not modified between
- * `head` and `remote`.
- */
-static int clean_index(const struct object_id *head, const struct object_id *remote)
-{
-	struct tree *head_tree, *remote_tree, *index_tree;
-	struct object_id index;
-
-	head_tree = parse_tree_indirect(head);
-	if (!head_tree)
-		return error(_("Could not parse object '%s'."), oid_to_hex(head));
-
-	remote_tree = parse_tree_indirect(remote);
-	if (!remote_tree)
-		return error(_("Could not parse object '%s'."), oid_to_hex(remote));
-
-	read_cache_unmerged();
-
-	if (fast_forward_to(head_tree, head_tree, 1))
-		return -1;
-
-	if (write_cache_as_tree(&index, 0, NULL))
-		return -1;
-
-	index_tree = parse_tree_indirect(&index);
-	if (!index_tree)
-		return error(_("Could not parse object '%s'."), oid_to_hex(&index));
-
-	if (fast_forward_to(index_tree, remote_tree, 0))
-		return -1;
-
-	if (merge_tree(remote_tree))
-		return -1;
-
-	remove_branch_state(the_repository, 0);
-
-	return 0;
-}
-
-/**
- * Resets rerere's merge resolution metadata.
- */
-static void am_rerere_clear(void)
-{
-	struct string_list merge_rr = STRING_LIST_INIT_DUP;
-	rerere_clear(the_repository, &merge_rr);
-	string_list_clear(&merge_rr, 1);
-}
-
-/**
- * Resume the current am session by skipping the current patch.
- */
-static void am_skip(struct am_state *state)
-{
-	struct object_id head;
-
-	am_rerere_clear();
-
-	if (get_oid("HEAD", &head))
-		oidcpy(&head, the_hash_algo->empty_tree);
-
-	if (clean_index(&head, &head))
-		die(_("failed to clean index"));
-
-	if (state->rebasing) {
-		FILE *fp = xfopen(am_path(state, "rewritten"), "a");
-
-		assert(!is_null_oid(&state->orig_commit));
-		fprintf(fp, "%s ", oid_to_hex(&state->orig_commit));
-		fprintf(fp, "%s\n", oid_to_hex(&head));
-		fclose(fp);
-	}
-
-	am_next(state);
-	am_load(state);
-	am_run(state, 0);
-}
-
-/**
- * Returns true if it is safe to reset HEAD to the ORIG_HEAD, false otherwise.
- *
- * It is not safe to reset HEAD when:
- * 1. git-am previously failed because the index was dirty.
- * 2. HEAD has moved since git-am previously failed.
- */
-static int safe_to_abort(const struct am_state *state)
-{
-	struct strbuf sb = STRBUF_INIT;
-	struct object_id abort_safety, head;
-
-	if (file_exists(am_path(state, "dirtyindex")))
-		return 0;
-
-	if (read_state_file(&sb, state, "abort-safety", 1) > 0) {
-		if (get_oid_hex(sb.buf, &abort_safety))
-			die(_("could not parse %s"), am_path(state, "abort-safety"));
-	} else
-		oidclr(&abort_safety);
-	strbuf_release(&sb);
-
-	if (get_oid("HEAD", &head))
-		oidclr(&head);
-
-	if (oideq(&head, &abort_safety))
-		return 1;
-
-	warning(_("You seem to have moved HEAD since the last 'am' failure.\n"
-		"Not rewinding to ORIG_HEAD"));
-
-	return 0;
-}
-
-/**
- * Aborts the current am session if it is safe to do so.
- */
-static void am_abort(struct am_state *state)
-{
-	struct object_id curr_head, orig_head;
-	int has_curr_head, has_orig_head;
-	char *curr_branch;
-
-	if (!safe_to_abort(state)) {
-		am_destroy(state);
-		return;
-	}
-
-	am_rerere_clear();
-
-	curr_branch = resolve_refdup("HEAD", 0, &curr_head, NULL);
-	has_curr_head = curr_branch && !is_null_oid(&curr_head);
-	if (!has_curr_head)
-		oidcpy(&curr_head, the_hash_algo->empty_tree);
-
-	has_orig_head = !get_oid("ORIG_HEAD", &orig_head);
-	if (!has_orig_head)
-		oidcpy(&orig_head, the_hash_algo->empty_tree);
-
-	clean_index(&curr_head, &orig_head);
-
-	if (has_orig_head)
-		update_ref("am --abort", "HEAD", &orig_head,
-			   has_curr_head ? &curr_head : NULL, 0,
-			   UPDATE_REFS_DIE_ON_ERR);
-	else if (curr_branch)
-		delete_ref(NULL, curr_branch, NULL, REF_NO_DEREF);
-
-	free(curr_branch);
-	am_destroy(state);
-}
-
-static int show_patch(struct am_state *state, enum show_patch_type sub_mode)
-{
-	struct strbuf sb = STRBUF_INIT;
-	const char *patch_path;
-	int len;
-
-	if (!is_null_oid(&state->orig_commit)) {
-		const char *av[4] = { "show", NULL, "--", NULL };
-		char *new_oid_str;
-		int ret;
-
-		av[1] = new_oid_str = xstrdup(oid_to_hex(&state->orig_commit));
-		ret = run_command_v_opt(av, RUN_GIT_CMD);
-		free(new_oid_str);
-		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");
-	}
-
-	len = strbuf_read_file(&sb, patch_path, 0);
-	if (len < 0)
-		die_errno(_("failed to read '%s'"), patch_path);
-
-	setup_pager();
-	write_in_full(1, sb.buf, sb.len);
-	strbuf_release(&sb);
-	return 0;
-}
-
-/**
- * parse_options() callback that validates and sets opt->value to the
- * PATCH_FORMAT_* enum value corresponding to `arg`.
- */
-static int parse_opt_patchformat(const struct option *opt, const char *arg, int unset)
-{
-	int *opt_value = opt->value;
-
-	if (unset)
-		*opt_value = PATCH_FORMAT_UNKNOWN;
-	else if (!strcmp(arg, "mbox"))
-		*opt_value = PATCH_FORMAT_MBOX;
-	else if (!strcmp(arg, "stgit"))
-		*opt_value = PATCH_FORMAT_STGIT;
-	else if (!strcmp(arg, "stgit-series"))
-		*opt_value = PATCH_FORMAT_STGIT_SERIES;
-	else if (!strcmp(arg, "hg"))
-		*opt_value = PATCH_FORMAT_HG;
-	else if (!strcmp(arg, "mboxrd"))
-		*opt_value = PATCH_FORMAT_MBOXRD;
-	/*
-	 * Please update $__git_patchformat in git-completion.bash
-	 * when you add new options
-	 */
-	else
-		return error(_("Invalid value for --patch-format: %s"), arg);
-	return 0;
-}
-
-enum resume_type {
-	RESUME_FALSE = 0,
-	RESUME_APPLY,
-	RESUME_RESOLVED,
-	RESUME_SKIP,
-	RESUME_ABORT,
-	RESUME_QUIT,
-	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;
-
-	BUG_ON_OPT_NEG(unset);
-
-	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;
-
-	status = git_gpg_config(k, v, NULL);
-	if (status)
-		return status;
-
-	return git_default_config(k, v, NULL);
-}
-
-int cmd_am(int argc, const char **argv, const char *prefix)
-{
-	struct am_state state;
-	int binary = -1;
-	int keep_cr = -1;
-	int patch_format = PATCH_FORMAT_UNKNOWN;
-	struct resume_mode resume = { .mode = RESUME_FALSE };
-	int in_progress;
-	int ret = 0;
-
-	const char * const usage[] = {
-		N_("git am [<options>] [(<mbox> | <Maildir>)...]"),
-		N_("git am [<options>] (--continue | --skip | --abort)"),
-		NULL
-	};
-
-	struct option options[] = {
-		OPT_BOOL('i', "interactive", &state.interactive,
-			N_("run interactively")),
-		OPT_HIDDEN_BOOL('b', "binary", &binary,
-			N_("historical option -- no-op")),
-		OPT_BOOL('3', "3way", &state.threeway,
-			N_("allow fall back on 3way merging if needed")),
-		OPT__QUIET(&state.quiet, N_("be quiet")),
-		OPT_SET_INT('s', "signoff", &state.signoff,
-			N_("add a Signed-off-by line to the commit message"),
-			SIGNOFF_EXPLICIT),
-		OPT_BOOL('u', "utf8", &state.utf8,
-			N_("recode into utf8 (default)")),
-		OPT_SET_INT('k', "keep", &state.keep,
-			N_("pass -k flag to git-mailinfo"), KEEP_TRUE),
-		OPT_SET_INT(0, "keep-non-patch", &state.keep,
-			N_("pass -b flag to git-mailinfo"), KEEP_NON_PATCH),
-		OPT_BOOL('m', "message-id", &state.message_id,
-			N_("pass -m flag to git-mailinfo")),
-		OPT_SET_INT_F(0, "keep-cr", &keep_cr,
-			N_("pass --keep-cr flag to git-mailsplit for mbox format"),
-			1, PARSE_OPT_NONEG),
-		OPT_SET_INT_F(0, "no-keep-cr", &keep_cr,
-			N_("do not pass --keep-cr flag to git-mailsplit independent of am.keepcr"),
-			0, PARSE_OPT_NONEG),
-		OPT_BOOL('c', "scissors", &state.scissors,
-			N_("strip everything before a scissors line")),
-		OPT_PASSTHRU_ARGV(0, "whitespace", &state.git_apply_opts, N_("action"),
-			N_("pass it through git-apply"),
-			0),
-		OPT_PASSTHRU_ARGV(0, "ignore-space-change", &state.git_apply_opts, NULL,
-			N_("pass it through git-apply"),
-			PARSE_OPT_NOARG),
-		OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &state.git_apply_opts, NULL,
-			N_("pass it through git-apply"),
-			PARSE_OPT_NOARG),
-		OPT_PASSTHRU_ARGV(0, "directory", &state.git_apply_opts, N_("root"),
-			N_("pass it through git-apply"),
-			0),
-		OPT_PASSTHRU_ARGV(0, "exclude", &state.git_apply_opts, N_("path"),
-			N_("pass it through git-apply"),
-			0),
-		OPT_PASSTHRU_ARGV(0, "include", &state.git_apply_opts, N_("path"),
-			N_("pass it through git-apply"),
-			0),
-		OPT_PASSTHRU_ARGV('C', NULL, &state.git_apply_opts, N_("n"),
-			N_("pass it through git-apply"),
-			0),
-		OPT_PASSTHRU_ARGV('p', NULL, &state.git_apply_opts, N_("num"),
-			N_("pass it through git-apply"),
-			0),
-		OPT_CALLBACK(0, "patch-format", &patch_format, N_("format"),
-			N_("format the patch(es) are in"),
-			parse_opt_patchformat),
-		OPT_PASSTHRU_ARGV(0, "reject", &state.git_apply_opts, NULL,
-			N_("pass it through git-apply"),
-			PARSE_OPT_NOARG),
-		OPT_STRING(0, "resolvemsg", &state.resolvemsg, NULL,
-			N_("override error message when patch failure occurs")),
-		OPT_CMDMODE(0, "continue", &resume.mode,
-			N_("continue applying patches after resolving a conflict"),
-			RESUME_RESOLVED),
-		OPT_CMDMODE('r', "resolved", &resume.mode,
-			N_("synonyms for --continue"),
-			RESUME_RESOLVED),
-		OPT_CMDMODE(0, "skip", &resume.mode,
-			N_("skip the current patch"),
-			RESUME_SKIP),
-		OPT_CMDMODE(0, "abort", &resume.mode,
-			N_("restore the original branch and abort the patching operation."),
-			RESUME_ABORT),
-		OPT_CMDMODE(0, "quit", &resume.mode,
-			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_BOOL(0, "committer-date-is-author-date",
-			&state.committer_date_is_author_date,
-			N_("lie about committer date")),
-		OPT_BOOL(0, "ignore-date", &state.ignore_date,
-			N_("use current timestamp for author date")),
-		OPT_RERERE_AUTOUPDATE(&state.allow_rerere_autoupdate),
-		{ OPTION_STRING, 'S', "gpg-sign", &state.sign_commit, N_("key-id"),
-		  N_("GPG-sign commits"),
-		  PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
-		OPT_HIDDEN_BOOL(0, "rebasing", &state.rebasing,
-			N_("(internal use for git-rebase)")),
-		OPT_END()
-	};
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage_with_options(usage, options);
-
-	git_config(git_am_config, NULL);
-
-	am_state_init(&state);
-
-	in_progress = am_in_progress(&state);
-	if (in_progress)
-		am_load(&state);
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-
-	if (binary >= 0)
-		fprintf_ln(stderr, _("The -b/--binary option has been a no-op for long time, and\n"
-				"it will be removed. Please do not use it anymore."));
-
-	/* Ensure a valid committer ident can be constructed */
-	git_committer_info(IDENT_STRICT);
-
-	if (repo_read_index_preload(the_repository, NULL, 0) < 0)
-		die(_("failed to read the index"));
-
-	if (in_progress) {
-		/*
-		 * Catch user error to feed us patches when there is a session
-		 * in progress:
-		 *
-		 * 1. mbox path(s) are provided on the command-line.
-		 * 2. stdin is not a tty: the user is trying to feed us a patch
-		 *    from standard input. This is somewhat unreliable -- stdin
-		 *    could be /dev/null for example and the caller did not
-		 *    intend to feed us a patch but wanted to continue
-		 *    unattended.
-		 */
-		if (argc || (resume.mode == 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 (state.signoff == SIGNOFF_EXPLICIT)
-			am_append_signoff(&state);
-	} else {
-		struct strvec paths = STRVEC_INIT;
-		int i;
-
-		/*
-		 * Handle stray state directory in the independent-run case. In
-		 * the --rebasing case, it is up to the caller to take care of
-		 * stray directories.
-		 */
-		if (file_exists(state.dir) && !state.rebasing) {
-			if (resume.mode == RESUME_ABORT || resume.mode == RESUME_QUIT) {
-				am_destroy(&state);
-				am_state_release(&state);
-				return 0;
-			}
-
-			die(_("Stray %s directory found.\n"
-				"Use \"git am --abort\" to remove it."),
-				state.dir);
-		}
-
-		if (resume.mode)
-			die(_("Resolve operation not in progress, we are not resuming."));
-
-		for (i = 0; i < argc; i++) {
-			if (is_absolute_path(argv[i]) || !prefix)
-				strvec_push(&paths, argv[i]);
-			else
-				strvec_push(&paths, mkpath("%s/%s", prefix, argv[i]));
-		}
-
-		if (state.interactive && !paths.nr)
-			die(_("interactive mode requires patches on the command line"));
-
-		am_setup(&state, patch_format, paths.v, keep_cr);
-
-		strvec_clear(&paths);
-	}
-
-	switch (resume.mode) {
-	case RESUME_FALSE:
-		am_run(&state, 0);
-		break;
-	case RESUME_APPLY:
-		am_run(&state, 1);
-		break;
-	case RESUME_RESOLVED:
-		am_resolve(&state);
-		break;
-	case RESUME_SKIP:
-		am_skip(&state);
-		break;
-	case RESUME_ABORT:
-		am_abort(&state);
-		break;
-	case RESUME_QUIT:
-		am_rerere_clear();
-		am_destroy(&state);
-		break;
-	case RESUME_SHOW_PATCH:
-		ret = show_patch(&state, resume.sub_mode);
-		break;
-	default:
-		BUG("invalid resume value");
-	}
-
-	am_state_release(&state);
-
-	return ret;
-}
diff --git a/third_party/git/builtin/annotate.c b/third_party/git/builtin/annotate.c
deleted file mode 100644
index 58ff977a2314..000000000000
--- a/third_party/git/builtin/annotate.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * "git annotate" builtin alias
- *
- * Copyright (C) 2006 Ryan Anderson
- */
-#include "git-compat-util.h"
-#include "builtin.h"
-#include "strvec.h"
-
-int cmd_annotate(int argc, const char **argv, const char *prefix)
-{
-	struct strvec args = STRVEC_INIT;
-	int i;
-
-	strvec_pushl(&args, "annotate", "-c", NULL);
-
-	for (i = 1; i < argc; i++) {
-		strvec_push(&args, argv[i]);
-	}
-
-	return cmd_blame(args.nr, args.v, prefix);
-}
diff --git a/third_party/git/builtin/apply.c b/third_party/git/builtin/apply.c
deleted file mode 100644
index 3f099b960565..000000000000
--- a/third_party/git/builtin/apply.c
+++ /dev/null
@@ -1,34 +0,0 @@
-#include "cache.h"
-#include "builtin.h"
-#include "parse-options.h"
-#include "lockfile.h"
-#include "apply.h"
-
-static const char * const apply_usage[] = {
-	N_("git apply [<options>] [<patch>...]"),
-	NULL
-};
-
-int cmd_apply(int argc, const char **argv, const char *prefix)
-{
-	int force_apply = 0;
-	int options = 0;
-	int ret;
-	struct apply_state state;
-
-	if (init_apply_state(&state, the_repository, prefix))
-		exit(128);
-
-	argc = apply_parse_options(argc, argv,
-				   &state, &force_apply, &options,
-				   apply_usage);
-
-	if (check_apply_state(&state, force_apply))
-		exit(128);
-
-	ret = apply_all_patches(&state, argc, argv, options);
-
-	clear_apply_state(&state);
-
-	return ret;
-}
diff --git a/third_party/git/builtin/archive.c b/third_party/git/builtin/archive.c
deleted file mode 100644
index 45d11669aae4..000000000000
--- a/third_party/git/builtin/archive.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2006 Franck Bui-Huu
- * Copyright (c) 2006 Rene Scharfe
- */
-#include "cache.h"
-#include "builtin.h"
-#include "archive.h"
-#include "transport.h"
-#include "parse-options.h"
-#include "pkt-line.h"
-#include "sideband.h"
-
-static void create_output_file(const char *output_file)
-{
-	int output_fd = open(output_file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
-	if (output_fd < 0)
-		die_errno(_("could not create archive file '%s'"), output_file);
-	if (output_fd != 1) {
-		if (dup2(output_fd, 1) < 0)
-			die_errno(_("could not redirect output"));
-		else
-			close(output_fd);
-	}
-}
-
-static int run_remote_archiver(int argc, const char **argv,
-			       const char *remote, const char *exec,
-			       const char *name_hint)
-{
-	int fd[2], i, rv;
-	struct transport *transport;
-	struct remote *_remote;
-	struct packet_reader reader;
-
-	_remote = remote_get(remote);
-	if (!_remote->url[0])
-		die(_("git archive: Remote with no URL"));
-	transport = transport_get(_remote, _remote->url[0]);
-	transport_connect(transport, "git-upload-archive", exec, fd);
-
-	/*
-	 * Inject a fake --format field at the beginning of the
-	 * arguments, with the format inferred from our output
-	 * filename. This way explicit --format options can override
-	 * it.
-	 */
-	if (name_hint) {
-		const char *format = archive_format_from_filename(name_hint);
-		if (format)
-			packet_write_fmt(fd[1], "argument --format=%s\n", format);
-	}
-	for (i = 1; i < argc; i++)
-		packet_write_fmt(fd[1], "argument %s\n", argv[i]);
-	packet_flush(fd[1]);
-
-	packet_reader_init(&reader, fd[0], NULL, 0,
-			   PACKET_READ_CHOMP_NEWLINE |
-			   PACKET_READ_DIE_ON_ERR_PACKET);
-
-	if (packet_reader_read(&reader) != PACKET_READ_NORMAL)
-		die(_("git archive: expected ACK/NAK, got a flush packet"));
-	if (strcmp(reader.line, "ACK")) {
-		if (starts_with(reader.line, "NACK "))
-			die(_("git archive: NACK %s"), reader.line + 5);
-		die(_("git archive: protocol error"));
-	}
-
-	if (packet_reader_read(&reader) != PACKET_READ_FLUSH)
-		die(_("git archive: expected a flush"));
-
-	/* Now, start reading from fd[0] and spit it out to stdout */
-	rv = recv_sideband("archive", fd[0], 1);
-	rv |= transport_disconnect(transport);
-
-	return !!rv;
-}
-
-#define PARSE_OPT_KEEP_ALL ( PARSE_OPT_KEEP_DASHDASH | 	\
-			     PARSE_OPT_KEEP_ARGV0 | 	\
-			     PARSE_OPT_KEEP_UNKNOWN |	\
-			     PARSE_OPT_NO_INTERNAL_HELP	)
-
-int cmd_archive(int argc, const char **argv, const char *prefix)
-{
-	const char *exec = "git-upload-archive";
-	const char *output = NULL;
-	const char *remote = NULL;
-	struct option local_opts[] = {
-		OPT_FILENAME('o', "output", &output,
-			     N_("write the archive to this file")),
-		OPT_STRING(0, "remote", &remote, N_("repo"),
-			N_("retrieve the archive from remote repository <repo>")),
-		OPT_STRING(0, "exec", &exec, N_("command"),
-			N_("path to the remote git-upload-archive command")),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, local_opts, NULL,
-			     PARSE_OPT_KEEP_ALL);
-
-	init_archivers();
-
-	if (output)
-		create_output_file(output);
-
-	if (remote)
-		return run_remote_archiver(argc, argv, remote, exec, output);
-
-	setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
-
-	return write_archive(argc, argv, prefix, the_repository, output, 0);
-}
diff --git a/third_party/git/builtin/bisect--helper.c b/third_party/git/builtin/bisect--helper.c
deleted file mode 100644
index 7512b880f0d6..000000000000
--- a/third_party/git/builtin/bisect--helper.c
+++ /dev/null
@@ -1,981 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "parse-options.h"
-#include "bisect.h"
-#include "refs.h"
-#include "dir.h"
-#include "strvec.h"
-#include "run-command.h"
-#include "prompt.h"
-#include "quote.h"
-#include "revision.h"
-
-static GIT_PATH_FUNC(git_path_bisect_terms, "BISECT_TERMS")
-static GIT_PATH_FUNC(git_path_bisect_expected_rev, "BISECT_EXPECTED_REV")
-static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, "BISECT_ANCESTORS_OK")
-static GIT_PATH_FUNC(git_path_bisect_start, "BISECT_START")
-static GIT_PATH_FUNC(git_path_bisect_log, "BISECT_LOG")
-static GIT_PATH_FUNC(git_path_head_name, "head-name")
-static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")
-static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT")
-
-static const char * const git_bisect_helper_usage[] = {
-	N_("git bisect--helper --next-all"),
-	N_("git bisect--helper --write-terms <bad_term> <good_term>"),
-	N_("git bisect--helper --bisect-clean-state"),
-	N_("git bisect--helper --bisect-reset [<commit>]"),
-	N_("git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>"),
-	N_("git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>"),
-	N_("git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]"),
-	N_("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]"),
-	N_("git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}=<term>]"
-					    " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]"),
-	N_("git bisect--helper --bisect-next"),
-	N_("git bisect--helper --bisect-auto-next"),
-	N_("git bisect--helper --bisect-autostart"),
-	NULL
-};
-
-struct add_bisect_ref_data {
-	struct rev_info *revs;
-	unsigned int object_flags;
-};
-
-struct bisect_terms {
-	char *term_good;
-	char *term_bad;
-};
-
-static void free_terms(struct bisect_terms *terms)
-{
-	FREE_AND_NULL(terms->term_good);
-	FREE_AND_NULL(terms->term_bad);
-}
-
-static void set_terms(struct bisect_terms *terms, const char *bad,
-		      const char *good)
-{
-	free((void *)terms->term_good);
-	terms->term_good = xstrdup(good);
-	free((void *)terms->term_bad);
-	terms->term_bad = xstrdup(bad);
-}
-
-static const char vocab_bad[] = "bad|new";
-static const char vocab_good[] = "good|old";
-
-static int bisect_autostart(struct bisect_terms *terms);
-
-/*
- * Check whether the string `term` belongs to the set of strings
- * included in the variable arguments.
- */
-LAST_ARG_MUST_BE_NULL
-static int one_of(const char *term, ...)
-{
-	int res = 0;
-	va_list matches;
-	const char *match;
-
-	va_start(matches, term);
-	while (!res && (match = va_arg(matches, const char *)))
-		res = !strcmp(term, match);
-	va_end(matches);
-
-	return res;
-}
-
-static int write_in_file(const char *path, const char *mode, const char *format, va_list args)
-{
-	FILE *fp = NULL;
-	int res = 0;
-
-	if (strcmp(mode, "w") && strcmp(mode, "a"))
-		BUG("write-in-file does not support '%s' mode", mode);
-	fp = fopen(path, mode);
-	if (!fp)
-		return error_errno(_("cannot open file '%s' in mode '%s'"), path, mode);
-	res = vfprintf(fp, format, args);
-
-	if (res < 0) {
-		int saved_errno = errno;
-		fclose(fp);
-		errno = saved_errno;
-		return error_errno(_("could not write to file '%s'"), path);
-	}
-
-	return fclose(fp);
-}
-
-static int write_to_file(const char *path, const char *format, ...)
-{
-	int res;
-	va_list args;
-
-	va_start(args, format);
-	res = write_in_file(path, "w", format, args);
-	va_end(args);
-
-	return res;
-}
-
-static int append_to_file(const char *path, const char *format, ...)
-{
-	int res;
-	va_list args;
-
-	va_start(args, format);
-	res = write_in_file(path, "a", format, args);
-	va_end(args);
-
-	return res;
-}
-
-static int check_term_format(const char *term, const char *orig_term)
-{
-	int res;
-	char *new_term = xstrfmt("refs/bisect/%s", term);
-
-	res = check_refname_format(new_term, 0);
-	free(new_term);
-
-	if (res)
-		return error(_("'%s' is not a valid term"), term);
-
-	if (one_of(term, "help", "start", "skip", "next", "reset",
-			"visualize", "view", "replay", "log", "run", "terms", NULL))
-		return error(_("can't use the builtin command '%s' as a term"), term);
-
-	/*
-	 * In theory, nothing prevents swapping completely good and bad,
-	 * but this situation could be confusing and hasn't been tested
-	 * enough. Forbid it for now.
-	 */
-
-	if ((strcmp(orig_term, "bad") && one_of(term, "bad", "new", NULL)) ||
-		 (strcmp(orig_term, "good") && one_of(term, "good", "old", NULL)))
-		return error(_("can't change the meaning of the term '%s'"), term);
-
-	return 0;
-}
-
-static int write_terms(const char *bad, const char *good)
-{
-	int res;
-
-	if (!strcmp(bad, good))
-		return error(_("please use two different terms"));
-
-	if (check_term_format(bad, "bad") || check_term_format(good, "good"))
-		return -1;
-
-	res = write_to_file(git_path_bisect_terms(), "%s\n%s\n", bad, good);
-
-	return res;
-}
-
-static int is_expected_rev(const char *expected_hex)
-{
-	struct strbuf actual_hex = STRBUF_INIT;
-	int res = 0;
-	if (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) >= 40) {
-		strbuf_trim(&actual_hex);
-		res = !strcmp(actual_hex.buf, expected_hex);
-	}
-	strbuf_release(&actual_hex);
-	return res;
-}
-
-static void check_expected_revs(const char **revs, int rev_nr)
-{
-	int i;
-
-	for (i = 0; i < rev_nr; i++) {
-		if (!is_expected_rev(revs[i])) {
-			unlink_or_warn(git_path_bisect_ancestors_ok());
-			unlink_or_warn(git_path_bisect_expected_rev());
-		}
-	}
-}
-
-static int bisect_reset(const char *commit)
-{
-	struct strbuf branch = STRBUF_INIT;
-
-	if (!commit) {
-		if (strbuf_read_file(&branch, git_path_bisect_start(), 0) < 1) {
-			printf(_("We are not bisecting.\n"));
-			return 0;
-		}
-		strbuf_rtrim(&branch);
-	} else {
-		struct object_id oid;
-
-		if (get_oid_commit(commit, &oid))
-			return error(_("'%s' is not a valid commit"), commit);
-		strbuf_addstr(&branch, commit);
-	}
-
-	if (!ref_exists("BISECT_HEAD")) {
-		struct strvec argv = STRVEC_INIT;
-
-		strvec_pushl(&argv, "checkout", branch.buf, "--", NULL);
-		if (run_command_v_opt(argv.v, RUN_GIT_CMD)) {
-			error(_("could not check out original"
-				" HEAD '%s'. Try 'git bisect"
-				" reset <commit>'."), branch.buf);
-			strbuf_release(&branch);
-			strvec_clear(&argv);
-			return -1;
-		}
-		strvec_clear(&argv);
-	}
-
-	strbuf_release(&branch);
-	return bisect_clean_state();
-}
-
-static void log_commit(FILE *fp, char *fmt, const char *state,
-		       struct commit *commit)
-{
-	struct pretty_print_context pp = {0};
-	struct strbuf commit_msg = STRBUF_INIT;
-	char *label = xstrfmt(fmt, state);
-
-	format_commit_message(commit, "%s", &commit_msg, &pp);
-
-	fprintf(fp, "# %s: [%s] %s\n", label, oid_to_hex(&commit->object.oid),
-		commit_msg.buf);
-
-	strbuf_release(&commit_msg);
-	free(label);
-}
-
-static int bisect_write(const char *state, const char *rev,
-			const struct bisect_terms *terms, int nolog)
-{
-	struct strbuf tag = STRBUF_INIT;
-	struct object_id oid;
-	struct commit *commit;
-	FILE *fp = NULL;
-	int res = 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);
-		goto finish;
-	}
-
-	if (get_oid(rev, &oid)) {
-		res = 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;
-		goto finish;
-	}
-
-	fp = fopen(git_path_bisect_log(), "a");
-	if (!fp) {
-		res = error_errno(_("couldn't open the file '%s'"), git_path_bisect_log());
-		goto finish;
-	}
-
-	commit = lookup_commit_reference(the_repository, &oid);
-	log_commit(fp, "%s", state, commit);
-
-	if (!nolog)
-		fprintf(fp, "git bisect %s %s\n", state, rev);
-
-finish:
-	if (fp)
-		fclose(fp);
-	strbuf_release(&tag);
-	return res;
-}
-
-static int check_and_set_terms(struct bisect_terms *terms, const char *cmd)
-{
-	int has_term_file = !is_empty_or_missing_file(git_path_bisect_terms());
-
-	if (one_of(cmd, "skip", "start", "terms", NULL))
-		return 0;
-
-	if (has_term_file && strcmp(cmd, terms->term_bad) &&
-	    strcmp(cmd, terms->term_good))
-		return error(_("Invalid command: you're currently in a "
-				"%s/%s bisect"), terms->term_bad,
-				terms->term_good);
-
-	if (!has_term_file) {
-		if (one_of(cmd, "bad", "good", NULL)) {
-			set_terms(terms, "bad", "good");
-			return write_terms(terms->term_bad, terms->term_good);
-		}
-		if (one_of(cmd, "new", "old", NULL)) {
-			set_terms(terms, "new", "old");
-			return write_terms(terms->term_bad, terms->term_good);
-		}
-	}
-
-	return 0;
-}
-
-static int mark_good(const char *refname, const struct object_id *oid,
-		     int flag, void *cb_data)
-{
-	int *m_good = (int *)cb_data;
-	*m_good = 0;
-	return 1;
-}
-
-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[] =
-	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)
-{
-	if (!missing_good && !missing_bad)
-		return 0;
-	if (!current_term)
-		return -1;
-
-	if (missing_good && !missing_bad &&
-	    !strcmp(current_term, terms->term_good)) {
-		char *yesno;
-		/*
-		 * have bad (or new) but not good (or old). We could bisect
-		 * although this is less optimum.
-		 */
-		warning(_("bisecting only with a %s commit"), terms->term_bad);
-		if (!isatty(0))
-			return 0;
-		/*
-		 * TRANSLATORS: Make sure to include [Y] and [n] in your
-		 * translation. The program will only accept English input
-		 * at this point.
-		 */
-		yesno = git_prompt(_("Are you sure [Y/n]? "), PROMPT_ECHO);
-		if (starts_with(yesno, "N") || starts_with(yesno, "n"))
-			return -1;
-		return 0;
-	}
-
-	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);
-}
-
-static int get_terms(struct bisect_terms *terms)
-{
-	struct strbuf str = STRBUF_INIT;
-	FILE *fp = NULL;
-	int res = 0;
-
-	fp = fopen(git_path_bisect_terms(), "r");
-	if (!fp) {
-		res = -1;
-		goto finish;
-	}
-
-	free_terms(terms);
-	strbuf_getline_lf(&str, fp);
-	terms->term_bad = strbuf_detach(&str, NULL);
-	strbuf_getline_lf(&str, fp);
-	terms->term_good = strbuf_detach(&str, NULL);
-
-finish:
-	if (fp)
-		fclose(fp);
-	strbuf_release(&str);
-	return res;
-}
-
-static int bisect_terms(struct bisect_terms *terms, const char *option)
-{
-	if (get_terms(terms))
-		return error(_("no terms defined"));
-
-	if (option == NULL) {
-		printf(_("Your current terms are %s for the old state\n"
-			 "and %s for the new state.\n"),
-		       terms->term_good, terms->term_bad);
-		return 0;
-	}
-	if (one_of(option, "--term-good", "--term-old", NULL))
-		printf("%s\n", terms->term_good);
-	else if (one_of(option, "--term-bad", "--term-new", NULL))
-		printf("%s\n", terms->term_bad);
-	else
-		return error(_("invalid argument %s for 'git bisect terms'.\n"
-			       "Supported options are: "
-			       "--term-good|--term-old and "
-			       "--term-bad|--term-new."), option);
-
-	return 0;
-}
-
-static int bisect_append_log_quoted(const char **argv)
-{
-	int res = 0;
-	FILE *fp = fopen(git_path_bisect_log(), "a");
-	struct strbuf orig_args = STRBUF_INIT;
-
-	if (!fp)
-		return -1;
-
-	if (fprintf(fp, "git bisect start") < 1) {
-		res = -1;
-		goto finish;
-	}
-
-	sq_quote_argv(&orig_args, argv);
-	if (fprintf(fp, "%s\n", orig_args.buf) < 1)
-		res = -1;
-
-finish:
-	fclose(fp);
-	strbuf_release(&orig_args);
-	return res;
-}
-
-static int add_bisect_ref(const char *refname, const struct object_id *oid,
-			  int flags, void *cb)
-{
-	struct add_bisect_ref_data *data = cb;
-
-	add_pending_oid(data->revs, refname, oid, data->object_flags);
-
-	return 0;
-}
-
-static int prepare_revs(struct bisect_terms *terms, struct rev_info *revs)
-{
-	int res = 0;
-	struct add_bisect_ref_data cb = { revs };
-	char *good = xstrfmt("%s-*", terms->term_good);
-
-	/*
-	 * We cannot use terms->term_bad directly in
-	 * for_each_glob_ref_in() and we have to append a '*' to it,
-	 * otherwise for_each_glob_ref_in() will append '/' and '*'.
-	 */
-	char *bad = xstrfmt("%s*", terms->term_bad);
-
-	/*
-	 * It is important to reset the flags used by revision walks
-	 * as the previous call to bisect_next_all() in turn
-	 * sets up a revision walk.
-	 */
-	reset_revision_walk();
-	init_revisions(revs, NULL);
-	setup_revisions(0, NULL, revs, NULL);
-	for_each_glob_ref_in(add_bisect_ref, bad, "refs/bisect/", &cb);
-	cb.object_flags = UNINTERESTING;
-	for_each_glob_ref_in(add_bisect_ref, good, "refs/bisect/", &cb);
-	if (prepare_revision_walk(revs))
-		res = error(_("revision walk setup failed\n"));
-
-	free(good);
-	free(bad);
-	return res;
-}
-
-static int bisect_skipped_commits(struct bisect_terms *terms)
-{
-	int res;
-	FILE *fp = NULL;
-	struct rev_info revs;
-	struct commit *commit;
-	struct pretty_print_context pp = {0};
-	struct strbuf commit_name = STRBUF_INIT;
-
-	res = prepare_revs(terms, &revs);
-	if (res)
-		return res;
-
-	fp = fopen(git_path_bisect_log(), "a");
-	if (!fp)
-		return error_errno(_("could not open '%s' for appending"),
-				  git_path_bisect_log());
-
-	if (fprintf(fp, "# only skipped commits left to test\n") < 0)
-		return error_errno(_("failed to write to '%s'"), git_path_bisect_log());
-
-	while ((commit = get_revision(&revs)) != NULL) {
-		strbuf_reset(&commit_name);
-		format_commit_message(commit, "%s",
-				      &commit_name, &pp);
-		fprintf(fp, "# possible first %s commit: [%s] %s\n",
-			terms->term_bad, oid_to_hex(&commit->object.oid),
-			commit_name.buf);
-	}
-
-	/*
-	 * Reset the flags used by revision walks in case
-	 * there is another revision walk after this one.
-	 */
-	reset_revision_walk();
-
-	strbuf_release(&commit_name);
-	fclose(fp);
-	return 0;
-}
-
-static int bisect_successful(struct bisect_terms *terms)
-{
-	struct object_id oid;
-	struct commit *commit;
-	struct pretty_print_context pp = {0};
-	struct strbuf commit_name = STRBUF_INIT;
-	char *bad_ref = xstrfmt("refs/bisect/%s",terms->term_bad);
-	int res;
-
-	read_ref(bad_ref, &oid);
-	commit = lookup_commit_reference_by_name(bad_ref);
-	format_commit_message(commit, "%s", &commit_name, &pp);
-
-	res = append_to_file(git_path_bisect_log(), "# first %s commit: [%s] %s\n",
-			    terms->term_bad, oid_to_hex(&commit->object.oid),
-			    commit_name.buf);
-
-	strbuf_release(&commit_name);
-	free(bad_ref);
-	return res;
-}
-
-static enum bisect_error bisect_next(struct bisect_terms *terms, const char *prefix)
-{
-	enum bisect_error res;
-
-	if (bisect_autostart(terms))
-		return BISECT_FAILED;
-
-	if (bisect_next_check(terms, terms->term_good))
-		return BISECT_FAILED;
-
-	/* Perform all bisection computation */
-	res = bisect_next_all(the_repository, prefix);
-
-	if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND) {
-		res = bisect_successful(terms);
-		return res ? res : BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND;
-	} else if (res == BISECT_ONLY_SKIPPED_LEFT) {
-		res = bisect_skipped_commits(terms);
-		return res ? res : BISECT_ONLY_SKIPPED_LEFT;
-	}
-	return res;
-}
-
-static enum bisect_error bisect_auto_next(struct bisect_terms *terms, const char *prefix)
-{
-	if (bisect_next_check(terms, NULL))
-		return BISECT_OK;
-
-	return bisect_next(terms, prefix);
-}
-
-static int bisect_start(struct bisect_terms *terms, const char **argv, int argc)
-{
-	int no_checkout = 0;
-	int first_parent_only = 0;
-	int i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0;
-	int flags, pathspec_pos, res = 0;
-	struct string_list revs = STRING_LIST_INIT_DUP;
-	struct string_list states = STRING_LIST_INIT_DUP;
-	struct strbuf start_head = STRBUF_INIT;
-	struct strbuf bisect_names = STRBUF_INIT;
-	struct object_id head_oid;
-	struct object_id oid;
-	const char *head;
-
-	if (is_bare_repository())
-		no_checkout = 1;
-
-	/*
-	 * Check for one bad and then some good revisions
-	 */
-	for (i = 0; i < argc; i++) {
-		if (!strcmp(argv[i], "--")) {
-			has_double_dash = 1;
-			break;
-		}
-	}
-
-	for (i = 0; i < argc; i++) {
-		const char *arg = argv[i];
-		if (!strcmp(argv[i], "--")) {
-			break;
-		} else if (!strcmp(arg, "--no-checkout")) {
-			no_checkout = 1;
-		} else if (!strcmp(arg, "--first-parent")) {
-			first_parent_only = 1;
-		} else if (!strcmp(arg, "--term-good") ||
-			 !strcmp(arg, "--term-old")) {
-			i++;
-			if (argc <= i)
-				return error(_("'' is not a valid term"));
-			must_write_terms = 1;
-			free((void *) terms->term_good);
-			terms->term_good = xstrdup(argv[i]);
-		} else if (skip_prefix(arg, "--term-good=", &arg) ||
-			   skip_prefix(arg, "--term-old=", &arg)) {
-			must_write_terms = 1;
-			free((void *) terms->term_good);
-			terms->term_good = xstrdup(arg);
-		} else if (!strcmp(arg, "--term-bad") ||
-			 !strcmp(arg, "--term-new")) {
-			i++;
-			if (argc <= i)
-				return error(_("'' is not a valid term"));
-			must_write_terms = 1;
-			free((void *) terms->term_bad);
-			terms->term_bad = xstrdup(argv[i]);
-		} else if (skip_prefix(arg, "--term-bad=", &arg) ||
-			   skip_prefix(arg, "--term-new=", &arg)) {
-			must_write_terms = 1;
-			free((void *) terms->term_bad);
-			terms->term_bad = xstrdup(arg);
-		} else if (starts_with(arg, "--")) {
-			return error(_("unrecognized option: '%s'"), arg);
-		} else if (!get_oidf(&oid, "%s^{commit}", arg)) {
-			string_list_append(&revs, oid_to_hex(&oid));
-		} else if (has_double_dash) {
-			die(_("'%s' does not appear to be a valid "
-			      "revision"), arg);
-		} else {
-			break;
-		}
-	}
-	pathspec_pos = i;
-
-	/*
-	 * The user ran "git bisect start <sha1> <sha1>", hence did not
-	 * explicitly specify the terms, but we are already starting to
-	 * set references named with the default terms, and won't be able
-	 * to change afterwards.
-	 */
-	if (revs.nr)
-		must_write_terms = 1;
-	for (i = 0; i < revs.nr; i++) {
-		if (bad_seen) {
-			string_list_append(&states, terms->term_good);
-		} else {
-			bad_seen = 1;
-			string_list_append(&states, terms->term_bad);
-		}
-	}
-
-	/*
-	 * Verify HEAD
-	 */
-	head = resolve_ref_unsafe("HEAD", 0, &head_oid, &flags);
-	if (!head)
-		if (get_oid("HEAD", &head_oid))
-			return error(_("bad HEAD - I need a HEAD"));
-
-	/*
-	 * Check if we are bisecting
-	 */
-	if (!is_empty_or_missing_file(git_path_bisect_start())) {
-		/* Reset to the rev from where we started */
-		strbuf_read_file(&start_head, git_path_bisect_start(), 0);
-		strbuf_trim(&start_head);
-		if (!no_checkout) {
-			struct strvec argv = STRVEC_INIT;
-
-			strvec_pushl(&argv, "checkout", start_head.buf,
-				     "--", NULL);
-			if (run_command_v_opt(argv.v, RUN_GIT_CMD)) {
-				res = error(_("checking out '%s' failed."
-						 " Try 'git bisect start "
-						 "<valid-branch>'."),
-					       start_head.buf);
-				goto finish;
-			}
-		}
-	} else {
-		/* Get the rev from where we start. */
-		if (!get_oid(head, &head_oid) &&
-		    !starts_with(head, "refs/heads/")) {
-			strbuf_reset(&start_head);
-			strbuf_addstr(&start_head, oid_to_hex(&head_oid));
-		} else if (!get_oid(head, &head_oid) &&
-			   skip_prefix(head, "refs/heads/", &head)) {
-			/*
-			 * This error message should only be triggered by
-			 * cogito usage, and cogito users should understand
-			 * it relates to cg-seek.
-			 */
-			if (!is_empty_or_missing_file(git_path_head_name()))
-				return error(_("won't bisect on cg-seek'ed tree"));
-			strbuf_addstr(&start_head, head);
-		} else {
-			return error(_("bad HEAD - strange symbolic ref"));
-		}
-	}
-
-	/*
-	 * Get rid of any old bisect state.
-	 */
-	if (bisect_clean_state())
-		return -1;
-
-	/*
-	 * In case of mistaken revs or checkout error, or signals received,
-	 * "bisect_auto_next" below may exit or misbehave.
-	 * We have to trap this to be able to clean up using
-	 * "bisect_clean_state".
-	 */
-
-	/*
-	 * Write new start state
-	 */
-	write_file(git_path_bisect_start(), "%s\n", start_head.buf);
-
-	if (first_parent_only)
-		write_file(git_path_bisect_first_parent(), "\n");
-
-	if (no_checkout) {
-		if (get_oid(start_head.buf, &oid) < 0) {
-			res = 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;
-			goto finish;
-		}
-	}
-
-	if (pathspec_pos < argc - 1)
-		sq_quote_argv(&bisect_names, argv + pathspec_pos);
-	write_file(git_path_bisect_names(), "%s\n", bisect_names.buf);
-
-	for (i = 0; i < states.nr; i++)
-		if (bisect_write(states.items[i].string,
-				 revs.items[i].string, terms, 1)) {
-			res = -1;
-			goto finish;
-		}
-
-	if (must_write_terms && write_terms(terms->term_bad,
-					    terms->term_good)) {
-		res = -1;
-		goto finish;
-	}
-
-	res = bisect_append_log_quoted(argv);
-	if (res)
-		res = -1;
-
-finish:
-	string_list_clear(&revs, 0);
-	string_list_clear(&states, 0);
-	strbuf_release(&start_head);
-	strbuf_release(&bisect_names);
-	return res;
-}
-
-static inline int file_is_not_empty(const char *path)
-{
-	return !is_empty_or_missing_file(path);
-}
-
-static int bisect_autostart(struct bisect_terms *terms)
-{
-	int res;
-	const char *yesno;
-
-	if (file_is_not_empty(git_path_bisect_start()))
-		return 0;
-
-	fprintf_ln(stderr, _("You need to start by \"git bisect "
-			  "start\"\n"));
-
-	if (!isatty(STDIN_FILENO))
-		return -1;
-
-	/*
-	 * TRANSLATORS: Make sure to include [Y] and [n] in your
-	 * translation. The program will only accept English input
-	 * at this point.
-	 */
-	yesno = git_prompt(_("Do you want me to do it for you "
-			     "[Y/n]? "), PROMPT_ECHO);
-	res = tolower(*yesno) == 'n' ?
-		-1 : bisect_start(terms, empty_strvec, 0);
-
-	return res;
-}
-
-int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
-{
-	enum {
-		NEXT_ALL = 1,
-		WRITE_TERMS,
-		BISECT_CLEAN_STATE,
-		CHECK_EXPECTED_REVS,
-		BISECT_RESET,
-		BISECT_WRITE,
-		CHECK_AND_SET_TERMS,
-		BISECT_NEXT_CHECK,
-		BISECT_TERMS,
-		BISECT_START,
-		BISECT_AUTOSTART,
-		BISECT_NEXT,
-		BISECT_AUTO_NEXT
-	} cmdmode = 0;
-	int res = 0, nolog = 0;
-	struct option options[] = {
-		OPT_CMDMODE(0, "next-all", &cmdmode,
-			 N_("perform 'git bisect next'"), NEXT_ALL),
-		OPT_CMDMODE(0, "write-terms", &cmdmode,
-			 N_("write the terms to .git/BISECT_TERMS"), WRITE_TERMS),
-		OPT_CMDMODE(0, "bisect-clean-state", &cmdmode,
-			 N_("cleanup the bisection state"), BISECT_CLEAN_STATE),
-		OPT_CMDMODE(0, "check-expected-revs", &cmdmode,
-			 N_("check for expected revs"), CHECK_EXPECTED_REVS),
-		OPT_CMDMODE(0, "bisect-reset", &cmdmode,
-			 N_("reset the bisection state"), BISECT_RESET),
-		OPT_CMDMODE(0, "bisect-write", &cmdmode,
-			 N_("write out the bisection state in BISECT_LOG"), BISECT_WRITE),
-		OPT_CMDMODE(0, "check-and-set-terms", &cmdmode,
-			 N_("check and set terms in a bisection state"), CHECK_AND_SET_TERMS),
-		OPT_CMDMODE(0, "bisect-next-check", &cmdmode,
-			 N_("check whether bad or good terms exist"), BISECT_NEXT_CHECK),
-		OPT_CMDMODE(0, "bisect-terms", &cmdmode,
-			 N_("print out the bisect terms"), BISECT_TERMS),
-		OPT_CMDMODE(0, "bisect-start", &cmdmode,
-			 N_("start the bisect session"), BISECT_START),
-		OPT_CMDMODE(0, "bisect-next", &cmdmode,
-			 N_("find the next bisection commit"), BISECT_NEXT),
-		OPT_CMDMODE(0, "bisect-auto-next", &cmdmode,
-			 N_("verify the next bisection state then checkout the next bisection commit"), BISECT_AUTO_NEXT),
-		OPT_CMDMODE(0, "bisect-autostart", &cmdmode,
-			 N_("start the bisection if it has not yet been started"), BISECT_AUTOSTART),
-		OPT_BOOL(0, "no-log", &nolog,
-			 N_("no log for BISECT_WRITE")),
-		OPT_END()
-	};
-	struct bisect_terms terms = { .term_good = NULL, .term_bad = NULL };
-
-	argc = parse_options(argc, argv, prefix, options,
-			     git_bisect_helper_usage,
-			     PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_UNKNOWN);
-
-	if (!cmdmode)
-		usage_with_options(git_bisect_helper_usage, options);
-
-	switch (cmdmode) {
-	case NEXT_ALL:
-		res = bisect_next_all(the_repository, prefix);
-		break;
-	case WRITE_TERMS:
-		if (argc != 2)
-			return error(_("--write-terms requires two arguments"));
-		return write_terms(argv[0], argv[1]);
-	case BISECT_CLEAN_STATE:
-		if (argc != 0)
-			return error(_("--bisect-clean-state requires no arguments"));
-		return bisect_clean_state();
-	case CHECK_EXPECTED_REVS:
-		check_expected_revs(argv, argc);
-		return 0;
-	case BISECT_RESET:
-		if (argc > 1)
-			return error(_("--bisect-reset requires either no argument or a commit"));
-		return !!bisect_reset(argc ? argv[0] : NULL);
-	case BISECT_WRITE:
-		if (argc != 4 && argc != 5)
-			return error(_("--bisect-write requires either 4 or 5 arguments"));
-		set_terms(&terms, argv[3], argv[2]);
-		res = bisect_write(argv[0], argv[1], &terms, nolog);
-		break;
-	case CHECK_AND_SET_TERMS:
-		if (argc != 3)
-			return error(_("--check-and-set-terms requires 3 arguments"));
-		set_terms(&terms, argv[2], argv[1]);
-		res = check_and_set_terms(&terms, argv[0]);
-		break;
-	case BISECT_NEXT_CHECK:
-		if (argc != 2 && argc != 3)
-			return error(_("--bisect-next-check requires 2 or 3 arguments"));
-		set_terms(&terms, argv[1], argv[0]);
-		res = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL);
-		break;
-	case BISECT_TERMS:
-		if (argc > 1)
-			return error(_("--bisect-terms requires 0 or 1 argument"));
-		res = bisect_terms(&terms, argc == 1 ? argv[0] : NULL);
-		break;
-	case BISECT_START:
-		set_terms(&terms, "bad", "good");
-		res = bisect_start(&terms, argv, argc);
-		break;
-	case BISECT_NEXT:
-		if (argc)
-			return error(_("--bisect-next requires 0 arguments"));
-		get_terms(&terms);
-		res = bisect_next(&terms, prefix);
-		break;
-	case BISECT_AUTO_NEXT:
-		if (argc)
-			return error(_("--bisect-auto-next requires 0 arguments"));
-		get_terms(&terms);
-		res = bisect_auto_next(&terms, prefix);
-		break;
-	case BISECT_AUTOSTART:
-		if (argc)
-			return error(_("--bisect-autostart does not accept arguments"));
-		set_terms(&terms, "bad", "good");
-		res = bisect_autostart(&terms);
-		break;
-	default:
-		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_INTERNAL_SUCCESS_1ST_BAD_FOUND))
-		res = BISECT_OK;
-
-	return -res;
-}
diff --git a/third_party/git/builtin/blame.c b/third_party/git/builtin/blame.c
deleted file mode 100644
index 7112be2afe16..000000000000
--- a/third_party/git/builtin/blame.c
+++ /dev/null
@@ -1,1204 +0,0 @@
-/*
- * Blame
- *
- * Copyright (c) 2006, 2014 by its authors
- * See COPYING for licensing conditions
- */
-
-#include "cache.h"
-#include "config.h"
-#include "color.h"
-#include "builtin.h"
-#include "repository.h"
-#include "commit.h"
-#include "diff.h"
-#include "revision.h"
-#include "quote.h"
-#include "string-list.h"
-#include "mailmap.h"
-#include "parse-options.h"
-#include "prio-queue.h"
-#include "utf8.h"
-#include "userdiff.h"
-#include "line-range.h"
-#include "line-log.h"
-#include "dir.h"
-#include "progress.h"
-#include "object-store.h"
-#include "blame.h"
-#include "refs.h"
-#include "tag.h"
-
-static char blame_usage[] = N_("git blame [<options>] [<rev-opts>] [<rev>] [--] <file>");
-
-static const char *blame_opt_usage[] = {
-	blame_usage,
-	"",
-	N_("<rev-opts> are documented in git-rev-list(1)"),
-	NULL
-};
-
-static int longest_file;
-static int longest_author;
-static int max_orig_digits;
-static int max_digits;
-static int max_score_digits;
-static int show_root;
-static int reverse;
-static int blank_boundary;
-static int incremental;
-static int xdl_opts;
-static int abbrev = -1;
-static int no_whole_file_rename;
-static int show_progress;
-static char repeated_meta_color[COLOR_MAXLEN];
-static int coloring_mode;
-static struct string_list ignore_revs_file_list = STRING_LIST_INIT_NODUP;
-static int mark_unblamable_lines;
-static int mark_ignored_lines;
-
-static struct date_mode blame_date_mode = { DATE_ISO8601 };
-static size_t blame_date_width;
-
-static struct string_list mailmap = STRING_LIST_INIT_NODUP;
-
-#ifndef DEBUG_BLAME
-#define DEBUG_BLAME 0
-#endif
-
-static unsigned blame_move_score;
-static unsigned blame_copy_score;
-
-/* Remember to update object flag allocation in object.h */
-#define METAINFO_SHOWN		(1u<<12)
-#define MORE_THAN_ONE_PATH	(1u<<13)
-
-struct progress_info {
-	struct progress *progress;
-	int blamed_lines;
-};
-
-static const char *nth_line_cb(void *data, long lno)
-{
-	return blame_nth_line((struct blame_scoreboard *)data, lno);
-}
-
-/*
- * Information on commits, used for output.
- */
-struct commit_info {
-	struct strbuf author;
-	struct strbuf author_mail;
-	timestamp_t author_time;
-	struct strbuf author_tz;
-
-	/* filled only when asked for details */
-	struct strbuf committer;
-	struct strbuf committer_mail;
-	timestamp_t committer_time;
-	struct strbuf committer_tz;
-
-	struct strbuf summary;
-};
-
-/*
- * Parse author/committer line in the commit object buffer
- */
-static void get_ac_line(const char *inbuf, const char *what,
-	struct strbuf *name, struct strbuf *mail,
-	timestamp_t *time, struct strbuf *tz)
-{
-	struct ident_split ident;
-	size_t len, maillen, namelen;
-	char *tmp, *endp;
-	const char *namebuf, *mailbuf;
-
-	tmp = strstr(inbuf, what);
-	if (!tmp)
-		goto error_out;
-	tmp += strlen(what);
-	endp = strchr(tmp, '\n');
-	if (!endp)
-		len = strlen(tmp);
-	else
-		len = endp - tmp;
-
-	if (split_ident_line(&ident, tmp, len)) {
-	error_out:
-		/* Ugh */
-		tmp = "(unknown)";
-		strbuf_addstr(name, tmp);
-		strbuf_addstr(mail, tmp);
-		strbuf_addstr(tz, tmp);
-		*time = 0;
-		return;
-	}
-
-	namelen = ident.name_end - ident.name_begin;
-	namebuf = ident.name_begin;
-
-	maillen = ident.mail_end - ident.mail_begin;
-	mailbuf = ident.mail_begin;
-
-	if (ident.date_begin && ident.date_end)
-		*time = strtoul(ident.date_begin, NULL, 10);
-	else
-		*time = 0;
-
-	if (ident.tz_begin && ident.tz_end)
-		strbuf_add(tz, ident.tz_begin, ident.tz_end - ident.tz_begin);
-	else
-		strbuf_addstr(tz, "(unknown)");
-
-	/*
-	 * Now, convert both name and e-mail using mailmap
-	 */
-	map_user(&mailmap, &mailbuf, &maillen,
-		 &namebuf, &namelen);
-
-	strbuf_addf(mail, "<%.*s>", (int)maillen, mailbuf);
-	strbuf_add(name, namebuf, namelen);
-}
-
-static void commit_info_init(struct commit_info *ci)
-{
-
-	strbuf_init(&ci->author, 0);
-	strbuf_init(&ci->author_mail, 0);
-	strbuf_init(&ci->author_tz, 0);
-	strbuf_init(&ci->committer, 0);
-	strbuf_init(&ci->committer_mail, 0);
-	strbuf_init(&ci->committer_tz, 0);
-	strbuf_init(&ci->summary, 0);
-}
-
-static void commit_info_destroy(struct commit_info *ci)
-{
-
-	strbuf_release(&ci->author);
-	strbuf_release(&ci->author_mail);
-	strbuf_release(&ci->author_tz);
-	strbuf_release(&ci->committer);
-	strbuf_release(&ci->committer_mail);
-	strbuf_release(&ci->committer_tz);
-	strbuf_release(&ci->summary);
-}
-
-static void get_commit_info(struct commit *commit,
-			    struct commit_info *ret,
-			    int detailed)
-{
-	int len;
-	const char *subject, *encoding;
-	const char *message;
-
-	commit_info_init(ret);
-
-	encoding = get_log_output_encoding();
-	message = logmsg_reencode(commit, NULL, encoding);
-	get_ac_line(message, "\nauthor ",
-		    &ret->author, &ret->author_mail,
-		    &ret->author_time, &ret->author_tz);
-
-	if (!detailed) {
-		unuse_commit_buffer(commit, message);
-		return;
-	}
-
-	get_ac_line(message, "\ncommitter ",
-		    &ret->committer, &ret->committer_mail,
-		    &ret->committer_time, &ret->committer_tz);
-
-	len = find_commit_subject(message, &subject);
-	if (len)
-		strbuf_add(&ret->summary, subject, len);
-	else
-		strbuf_addf(&ret->summary, "(%s)", oid_to_hex(&commit->object.oid));
-
-	unuse_commit_buffer(commit, message);
-}
-
-/*
- * Write out any suspect information which depends on the path. This must be
- * handled separately from emit_one_suspect_detail(), because a given commit
- * may have changes in multiple paths. So this needs to appear each time
- * we mention a new group.
- *
- * To allow LF and other nonportable characters in pathnames,
- * they are c-style quoted as needed.
- */
-static void write_filename_info(struct blame_origin *suspect)
-{
-	if (suspect->previous) {
-		struct blame_origin *prev = suspect->previous;
-		printf("previous %s ", oid_to_hex(&prev->commit->object.oid));
-		write_name_quoted(prev->path, stdout, '\n');
-	}
-	printf("filename ");
-	write_name_quoted(suspect->path, stdout, '\n');
-}
-
-/*
- * Porcelain/Incremental format wants to show a lot of details per
- * commit.  Instead of repeating this every line, emit it only once,
- * the first time each commit appears in the output (unless the
- * user has specifically asked for us to repeat).
- */
-static int emit_one_suspect_detail(struct blame_origin *suspect, int repeat)
-{
-	struct commit_info ci;
-
-	if (!repeat && (suspect->commit->object.flags & METAINFO_SHOWN))
-		return 0;
-
-	suspect->commit->object.flags |= METAINFO_SHOWN;
-	get_commit_info(suspect->commit, &ci, 1);
-	printf("author %s\n", ci.author.buf);
-	printf("author-mail %s\n", ci.author_mail.buf);
-	printf("author-time %"PRItime"\n", ci.author_time);
-	printf("author-tz %s\n", ci.author_tz.buf);
-	printf("committer %s\n", ci.committer.buf);
-	printf("committer-mail %s\n", ci.committer_mail.buf);
-	printf("committer-time %"PRItime"\n", ci.committer_time);
-	printf("committer-tz %s\n", ci.committer_tz.buf);
-	printf("summary %s\n", ci.summary.buf);
-	if (suspect->commit->object.flags & UNINTERESTING)
-		printf("boundary\n");
-
-	commit_info_destroy(&ci);
-
-	return 1;
-}
-
-/*
- * The blame_entry is found to be guilty for the range.
- * Show it in incremental output.
- */
-static void found_guilty_entry(struct blame_entry *ent, void *data)
-{
-	struct progress_info *pi = (struct progress_info *)data;
-
-	if (incremental) {
-		struct blame_origin *suspect = ent->suspect;
-
-		printf("%s %d %d %d\n",
-		       oid_to_hex(&suspect->commit->object.oid),
-		       ent->s_lno + 1, ent->lno + 1, ent->num_lines);
-		emit_one_suspect_detail(suspect, 0);
-		write_filename_info(suspect);
-		maybe_flush_or_die(stdout, "stdout");
-	}
-	pi->blamed_lines += ent->num_lines;
-	display_progress(pi->progress, pi->blamed_lines);
-}
-
-static const char *format_time(timestamp_t time, const char *tz_str,
-			       int show_raw_time)
-{
-	static struct strbuf time_buf = STRBUF_INIT;
-
-	strbuf_reset(&time_buf);
-	if (show_raw_time) {
-		strbuf_addf(&time_buf, "%"PRItime" %s", time, tz_str);
-	}
-	else {
-		const char *time_str;
-		size_t time_width;
-		int tz;
-		tz = atoi(tz_str);
-		time_str = show_date(time, tz, &blame_date_mode);
-		strbuf_addstr(&time_buf, time_str);
-		/*
-		 * Add space paddings to time_buf to display a fixed width
-		 * string, and use time_width for display width calibration.
-		 */
-		for (time_width = utf8_strwidth(time_str);
-		     time_width < blame_date_width;
-		     time_width++)
-			strbuf_addch(&time_buf, ' ');
-	}
-	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)
-
-static void emit_porcelain_details(struct blame_origin *suspect, int repeat)
-{
-	if (emit_one_suspect_detail(suspect, repeat) ||
-	    (suspect->commit->object.flags & MORE_THAN_ONE_PATH))
-		write_filename_info(suspect);
-}
-
-static void emit_porcelain(struct blame_scoreboard *sb, struct blame_entry *ent,
-			   int opt)
-{
-	int repeat = opt & OUTPUT_LINE_PORCELAIN;
-	int cnt;
-	const char *cp;
-	struct blame_origin *suspect = ent->suspect;
-	char hex[GIT_MAX_HEXSZ + 1];
-
-	oid_to_hex_r(hex, &suspect->commit->object.oid);
-	printf("%s %d %d %d\n",
-	       hex,
-	       ent->s_lno + 1,
-	       ent->lno + 1,
-	       ent->num_lines);
-	emit_porcelain_details(suspect, repeat);
-
-	cp = blame_nth_line(sb, ent->lno);
-	for (cnt = 0; cnt < ent->num_lines; cnt++) {
-		char ch;
-		if (cnt) {
-			printf("%s %d %d\n", hex,
-			       ent->s_lno + 1 + cnt,
-			       ent->lno + 1 + cnt);
-			if (repeat)
-				emit_porcelain_details(suspect, 1);
-		}
-		putchar('\t');
-		do {
-			ch = *cp++;
-			putchar(ch);
-		} while (ch != '\n' &&
-			 cp < sb->final_buf + sb->final_buf_size);
-	}
-
-	if (sb->final_buf_size && cp[-1] != '\n')
-		putchar('\n');
-}
-
-static struct color_field {
-	timestamp_t hop;
-	char col[COLOR_MAXLEN];
-} *colorfield;
-static int colorfield_nr, colorfield_alloc;
-
-static void parse_color_fields(const char *s)
-{
-	struct string_list l = STRING_LIST_INIT_DUP;
-	struct string_list_item *item;
-	enum { EXPECT_DATE, EXPECT_COLOR } next = EXPECT_COLOR;
-
-	colorfield_nr = 0;
-
-	/* Ideally this would be stripped and split at the same time? */
-	string_list_split(&l, s, ',', -1);
-	ALLOC_GROW(colorfield, colorfield_nr + 1, colorfield_alloc);
-
-	for_each_string_list_item(item, &l) {
-		switch (next) {
-		case EXPECT_DATE:
-			colorfield[colorfield_nr].hop = approxidate(item->string);
-			next = EXPECT_COLOR;
-			colorfield_nr++;
-			ALLOC_GROW(colorfield, colorfield_nr + 1, colorfield_alloc);
-			break;
-		case EXPECT_COLOR:
-			if (color_parse(item->string, colorfield[colorfield_nr].col))
-				die(_("expecting a color: %s"), item->string);
-			next = EXPECT_DATE;
-			break;
-		}
-	}
-
-	if (next == EXPECT_COLOR)
-		die(_("must end with a color"));
-
-	colorfield[colorfield_nr].hop = TIME_MAX;
-	string_list_clear(&l, 0);
-}
-
-static void setup_default_color_by_age(void)
-{
-	parse_color_fields("blue,12 month ago,white,1 month ago,red");
-}
-
-static void determine_line_heat(struct blame_entry *ent, const char **dest_color)
-{
-	int i = 0;
-	struct commit_info ci;
-	get_commit_info(ent->suspect->commit, &ci, 1);
-
-	while (i < colorfield_nr && ci.author_time > colorfield[i].hop)
-		i++;
-
-	*dest_color = colorfield[i].col;
-}
-
-static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int opt)
-{
-	int cnt;
-	const char *cp;
-	struct blame_origin *suspect = ent->suspect;
-	struct commit_info ci;
-	char hex[GIT_MAX_HEXSZ + 1];
-	int show_raw_time = !!(opt & OUTPUT_RAW_TIMESTAMP);
-	const char *default_color = NULL, *color = NULL, *reset = NULL;
-
-	get_commit_info(suspect->commit, &ci, 1);
-	oid_to_hex_r(hex, &suspect->commit->object.oid);
-
-	cp = blame_nth_line(sb, ent->lno);
-
-	if (opt & OUTPUT_SHOW_AGE_WITH_COLOR) {
-		determine_line_heat(ent, &default_color);
-		color = default_color;
-		reset = GIT_COLOR_RESET;
-	}
-
-	for (cnt = 0; cnt < ent->num_lines; cnt++) {
-		char ch;
-		int length = (opt & OUTPUT_LONG_OBJECT_NAME) ? the_hash_algo->hexsz : abbrev;
-
-		if (opt & OUTPUT_COLOR_LINE) {
-			if (cnt > 0) {
-				color = repeated_meta_color;
-				reset = GIT_COLOR_RESET;
-			} else  {
-				color = default_color ? default_color : NULL;
-				reset = default_color ? GIT_COLOR_RESET : NULL;
-			}
-		}
-		if (color)
-			fputs(color, stdout);
-
-		if (suspect->commit->object.flags & UNINTERESTING) {
-			if (blank_boundary)
-				memset(hex, ' ', length);
-			else if (!(opt & OUTPUT_ANNOTATE_COMPAT)) {
-				length--;
-				putchar('^');
-			}
-		}
-
-		if (mark_unblamable_lines && ent->unblamable) {
-			length--;
-			putchar('*');
-		}
-		if (mark_ignored_lines && ent->ignored) {
-			length--;
-			putchar('?');
-		}
-		printf("%.*s", length, hex);
-		if (opt & OUTPUT_ANNOTATE_COMPAT) {
-			const char *name;
-			if (opt & OUTPUT_SHOW_EMAIL)
-				name = ci.author_mail.buf;
-			else
-				name = ci.author.buf;
-			printf("\t(%10s\t%10s\t%d)", name,
-			       format_time(ci.author_time, ci.author_tz.buf,
-					   show_raw_time),
-			       ent->lno + 1 + cnt);
-		} else {
-			if (opt & OUTPUT_SHOW_SCORE)
-				printf(" %*d %02d",
-				       max_score_digits, ent->score,
-				       ent->suspect->refcnt);
-			if (opt & OUTPUT_SHOW_NAME)
-				printf(" %-*.*s", longest_file, longest_file,
-				       suspect->path);
-			if (opt & OUTPUT_SHOW_NUMBER)
-				printf(" %*d", max_orig_digits,
-				       ent->s_lno + 1 + cnt);
-
-			if (!(opt & OUTPUT_NO_AUTHOR)) {
-				const char *name;
-				int pad;
-				if (opt & OUTPUT_SHOW_EMAIL)
-					name = ci.author_mail.buf;
-				else
-					name = ci.author.buf;
-				pad = longest_author - utf8_strwidth(name);
-				printf(" (%s%*s %10s",
-				       name, pad, "",
-				       format_time(ci.author_time,
-						   ci.author_tz.buf,
-						   show_raw_time));
-			}
-			printf(" %*d) ",
-			       max_digits, ent->lno + 1 + cnt);
-		}
-		if (reset)
-			fputs(reset, stdout);
-		do {
-			ch = *cp++;
-			putchar(ch);
-		} while (ch != '\n' &&
-			 cp < sb->final_buf + sb->final_buf_size);
-	}
-
-	if (sb->final_buf_size && cp[-1] != '\n')
-		putchar('\n');
-
-	commit_info_destroy(&ci);
-}
-
-static void output(struct blame_scoreboard *sb, int option)
-{
-	struct blame_entry *ent;
-
-	if (option & OUTPUT_PORCELAIN) {
-		for (ent = sb->ent; ent; ent = ent->next) {
-			int count = 0;
-			struct blame_origin *suspect;
-			struct commit *commit = ent->suspect->commit;
-			if (commit->object.flags & MORE_THAN_ONE_PATH)
-				continue;
-			for (suspect = get_blame_suspects(commit); suspect; suspect = suspect->next) {
-				if (suspect->guilty && count++) {
-					commit->object.flags |= MORE_THAN_ONE_PATH;
-					break;
-				}
-			}
-		}
-	}
-
-	for (ent = sb->ent; ent; ent = ent->next) {
-		if (option & OUTPUT_PORCELAIN)
-			emit_porcelain(sb, ent, option);
-		else {
-			emit_other(sb, ent, option);
-		}
-	}
-}
-
-/*
- * Add phony grafts for use with -S; this is primarily to
- * support git's cvsserver that wants to give a linear history
- * to its clients.
- */
-static int read_ancestry(const char *graft_file)
-{
-	FILE *fp = fopen_or_warn(graft_file, "r");
-	struct strbuf buf = STRBUF_INIT;
-	if (!fp)
-		return -1;
-	while (!strbuf_getwholeline(&buf, fp, '\n')) {
-		/* The format is just "Commit Parent1 Parent2 ...\n" */
-		struct commit_graft *graft = read_graft_line(&buf);
-		if (graft)
-			register_commit_graft(the_repository, graft, 0);
-	}
-	fclose(fp);
-	strbuf_release(&buf);
-	return 0;
-}
-
-static int update_auto_abbrev(int auto_abbrev, struct blame_origin *suspect)
-{
-	const char *uniq = find_unique_abbrev(&suspect->commit->object.oid,
-					      auto_abbrev);
-	int len = strlen(uniq);
-	if (auto_abbrev < len)
-		return len;
-	return auto_abbrev;
-}
-
-/*
- * How many columns do we need to show line numbers, authors,
- * and filenames?
- */
-static void find_alignment(struct blame_scoreboard *sb, int *option)
-{
-	int longest_src_lines = 0;
-	int longest_dst_lines = 0;
-	unsigned largest_score = 0;
-	struct blame_entry *e;
-	int compute_auto_abbrev = (abbrev < 0);
-	int auto_abbrev = DEFAULT_ABBREV;
-
-	for (e = sb->ent; e; e = e->next) {
-		struct blame_origin *suspect = e->suspect;
-		int num;
-
-		if (compute_auto_abbrev)
-			auto_abbrev = update_auto_abbrev(auto_abbrev, suspect);
-		if (strcmp(suspect->path, sb->path))
-			*option |= OUTPUT_SHOW_NAME;
-		num = strlen(suspect->path);
-		if (longest_file < num)
-			longest_file = num;
-		if (!(suspect->commit->object.flags & METAINFO_SHOWN)) {
-			struct commit_info ci;
-			suspect->commit->object.flags |= METAINFO_SHOWN;
-			get_commit_info(suspect->commit, &ci, 1);
-			if (*option & OUTPUT_SHOW_EMAIL)
-				num = utf8_strwidth(ci.author_mail.buf);
-			else
-				num = utf8_strwidth(ci.author.buf);
-			if (longest_author < num)
-				longest_author = num;
-			commit_info_destroy(&ci);
-		}
-		num = e->s_lno + e->num_lines;
-		if (longest_src_lines < num)
-			longest_src_lines = num;
-		num = e->lno + e->num_lines;
-		if (longest_dst_lines < num)
-			longest_dst_lines = num;
-		if (largest_score < blame_entry_score(sb, e))
-			largest_score = blame_entry_score(sb, e);
-	}
-	max_orig_digits = decimal_width(longest_src_lines);
-	max_digits = decimal_width(longest_dst_lines);
-	max_score_digits = decimal_width(largest_score);
-
-	if (compute_auto_abbrev)
-		/* one more abbrev length is needed for the boundary commit */
-		abbrev = auto_abbrev + 1;
-}
-
-static void sanity_check_on_fail(struct blame_scoreboard *sb, int baa)
-{
-	int opt = OUTPUT_SHOW_SCORE | OUTPUT_SHOW_NUMBER | OUTPUT_SHOW_NAME;
-	find_alignment(sb, &opt);
-	output(sb, opt);
-	die("Baa %d!", baa);
-}
-
-static unsigned parse_score(const char *arg)
-{
-	char *end;
-	unsigned long score = strtoul(arg, &end, 10);
-	if (*end)
-		return 0;
-	return score;
-}
-
-static const char *add_prefix(const char *prefix, const char *path)
-{
-	return prefix_path(prefix, prefix ? strlen(prefix) : 0, path);
-}
-
-static int git_blame_config(const char *var, const char *value, void *cb)
-{
-	if (!strcmp(var, "blame.showroot")) {
-		show_root = git_config_bool(var, value);
-		return 0;
-	}
-	if (!strcmp(var, "blame.blankboundary")) {
-		blank_boundary = git_config_bool(var, value);
-		return 0;
-	}
-	if (!strcmp(var, "blame.showemail")) {
-		int *output_option = cb;
-		if (git_config_bool(var, value))
-			*output_option |= OUTPUT_SHOW_EMAIL;
-		else
-			*output_option &= ~OUTPUT_SHOW_EMAIL;
-		return 0;
-	}
-	if (!strcmp(var, "blame.date")) {
-		if (!value)
-			return config_error_nonbool(var);
-		parse_date_format(value, &blame_date_mode);
-		return 0;
-	}
-	if (!strcmp(var, "blame.ignorerevsfile")) {
-		const char *str;
-		int ret;
-
-		ret = git_config_pathname(&str, var, value);
-		if (ret)
-			return ret;
-		string_list_insert(&ignore_revs_file_list, str);
-		return 0;
-	}
-	if (!strcmp(var, "blame.markunblamablelines")) {
-		mark_unblamable_lines = git_config_bool(var, value);
-		return 0;
-	}
-	if (!strcmp(var, "blame.markignoredlines")) {
-		mark_ignored_lines = git_config_bool(var, value);
-		return 0;
-	}
-	if (!strcmp(var, "color.blame.repeatedlines")) {
-		if (color_parse_mem(value, strlen(value), repeated_meta_color))
-			warning(_("invalid color '%s' in color.blame.repeatedLines"),
-				value);
-		return 0;
-	}
-	if (!strcmp(var, "color.blame.highlightrecent")) {
-		parse_color_fields(value);
-		return 0;
-	}
-
-	if (!strcmp(var, "blame.coloring")) {
-		if (!strcmp(value, "repeatedLines")) {
-			coloring_mode |= OUTPUT_COLOR_LINE;
-		} else if (!strcmp(value, "highlightRecent")) {
-			coloring_mode |= OUTPUT_SHOW_AGE_WITH_COLOR;
-		} else if (!strcmp(value, "none")) {
-			coloring_mode &= ~(OUTPUT_COLOR_LINE |
-					    OUTPUT_SHOW_AGE_WITH_COLOR);
-		} else {
-			warning(_("invalid value for blame.coloring"));
-			return 0;
-		}
-	}
-
-	if (git_diff_heuristic_config(var, value, cb) < 0)
-		return -1;
-	if (userdiff_config(var, value) < 0)
-		return -1;
-
-	return git_default_config(var, value, cb);
-}
-
-static int blame_copy_callback(const struct option *option, const char *arg, int unset)
-{
-	int *opt = option->value;
-
-	BUG_ON_OPT_NEG(unset);
-
-	/*
-	 * -C enables copy from removed files;
-	 * -C -C enables copy from existing files, but only
-	 *       when blaming a new file;
-	 * -C -C -C enables copy from existing files for
-	 *          everybody
-	 */
-	if (*opt & PICKAXE_BLAME_COPY_HARDER)
-		*opt |= PICKAXE_BLAME_COPY_HARDEST;
-	if (*opt & PICKAXE_BLAME_COPY)
-		*opt |= PICKAXE_BLAME_COPY_HARDER;
-	*opt |= PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE;
-
-	if (arg)
-		blame_copy_score = parse_score(arg);
-	return 0;
-}
-
-static int blame_move_callback(const struct option *option, const char *arg, int unset)
-{
-	int *opt = option->value;
-
-	BUG_ON_OPT_NEG(unset);
-
-	*opt |= PICKAXE_BLAME_MOVE;
-
-	if (arg)
-		blame_move_score = parse_score(arg);
-	return 0;
-}
-
-static int is_a_rev(const char *name)
-{
-	struct object_id oid;
-
-	if (get_oid(name, &oid))
-		return 0;
-	return OBJ_NONE < oid_object_info(the_repository, &oid, NULL);
-}
-
-static int peel_to_commit_oid(struct object_id *oid_ret, void *cbdata)
-{
-	struct repository *r = ((struct blame_scoreboard *)cbdata)->repo;
-	struct object_id oid;
-
-	oidcpy(&oid, oid_ret);
-	while (1) {
-		struct object *obj;
-		int kind = oid_object_info(r, &oid, NULL);
-		if (kind == OBJ_COMMIT) {
-			oidcpy(oid_ret, &oid);
-			return 0;
-		}
-		if (kind != OBJ_TAG)
-			return -1;
-		obj = deref_tag(r, parse_object(r, &oid), NULL, 0);
-		oidcpy(&oid, &obj->oid);
-	}
-}
-
-static void build_ignorelist(struct blame_scoreboard *sb,
-			     struct string_list *ignore_revs_file_list,
-			     struct string_list *ignore_rev_list)
-{
-	struct string_list_item *i;
-	struct object_id oid;
-
-	oidset_init(&sb->ignore_list, 0);
-	for_each_string_list_item(i, ignore_revs_file_list) {
-		if (!strcmp(i->string, ""))
-			oidset_clear(&sb->ignore_list);
-		else
-			oidset_parse_file_carefully(&sb->ignore_list, i->string,
-						    peel_to_commit_oid, sb);
-	}
-	for_each_string_list_item(i, ignore_rev_list) {
-		if (get_oid_committish(i->string, &oid) ||
-		    peel_to_commit_oid(&oid, sb))
-			die(_("cannot find revision %s to ignore"), i->string);
-		oidset_insert(&sb->ignore_list, &oid);
-	}
-}
-
-int cmd_blame(int argc, const char **argv, const char *prefix)
-{
-	struct rev_info revs;
-	const char *path;
-	struct blame_scoreboard sb;
-	struct blame_origin *o;
-	struct blame_entry *ent = NULL;
-	long dashdash_pos, lno;
-	struct progress_info pi = { NULL, 0 };
-
-	struct string_list range_list = STRING_LIST_INIT_NODUP;
-	struct string_list ignore_rev_list = STRING_LIST_INIT_NODUP;
-	int output_option = 0, opt = 0;
-	int show_stats = 0;
-	const char *revs_file = NULL;
-	const char *contents_from = NULL;
-	const struct option options[] = {
-		OPT_BOOL(0, "incremental", &incremental, N_("Show blame entries as we find them, incrementally")),
-		OPT_BOOL('b', NULL, &blank_boundary, N_("Do not show object names of boundary commits (Default: off)")),
-		OPT_BOOL(0, "root", &show_root, N_("Do not treat root commits as boundaries (Default: off)")),
-		OPT_BOOL(0, "show-stats", &show_stats, N_("Show work cost statistics")),
-		OPT_BOOL(0, "progress", &show_progress, N_("Force progress reporting")),
-		OPT_BIT(0, "score-debug", &output_option, N_("Show output score for blame entries"), OUTPUT_SHOW_SCORE),
-		OPT_BIT('f', "show-name", &output_option, N_("Show original filename (Default: auto)"), OUTPUT_SHOW_NAME),
-		OPT_BIT('n', "show-number", &output_option, N_("Show original linenumber (Default: off)"), OUTPUT_SHOW_NUMBER),
-		OPT_BIT('p', "porcelain", &output_option, N_("Show in a format designed for machine consumption"), OUTPUT_PORCELAIN),
-		OPT_BIT(0, "line-porcelain", &output_option, N_("Show porcelain format with per-line commit information"), OUTPUT_PORCELAIN|OUTPUT_LINE_PORCELAIN),
-		OPT_BIT('c', NULL, &output_option, N_("Use the same output mode as git-annotate (Default: off)"), OUTPUT_ANNOTATE_COMPAT),
-		OPT_BIT('t', NULL, &output_option, N_("Show raw timestamp (Default: off)"), OUTPUT_RAW_TIMESTAMP),
-		OPT_BIT('l', NULL, &output_option, N_("Show long commit SHA1 (Default: off)"), OUTPUT_LONG_OBJECT_NAME),
-		OPT_BIT('s', NULL, &output_option, N_("Suppress author name and timestamp (Default: off)"), OUTPUT_NO_AUTHOR),
-		OPT_BIT('e', "show-email", &output_option, N_("Show author email instead of name (Default: off)"), OUTPUT_SHOW_EMAIL),
-		OPT_BIT('w', NULL, &xdl_opts, N_("Ignore whitespace differences"), XDF_IGNORE_WHITESPACE),
-		OPT_STRING_LIST(0, "ignore-rev", &ignore_rev_list, N_("rev"), N_("Ignore <rev> when blaming")),
-		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),
-		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")),
-		OPT_CALLBACK_F('C', NULL, &opt, N_("score"), N_("Find line copies within and across files"), PARSE_OPT_OPTARG, blame_copy_callback),
-		OPT_CALLBACK_F('M', NULL, &opt, N_("score"), N_("Find line movements within and across files"), PARSE_OPT_OPTARG, blame_move_callback),
-		OPT_STRING_LIST('L', NULL, &range_list, N_("n,m"), N_("Process only line range n,m, counting from 1")),
-		OPT__ABBREV(&abbrev),
-		OPT_END()
-	};
-
-	struct parse_opt_ctx_t ctx;
-	int cmd_is_annotate = !strcmp(argv[0], "annotate");
-	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);
-	repo_init_revisions(the_repository, &revs, NULL);
-	revs.date_mode = blame_date_mode;
-	revs.diffopt.flags.allow_textconv = 1;
-	revs.diffopt.flags.follow_renames = 1;
-
-	save_commit_buffer = 0;
-	dashdash_pos = 0;
-	show_progress = -1;
-
-	parse_options_start(&ctx, argc, argv, prefix, options,
-			    PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0);
-	for (;;) {
-		switch (parse_options_step(&ctx, options, blame_opt_usage)) {
-		case PARSE_OPT_HELP:
-		case PARSE_OPT_ERROR:
-			exit(129);
-		case PARSE_OPT_COMPLETE:
-			exit(0);
-		case PARSE_OPT_DONE:
-			if (ctx.argv[0])
-				dashdash_pos = ctx.cpidx;
-			goto parse_done;
-		}
-
-		if (!strcmp(ctx.argv[0], "--reverse")) {
-			ctx.argv[0] = "--children";
-			reverse = 1;
-		}
-		parse_revision_opt(&revs, &ctx, options, blame_opt_usage);
-	}
-parse_done:
-	no_whole_file_rename = !revs.diffopt.flags.follow_renames;
-	xdl_opts |= revs.diffopt.xdl_opts & XDF_INDENT_HEURISTIC;
-	revs.diffopt.flags.follow_renames = 0;
-	argc = parse_options_end(&ctx);
-
-	if (incremental || (output_option & OUTPUT_PORCELAIN)) {
-		if (show_progress > 0)
-			die(_("--progress can't be used with --incremental or porcelain formats"));
-		show_progress = 0;
-	} else if (show_progress < 0)
-		show_progress = isatty(2);
-
-	if (0 < abbrev && abbrev < hexsz)
-		/* one more abbrev length is needed for the boundary commit */
-		abbrev++;
-	else if (!abbrev)
-		abbrev = hexsz;
-
-	if (revs_file && read_ancestry(revs_file))
-		die_errno("reading graft file '%s' failed", revs_file);
-
-	if (cmd_is_annotate) {
-		output_option |= OUTPUT_ANNOTATE_COMPAT;
-		blame_date_mode.type = DATE_ISO8601;
-	} else {
-		blame_date_mode = revs.date_mode;
-	}
-
-	/* The maximum width used to show the dates */
-	switch (blame_date_mode.type) {
-	case DATE_RFC2822:
-		blame_date_width = sizeof("Thu, 19 Oct 2006 16:00:04 -0700");
-		break;
-	case DATE_ISO8601_STRICT:
-		blame_date_width = sizeof("2006-10-19T16:00:04-07:00");
-		break;
-	case DATE_ISO8601:
-		blame_date_width = sizeof("2006-10-19 16:00:04 -0700");
-		break;
-	case DATE_RAW:
-		blame_date_width = sizeof("1161298804 -0700");
-		break;
-	case DATE_UNIX:
-		blame_date_width = sizeof("1161298804");
-		break;
-	case DATE_SHORT:
-		blame_date_width = sizeof("2006-10-19");
-		break;
-	case DATE_RELATIVE:
-		/*
-		 * TRANSLATORS: This string is used to tell us the
-		 * maximum display width for a relative timestamp in
-		 * "git blame" output.  For C locale, "4 years, 11
-		 * months ago", which takes 22 places, is the longest
-		 * among various forms of relative timestamps, but
-		 * your language may need more or fewer display
-		 * columns.
-		 */
-		blame_date_width = utf8_strwidth(_("4 years, 11 months ago")) + 1; /* add the null */
-		break;
-	case DATE_HUMAN:
-		/* If the year is shown, no time is shown */
-		blame_date_width = sizeof("Thu Oct 19 16:00");
-		break;
-	case DATE_NORMAL:
-		blame_date_width = sizeof("Thu Oct 19 16:00:04 2006 -0700");
-		break;
-	case DATE_STRFTIME:
-		blame_date_width = strlen(show_date(0, 0, &blame_date_mode)) + 1; /* add the null */
-		break;
-	case DATE_DOTTIME:
-		blame_date_width = sizeof("2006-10-19T15ยท00-0700");
-		break;
-	}
-	blame_date_width -= 1; /* strip the null */
-
-	if (revs.diffopt.flags.find_copies_harder)
-		opt |= (PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE |
-			PICKAXE_BLAME_COPY_HARDER);
-
-	/*
-	 * We have collected options unknown to us in argv[1..unk]
-	 * which are to be passed to revision machinery if we are
-	 * going to do the "bottom" processing.
-	 *
-	 * The remaining are:
-	 *
-	 * (1) if dashdash_pos != 0, it is either
-	 *     "blame [revisions] -- <path>" or
-	 *     "blame -- <path> <rev>"
-	 *
-	 * (2) otherwise, it is one of the two:
-	 *     "blame [revisions] <path>"
-	 *     "blame <path> <rev>"
-	 *
-	 * Note that we must strip out <path> from the arguments: we do not
-	 * want the path pruning but we may want "bottom" processing.
-	 */
-	if (dashdash_pos) {
-		switch (argc - dashdash_pos - 1) {
-		case 2: /* (1b) */
-			if (argc != 4)
-				usage_with_options(blame_opt_usage, options);
-			/* reorder for the new way: <rev> -- <path> */
-			argv[1] = argv[3];
-			argv[3] = argv[2];
-			argv[2] = "--";
-			/* FALLTHROUGH */
-		case 1: /* (1a) */
-			path = add_prefix(prefix, argv[--argc]);
-			argv[argc] = NULL;
-			break;
-		default:
-			usage_with_options(blame_opt_usage, options);
-		}
-	} else {
-		if (argc < 2)
-			usage_with_options(blame_opt_usage, options);
-		if (argc == 3 && is_a_rev(argv[argc - 1])) { /* (2b) */
-			path = add_prefix(prefix, argv[1]);
-			argv[1] = argv[2];
-		} else {	/* (2a) */
-			if (argc == 2 && is_a_rev(argv[1]) && !get_git_work_tree())
-				die("missing <path> to blame");
-			path = add_prefix(prefix, argv[argc - 1]);
-		}
-		argv[argc - 1] = "--";
-	}
-
-	revs.disable_stdin = 1;
-	setup_revisions(argc, argv, &revs, NULL);
-	if (!revs.pending.nr && is_bare_repository()) {
-		struct commit *head_commit;
-		struct object_id head_oid;
-
-		if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
-					&head_oid, NULL) ||
-		    !(head_commit = lookup_commit_reference_gently(revs.repo,
-							     &head_oid, 1)))
-			die("no such ref: HEAD");
-
-		add_pending_object(&revs, &head_commit->object, "HEAD");
-	}
-
-	init_scoreboard(&sb);
-	sb.revs = &revs;
-	sb.contents_from = contents_from;
-	sb.reverse = reverse;
-	sb.repo = the_repository;
-	build_ignorelist(&sb, &ignore_revs_file_list, &ignore_rev_list);
-	string_list_clear(&ignore_revs_file_list, 0);
-	string_list_clear(&ignore_rev_list, 0);
-	setup_scoreboard(&sb, path, &o);
-
-	/*
-	 * Changed-path Bloom filters are disabled when looking
-	 * for copies.
-	 */
-	if (!(opt & PICKAXE_BLAME_COPY))
-		setup_blame_bloom_data(&sb, path);
-
-	lno = sb.num_lines;
-
-	if (lno && !range_list.nr)
-		string_list_append(&range_list, "1");
-
-	anchor = 1;
-	range_set_init(&ranges, range_list.nr);
-	for (range_i = 0; range_i < range_list.nr; ++range_i) {
-		long bottom, top;
-		if (parse_range_arg(range_list.items[range_i].string,
-				    nth_line_cb, &sb, lno, anchor,
-				    &bottom, &top, sb.path,
-				    the_repository->index))
-			usage(blame_usage);
-		if ((!lno && (top || bottom)) || lno < bottom)
-			die(Q_("file %s has only %lu line",
-			       "file %s has only %lu lines",
-			       lno), path, lno);
-		if (bottom < 1)
-			bottom = 1;
-		if (top < 1 || lno < top)
-			top = lno;
-		bottom--;
-		range_set_append_unsafe(&ranges, bottom, top);
-		anchor = top + 1;
-	}
-	sort_and_merge_range_set(&ranges);
-
-	for (range_i = ranges.nr; range_i > 0; --range_i) {
-		const struct range *r = &ranges.ranges[range_i - 1];
-		ent = blame_entry_prepend(ent, r->start, r->end, o);
-	}
-
-	o->suspects = ent;
-	prio_queue_put(&sb.commits, o->commit);
-
-	blame_origin_decref(o);
-
-	range_set_release(&ranges);
-	string_list_clear(&range_list, 0);
-
-	sb.ent = NULL;
-	sb.path = path;
-
-	if (blame_move_score)
-		sb.move_score = blame_move_score;
-	if (blame_copy_score)
-		sb.copy_score = blame_copy_score;
-
-	sb.debug = DEBUG_BLAME;
-	sb.on_sanity_fail = &sanity_check_on_fail;
-
-	sb.show_root = show_root;
-	sb.xdl_opts = xdl_opts;
-	sb.no_whole_file_rename = no_whole_file_rename;
-
-	read_mailmap(&mailmap, NULL);
-
-	sb.found_guilty_entry = &found_guilty_entry;
-	sb.found_guilty_entry_data = &pi;
-	if (show_progress)
-		pi.progress = start_delayed_progress(_("Blaming lines"), sb.num_lines);
-
-	assign_blame(&sb, opt);
-
-	stop_progress(&pi.progress);
-
-	if (!incremental)
-		setup_pager();
-	else
-		return 0;
-
-	blame_sort_final(&sb);
-
-	blame_coalesce(&sb);
-
-	if (!(output_option & (OUTPUT_COLOR_LINE | OUTPUT_SHOW_AGE_WITH_COLOR)))
-		output_option |= coloring_mode;
-
-	if (!(output_option & OUTPUT_PORCELAIN)) {
-		find_alignment(&sb, &output_option);
-		if (!*repeated_meta_color &&
-		    (output_option & OUTPUT_COLOR_LINE))
-			xsnprintf(repeated_meta_color,
-				  sizeof(repeated_meta_color),
-				  "%s", GIT_COLOR_CYAN);
-	}
-	if (output_option & OUTPUT_ANNOTATE_COMPAT)
-		output_option &= ~(OUTPUT_COLOR_LINE | OUTPUT_SHOW_AGE_WITH_COLOR);
-
-	output(&sb, output_option);
-	free((void *)sb.final_buf);
-	for (ent = sb.ent; ent; ) {
-		struct blame_entry *e = ent->next;
-		free(ent);
-		ent = e;
-	}
-
-	if (show_stats) {
-		printf("num read blob: %d\n", sb.num_read_blob);
-		printf("num get patch: %d\n", sb.num_get_patch);
-		printf("num commits: %d\n", sb.num_commits);
-	}
-
-	cleanup_scoreboard(&sb);
-	return 0;
-}
diff --git a/third_party/git/builtin/branch.c b/third_party/git/builtin/branch.c
deleted file mode 100644
index efb30b882069..000000000000
--- a/third_party/git/builtin/branch.c
+++ /dev/null
@@ -1,853 +0,0 @@
-/*
- * Builtin "git branch"
- *
- * Copyright (c) 2006 Kristian Hรธgsberg <krh@redhat.com>
- * Based on git-branch.sh by Junio C Hamano.
- */
-
-#include "cache.h"
-#include "config.h"
-#include "color.h"
-#include "refs.h"
-#include "commit.h"
-#include "builtin.h"
-#include "remote.h"
-#include "parse-options.h"
-#include "branch.h"
-#include "diff.h"
-#include "revision.h"
-#include "string-list.h"
-#include "column.h"
-#include "utf8.h"
-#include "wt-status.h"
-#include "ref-filter.h"
-#include "worktree.h"
-#include "help.h"
-#include "commit-reach.h"
-
-static const char * const builtin_branch_usage[] = {
-	N_("git branch [<options>] [-r | -a] [--merged] [--no-merged]"),
-	N_("git branch [<options>] [-l] [-f] <branch-name> [<start-point>]"),
-	N_("git branch [<options>] [-r] (-d | -D) <branch-name>..."),
-	N_("git branch [<options>] (-m | -M) [<old-branch>] <new-branch>"),
-	N_("git branch [<options>] (-c | -C) [<old-branch>] <new-branch>"),
-	N_("git branch [<options>] [-r | -a] [--points-at]"),
-	N_("git branch [<options>] [-r | -a] [--format]"),
-	NULL
-};
-
-static const char *head;
-static struct object_id head_oid;
-
-static int branch_use_color = -1;
-static char branch_colors[][COLOR_MAXLEN] = {
-	GIT_COLOR_RESET,
-	GIT_COLOR_NORMAL,       /* PLAIN */
-	GIT_COLOR_RED,          /* REMOTE */
-	GIT_COLOR_NORMAL,       /* LOCAL */
-	GIT_COLOR_GREEN,        /* CURRENT */
-	GIT_COLOR_BLUE,         /* UPSTREAM */
-	GIT_COLOR_CYAN,         /* WORKTREE */
-};
-enum color_branch {
-	BRANCH_COLOR_RESET = 0,
-	BRANCH_COLOR_PLAIN = 1,
-	BRANCH_COLOR_REMOTE = 2,
-	BRANCH_COLOR_LOCAL = 3,
-	BRANCH_COLOR_CURRENT = 4,
-	BRANCH_COLOR_UPSTREAM = 5,
-	BRANCH_COLOR_WORKTREE = 6
-};
-
-static const char *color_branch_slots[] = {
-	[BRANCH_COLOR_RESET]	= "reset",
-	[BRANCH_COLOR_PLAIN]	= "plain",
-	[BRANCH_COLOR_REMOTE]	= "remote",
-	[BRANCH_COLOR_LOCAL]	= "local",
-	[BRANCH_COLOR_CURRENT]	= "current",
-	[BRANCH_COLOR_UPSTREAM] = "upstream",
-	[BRANCH_COLOR_WORKTREE] = "worktree",
-};
-
-static struct string_list output = STRING_LIST_INIT_DUP;
-static unsigned int colopts;
-
-define_list_config_array(color_branch_slots);
-
-static int git_branch_config(const char *var, const char *value, void *cb)
-{
-	const char *slot_name;
-	struct ref_sorting **sorting_tail = (struct ref_sorting **)cb;
-
-	if (!strcmp(var, "branch.sort")) {
-		if (!value)
-			return config_error_nonbool(var);
-		parse_ref_sorting(sorting_tail, value);
-		return 0;
-	}
-
-	if (starts_with(var, "column."))
-		return git_column_config(var, value, "branch", &colopts);
-	if (!strcmp(var, "color.branch")) {
-		branch_use_color = git_config_colorbool(var, value);
-		return 0;
-	}
-	if (skip_prefix(var, "color.branch.", &slot_name)) {
-		int slot = LOOKUP_CONFIG(color_branch_slots, slot_name);
-		if (slot < 0)
-			return 0;
-		if (!value)
-			return config_error_nonbool(var);
-		return color_parse(value, branch_colors[slot]);
-	}
-	return git_color_default_config(var, value, cb);
-}
-
-static const char *branch_get_color(enum color_branch ix)
-{
-	if (want_color(branch_use_color))
-		return branch_colors[ix];
-	return "";
-}
-
-static int branch_merged(int kind, const char *name,
-			 struct commit *rev, struct commit *head_rev)
-{
-	/*
-	 * This checks whether the merge bases of branch and HEAD (or
-	 * the other branch this branch builds upon) contains the
-	 * branch, which means that the branch has already been merged
-	 * safely to HEAD (or the other branch).
-	 */
-	struct commit *reference_rev = NULL;
-	const char *reference_name = NULL;
-	void *reference_name_to_free = NULL;
-	int merged;
-
-	if (kind == FILTER_REFS_BRANCHES) {
-		struct branch *branch = branch_get(name);
-		const char *upstream = branch_get_upstream(branch, NULL);
-		struct object_id oid;
-
-		if (upstream &&
-		    (reference_name = reference_name_to_free =
-		     resolve_refdup(upstream, RESOLVE_REF_READING,
-				    &oid, NULL)) != NULL)
-			reference_rev = lookup_commit_reference(the_repository,
-								&oid);
-	}
-	if (!reference_rev)
-		reference_rev = head_rev;
-
-	merged = in_merge_bases(rev, reference_rev);
-
-	/*
-	 * After the safety valve is fully redefined to "check with
-	 * upstream, if any, otherwise with HEAD", we should just
-	 * return the result of the in_merge_bases() above without
-	 * any of the following code, but during the transition period,
-	 * a gentle reminder is in order.
-	 */
-	if ((head_rev != reference_rev) &&
-	    in_merge_bases(rev, head_rev) != merged) {
-		if (merged)
-			warning(_("deleting branch '%s' that has been merged to\n"
-				"         '%s', but not yet merged to HEAD."),
-				name, reference_name);
-		else
-			warning(_("not deleting branch '%s' that is not yet merged to\n"
-				"         '%s', even though it is merged to HEAD."),
-				name, reference_name);
-	}
-	free(reference_name_to_free);
-	return merged;
-}
-
-static int check_branch_commit(const char *branchname, const char *refname,
-			       const struct object_id *oid, struct commit *head_rev,
-			       int kinds, int force)
-{
-	struct commit *rev = lookup_commit_reference(the_repository, oid);
-	if (!rev) {
-		error(_("Couldn't look up commit object for '%s'"), refname);
-		return -1;
-	}
-	if (!force && !branch_merged(kinds, branchname, rev, head_rev)) {
-		error(_("The branch '%s' is not fully merged.\n"
-		      "If you are sure you want to delete it, "
-		      "run 'git branch -D %s'."), branchname, branchname);
-		return -1;
-	}
-	return 0;
-}
-
-static void delete_branch_config(const char *branchname)
-{
-	struct strbuf buf = STRBUF_INIT;
-	strbuf_addf(&buf, "branch.%s", branchname);
-	if (git_config_rename_section(buf.buf, NULL) < 0)
-		warning(_("Update of config-file failed"));
-	strbuf_release(&buf);
-}
-
-static int delete_branches(int argc, const char **argv, int force, int kinds,
-			   int quiet)
-{
-	struct commit *head_rev = NULL;
-	struct object_id oid;
-	char *name = NULL;
-	const char *fmt;
-	int i;
-	int ret = 0;
-	int remote_branch = 0;
-	struct strbuf bname = STRBUF_INIT;
-	unsigned allowed_interpret;
-
-	switch (kinds) {
-	case FILTER_REFS_REMOTES:
-		fmt = "refs/remotes/%s";
-		/* For subsequent UI messages */
-		remote_branch = 1;
-		allowed_interpret = INTERPRET_BRANCH_REMOTE;
-
-		force = 1;
-		break;
-	case FILTER_REFS_BRANCHES:
-		fmt = "refs/heads/%s";
-		allowed_interpret = INTERPRET_BRANCH_LOCAL;
-		break;
-	default:
-		die(_("cannot use -a with -d"));
-	}
-
-	if (!force) {
-		head_rev = lookup_commit_reference(the_repository, &head_oid);
-		if (!head_rev)
-			die(_("Couldn't look up commit object for HEAD"));
-	}
-	for (i = 0; i < argc; i++, strbuf_reset(&bname)) {
-		char *target = NULL;
-		int flags = 0;
-
-		strbuf_branchname(&bname, argv[i], allowed_interpret);
-		free(name);
-		name = mkpathdup(fmt, bname.buf);
-
-		if (kinds == FILTER_REFS_BRANCHES) {
-			const struct worktree *wt =
-				find_shared_symref("HEAD", name);
-			if (wt) {
-				error(_("Cannot delete branch '%s' "
-					"checked out at '%s'"),
-				      bname.buf, wt->path);
-				ret = 1;
-				continue;
-			}
-		}
-
-		target = resolve_refdup(name,
-					RESOLVE_REF_READING
-					| RESOLVE_REF_NO_RECURSE
-					| RESOLVE_REF_ALLOW_BAD_NAME,
-					&oid, &flags);
-		if (!target) {
-			error(remote_branch
-			      ? _("remote-tracking branch '%s' not found.")
-			      : _("branch '%s' not found."), bname.buf);
-			ret = 1;
-			continue;
-		}
-
-		if (!(flags & (REF_ISSYMREF|REF_ISBROKEN)) &&
-		    check_branch_commit(bname.buf, name, &oid, head_rev, kinds,
-					force)) {
-			ret = 1;
-			goto next;
-		}
-
-		if (delete_ref(NULL, name, is_null_oid(&oid) ? NULL : &oid,
-			       REF_NO_DEREF)) {
-			error(remote_branch
-			      ? _("Error deleting remote-tracking branch '%s'")
-			      : _("Error deleting branch '%s'"),
-			      bname.buf);
-			ret = 1;
-			goto next;
-		}
-		if (!quiet) {
-			printf(remote_branch
-			       ? _("Deleted remote-tracking branch %s (was %s).\n")
-			       : _("Deleted branch %s (was %s).\n"),
-			       bname.buf,
-			       (flags & REF_ISBROKEN) ? "broken"
-			       : (flags & REF_ISSYMREF) ? target
-			       : find_unique_abbrev(&oid, DEFAULT_ABBREV));
-		}
-		delete_branch_config(bname.buf);
-
-	next:
-		free(target);
-	}
-
-	free(name);
-	strbuf_release(&bname);
-
-	return ret;
-}
-
-static int calc_maxwidth(struct ref_array *refs, int remote_bonus)
-{
-	int i, max = 0;
-	for (i = 0; i < refs->nr; i++) {
-		struct ref_array_item *it = refs->items[i];
-		const char *desc = it->refname;
-		int w;
-
-		skip_prefix(it->refname, "refs/heads/", &desc);
-		skip_prefix(it->refname, "refs/remotes/", &desc);
-		if (it->kind == FILTER_REFS_DETACHED_HEAD) {
-			char *head_desc = get_head_description();
-			w = utf8_strwidth(head_desc);
-			free(head_desc);
-		} else
-			w = utf8_strwidth(desc);
-
-		if (it->kind == FILTER_REFS_REMOTES)
-			w += remote_bonus;
-		if (w > max)
-			max = w;
-	}
-	return max;
-}
-
-static const char *quote_literal_for_format(const char *s)
-{
-	static struct strbuf buf = STRBUF_INIT;
-
-	strbuf_reset(&buf);
-	while (*s) {
-		const char *ep = strchrnul(s, '%');
-		if (s < ep)
-			strbuf_add(&buf, s, ep - s);
-		if (*ep == '%') {
-			strbuf_addstr(&buf, "%%");
-			s = ep + 1;
-		} else {
-			s = ep;
-		}
-	}
-	return buf.buf;
-}
-
-static char *build_format(struct ref_filter *filter, int maxwidth, const char *remote_prefix)
-{
-	struct strbuf fmt = STRBUF_INIT;
-	struct strbuf local = STRBUF_INIT;
-	struct strbuf remote = STRBUF_INIT;
-
-	strbuf_addf(&local, "%%(if)%%(HEAD)%%(then)* %s%%(else)%%(if)%%(worktreepath)%%(then)+ %s%%(else)  %s%%(end)%%(end)",
-			branch_get_color(BRANCH_COLOR_CURRENT),
-			branch_get_color(BRANCH_COLOR_WORKTREE),
-			branch_get_color(BRANCH_COLOR_LOCAL));
-	strbuf_addf(&remote, "  %s",
-		    branch_get_color(BRANCH_COLOR_REMOTE));
-
-	if (filter->verbose) {
-		struct strbuf obname = STRBUF_INIT;
-
-		if (filter->abbrev < 0)
-			strbuf_addf(&obname, "%%(objectname:short)");
-		else if (!filter->abbrev)
-			strbuf_addf(&obname, "%%(objectname)");
-		else
-			strbuf_addf(&obname, "%%(objectname:short=%d)", filter->abbrev);
-
-		strbuf_addf(&local, "%%(align:%d,left)%%(refname:lstrip=2)%%(end)", maxwidth);
-		strbuf_addstr(&local, branch_get_color(BRANCH_COLOR_RESET));
-		strbuf_addf(&local, " %s ", obname.buf);
-
-		if (filter->verbose > 1)
-		{
-			strbuf_addf(&local, "%%(if:notequals=*)%%(HEAD)%%(then)%%(if)%%(worktreepath)%%(then)(%s%%(worktreepath)%s) %%(end)%%(end)",
-				    branch_get_color(BRANCH_COLOR_WORKTREE), branch_get_color(BRANCH_COLOR_RESET));
-			strbuf_addf(&local, "%%(if)%%(upstream)%%(then)[%s%%(upstream:short)%s%%(if)%%(upstream:track)"
-				    "%%(then): %%(upstream:track,nobracket)%%(end)] %%(end)%%(contents:subject)",
-				    branch_get_color(BRANCH_COLOR_UPSTREAM), branch_get_color(BRANCH_COLOR_RESET));
-		}
-		else
-			strbuf_addf(&local, "%%(if)%%(upstream:track)%%(then)%%(upstream:track) %%(end)%%(contents:subject)");
-
-		strbuf_addf(&remote, "%%(align:%d,left)%s%%(refname:lstrip=2)%%(end)%s"
-			    "%%(if)%%(symref)%%(then) -> %%(symref:short)"
-			    "%%(else) %s %%(contents:subject)%%(end)",
-			    maxwidth, quote_literal_for_format(remote_prefix),
-			    branch_get_color(BRANCH_COLOR_RESET), obname.buf);
-		strbuf_release(&obname);
-	} else {
-		strbuf_addf(&local, "%%(refname:lstrip=2)%s%%(if)%%(symref)%%(then) -> %%(symref:short)%%(end)",
-			    branch_get_color(BRANCH_COLOR_RESET));
-		strbuf_addf(&remote, "%s%%(refname:lstrip=2)%s%%(if)%%(symref)%%(then) -> %%(symref:short)%%(end)",
-			    quote_literal_for_format(remote_prefix),
-			    branch_get_color(BRANCH_COLOR_RESET));
-	}
-
-	strbuf_addf(&fmt, "%%(if:notequals=refs/remotes)%%(refname:rstrip=-2)%%(then)%s%%(else)%s%%(end)", local.buf, remote.buf);
-
-	strbuf_release(&local);
-	strbuf_release(&remote);
-	return strbuf_detach(&fmt, NULL);
-}
-
-static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sorting, struct ref_format *format)
-{
-	int i;
-	struct ref_array array;
-	int maxwidth = 0;
-	const char *remote_prefix = "";
-	char *to_free = NULL;
-
-	/*
-	 * If we are listing more than just remote branches,
-	 * then remote branches will have a "remotes/" prefix.
-	 * We need to account for this in the width.
-	 */
-	if (filter->kind != FILTER_REFS_REMOTES)
-		remote_prefix = "remotes/";
-
-	memset(&array, 0, sizeof(array));
-
-	filter_refs(&array, filter, filter->kind | FILTER_REFS_INCLUDE_BROKEN);
-
-	if (filter->verbose)
-		maxwidth = calc_maxwidth(&array, strlen(remote_prefix));
-
-	if (!format->format)
-		format->format = to_free = build_format(filter, maxwidth, remote_prefix);
-	format->use_color = branch_use_color;
-
-	if (verify_ref_format(format))
-		die(_("unable to parse format string"));
-
-	ref_array_sort(sorting, &array);
-
-	for (i = 0; i < array.nr; i++) {
-		struct strbuf out = STRBUF_INIT;
-		struct strbuf err = STRBUF_INIT;
-		if (format_ref_array_item(array.items[i], format, &out, &err))
-			die("%s", err.buf);
-		if (column_active(colopts)) {
-			assert(!filter->verbose && "--column and --verbose are incompatible");
-			 /* format to a string_list to let print_columns() do its job */
-			string_list_append(&output, out.buf);
-		} else {
-			fwrite(out.buf, 1, out.len, stdout);
-			putchar('\n');
-		}
-		strbuf_release(&err);
-		strbuf_release(&out);
-	}
-
-	ref_array_clear(&array);
-	free(to_free);
-}
-
-static void print_current_branch_name(void)
-{
-	int flags;
-	const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, &flags);
-	const char *shortname;
-	if (!refname)
-		die(_("could not resolve HEAD"));
-	else if (!(flags & REF_ISSYMREF))
-		return;
-	else if (skip_prefix(refname, "refs/heads/", &shortname))
-		puts(shortname);
-	else
-		die(_("HEAD (%s) points outside of refs/heads/"), refname);
-}
-
-static void reject_rebase_or_bisect_branch(const char *target)
-{
-	struct worktree **worktrees = get_worktrees();
-	int i;
-
-	for (i = 0; worktrees[i]; i++) {
-		struct worktree *wt = worktrees[i];
-
-		if (!wt->is_detached)
-			continue;
-
-		if (is_worktree_being_rebased(wt, target))
-			die(_("Branch %s is being rebased at %s"),
-			    target, wt->path);
-
-		if (is_worktree_being_bisected(wt, target))
-			die(_("Branch %s is being bisected at %s"),
-			    target, wt->path);
-	}
-
-	free_worktrees(worktrees);
-}
-
-static void copy_or_rename_branch(const char *oldname, const char *newname, int copy, int force)
-{
-	struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT;
-	struct strbuf oldsection = STRBUF_INIT, newsection = STRBUF_INIT;
-	const char *interpreted_oldname = NULL;
-	const char *interpreted_newname = NULL;
-	int recovery = 0;
-
-	if (!oldname) {
-		if (copy)
-			die(_("cannot copy the current branch while not on any."));
-		else
-			die(_("cannot rename the current branch while not on any."));
-	}
-
-	if (strbuf_check_branch_ref(&oldref, oldname)) {
-		/*
-		 * Bad name --- this could be an attempt to rename a
-		 * ref that we used to allow to be created by accident.
-		 */
-		if (ref_exists(oldref.buf))
-			recovery = 1;
-		else
-			die(_("Invalid branch name: '%s'"), oldname);
-	}
-
-	/*
-	 * A command like "git branch -M currentbranch currentbranch" cannot
-	 * cause the worktree to become inconsistent with HEAD, so allow it.
-	 */
-	if (!strcmp(oldname, newname))
-		validate_branchname(newname, &newref);
-	else
-		validate_new_branchname(newname, &newref, force);
-
-	reject_rebase_or_bisect_branch(oldref.buf);
-
-	if (!skip_prefix(oldref.buf, "refs/heads/", &interpreted_oldname) ||
-	    !skip_prefix(newref.buf, "refs/heads/", &interpreted_newname)) {
-		BUG("expected prefix missing for refs");
-	}
-
-	if (copy)
-		strbuf_addf(&logmsg, "Branch: copied %s to %s",
-			    oldref.buf, newref.buf);
-	else
-		strbuf_addf(&logmsg, "Branch: renamed %s to %s",
-			    oldref.buf, newref.buf);
-
-	if (!copy && rename_ref(oldref.buf, newref.buf, logmsg.buf))
-		die(_("Branch rename failed"));
-	if (copy && copy_existing_ref(oldref.buf, newref.buf, logmsg.buf))
-		die(_("Branch copy failed"));
-
-	if (recovery) {
-		if (copy)
-			warning(_("Created a copy of a misnamed branch '%s'"),
-				interpreted_oldname);
-		else
-			warning(_("Renamed a misnamed branch '%s' away"),
-				interpreted_oldname);
-	}
-
-	if (!copy &&
-	    replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf))
-		die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
-
-	strbuf_release(&logmsg);
-
-	strbuf_addf(&oldsection, "branch.%s", interpreted_oldname);
-	strbuf_release(&oldref);
-	strbuf_addf(&newsection, "branch.%s", interpreted_newname);
-	strbuf_release(&newref);
-	if (!copy && git_config_rename_section(oldsection.buf, newsection.buf) < 0)
-		die(_("Branch is renamed, but update of config-file failed"));
-	if (copy && strcmp(oldname, newname) && git_config_copy_section(oldsection.buf, newsection.buf) < 0)
-		die(_("Branch is copied, but update of config-file failed"));
-	strbuf_release(&oldsection);
-	strbuf_release(&newsection);
-}
-
-static GIT_PATH_FUNC(edit_description, "EDIT_DESCRIPTION")
-
-static int edit_branch_description(const char *branch_name)
-{
-	struct strbuf buf = STRBUF_INIT;
-	struct strbuf name = STRBUF_INIT;
-
-	read_branch_desc(&buf, branch_name);
-	if (!buf.len || buf.buf[buf.len-1] != '\n')
-		strbuf_addch(&buf, '\n');
-	strbuf_commented_addf(&buf,
-		    _("Please edit the description for the branch\n"
-		      "  %s\n"
-		      "Lines starting with '%c' will be stripped.\n"),
-		    branch_name, comment_line_char);
-	write_file_buf(edit_description(), buf.buf, buf.len);
-	strbuf_reset(&buf);
-	if (launch_editor(edit_description(), &buf, NULL)) {
-		strbuf_release(&buf);
-		return -1;
-	}
-	strbuf_stripspace(&buf, 1);
-
-	strbuf_addf(&name, "branch.%s.description", branch_name);
-	git_config_set(name.buf, buf.len ? buf.buf : NULL);
-	strbuf_release(&name);
-	strbuf_release(&buf);
-
-	return 0;
-}
-
-int cmd_branch(int argc, const char **argv, const char *prefix)
-{
-	int delete = 0, rename = 0, copy = 0, force = 0, list = 0;
-	int show_current = 0;
-	int reflog = 0, edit_description = 0;
-	int quiet = 0, unset_upstream = 0;
-	const char *new_upstream = NULL;
-	enum branch_track track;
-	struct ref_filter filter;
-	int icase = 0;
-	static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
-	struct ref_format format = REF_FORMAT_INIT;
-
-	struct option options[] = {
-		OPT_GROUP(N_("Generic options")),
-		OPT__VERBOSE(&filter.verbose,
-			N_("show hash and subject, give twice for upstream branch")),
-		OPT__QUIET(&quiet, N_("suppress informational messages")),
-		OPT_SET_INT('t', "track",  &track, N_("set up tracking mode (see git-pull(1))"),
-			BRANCH_TRACK_EXPLICIT),
-		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__COLOR(&branch_use_color, N_("use colored output")),
-		OPT_SET_INT('r', "remotes",     &filter.kind, N_("act on remote-tracking branches"),
-			FILTER_REFS_REMOTES),
-		OPT_CONTAINS(&filter.with_commit, N_("print only branches that contain the commit")),
-		OPT_NO_CONTAINS(&filter.no_commit, N_("print only branches that don't contain the commit")),
-		OPT_WITH(&filter.with_commit, N_("print only branches that contain the commit")),
-		OPT_WITHOUT(&filter.no_commit, N_("print only branches that don't contain the commit")),
-		OPT__ABBREV(&filter.abbrev),
-
-		OPT_GROUP(N_("Specific git-branch actions:")),
-		OPT_SET_INT('a', "all", &filter.kind, N_("list both remote-tracking and local branches"),
-			FILTER_REFS_REMOTES | FILTER_REFS_BRANCHES),
-		OPT_BIT('d', "delete", &delete, N_("delete fully merged branch"), 1),
-		OPT_BIT('D', NULL, &delete, N_("delete branch (even if not merged)"), 2),
-		OPT_BIT('m', "move", &rename, N_("move/rename a branch and its reflog"), 1),
-		OPT_BIT('M', NULL, &rename, N_("move/rename a branch, even if target exists"), 2),
-		OPT_BIT('c', "copy", &copy, N_("copy a branch and its reflog"), 1),
-		OPT_BIT('C', NULL, &copy, N_("copy a branch, even if target exists"), 2),
-		OPT_BOOL('l', "list", &list, N_("list branch names")),
-		OPT_BOOL(0, "show-current", &show_current, N_("show current branch name")),
-		OPT_BOOL(0, "create-reflog", &reflog, N_("create the branch's reflog")),
-		OPT_BOOL(0, "edit-description", &edit_description,
-			 N_("edit the description for the branch")),
-		OPT__FORCE(&force, N_("force creation, move/rename, deletion"), PARSE_OPT_NOCOMPLETE),
-		OPT_MERGED(&filter, N_("print only branches that are merged")),
-		OPT_NO_MERGED(&filter, N_("print only branches that are not merged")),
-		OPT_COLUMN(0, "column", &colopts, N_("list branches in columns")),
-		OPT_REF_SORT(sorting_tail),
-		OPT_CALLBACK(0, "points-at", &filter.points_at, N_("object"),
-			N_("print only branches of the object"), parse_opt_object_name),
-		OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
-		OPT_STRING(  0 , "format", &format.format, N_("format"), N_("format to use for the output")),
-		OPT_END(),
-	};
-
-	setup_ref_filter_porcelain_msg();
-
-	memset(&filter, 0, sizeof(filter));
-	filter.kind = FILTER_REFS_BRANCHES;
-	filter.abbrev = -1;
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage_with_options(builtin_branch_usage, options);
-
-	git_config(git_branch_config, sorting_tail);
-
-	track = git_branch_track;
-
-	head = resolve_refdup("HEAD", 0, &head_oid, NULL);
-	if (!head)
-		die(_("Failed to resolve HEAD as a valid ref."));
-	if (!strcmp(head, "HEAD"))
-		filter.detached = 1;
-	else if (!skip_prefix(head, "refs/heads/", &head))
-		die(_("HEAD not found below refs/heads!"));
-
-	argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
-			     0);
-
-	if (!delete && !rename && !copy && !edit_description && !new_upstream &&
-	    !show_current && !unset_upstream && argc == 0)
-		list = 1;
-
-	if (filter.with_commit || filter.no_commit ||
-	    filter.reachable_from || filter.unreachable_from || filter.points_at.nr)
-		list = 1;
-
-	if (!!delete + !!rename + !!copy + !!new_upstream + !!show_current +
-	    list + edit_description + unset_upstream > 1)
-		usage_with_options(builtin_branch_usage, options);
-
-	if (filter.abbrev == -1)
-		filter.abbrev = DEFAULT_ABBREV;
-	filter.ignore_case = icase;
-
-	finalize_colopts(&colopts, -1);
-	if (filter.verbose) {
-		if (explicitly_enable_column(colopts))
-			die(_("--column and --verbose are incompatible"));
-		colopts = 0;
-	}
-
-	if (force) {
-		delete *= 2;
-		rename *= 2;
-		copy *= 2;
-	}
-
-	if (list)
-		setup_auto_pager("branch", 1);
-
-	if (delete) {
-		if (!argc)
-			die(_("branch name required"));
-		return delete_branches(argc, argv, delete > 1, filter.kind, quiet);
-	} else if (show_current) {
-		print_current_branch_name();
-		return 0;
-	} else if (list) {
-		/*  git branch --local also shows HEAD when it is detached */
-		if ((filter.kind & FILTER_REFS_BRANCHES) && filter.detached)
-			filter.kind |= FILTER_REFS_DETACHED_HEAD;
-		filter.name_patterns = argv;
-		/*
-		 * If no sorting parameter is given then we default to sorting
-		 * by 'refname'. This would give us an alphabetically sorted
-		 * array with the 'HEAD' ref at the beginning followed by
-		 * local branches 'refs/heads/...' and finally remote-tracking
-		 * branches 'refs/remotes/...'.
-		 */
-		if (!sorting)
-			sorting = ref_default_sorting();
-		ref_sorting_icase_all(sorting, icase);
-		print_ref_list(&filter, sorting, &format);
-		print_columns(&output, colopts, NULL);
-		string_list_clear(&output, 0);
-		return 0;
-	} else if (edit_description) {
-		const char *branch_name;
-		struct strbuf branch_ref = STRBUF_INIT;
-
-		if (!argc) {
-			if (filter.detached)
-				die(_("Cannot give description to detached HEAD"));
-			branch_name = head;
-		} else if (argc == 1)
-			branch_name = argv[0];
-		else
-			die(_("cannot edit description of more than one branch"));
-
-		strbuf_addf(&branch_ref, "refs/heads/%s", branch_name);
-		if (!ref_exists(branch_ref.buf)) {
-			strbuf_release(&branch_ref);
-
-			if (!argc)
-				return error(_("No commit on branch '%s' yet."),
-					     branch_name);
-			else
-				return error(_("No branch named '%s'."),
-					     branch_name);
-		}
-		strbuf_release(&branch_ref);
-
-		if (edit_branch_description(branch_name))
-			return 1;
-	} else if (copy) {
-		if (!argc)
-			die(_("branch name required"));
-		else if (argc == 1)
-			copy_or_rename_branch(head, argv[0], 1, copy > 1);
-		else if (argc == 2)
-			copy_or_rename_branch(argv[0], argv[1], 1, copy > 1);
-		else
-			die(_("too many branches for a copy operation"));
-	} else if (rename) {
-		if (!argc)
-			die(_("branch name required"));
-		else if (argc == 1)
-			copy_or_rename_branch(head, argv[0], 0, rename > 1);
-		else if (argc == 2)
-			copy_or_rename_branch(argv[0], argv[1], 0, rename > 1);
-		else
-			die(_("too many arguments for a rename operation"));
-	} else if (new_upstream) {
-		struct branch *branch = branch_get(argv[0]);
-
-		if (argc > 1)
-			die(_("too many arguments to set new upstream"));
-
-		if (!branch) {
-			if (!argc || !strcmp(argv[0], "HEAD"))
-				die(_("could not set upstream of HEAD to %s when "
-				      "it does not point to any branch."),
-				    new_upstream);
-			die(_("no such branch '%s'"), argv[0]);
-		}
-
-		if (!ref_exists(branch->refname))
-			die(_("branch '%s' does not exist"), branch->name);
-
-		/*
-		 * create_branch takes care of setting up the tracking
-		 * info and making sure new_upstream is correct
-		 */
-		create_branch(the_repository, branch->name, new_upstream,
-			      0, 0, 0, quiet, BRANCH_TRACK_OVERRIDE);
-	} else if (unset_upstream) {
-		struct branch *branch = branch_get(argv[0]);
-		struct strbuf buf = STRBUF_INIT;
-
-		if (argc > 1)
-			die(_("too many arguments to unset upstream"));
-
-		if (!branch) {
-			if (!argc || !strcmp(argv[0], "HEAD"))
-				die(_("could not unset upstream of HEAD when "
-				      "it does not point to any branch."));
-			die(_("no such branch '%s'"), argv[0]);
-		}
-
-		if (!branch_has_merge_config(branch))
-			die(_("Branch '%s' has no upstream information"), branch->name);
-
-		strbuf_addf(&buf, "branch.%s.remote", branch->name);
-		git_config_set_multivar(buf.buf, NULL, NULL, 1);
-		strbuf_reset(&buf);
-		strbuf_addf(&buf, "branch.%s.merge", branch->name);
-		git_config_set_multivar(buf.buf, NULL, NULL, 1);
-		strbuf_release(&buf);
-	} else if (argc > 0 && argc <= 2) {
-		if (filter.kind != FILTER_REFS_BRANCHES)
-			die(_("The -a, and -r, options to 'git branch' do not take a branch name.\n"
-				  "Did you mean to use: -a|-r --list <pattern>?"));
-
-		if (track == BRANCH_TRACK_OVERRIDE)
-			die(_("the '--set-upstream' option is no longer supported. Please use '--track' or '--set-upstream-to' instead."));
-
-		create_branch(the_repository,
-			      argv[0], (argc == 2) ? argv[1] : head,
-			      force, 0, reflog, quiet, track);
-
-	} else
-		usage_with_options(builtin_branch_usage, options);
-
-	return 0;
-}
diff --git a/third_party/git/builtin/bugreport.c b/third_party/git/builtin/bugreport.c
deleted file mode 100644
index 3ad4b9b62e84..000000000000
--- a/third_party/git/builtin/bugreport.c
+++ /dev/null
@@ -1,194 +0,0 @@
-#include "builtin.h"
-#include "parse-options.h"
-#include "strbuf.h"
-#include "help.h"
-#include "compat/compiler.h"
-#include "run-command.h"
-
-
-static void get_system_info(struct strbuf *sys_info)
-{
-	struct utsname uname_info;
-	char *shell = NULL;
-
-	/* get git version from native cmd */
-	strbuf_addstr(sys_info, _("git version:\n"));
-	get_version_info(sys_info, 1);
-
-	/* system call for other version info */
-	strbuf_addstr(sys_info, "uname: ");
-	if (uname(&uname_info))
-		strbuf_addf(sys_info, _("uname() failed with error '%s' (%d)\n"),
-			    strerror(errno),
-			    errno);
-	else
-		strbuf_addf(sys_info, "%s %s %s %s\n",
-			    uname_info.sysname,
-			    uname_info.release,
-			    uname_info.version,
-			    uname_info.machine);
-
-	strbuf_addstr(sys_info, _("compiler info: "));
-	get_compiler_info(sys_info);
-
-	strbuf_addstr(sys_info, _("libc info: "));
-	get_libc_info(sys_info);
-
-	shell = getenv("SHELL");
-	strbuf_addf(sys_info, "$SHELL (typically, interactive shell): %s\n",
-		    shell ? shell : "<unset>");
-}
-
-static void get_populated_hooks(struct strbuf *hook_info, int nongit)
-{
-	/*
-	 * NEEDSWORK: Doesn't look like there is a list of all possible hooks;
-	 * so below is a transcription of `git help hooks`. Later, this should
-	 * be replaced with some programmatically generated list (generated from
-	 * doc or else taken from some library which tells us about all the
-	 * hooks)
-	 */
-	static const char *hook[] = {
-		"applypatch-msg",
-		"pre-applypatch",
-		"post-applypatch",
-		"pre-commit",
-		"pre-merge-commit",
-		"prepare-commit-msg",
-		"commit-msg",
-		"post-commit",
-		"pre-rebase",
-		"post-checkout",
-		"post-merge",
-		"pre-push",
-		"pre-receive",
-		"update",
-		"post-receive",
-		"post-update",
-		"push-to-checkout",
-		"pre-auto-gc",
-		"post-rewrite",
-		"sendemail-validate",
-		"fsmonitor-watchman",
-		"p4-pre-submit",
-		"post-index-change",
-	};
-	int i;
-
-	if (nongit) {
-		strbuf_addstr(hook_info,
-			_("not run from a git repository - no hooks to show\n"));
-		return;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(hook); i++)
-		if (find_hook(hook[i]))
-			strbuf_addf(hook_info, "%s\n", hook[i]);
-}
-
-static const char * const bugreport_usage[] = {
-	N_("git bugreport [-o|--output-directory <file>] [-s|--suffix <format>]"),
-	NULL
-};
-
-static int get_bug_template(struct strbuf *template)
-{
-	const char template_text[] = N_(
-"Thank you for filling out a Git bug report!\n"
-"Please answer the following questions to help us understand your issue.\n"
-"\n"
-"What did you do before the bug happened? (Steps to reproduce your issue)\n"
-"\n"
-"What did you expect to happen? (Expected behavior)\n"
-"\n"
-"What happened instead? (Actual behavior)\n"
-"\n"
-"What's different between what you expected and what actually happened?\n"
-"\n"
-"Anything else you want to add:\n"
-"\n"
-"Please review the rest of the bug report below.\n"
-"You can delete any lines you don't wish to share.\n");
-
-	strbuf_addstr(template, _(template_text));
-	return 0;
-}
-
-static void get_header(struct strbuf *buf, const char *title)
-{
-	strbuf_addf(buf, "\n\n[%s]\n", title);
-}
-
-int cmd_bugreport(int argc, const char **argv, const char *prefix)
-{
-	struct strbuf buffer = STRBUF_INIT;
-	struct strbuf report_path = STRBUF_INIT;
-	int report = -1;
-	time_t now = time(NULL);
-	char *option_output = NULL;
-	char *option_suffix = "%Y-%m-%d-%H%M";
-	const char *user_relative_path = NULL;
-
-	const struct option bugreport_options[] = {
-		OPT_STRING('o', "output-directory", &option_output, N_("path"),
-			   N_("specify a destination for the bugreport file")),
-		OPT_STRING('s', "suffix", &option_suffix, N_("format"),
-			   N_("specify a strftime format suffix for the filename")),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, bugreport_options,
-			     bugreport_usage, 0);
-
-	/* Prepare the path to put the result */
-	strbuf_addstr(&report_path,
-		      prefix_filename(prefix,
-				      option_output ? option_output : ""));
-	strbuf_complete(&report_path, '/');
-
-	strbuf_addstr(&report_path, "git-bugreport-");
-	strbuf_addftime(&report_path, option_suffix, localtime(&now), 0, 0);
-	strbuf_addstr(&report_path, ".txt");
-
-	switch (safe_create_leading_directories(report_path.buf)) {
-	case SCLD_OK:
-	case SCLD_EXISTS:
-		break;
-	default:
-		die(_("could not create leading directories for '%s'"),
-		    report_path.buf);
-	}
-
-	/* Prepare the report contents */
-	get_bug_template(&buffer);
-
-	get_header(&buffer, _("System Info"));
-	get_system_info(&buffer);
-
-	get_header(&buffer, _("Enabled Hooks"));
-	get_populated_hooks(&buffer, !startup_info->have_repository);
-
-	/* fopen doesn't offer us an O_EXCL alternative, except with glibc. */
-	report = open(report_path.buf, O_CREAT | O_EXCL | O_WRONLY, 0666);
-
-	if (report < 0)
-		die(_("couldn't create a new file at '%s'"), report_path.buf);
-
-	if (write_in_full(report, buffer.buf, buffer.len) < 0)
-		die_errno(_("unable to write to %s"), report_path.buf);
-
-	close(report);
-
-	/*
-	 * We want to print the path relative to the user, but we still need the
-	 * path relative to us to give to the editor.
-	 */
-	if (!(prefix && skip_prefix(report_path.buf, prefix, &user_relative_path)))
-		user_relative_path = report_path.buf;
-	fprintf(stderr, _("Created new report at '%s'.\n"),
-		user_relative_path);
-
-	UNLEAK(buffer);
-	UNLEAK(report_path);
-	return !!launch_editor(report_path.buf, NULL, NULL);
-}
diff --git a/third_party/git/builtin/bundle.c b/third_party/git/builtin/bundle.c
deleted file mode 100644
index ea6948110b0f..000000000000
--- a/third_party/git/builtin/bundle.c
+++ /dev/null
@@ -1,197 +0,0 @@
-#include "builtin.h"
-#include "strvec.h"
-#include "parse-options.h"
-#include "cache.h"
-#include "bundle.h"
-
-/*
- * Basic handler for bundle files to connect repositories via sneakernet.
- * Invocation must include action.
- * This function can create a bundle or provide information on an existing
- * 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 * 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 strvec pack_opts;
-	int version = -1;
-
-	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_INTEGER(0, "version", &version,
-			    N_("specify bundle format version")),
-		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 */
-
-	strvec_init(&pack_opts);
-	if (progress == 0)
-		strvec_push(&pack_opts, "--quiet");
-	else if (progress == 1)
-		strvec_push(&pack_opts, "--progress");
-	else if (progress == 2)
-		strvec_push(&pack_opts, "--all-progress");
-	if (progress && all_progress_implied)
-		strvec_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, version);
-}
-
-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) {
-	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_unbundle_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;
-	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);
-	}
-	return result ? 1 : 0;
-}
diff --git a/third_party/git/builtin/cat-file.c b/third_party/git/builtin/cat-file.c
deleted file mode 100644
index 5ebf13359e83..000000000000
--- a/third_party/git/builtin/cat-file.c
+++ /dev/null
@@ -1,721 +0,0 @@
-/*
- * GIT - The information manager from hell
- *
- * Copyright (C) Linus Torvalds, 2005
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "config.h"
-#include "builtin.h"
-#include "diff.h"
-#include "parse-options.h"
-#include "userdiff.h"
-#include "streaming.h"
-#include "tree-walk.h"
-#include "oid-array.h"
-#include "packfile.h"
-#include "object-store.h"
-#include "promisor-remote.h"
-
-struct batch_options {
-	int enabled;
-	int follow_symlinks;
-	int print_contents;
-	int buffer_output;
-	int all_objects;
-	int unordered;
-	int cmdmode; /* may be 'w' or 'c' for --filters or --textconv */
-	const char *format;
-};
-
-static const char *force_path;
-
-static int filter_object(const char *path, unsigned mode,
-			 const struct object_id *oid,
-			 char **buf, unsigned long *size)
-{
-	enum object_type type;
-
-	*buf = read_object_file(oid, &type, size);
-	if (!*buf)
-		return error(_("cannot read object %s '%s'"),
-			     oid_to_hex(oid), path);
-	if ((type == OBJ_BLOB) && S_ISREG(mode)) {
-		struct strbuf strbuf = STRBUF_INIT;
-		struct checkout_metadata meta;
-
-		init_checkout_metadata(&meta, NULL, NULL, oid);
-		if (convert_to_working_tree(&the_index, path, *buf, *size, &strbuf, &meta)) {
-			free(*buf);
-			*size = strbuf.len;
-			*buf = strbuf_detach(&strbuf, NULL);
-		}
-	}
-
-	return 0;
-}
-
-static int stream_blob(const struct object_id *oid)
-{
-	if (stream_blob_to_fd(1, oid, NULL, 0))
-		die("unable to stream %s to stdout", oid_to_hex(oid));
-	return 0;
-}
-
-static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
-			int unknown_type)
-{
-	struct object_id oid;
-	enum object_type type;
-	char *buf;
-	unsigned long size;
-	struct object_context obj_context;
-	struct object_info oi = OBJECT_INFO_INIT;
-	struct strbuf sb = STRBUF_INIT;
-	unsigned flags = OBJECT_INFO_LOOKUP_REPLACE;
-	const char *path = force_path;
-
-	if (unknown_type)
-		flags |= OBJECT_INFO_ALLOW_UNKNOWN_TYPE;
-
-	if (get_oid_with_context(the_repository, obj_name,
-				 GET_OID_RECORD_PATH,
-				 &oid, &obj_context))
-		die("Not a valid object name %s", obj_name);
-
-	if (!path)
-		path = obj_context.path;
-	if (obj_context.mode == S_IFINVALID)
-		obj_context.mode = 0100644;
-
-	buf = NULL;
-	switch (opt) {
-	case 't':
-		oi.type_name = &sb;
-		if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0)
-			die("git cat-file: could not get object info");
-		if (sb.len) {
-			printf("%s\n", sb.buf);
-			strbuf_release(&sb);
-			return 0;
-		}
-		break;
-
-	case 's':
-		oi.sizep = &size;
-		if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0)
-			die("git cat-file: could not get object info");
-		printf("%"PRIuMAX"\n", (uintmax_t)size);
-		return 0;
-
-	case 'e':
-		return !has_object_file(&oid);
-
-	case 'w':
-		if (!path)
-			die("git cat-file --filters %s: <object> must be "
-			    "<sha1:path>", obj_name);
-
-		if (filter_object(path, obj_context.mode,
-				  &oid, &buf, &size))
-			return -1;
-		break;
-
-	case 'c':
-		if (!path)
-			die("git cat-file --textconv %s: <object> must be <sha1:path>",
-			    obj_name);
-
-		if (textconv_object(the_repository, path, obj_context.mode,
-				    &oid, 1, &buf, &size))
-			break;
-		/* else fallthrough */
-
-	case 'p':
-		type = oid_object_info(the_repository, &oid, NULL);
-		if (type < 0)
-			die("Not a valid object name %s", obj_name);
-
-		/* custom pretty-print here */
-		if (type == OBJ_TREE) {
-			const char *ls_args[3] = { NULL };
-			ls_args[0] =  "ls-tree";
-			ls_args[1] =  obj_name;
-			return cmd_ls_tree(2, ls_args, NULL);
-		}
-
-		if (type == OBJ_BLOB)
-			return stream_blob(&oid);
-		buf = read_object_file(&oid, &type, &size);
-		if (!buf)
-			die("Cannot read object %s", obj_name);
-
-		/* otherwise just spit out the data */
-		break;
-
-	case 0:
-		if (type_from_string(exp_type) == OBJ_BLOB) {
-			struct object_id blob_oid;
-			if (oid_object_info(the_repository, &oid, NULL) == OBJ_TAG) {
-				char *buffer = read_object_file(&oid, &type,
-								&size);
-				const char *target;
-				if (!skip_prefix(buffer, "object ", &target) ||
-				    get_oid_hex(target, &blob_oid))
-					die("%s not a valid tag", oid_to_hex(&oid));
-				free(buffer);
-			} else
-				oidcpy(&blob_oid, &oid);
-
-			if (oid_object_info(the_repository, &blob_oid, NULL) == OBJ_BLOB)
-				return stream_blob(&blob_oid);
-			/*
-			 * we attempted to dereference a tag to a blob
-			 * and failed; there may be new dereference
-			 * mechanisms this code is not aware of.
-			 * fall-back to the usual case.
-			 */
-		}
-		buf = read_object_with_reference(the_repository,
-						 &oid, exp_type, &size, NULL);
-		break;
-
-	default:
-		die("git cat-file: unknown option: %s", exp_type);
-	}
-
-	if (!buf)
-		die("git cat-file %s: bad file", obj_name);
-
-	write_or_die(1, buf, size);
-	free(buf);
-	free(obj_context.path);
-	return 0;
-}
-
-struct expand_data {
-	struct object_id oid;
-	enum object_type type;
-	unsigned long size;
-	off_t disk_size;
-	const char *rest;
-	struct object_id delta_base_oid;
-
-	/*
-	 * If mark_query is true, we do not expand anything, but rather
-	 * just mark the object_info with items we wish to query.
-	 */
-	int mark_query;
-
-	/*
-	 * Whether to split the input on whitespace before feeding it to
-	 * get_sha1; this is decided during the mark_query phase based on
-	 * whether we have a %(rest) token in our format.
-	 */
-	int split_on_whitespace;
-
-	/*
-	 * After a mark_query run, this object_info is set up to be
-	 * passed to oid_object_info_extended. It will point to the data
-	 * elements above, so you can retrieve the response from there.
-	 */
-	struct object_info info;
-
-	/*
-	 * This flag will be true if the requested batch format and options
-	 * don't require us to call oid_object_info, which can then be
-	 * optimized out.
-	 */
-	unsigned skip_object_info : 1;
-};
-
-static int is_atom(const char *atom, const char *s, int slen)
-{
-	int alen = strlen(atom);
-	return alen == slen && !memcmp(atom, s, alen);
-}
-
-static void expand_atom(struct strbuf *sb, const char *atom, int len,
-			void *vdata)
-{
-	struct expand_data *data = vdata;
-
-	if (is_atom("objectname", atom, len)) {
-		if (!data->mark_query)
-			strbuf_addstr(sb, oid_to_hex(&data->oid));
-	} else if (is_atom("objecttype", atom, len)) {
-		if (data->mark_query)
-			data->info.typep = &data->type;
-		else
-			strbuf_addstr(sb, type_name(data->type));
-	} else if (is_atom("objectsize", atom, len)) {
-		if (data->mark_query)
-			data->info.sizep = &data->size;
-		else
-			strbuf_addf(sb, "%"PRIuMAX , (uintmax_t)data->size);
-	} else if (is_atom("objectsize:disk", atom, len)) {
-		if (data->mark_query)
-			data->info.disk_sizep = &data->disk_size;
-		else
-			strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
-	} else if (is_atom("rest", atom, len)) {
-		if (data->mark_query)
-			data->split_on_whitespace = 1;
-		else if (data->rest)
-			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;
-		else
-			strbuf_addstr(sb,
-				      oid_to_hex(&data->delta_base_oid));
-	} else
-		die("unknown format element: %.*s", len, atom);
-}
-
-static size_t expand_format(struct strbuf *sb, const char *start, void *data)
-{
-	const char *end;
-
-	if (*start != '(')
-		return 0;
-	end = strchr(start + 1, ')');
-	if (!end)
-		die("format element '%s' does not end in ')'", start);
-
-	expand_atom(sb, start + 1, end - start - 1, data);
-
-	return end - start + 1;
-}
-
-static void batch_write(struct batch_options *opt, const void *data, int len)
-{
-	if (opt->buffer_output) {
-		if (fwrite(data, 1, len, stdout) != len)
-			die_errno("unable to write to stdout");
-	} else
-		write_or_die(1, data, len);
-}
-
-static void print_object_or_die(struct batch_options *opt, struct expand_data *data)
-{
-	const struct object_id *oid = &data->oid;
-
-	assert(data->info.typep);
-
-	if (data->type == OBJ_BLOB) {
-		if (opt->buffer_output)
-			fflush(stdout);
-		if (opt->cmdmode) {
-			char *contents;
-			unsigned long size;
-
-			if (!data->rest)
-				die("missing path for '%s'", oid_to_hex(oid));
-
-			if (opt->cmdmode == 'w') {
-				if (filter_object(data->rest, 0100644, oid,
-						  &contents, &size))
-					die("could not convert '%s' %s",
-					    oid_to_hex(oid), data->rest);
-			} else if (opt->cmdmode == 'c') {
-				enum object_type type;
-				if (!textconv_object(the_repository,
-						     data->rest, 0100644, oid,
-						     1, &contents, &size))
-					contents = read_object_file(oid,
-								    &type,
-								    &size);
-				if (!contents)
-					die("could not convert '%s' %s",
-					    oid_to_hex(oid), data->rest);
-			} else
-				BUG("invalid cmdmode: %c", opt->cmdmode);
-			batch_write(opt, contents, size);
-			free(contents);
-		} else {
-			stream_blob(oid);
-		}
-	}
-	else {
-		enum object_type type;
-		unsigned long size;
-		void *contents;
-
-		contents = read_object_file(oid, &type, &size);
-		if (!contents)
-			die("object %s disappeared", oid_to_hex(oid));
-		if (type != data->type)
-			die("object %s changed type!?", oid_to_hex(oid));
-		if (data->info.sizep && size != data->size)
-			die("object %s changed size!?", oid_to_hex(oid));
-
-		batch_write(opt, contents, size);
-		free(contents);
-	}
-}
-
-static void batch_object_write(const char *obj_name,
-			       struct strbuf *scratch,
-			       struct batch_options *opt,
-			       struct expand_data *data)
-{
-	if (!data->skip_object_info &&
-	    oid_object_info_extended(the_repository, &data->oid, &data->info,
-				     OBJECT_INFO_LOOKUP_REPLACE) < 0) {
-		printf("%s missing\n",
-		       obj_name ? obj_name : oid_to_hex(&data->oid));
-		fflush(stdout);
-		return;
-	}
-
-	strbuf_reset(scratch);
-	strbuf_expand(scratch, opt->format, expand_format, data);
-	strbuf_addch(scratch, '\n');
-	batch_write(opt, scratch->buf, scratch->len);
-
-	if (opt->print_contents) {
-		print_object_or_die(opt, data);
-		batch_write(opt, "\n", 1);
-	}
-}
-
-static void batch_one_object(const char *obj_name,
-			     struct strbuf *scratch,
-			     struct batch_options *opt,
-			     struct expand_data *data)
-{
-	struct object_context ctx;
-	int flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0;
-	enum get_oid_result result;
-
-	result = get_oid_with_context(the_repository, obj_name,
-				      flags, &data->oid, &ctx);
-	if (result != FOUND) {
-		switch (result) {
-		case MISSING_OBJECT:
-			printf("%s missing\n", obj_name);
-			break;
-		case SHORT_NAME_AMBIGUOUS:
-			printf("%s ambiguous\n", obj_name);
-			break;
-		case DANGLING_SYMLINK:
-			printf("dangling %"PRIuMAX"\n%s\n",
-			       (uintmax_t)strlen(obj_name), obj_name);
-			break;
-		case SYMLINK_LOOP:
-			printf("loop %"PRIuMAX"\n%s\n",
-			       (uintmax_t)strlen(obj_name), obj_name);
-			break;
-		case NOT_DIR:
-			printf("notdir %"PRIuMAX"\n%s\n",
-			       (uintmax_t)strlen(obj_name), obj_name);
-			break;
-		default:
-			BUG("unknown get_sha1_with_context result %d\n",
-			       result);
-			break;
-		}
-		fflush(stdout);
-		return;
-	}
-
-	if (ctx.mode == 0) {
-		printf("symlink %"PRIuMAX"\n%s\n",
-		       (uintmax_t)ctx.symlink_path.len,
-		       ctx.symlink_path.buf);
-		fflush(stdout);
-		return;
-	}
-
-	batch_object_write(obj_name, scratch, opt, data);
-}
-
-struct object_cb_data {
-	struct batch_options *opt;
-	struct expand_data *expand;
-	struct oidset *seen;
-	struct strbuf *scratch;
-};
-
-static int batch_object_cb(const struct object_id *oid, void *vdata)
-{
-	struct object_cb_data *data = vdata;
-	oidcpy(&data->expand->oid, oid);
-	batch_object_write(NULL, data->scratch, data->opt, data->expand);
-	return 0;
-}
-
-static int collect_loose_object(const struct object_id *oid,
-				const char *path,
-				void *data)
-{
-	oid_array_append(data, oid);
-	return 0;
-}
-
-static int collect_packed_object(const struct object_id *oid,
-				 struct packed_git *pack,
-				 uint32_t pos,
-				 void *data)
-{
-	oid_array_append(data, oid);
-	return 0;
-}
-
-static int batch_unordered_object(const struct object_id *oid, void *vdata)
-{
-	struct object_cb_data *data = vdata;
-
-	if (oidset_insert(data->seen, oid))
-		return 0;
-
-	return batch_object_cb(oid, data);
-}
-
-static int batch_unordered_loose(const struct object_id *oid,
-				 const char *path,
-				 void *data)
-{
-	return batch_unordered_object(oid, data);
-}
-
-static int batch_unordered_packed(const struct object_id *oid,
-				  struct packed_git *pack,
-				  uint32_t pos,
-				  void *data)
-{
-	return batch_unordered_object(oid, data);
-}
-
-static int batch_objects(struct batch_options *opt)
-{
-	struct strbuf input = STRBUF_INIT;
-	struct strbuf output = STRBUF_INIT;
-	struct expand_data data;
-	int save_warning;
-	int retval = 0;
-
-	if (!opt->format)
-		opt->format = "%(objectname) %(objecttype) %(objectsize)";
-
-	/*
-	 * Expand once with our special mark_query flag, which will prime the
-	 * object_info to be handed to oid_object_info_extended for each
-	 * object.
-	 */
-	memset(&data, 0, sizeof(data));
-	data.mark_query = 1;
-	strbuf_expand(&output, opt->format, expand_format, &data);
-	data.mark_query = 0;
-	strbuf_release(&output);
-	if (opt->cmdmode)
-		data.split_on_whitespace = 1;
-
-	if (opt->all_objects) {
-		struct object_info empty = OBJECT_INFO_INIT;
-		if (!memcmp(&data.info, &empty, sizeof(empty)))
-			data.skip_object_info = 1;
-	}
-
-	/*
-	 * If we are printing out the object, then always fill in the type,
-	 * since we will want to decide whether or not to stream.
-	 */
-	if (opt->print_contents)
-		data.info.typep = &data.type;
-
-	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.");
-
-		cb.opt = opt;
-		cb.expand = &data;
-		cb.scratch = &output;
-
-		if (opt->unordered) {
-			struct oidset seen = OIDSET_INIT;
-
-			cb.seen = &seen;
-
-			for_each_loose_object(batch_unordered_loose, &cb, 0);
-			for_each_packed_object(batch_unordered_packed, &cb,
-					       FOR_EACH_OBJECT_PACK_ORDER);
-
-			oidset_clear(&seen);
-		} else {
-			struct oid_array sa = OID_ARRAY_INIT;
-
-			for_each_loose_object(collect_loose_object, &sa, 0);
-			for_each_packed_object(collect_packed_object, &sa, 0);
-
-			oid_array_for_each_unique(&sa, batch_object_cb, &cb);
-
-			oid_array_clear(&sa);
-		}
-
-		strbuf_release(&output);
-		return 0;
-	}
-
-	/*
-	 * We are going to call get_sha1 on a potentially very large number of
-	 * objects. In most large cases, these will be actual object sha1s. The
-	 * cost to double-check that each one is not also a ref (just so we can
-	 * warn) ends up dwarfing the actual cost of the object lookups
-	 * themselves. We can work around it by just turning off the warning.
-	 */
-	save_warning = warn_on_object_refname_ambiguity;
-	warn_on_object_refname_ambiguity = 0;
-
-	while (strbuf_getline(&input, stdin) != EOF) {
-		if (data.split_on_whitespace) {
-			/*
-			 * Split at first whitespace, tying off the beginning
-			 * of the string and saving the remainder (or NULL) in
-			 * data.rest.
-			 */
-			char *p = strpbrk(input.buf, " \t");
-			if (p) {
-				while (*p && strchr(" \t", *p))
-					*p++ = '\0';
-			}
-			data.rest = p;
-		}
-
-		batch_one_object(input.buf, &output, opt, &data);
-	}
-
-	strbuf_release(&input);
-	strbuf_release(&output);
-	warn_on_object_refname_ambiguity = save_warning;
-	return retval;
-}
-
-static const char * const cat_file_usage[] = {
-	N_("git cat-file (-t [--allow-unknown-type] | -s [--allow-unknown-type] | -e | -p | <type> | --textconv | --filters) [--path=<path>] <object>"),
-	N_("git cat-file (--batch[=<format>] | --batch-check[=<format>]) [--follow-symlinks] [--textconv | --filters]"),
-	NULL
-};
-
-static int git_cat_file_config(const char *var, const char *value, void *cb)
-{
-	if (userdiff_config(var, value) < 0)
-		return -1;
-
-	return git_default_config(var, value, cb);
-}
-
-static int batch_option_callback(const struct option *opt,
-				 const char *arg,
-				 int unset)
-{
-	struct batch_options *bo = opt->value;
-
-	BUG_ON_OPT_NEG(unset);
-
-	if (bo->enabled) {
-		return error(_("only one batch option may be specified"));
-	}
-
-	bo->enabled = 1;
-	bo->print_contents = !strcmp(opt->long_name, "batch");
-	bo->format = arg;
-
-	return 0;
-}
-
-int cmd_cat_file(int argc, const char **argv, const char *prefix)
-{
-	int opt = 0;
-	const char *exp_type = NULL, *obj_name = NULL;
-	struct batch_options batch = {0};
-	int unknown_type = 0;
-
-	const struct option options[] = {
-		OPT_GROUP(N_("<type> can be one of: blob, tree, commit, tag")),
-		OPT_CMDMODE('t', NULL, &opt, N_("show object type"), 't'),
-		OPT_CMDMODE('s', NULL, &opt, N_("show object size"), 's'),
-		OPT_CMDMODE('e', NULL, &opt,
-			    N_("exit with zero when there's no error"), 'e'),
-		OPT_CMDMODE('p', NULL, &opt, N_("pretty-print object's content"), 'p'),
-		OPT_CMDMODE(0, "textconv", &opt,
-			    N_("for blob objects, run textconv on object's content"), 'c'),
-		OPT_CMDMODE(0, "filters", &opt,
-			    N_("for blob objects, run filters on object's content"), 'w'),
-		OPT_STRING(0, "path", &force_path, N_("blob"),
-			   N_("use a specific path for --textconv/--filters")),
-		OPT_BOOL(0, "allow-unknown-type", &unknown_type,
-			  N_("allow -s and -t to work with broken/corrupt objects")),
-		OPT_BOOL(0, "buffer", &batch.buffer_output, N_("buffer --batch output")),
-		OPT_CALLBACK_F(0, "batch", &batch, "format",
-			N_("show info and content of objects fed from the standard input"),
-			PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
-			batch_option_callback),
-		OPT_CALLBACK_F(0, "batch-check", &batch, "format",
-			N_("show info about objects fed from the standard input"),
-			PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
-			batch_option_callback),
-		OPT_BOOL(0, "follow-symlinks", &batch.follow_symlinks,
-			 N_("follow in-tree symlinks (used with --batch or --batch-check)")),
-		OPT_BOOL(0, "batch-all-objects", &batch.all_objects,
-			 N_("show all objects with --batch or --batch-check")),
-		OPT_BOOL(0, "unordered", &batch.unordered,
-			 N_("do not order --batch-all-objects output")),
-		OPT_END()
-	};
-
-	git_config(git_cat_file_config, NULL);
-
-	batch.buffer_output = -1;
-	argc = parse_options(argc, argv, prefix, options, cat_file_usage, 0);
-
-	if (opt) {
-		if (batch.enabled && (opt == 'c' || opt == 'w'))
-			batch.cmdmode = opt;
-		else if (argc == 1)
-			obj_name = argv[0];
-		else
-			usage_with_options(cat_file_usage, options);
-	}
-	if (!opt && !batch.enabled) {
-		if (argc == 2) {
-			exp_type = argv[0];
-			obj_name = argv[1];
-		} else
-			usage_with_options(cat_file_usage, options);
-	}
-	if (batch.enabled) {
-		if (batch.cmdmode != opt || argc)
-			usage_with_options(cat_file_usage, options);
-		if (batch.cmdmode && batch.all_objects)
-			die("--batch-all-objects cannot be combined with "
-			    "--textconv nor with --filters");
-	}
-
-	if ((batch.follow_symlinks || batch.all_objects) && !batch.enabled) {
-		usage_with_options(cat_file_usage, options);
-	}
-
-	if (force_path && opt != 'c' && opt != 'w') {
-		error("--path=<path> needs --textconv or --filters");
-		usage_with_options(cat_file_usage, options);
-	}
-
-	if (force_path && batch.enabled) {
-		error("--path=<path> incompatible with --batch");
-		usage_with_options(cat_file_usage, options);
-	}
-
-	if (batch.buffer_output < 0)
-		batch.buffer_output = batch.all_objects;
-
-	if (batch.enabled)
-		return batch_objects(&batch);
-
-	if (unknown_type && opt != 't' && opt != 's')
-		die("git cat-file --allow-unknown-type: use with -s or -t");
-	return cat_one_file(opt, exp_type, obj_name, unknown_type);
-}
diff --git a/third_party/git/builtin/check-attr.c b/third_party/git/builtin/check-attr.c
deleted file mode 100644
index dd833977864d..000000000000
--- a/third_party/git/builtin/check-attr.c
+++ /dev/null
@@ -1,189 +0,0 @@
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "attr.h"
-#include "quote.h"
-#include "parse-options.h"
-
-static int all_attrs;
-static int cached_attrs;
-static int stdin_paths;
-static const char * const check_attr_usage[] = {
-N_("git check-attr [-a | --all | <attr>...] [--] <pathname>..."),
-N_("git check-attr --stdin [-z] [-a | --all | <attr>...]"),
-NULL
-};
-
-static int nul_term_line;
-
-static const struct option check_attr_options[] = {
-	OPT_BOOL('a', "all", &all_attrs, N_("report all attributes set on file")),
-	OPT_BOOL(0,  "cached", &cached_attrs, N_("use .gitattributes only from the index")),
-	OPT_BOOL(0 , "stdin", &stdin_paths, N_("read file names from stdin")),
-	OPT_BOOL('z', NULL, &nul_term_line,
-		 N_("terminate input and output records by a NUL character")),
-	OPT_END()
-};
-
-static void output_attr(struct attr_check *check, const char *file)
-{
-	int j;
-	int cnt = check->nr;
-
-	for (j = 0; j < cnt; j++) {
-		const char *value = check->items[j].value;
-
-		if (ATTR_TRUE(value))
-			value = "set";
-		else if (ATTR_FALSE(value))
-			value = "unset";
-		else if (ATTR_UNSET(value))
-			value = "unspecified";
-
-		if (nul_term_line) {
-			printf("%s%c" /* path */
-			       "%s%c" /* attrname */
-			       "%s%c" /* attrvalue */,
-			       file, 0,
-			       git_attr_name(check->items[j].attr), 0, value, 0);
-		} else {
-			quote_c_style(file, NULL, stdout, 0);
-			printf(": %s: %s\n",
-			       git_attr_name(check->items[j].attr), value);
-		}
-	}
-}
-
-static void check_attr(const char *prefix,
-		       struct attr_check *check,
-		       int collect_all,
-		       const char *file)
-{
-	char *full_path =
-		prefix_path(prefix, prefix ? strlen(prefix) : 0, file);
-
-	if (collect_all) {
-		git_all_attrs(&the_index, full_path, check);
-	} else {
-		git_check_attr(&the_index, full_path, check);
-	}
-	output_attr(check, file);
-
-	free(full_path);
-}
-
-static void check_attr_stdin_paths(const char *prefix,
-				   struct attr_check *check,
-				   int collect_all)
-{
-	struct strbuf buf = STRBUF_INIT;
-	struct strbuf unquoted = STRBUF_INIT;
-	strbuf_getline_fn getline_fn;
-
-	getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
-	while (getline_fn(&buf, stdin) != EOF) {
-		if (!nul_term_line && buf.buf[0] == '"') {
-			strbuf_reset(&unquoted);
-			if (unquote_c_style(&unquoted, buf.buf, NULL))
-				die("line is badly quoted");
-			strbuf_swap(&buf, &unquoted);
-		}
-		check_attr(prefix, check, collect_all, buf.buf);
-		maybe_flush_or_die(stdout, "attribute to stdout");
-	}
-	strbuf_release(&buf);
-	strbuf_release(&unquoted);
-}
-
-static NORETURN void error_with_usage(const char *msg)
-{
-	error("%s", msg);
-	usage_with_options(check_attr_usage, check_attr_options);
-}
-
-int cmd_check_attr(int argc, const char **argv, const char *prefix)
-{
-	struct attr_check *check;
-	int cnt, i, doubledash, filei;
-
-	if (!is_bare_repository())
-		setup_work_tree();
-
-	git_config(git_default_config, NULL);
-
-	argc = parse_options(argc, argv, prefix, check_attr_options,
-			     check_attr_usage, PARSE_OPT_KEEP_DASHDASH);
-
-	if (read_cache() < 0) {
-		die("invalid cache");
-	}
-
-	if (cached_attrs)
-		git_attr_set_direction(GIT_ATTR_INDEX);
-
-	doubledash = -1;
-	for (i = 0; doubledash < 0 && i < argc; i++) {
-		if (!strcmp(argv[i], "--"))
-			doubledash = i;
-	}
-
-	/* Process --all and/or attribute arguments: */
-	if (all_attrs) {
-		if (doubledash >= 1)
-			error_with_usage("Attributes and --all both specified");
-
-		cnt = 0;
-		filei = doubledash + 1;
-	} else if (doubledash == 0) {
-		error_with_usage("No attribute specified");
-	} else if (doubledash < 0) {
-		if (!argc)
-			error_with_usage("No attribute specified");
-
-		if (stdin_paths) {
-			/* Treat all arguments as attribute names. */
-			cnt = argc;
-			filei = argc;
-		} else {
-			/* Treat exactly one argument as an attribute name. */
-			cnt = 1;
-			filei = 1;
-		}
-	} else {
-		cnt = doubledash;
-		filei = doubledash + 1;
-	}
-
-	/* Check file argument(s): */
-	if (stdin_paths) {
-		if (filei < argc)
-			error_with_usage("Can't specify files with --stdin");
-	} else {
-		if (filei >= argc)
-			error_with_usage("No file specified");
-	}
-
-	check = attr_check_alloc();
-	if (!all_attrs) {
-		for (i = 0; i < cnt; i++) {
-			const struct git_attr *a = git_attr(argv[i]);
-
-			if (!a)
-				return error("%s: not a valid attribute name",
-					     argv[i]);
-			attr_check_append(check, a);
-		}
-	}
-
-	if (stdin_paths)
-		check_attr_stdin_paths(prefix, check, all_attrs);
-	else {
-		for (i = filei; i < argc; i++)
-			check_attr(prefix, check, all_attrs, argv[i]);
-		maybe_flush_or_die(stdout, "attribute to stdout");
-	}
-
-	attr_check_free(check);
-	return 0;
-}
diff --git a/third_party/git/builtin/check-ignore.c b/third_party/git/builtin/check-ignore.c
deleted file mode 100644
index 3c652748d58c..000000000000
--- a/third_party/git/builtin/check-ignore.c
+++ /dev/null
@@ -1,196 +0,0 @@
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "dir.h"
-#include "quote.h"
-#include "pathspec.h"
-#include "parse-options.h"
-#include "submodule.h"
-
-static int quiet, verbose, stdin_paths, show_non_matching, no_index;
-static const char * const check_ignore_usage[] = {
-"git check-ignore [<options>] <pathname>...",
-"git check-ignore [<options>] --stdin",
-NULL
-};
-
-static int nul_term_line;
-
-static const struct option check_ignore_options[] = {
-	OPT__QUIET(&quiet, N_("suppress progress reporting")),
-	OPT__VERBOSE(&verbose, N_("be verbose")),
-	OPT_GROUP(""),
-	OPT_BOOL(0, "stdin", &stdin_paths,
-		 N_("read file names from stdin")),
-	OPT_BOOL('z', NULL, &nul_term_line,
-		 N_("terminate input and output records by a NUL character")),
-	OPT_BOOL('n', "non-matching", &show_non_matching,
-		 N_("show non-matching input paths")),
-	OPT_BOOL(0, "no-index", &no_index,
-		 N_("ignore index when checking")),
-	OPT_END()
-};
-
-static void output_pattern(const char *path, struct path_pattern *pattern)
-{
-	char *bang  = (pattern && pattern->flags & PATTERN_FLAG_NEGATIVE)  ? "!" : "";
-	char *slash = (pattern && pattern->flags & PATTERN_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);
-				printf(":%d:%s%s%s\t",
-				       pattern->srcpos,
-				       bang, pattern->pattern, slash);
-			}
-			else {
-				printf("::\t");
-			}
-			quote_c_style(path, NULL, stdout, 0);
-			fputc('\n', stdout);
-		}
-	} else {
-		if (!verbose) {
-			printf("%s%c", path, '\0');
-		} else {
-			if (pattern)
-				printf("%s%c%d%c%s%s%s%c%s%c",
-				       pattern->pl->src, '\0',
-				       pattern->srcpos, '\0',
-				       bang, pattern->pattern, slash, '\0',
-				       path, '\0');
-			else
-				printf("%c%c%c%s%c", '\0', '\0', '\0', path, '\0');
-		}
-	}
-}
-
-static int check_ignore(struct dir_struct *dir,
-			const char *prefix, int argc, const char **argv)
-{
-	const char *full_path;
-	char *seen;
-	int num_ignored = 0, i;
-	struct path_pattern *pattern;
-	struct pathspec pathspec;
-
-	if (!argc) {
-		if (!quiet)
-			fprintf(stderr, "no pathspec given.\n");
-		return 0;
-	}
-
-	/*
-	 * check-ignore just needs paths. Magic beyond :/ is really
-	 * irrelevant.
-	 */
-	parse_pathspec(&pathspec,
-		       PATHSPEC_ALL_MAGIC & ~PATHSPEC_FROMTOP,
-		       PATHSPEC_SYMLINK_LEADING_PATH |
-		       PATHSPEC_KEEP_ORDER,
-		       prefix, argv);
-
-	die_path_inside_submodule(&the_index, &pathspec);
-
-	/*
-	 * look for pathspecs matching entries in the index, since these
-	 * should not be ignored, in order to be consistent with
-	 * 'git status', 'git add' etc.
-	 */
-	seen = find_pathspecs_matching_against_index(&pathspec, &the_index);
-	for (i = 0; i < pathspec.nr; i++) {
-		full_path = pathspec.items[i].match;
-		pattern = NULL;
-		if (!seen[i]) {
-			int dtype = DT_UNKNOWN;
-			pattern = last_matching_pattern(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)
-			num_ignored++;
-	}
-	free(seen);
-
-	return num_ignored;
-}
-
-static int check_ignore_stdin_paths(struct dir_struct *dir, const char *prefix)
-{
-	struct strbuf buf = STRBUF_INIT;
-	struct strbuf unquoted = STRBUF_INIT;
-	char *pathspec[2] = { NULL, NULL };
-	strbuf_getline_fn getline_fn;
-	int num_ignored = 0;
-
-	getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
-	while (getline_fn(&buf, stdin) != EOF) {
-		if (!nul_term_line && buf.buf[0] == '"') {
-			strbuf_reset(&unquoted);
-			if (unquote_c_style(&unquoted, buf.buf, NULL))
-				die("line is badly quoted");
-			strbuf_swap(&buf, &unquoted);
-		}
-		pathspec[0] = buf.buf;
-		num_ignored += check_ignore(dir, prefix,
-					    1, (const char **)pathspec);
-		maybe_flush_or_die(stdout, "check-ignore to stdout");
-	}
-	strbuf_release(&buf);
-	strbuf_release(&unquoted);
-	return num_ignored;
-}
-
-int cmd_check_ignore(int argc, const char **argv, const char *prefix)
-{
-	int num_ignored;
-	struct dir_struct dir;
-
-	git_config(git_default_config, NULL);
-
-	argc = parse_options(argc, argv, prefix, check_ignore_options,
-			     check_ignore_usage, 0);
-
-	if (stdin_paths) {
-		if (argc > 0)
-			die(_("cannot specify pathnames with --stdin"));
-	} else {
-		if (nul_term_line)
-			die(_("-z only makes sense with --stdin"));
-		if (argc == 0)
-			die(_("no path specified"));
-	}
-	if (quiet) {
-		if (argc > 1)
-			die(_("--quiet is only valid with a single pathname"));
-		if (verbose)
-			die(_("cannot have both --quiet and --verbose"));
-	}
-	if (show_non_matching && !verbose)
-		die(_("--non-matching is only valid with --verbose"));
-
-	/* read_cache() is only necessary so we can watch out for submodules. */
-	if (!no_index && read_cache() < 0)
-		die(_("index file corrupt"));
-
-	dir_init(&dir);
-	setup_standard_excludes(&dir);
-
-	if (stdin_paths) {
-		num_ignored = check_ignore_stdin_paths(&dir, prefix);
-	} else {
-		num_ignored = check_ignore(&dir, prefix, argc, argv);
-		maybe_flush_or_die(stdout, "ignore to stdout");
-	}
-
-	dir_clear(&dir);
-
-	return !num_ignored;
-}
diff --git a/third_party/git/builtin/check-mailmap.c b/third_party/git/builtin/check-mailmap.c
deleted file mode 100644
index cdce144f3b7f..000000000000
--- a/third_party/git/builtin/check-mailmap.c
+++ /dev/null
@@ -1,67 +0,0 @@
-#include "builtin.h"
-#include "config.h"
-#include "mailmap.h"
-#include "parse-options.h"
-#include "string-list.h"
-
-static int use_stdin;
-static const char * const check_mailmap_usage[] = {
-N_("git check-mailmap [<options>] <contact>..."),
-NULL
-};
-
-static const struct option check_mailmap_options[] = {
-	OPT_BOOL(0, "stdin", &use_stdin, N_("also read contacts from stdin")),
-	OPT_END()
-};
-
-static void check_mailmap(struct string_list *mailmap, const char *contact)
-{
-	const char *name, *mail;
-	size_t namelen, maillen;
-	struct ident_split ident;
-
-	if (split_ident_line(&ident, contact, strlen(contact)))
-		die(_("unable to parse contact: %s"), contact);
-
-	name = ident.name_begin;
-	namelen = ident.name_end - ident.name_begin;
-	mail = ident.mail_begin;
-	maillen = ident.mail_end - ident.mail_begin;
-
-	map_user(mailmap, &mail, &maillen, &name, &namelen);
-
-	if (namelen)
-		printf("%.*s ", (int)namelen, name);
-	printf("<%.*s>\n", (int)maillen, mail);
-}
-
-int cmd_check_mailmap(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	struct string_list mailmap = STRING_LIST_INIT_NODUP;
-
-	git_config(git_default_config, NULL);
-	argc = parse_options(argc, argv, prefix, check_mailmap_options,
-			     check_mailmap_usage, 0);
-	if (argc == 0 && !use_stdin)
-		die(_("no contacts specified"));
-
-	read_mailmap(&mailmap, NULL);
-
-	for (i = 0; i < argc; ++i)
-		check_mailmap(&mailmap, argv[i]);
-	maybe_flush_or_die(stdout, "stdout");
-
-	if (use_stdin) {
-		struct strbuf buf = STRBUF_INIT;
-		while (strbuf_getline_lf(&buf, stdin) != EOF) {
-			check_mailmap(&mailmap, buf.buf);
-			maybe_flush_or_die(stdout, "stdout");
-		}
-		strbuf_release(&buf);
-	}
-
-	clear_mailmap(&mailmap);
-	return 0;
-}
diff --git a/third_party/git/builtin/check-ref-format.c b/third_party/git/builtin/check-ref-format.c
deleted file mode 100644
index bc67d3f0a83d..000000000000
--- a/third_party/git/builtin/check-ref-format.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * GIT - The information manager from hell
- */
-
-#include "cache.h"
-#include "refs.h"
-#include "builtin.h"
-#include "strbuf.h"
-
-static const char builtin_check_ref_format_usage[] =
-"git check-ref-format [--normalize] [<options>] <refname>\n"
-"   or: git check-ref-format --branch <branchname-shorthand>";
-
-/*
- * Return a copy of refname but with leading slashes removed and runs
- * of adjacent slashes replaced with single slashes.
- *
- * This function is similar to normalize_path_copy(), but stripped down
- * to meet check_ref_format's simpler needs.
- */
-static char *collapse_slashes(const char *refname)
-{
-	char *ret = xmallocz(strlen(refname));
-	char ch;
-	char prev = '/';
-	char *cp = ret;
-
-	while ((ch = *refname++) != '\0') {
-		if (prev == '/' && ch == prev)
-			continue;
-
-		*cp++ = ch;
-		prev = ch;
-	}
-	*cp = '\0';
-	return ret;
-}
-
-static int check_ref_format_branch(const char *arg)
-{
-	struct strbuf sb = STRBUF_INIT;
-	const char *name;
-	int nongit;
-
-	setup_git_directory_gently(&nongit);
-	if (strbuf_check_branch_ref(&sb, arg) ||
-	    !skip_prefix(sb.buf, "refs/heads/", &name))
-		die("'%s' is not a valid branch name", arg);
-	printf("%s\n", name);
-	strbuf_release(&sb);
-	return 0;
-}
-
-int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	int normalize = 0;
-	int flags = 0;
-	const char *refname;
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage(builtin_check_ref_format_usage);
-
-	if (argc == 3 && !strcmp(argv[1], "--branch"))
-		return check_ref_format_branch(argv[2]);
-
-	for (i = 1; i < argc && argv[i][0] == '-'; i++) {
-		if (!strcmp(argv[i], "--normalize") || !strcmp(argv[i], "--print"))
-			normalize = 1;
-		else if (!strcmp(argv[i], "--allow-onelevel"))
-			flags |= REFNAME_ALLOW_ONELEVEL;
-		else if (!strcmp(argv[i], "--no-allow-onelevel"))
-			flags &= ~REFNAME_ALLOW_ONELEVEL;
-		else if (!strcmp(argv[i], "--refspec-pattern"))
-			flags |= REFNAME_REFSPEC_PATTERN;
-		else
-			usage(builtin_check_ref_format_usage);
-	}
-	if (! (i == argc - 1))
-		usage(builtin_check_ref_format_usage);
-
-	refname = argv[i];
-	if (normalize)
-		refname = collapse_slashes(refname);
-	if (check_refname_format(refname, flags))
-		return 1;
-	if (normalize)
-		printf("%s\n", refname);
-
-	return 0;
-}
diff --git a/third_party/git/builtin/checkout-index.c b/third_party/git/builtin/checkout-index.c
deleted file mode 100644
index a854fd16e779..000000000000
--- a/third_party/git/builtin/checkout-index.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Check-out files from the "current cache directory"
- *
- * Copyright (C) 2005 Linus Torvalds
- *
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "config.h"
-#include "lockfile.h"
-#include "quote.h"
-#include "cache-tree.h"
-#include "parse-options.h"
-
-#define CHECKOUT_ALL 4
-static int nul_term_line;
-static int checkout_stage; /* default to checkout stage0 */
-static int to_tempfile;
-static char topath[4][TEMPORARY_FILENAME_LENGTH + 1];
-
-static struct checkout state = CHECKOUT_INIT;
-
-static void write_tempfile_record(const char *name, const char *prefix)
-{
-	int i;
-
-	if (CHECKOUT_ALL == checkout_stage) {
-		for (i = 1; i < 4; i++) {
-			if (i > 1)
-				putchar(' ');
-			if (topath[i][0])
-				fputs(topath[i], stdout);
-			else
-				putchar('.');
-		}
-	} else
-		fputs(topath[checkout_stage], stdout);
-
-	putchar('\t');
-	write_name_quoted_relative(name, prefix, stdout,
-				   nul_term_line ? '\0' : '\n');
-
-	for (i = 0; i < 4; i++) {
-		topath[i][0] = 0;
-	}
-}
-
-static int checkout_file(const char *name, const char *prefix)
-{
-	int namelen = strlen(name);
-	int pos = cache_name_pos(name, namelen);
-	int has_same_name = 0;
-	int did_checkout = 0;
-	int errs = 0;
-
-	if (pos < 0)
-		pos = -pos - 1;
-
-	while (pos < active_nr) {
-		struct cache_entry *ce = active_cache[pos];
-		if (ce_namelen(ce) != namelen ||
-		    memcmp(ce->name, name, namelen))
-			break;
-		has_same_name = 1;
-		pos++;
-		if (ce_stage(ce) != checkout_stage
-		    && (CHECKOUT_ALL != checkout_stage || !ce_stage(ce)))
-			continue;
-		did_checkout = 1;
-		if (checkout_entry(ce, &state,
-				   to_tempfile ? topath[ce_stage(ce)] : NULL,
-				   NULL) < 0)
-			errs++;
-	}
-
-	if (did_checkout) {
-		if (to_tempfile)
-			write_tempfile_record(name, prefix);
-		return errs > 0 ? -1 : 0;
-	}
-
-	if (!state.quiet) {
-		fprintf(stderr, "git checkout-index: %s ", name);
-		if (!has_same_name)
-			fprintf(stderr, "is not in the cache");
-		else if (checkout_stage)
-			fprintf(stderr, "does not exist at stage %d",
-				checkout_stage);
-		else
-			fprintf(stderr, "is unmerged");
-		fputc('\n', stderr);
-	}
-	return -1;
-}
-
-static void checkout_all(const char *prefix, int prefix_length)
-{
-	int i, errs = 0;
-	struct cache_entry *last_ce = NULL;
-
-	for (i = 0; i < active_nr ; i++) {
-		struct cache_entry *ce = active_cache[i];
-		if (ce_stage(ce) != checkout_stage
-		    && (CHECKOUT_ALL != checkout_stage || !ce_stage(ce)))
-			continue;
-		if (prefix && *prefix &&
-		    (ce_namelen(ce) <= prefix_length ||
-		     memcmp(prefix, ce->name, prefix_length)))
-			continue;
-		if (last_ce && to_tempfile) {
-			if (ce_namelen(last_ce) != ce_namelen(ce)
-			    || memcmp(last_ce->name, ce->name, ce_namelen(ce)))
-				write_tempfile_record(last_ce->name, prefix);
-		}
-		if (checkout_entry(ce, &state,
-				   to_tempfile ? topath[ce_stage(ce)] : NULL,
-				   NULL) < 0)
-			errs++;
-		last_ce = ce;
-	}
-	if (last_ce && to_tempfile)
-		write_tempfile_record(last_ce->name, prefix);
-	if (errs)
-		/* we have already done our error reporting.
-		 * exit with the same code as die().
-		 */
-		exit(128);
-}
-
-static const char * const builtin_checkout_index_usage[] = {
-	N_("git checkout-index [<options>] [--] [<file>...]"),
-	NULL
-};
-
-static int option_parse_stage(const struct option *opt,
-			      const char *arg, int unset)
-{
-	BUG_ON_OPT_NEG(unset);
-
-	if (!strcmp(arg, "all")) {
-		to_tempfile = 1;
-		checkout_stage = CHECKOUT_ALL;
-	} else {
-		int ch = arg[0];
-		if ('1' <= ch && ch <= '3')
-			checkout_stage = arg[0] - '0';
-		else
-			die(_("stage should be between 1 and 3 or all"));
-	}
-	return 0;
-}
-
-int cmd_checkout_index(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	struct lock_file lock_file = LOCK_INIT;
-	int all = 0;
-	int read_from_stdin = 0;
-	int prefix_length;
-	int force = 0, quiet = 0, not_new = 0;
-	int index_opt = 0;
-	struct option builtin_checkout_index_options[] = {
-		OPT_BOOL('a', "all", &all,
-			N_("check out all files in the index")),
-		OPT__FORCE(&force, N_("force overwrite of existing files"), 0),
-		OPT__QUIET(&quiet,
-			N_("no warning for existing files and files not in index")),
-		OPT_BOOL('n', "no-create", &not_new,
-			N_("don't checkout new files")),
-		OPT_BOOL('u', "index", &index_opt,
-			 N_("update stat information in the index file")),
-		OPT_BOOL('z', NULL, &nul_term_line,
-			N_("paths are separated with NUL character")),
-		OPT_BOOL(0, "stdin", &read_from_stdin,
-			N_("read list of paths from the standard input")),
-		OPT_BOOL(0, "temp", &to_tempfile,
-			N_("write the content to temporary files")),
-		OPT_STRING(0, "prefix", &state.base_dir, N_("string"),
-			N_("when creating files, prepend <string>")),
-		OPT_CALLBACK_F(0, "stage", NULL, "(1|2|3|all)",
-			N_("copy out the files from named stage"),
-			PARSE_OPT_NONEG, option_parse_stage),
-		OPT_END()
-	};
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage_with_options(builtin_checkout_index_usage,
-				   builtin_checkout_index_options);
-	git_config(git_default_config, NULL);
-	prefix_length = prefix ? strlen(prefix) : 0;
-
-	if (read_cache() < 0) {
-		die("invalid cache");
-	}
-
-	argc = parse_options(argc, argv, prefix, builtin_checkout_index_options,
-			builtin_checkout_index_usage, 0);
-	state.istate = &the_index;
-	state.force = force;
-	state.quiet = quiet;
-	state.not_new = not_new;
-
-	if (!state.base_dir)
-		state.base_dir = "";
-	state.base_dir_len = strlen(state.base_dir);
-
-	/*
-	 * when --prefix is specified we do not want to update cache.
-	 */
-	if (index_opt && !state.base_dir_len && !to_tempfile) {
-		state.refresh_cache = 1;
-		state.istate = &the_index;
-		hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
-	}
-
-	/* Check out named files first */
-	for (i = 0; i < argc; i++) {
-		const char *arg = argv[i];
-		char *p;
-
-		if (all)
-			die("git checkout-index: don't mix '--all' and explicit filenames");
-		if (read_from_stdin)
-			die("git checkout-index: don't mix '--stdin' and explicit filenames");
-		p = prefix_path(prefix, prefix_length, arg);
-		checkout_file(p, prefix);
-		free(p);
-	}
-
-	if (read_from_stdin) {
-		struct strbuf buf = STRBUF_INIT;
-		struct strbuf unquoted = STRBUF_INIT;
-		strbuf_getline_fn getline_fn;
-
-		if (all)
-			die("git checkout-index: don't mix '--all' and '--stdin'");
-
-		getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
-		while (getline_fn(&buf, stdin) != EOF) {
-			char *p;
-			if (!nul_term_line && buf.buf[0] == '"') {
-				strbuf_reset(&unquoted);
-				if (unquote_c_style(&unquoted, buf.buf, NULL))
-					die("line is badly quoted");
-				strbuf_swap(&buf, &unquoted);
-			}
-			p = prefix_path(prefix, prefix_length, buf.buf);
-			checkout_file(p, prefix);
-			free(p);
-		}
-		strbuf_release(&unquoted);
-		strbuf_release(&buf);
-	}
-
-	if (all)
-		checkout_all(prefix, prefix_length);
-
-	if (is_lock_file_locked(&lock_file) &&
-	    write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
-		die("Unable to write new index file");
-	return 0;
-}
diff --git a/third_party/git/builtin/checkout.c b/third_party/git/builtin/checkout.c
deleted file mode 100644
index 0951f8fee5cc..000000000000
--- a/third_party/git/builtin/checkout.c
+++ /dev/null
@@ -1,1868 +0,0 @@
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "advice.h"
-#include "blob.h"
-#include "branch.h"
-#include "cache-tree.h"
-#include "checkout.h"
-#include "commit.h"
-#include "config.h"
-#include "diff.h"
-#include "dir.h"
-#include "ll-merge.h"
-#include "lockfile.h"
-#include "merge-recursive.h"
-#include "object-store.h"
-#include "parse-options.h"
-#include "refs.h"
-#include "remote.h"
-#include "resolve-undo.h"
-#include "revision.h"
-#include "run-command.h"
-#include "submodule.h"
-#include "submodule-config.h"
-#include "tree.h"
-#include "tree-walk.h"
-#include "unpack-trees.h"
-#include "wt-status.h"
-#include "xdiff-interface.h"
-
-static const char * const checkout_usage[] = {
-	N_("git checkout [<options>] <branch>"),
-	N_("git checkout [<options>] [<branch>] -- <file>..."),
-	NULL,
-};
-
-static const char * const switch_branch_usage[] = {
-	N_("git switch [<options>] [<branch>]"),
-	NULL,
-};
-
-static const char * const restore_usage[] = {
-	N_("git restore [<options>] [--source=<branch>] <file>..."),
-	NULL,
-};
-
-struct checkout_opts {
-	int patch_mode;
-	int quiet;
-	int merge;
-	int force;
-	int force_detach;
-	int implicit_detach;
-	int writeout_stage;
-	int overwrite_ignore;
-	int ignore_skipworktree;
-	int ignore_other_worktrees;
-	int show_progress;
-	int count_checkout_paths;
-	int overlay_mode;
-	int dwim_new_local_branch;
-	int discard_changes;
-	int accept_ref;
-	int accept_pathspec;
-	int switch_branch_doing_nothing_is_ok;
-	int only_merge_on_switching_branches;
-	int can_switch_when_in_progress;
-	int orphan_from_empty_tree;
-	int empty_pathspec_ok;
-	int checkout_index;
-	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;
-	const char *new_orphan_branch;
-	int new_branch_log;
-	enum branch_track track;
-	struct diff_options diff_options;
-	char *conflict_style;
-
-	int branch_exists;
-	const char *prefix;
-	struct pathspec pathspec;
-	const char *from_treeish;
-	struct tree *source_tree;
-};
-
-struct branch_info {
-	const char *name; /* The short name used */
-	const char *path; /* The full name of a real branch */
-	struct commit *commit; /* The named commit */
-	char *refname; /* The full name of the ref being checked out. */
-	struct object_id oid; /* The object ID of the commit being checked out. */
-	/*
-	 * if not null the branch is detached because it's already
-	 * checked out in this checkout
-	 */
-	char *checkout;
-};
-
-static int post_checkout_hook(struct commit *old_commit, struct commit *new_commit,
-			      int changed)
-{
-	return run_hook_le(NULL, "post-checkout",
-			   oid_to_hex(old_commit ? &old_commit->object.oid : &null_oid),
-			   oid_to_hex(new_commit ? &new_commit->object.oid : &null_oid),
-			   changed ? "1" : "0", NULL);
-	/* "new_commit" can be NULL when checking out from the index before
-	   a commit exists. */
-
-}
-
-static int update_some(const struct object_id *oid, struct strbuf *base,
-		const char *pathname, unsigned mode, int stage, void *context)
-{
-	int len;
-	struct cache_entry *ce;
-	int pos;
-
-	if (S_ISDIR(mode))
-		return READ_TREE_RECURSIVE;
-
-	len = base->len + strlen(pathname);
-	ce = make_empty_cache_entry(&the_index, len);
-	oidcpy(&ce->oid, oid);
-	memcpy(ce->name, base->buf, base->len);
-	memcpy(ce->name + base->len, pathname, len - base->len);
-	ce->ce_flags = create_ce_flags(0) | CE_UPDATE;
-	ce->ce_namelen = len;
-	ce->ce_mode = create_ce_mode(mode);
-
-	/*
-	 * If the entry is the same as the current index, we can leave the old
-	 * entry in place. Whether it is UPTODATE or not, checkout_entry will
-	 * do the right thing.
-	 */
-	pos = cache_name_pos(ce->name, ce->ce_namelen);
-	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);
-			return 0;
-		}
-	}
-
-	add_cache_entry(ce, ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
-	return 0;
-}
-
-static int read_tree_some(struct tree *tree, const struct pathspec *pathspec)
-{
-	read_tree_recursive(the_repository, tree, "", 0, 0,
-			    pathspec, update_some, NULL);
-
-	/* update the index with the given tree's info
-	 * for all args, expanding wildcards, and exit
-	 * with any non-zero return code.
-	 */
-	return 0;
-}
-
-static int skip_same_name(const struct cache_entry *ce, int pos)
-{
-	while (++pos < active_nr &&
-	       !strcmp(active_cache[pos]->name, ce->name))
-		; /* skip */
-	return pos;
-}
-
-static int check_stage(int stage, const struct cache_entry *ce, int pos,
-		       int overlay_mode)
-{
-	while (pos < active_nr &&
-	       !strcmp(active_cache[pos]->name, ce->name)) {
-		if (ce_stage(active_cache[pos]) == stage)
-			return 0;
-		pos++;
-	}
-	if (!overlay_mode)
-		return 0;
-	if (stage == 2)
-		return error(_("path '%s' does not have our version"), ce->name);
-	else
-		return error(_("path '%s' does not have their version"), ce->name);
-}
-
-static int check_stages(unsigned stages, const struct cache_entry *ce, int pos)
-{
-	unsigned seen = 0;
-	const char *name = ce->name;
-
-	while (pos < active_nr) {
-		ce = active_cache[pos];
-		if (strcmp(name, ce->name))
-			break;
-		seen |= (1 << ce_stage(ce));
-		pos++;
-	}
-	if ((stages & seen) != stages)
-		return error(_("path '%s' does not have all necessary versions"),
-			     name);
-	return 0;
-}
-
-static int checkout_stage(int stage, const struct cache_entry *ce, int pos,
-			  const struct checkout *state, int *nr_checkouts,
-			  int overlay_mode)
-{
-	while (pos < active_nr &&
-	       !strcmp(active_cache[pos]->name, ce->name)) {
-		if (ce_stage(active_cache[pos]) == stage)
-			return checkout_entry(active_cache[pos], state,
-					      NULL, nr_checkouts);
-		pos++;
-	}
-	if (!overlay_mode) {
-		unlink_entry(ce);
-		return 0;
-	}
-	if (stage == 2)
-		return error(_("path '%s' does not have our version"), ce->name);
-	else
-		return error(_("path '%s' does not have their version"), ce->name);
-}
-
-static int checkout_merged(int pos, const struct checkout *state, int *nr_checkouts)
-{
-	struct cache_entry *ce = active_cache[pos];
-	const char *path = ce->name;
-	mmfile_t ancestor, ours, theirs;
-	int status;
-	struct object_id oid;
-	mmbuffer_t result_buf;
-	struct object_id threeway[3];
-	unsigned mode = 0;
-	struct ll_merge_options ll_opts;
-	int renormalize = 0;
-
-	memset(threeway, 0, sizeof(threeway));
-	while (pos < active_nr) {
-		int stage;
-		stage = ce_stage(ce);
-		if (!stage || strcmp(path, ce->name))
-			break;
-		oidcpy(&threeway[stage - 1], &ce->oid);
-		if (stage == 2)
-			mode = create_ce_mode(ce->ce_mode);
-		pos++;
-		ce = active_cache[pos];
-	}
-	if (is_null_oid(&threeway[1]) || is_null_oid(&threeway[2]))
-		return error(_("path '%s' does not have necessary versions"), path);
-
-	read_mmblob(&ancestor, &threeway[0]);
-	read_mmblob(&ours, &threeway[1]);
-	read_mmblob(&theirs, &threeway[2]);
-
-	memset(&ll_opts, 0, sizeof(ll_opts));
-	git_config_get_bool("merge.renormalize", &renormalize);
-	ll_opts.renormalize = renormalize;
-	status = ll_merge(&result_buf, path, &ancestor, "base",
-			  &ours, "ours", &theirs, "theirs",
-			  state->istate, &ll_opts);
-	free(ancestor.ptr);
-	free(ours.ptr);
-	free(theirs.ptr);
-	if (status < 0 || !result_buf.ptr) {
-		free(result_buf.ptr);
-		return error(_("path '%s': cannot merge"), path);
-	}
-
-	/*
-	 * NEEDSWORK:
-	 * There is absolutely no reason to write this as a blob object
-	 * and create a phony cache entry.  This hack is primarily to get
-	 * to the write_entry() machinery that massages the contents to
-	 * work-tree format and writes out which only allows it for a
-	 * cache entry.  The code in write_entry() needs to be refactored
-	 * to allow us to feed a <buffer, size, mode> instead of a cache
-	 * entry.  Such a refactoring would help merge_recursive as well
-	 * (it also writes the merge result to the object database even
-	 * when it may contain conflicts).
-	 */
-	if (write_object_file(result_buf.ptr, result_buf.size, blob_type, &oid))
-		die(_("Unable to add merge result for '%s'"), path);
-	free(result_buf.ptr);
-	ce = make_transient_cache_entry(mode, &oid, path, 2);
-	if (!ce)
-		die(_("make_cache_entry failed for path '%s'"), path);
-	status = checkout_entry(ce, state, NULL, nr_checkouts);
-	discard_cache_entry(ce);
-	return status;
-}
-
-static void mark_ce_for_checkout_overlay(struct cache_entry *ce,
-					 char *ps_matched,
-					 const struct checkout_opts *opts)
-{
-	ce->ce_flags &= ~CE_MATCHED;
-	if (!opts->ignore_skipworktree && ce_skip_worktree(ce))
-		return;
-	if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
-		/*
-		 * "git checkout tree-ish -- path", but this entry
-		 * is in the original index but is not in tree-ish
-		 * or does not match the pathspec; it will not be
-		 * checked out to the working tree.  We will not do
-		 * anything to this entry at all.
-		 */
-		return;
-	/*
-	 * Either this entry came from the tree-ish we are
-	 * checking the paths out of, or we are checking out
-	 * of the index.
-	 *
-	 * If it comes from the tree-ish, we already know it
-	 * matches the pathspec and could just stamp
-	 * CE_MATCHED to it from update_some(). But we still
-	 * need ps_matched and read_tree_recursive (and
-	 * eventually tree_entry_interesting) cannot fill
-	 * ps_matched yet. Once it can, we can avoid calling
-	 * match_pathspec() for _all_ entries when
-	 * opts->source_tree != NULL.
-	 */
-	if (ce_path_match(&the_index, ce, &opts->pathspec, ps_matched))
-		ce->ce_flags |= CE_MATCHED;
-}
-
-static void mark_ce_for_checkout_no_overlay(struct cache_entry *ce,
-					    char *ps_matched,
-					    const struct checkout_opts *opts)
-{
-	ce->ce_flags &= ~CE_MATCHED;
-	if (!opts->ignore_skipworktree && ce_skip_worktree(ce))
-		return;
-	if (ce_path_match(&the_index, ce, &opts->pathspec, ps_matched)) {
-		ce->ce_flags |= CE_MATCHED;
-		if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
-			/*
-			 * In overlay mode, but the path is not in
-			 * tree-ish, which means we should remove it
-			 * from the index and the working tree.
-			 */
-			ce->ce_flags |= CE_REMOVE | CE_WT_REMOVE;
-	}
-}
-
-static int checkout_worktree(const struct checkout_opts *opts,
-			     const struct branch_info *info)
-{
-	struct checkout state = CHECKOUT_INIT;
-	int nr_checkouts = 0, nr_unmerged = 0;
-	int errs = 0;
-	int pos;
-
-	state.force = 1;
-	state.refresh_cache = 1;
-	state.istate = &the_index;
-
-	init_checkout_metadata(&state.meta, info->refname,
-			       info->commit ? &info->commit->object.oid : &info->oid,
-			       NULL);
-
-	enable_delayed_checkout(&state);
-	for (pos = 0; pos < active_nr; pos++) {
-		struct cache_entry *ce = active_cache[pos];
-		if (ce->ce_flags & CE_MATCHED) {
-			if (!ce_stage(ce)) {
-				errs |= checkout_entry(ce, &state,
-						       NULL, &nr_checkouts);
-				continue;
-			}
-			if (opts->writeout_stage)
-				errs |= checkout_stage(opts->writeout_stage,
-						       ce, pos,
-						       &state,
-						       &nr_checkouts, opts->overlay_mode);
-			else if (opts->merge)
-				errs |= checkout_merged(pos, &state,
-							&nr_unmerged);
-			pos = skip_same_name(ce, pos) - 1;
-		}
-	}
-	remove_marked_cache_entries(&the_index, 1);
-	remove_scheduled_dirs();
-	errs |= finish_delayed_checkout(&state, &nr_checkouts);
-
-	if (opts->count_checkout_paths) {
-		if (nr_unmerged)
-			fprintf_ln(stderr, Q_("Recreated %d merge conflict",
-					      "Recreated %d merge conflicts",
-					      nr_unmerged),
-				   nr_unmerged);
-		if (opts->source_tree)
-			fprintf_ln(stderr, Q_("Updated %d path from %s",
-					      "Updated %d paths from %s",
-					      nr_checkouts),
-				   nr_checkouts,
-				   find_unique_abbrev(&opts->source_tree->object.oid,
-						      DEFAULT_ABBREV));
-		else if (!nr_unmerged || nr_checkouts)
-			fprintf_ln(stderr, Q_("Updated %d path from the index",
-					      "Updated %d paths from the index",
-					      nr_checkouts),
-				   nr_checkouts);
-	}
-
-	return errs;
-}
-
-static int checkout_paths(const struct checkout_opts *opts,
-			  const struct branch_info *new_branch_info)
-{
-	int pos;
-	static char *ps_matched;
-	struct object_id rev;
-	struct commit *head;
-	int errs = 0;
-	struct lock_file lock_file = LOCK_INIT;
-	int checkout_index;
-
-	trace2_cmd_mode(opts->patch_mode ? "patch" : "path");
-
-	if (opts->track != BRANCH_TRACK_UNSPECIFIED)
-		die(_("'%s' cannot be used with updating paths"), "--track");
-
-	if (opts->new_branch_log)
-		die(_("'%s' cannot be used with updating paths"), "-l");
-
-	if (opts->ignore_unmerged && opts->patch_mode)
-		die(_("'%s' cannot be used with updating paths"),
-		    opts->ignore_unmerged_opt);
-
-	if (opts->force_detach)
-		die(_("'%s' cannot be used with updating paths"), "--detach");
-
-	if (opts->merge && opts->patch_mode)
-		die(_("'%s' cannot be used with %s"), "--merge", "--patch");
-
-	if (opts->ignore_unmerged && opts->merge)
-		die(_("'%s' cannot be used with %s"),
-		    opts->ignore_unmerged_opt, "-m");
-
-	if (opts->new_branch)
-		die(_("Cannot update paths and switch to branch '%s' at the same time."),
-		    opts->new_branch);
-
-	if (!opts->checkout_worktree && !opts->checkout_index)
-		die(_("neither '%s' or '%s' is specified"),
-		    "--staged", "--worktree");
-
-	if (!opts->checkout_worktree && !opts->from_treeish)
-		die(_("'%s' must be used when '%s' is not specified"),
-		    "--worktree", "--source");
-
-	if (opts->checkout_index && !opts->checkout_worktree &&
-	    opts->writeout_stage)
-		die(_("'%s' or '%s' cannot be used with %s"),
-		    "--ours", "--theirs", "--staged");
-
-	if (opts->checkout_index && !opts->checkout_worktree &&
-	    opts->merge)
-		die(_("'%s' or '%s' cannot be used with %s"),
-		    "--merge", "--conflict", "--staged");
-
-	if (opts->patch_mode) {
-		const char *patch_mode;
-
-		if (opts->checkout_index && opts->checkout_worktree)
-			patch_mode = "--patch=checkout";
-		else if (opts->checkout_index && !opts->checkout_worktree)
-			patch_mode = "--patch=reset";
-		else if (!opts->checkout_index && opts->checkout_worktree)
-			patch_mode = "--patch=worktree";
-		else
-			BUG("either flag must have been set, worktree=%d, index=%d",
-			    opts->checkout_worktree, opts->checkout_index);
-		return run_add_interactive(new_branch_info->name, patch_mode, &opts->pathspec);
-	}
-
-	repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
-	if (read_cache_preload(&opts->pathspec) < 0)
-		return error(_("index file corrupt"));
-
-	if (opts->source_tree)
-		read_tree_some(opts->source_tree, &opts->pathspec);
-
-	ps_matched = xcalloc(opts->pathspec.nr, 1);
-
-	/*
-	 * Make sure all pathspecs participated in locating the paths
-	 * to be checked out.
-	 */
-	for (pos = 0; pos < active_nr; pos++)
-		if (opts->overlay_mode)
-			mark_ce_for_checkout_overlay(active_cache[pos],
-						     ps_matched,
-						     opts);
-		else
-			mark_ce_for_checkout_no_overlay(active_cache[pos],
-							ps_matched,
-							opts);
-
-	if (report_path_error(ps_matched, &opts->pathspec)) {
-		free(ps_matched);
-		return 1;
-	}
-	free(ps_matched);
-
-	/* "checkout -m path" to recreate conflicted state */
-	if (opts->merge)
-		unmerge_marked_index(&the_index);
-
-	/* Any unmerged paths? */
-	for (pos = 0; pos < active_nr; pos++) {
-		const struct cache_entry *ce = active_cache[pos];
-		if (ce->ce_flags & CE_MATCHED) {
-			if (!ce_stage(ce))
-				continue;
-			if (opts->ignore_unmerged) {
-				if (!opts->quiet)
-					warning(_("path '%s' is unmerged"), ce->name);
-			} else if (opts->writeout_stage) {
-				errs |= check_stage(opts->writeout_stage, ce, pos, opts->overlay_mode);
-			} else if (opts->merge) {
-				errs |= check_stages((1<<2) | (1<<3), ce, pos);
-			} else {
-				errs = 1;
-				error(_("path '%s' is unmerged"), ce->name);
-			}
-			pos = skip_same_name(ce, pos) - 1;
-		}
-	}
-	if (errs)
-		return 1;
-
-	/* Now we are committed to check them out */
-	if (opts->checkout_worktree)
-		errs |= checkout_worktree(opts, new_branch_info);
-	else
-		remove_marked_cache_entries(&the_index, 1);
-
-	/*
-	 * Allow updating the index when checking out from the index.
-	 * This is to save new stat info.
-	 */
-	if (opts->checkout_worktree && !opts->checkout_index && !opts->source_tree)
-		checkout_index = 1;
-	else
-		checkout_index = opts->checkout_index;
-
-	if (checkout_index) {
-		if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
-			die(_("unable to write new index file"));
-	} else {
-		/*
-		 * NEEDSWORK: if --worktree is not specified, we
-		 * should save stat info of checked out files in the
-		 * index to avoid the next (potentially costly)
-		 * refresh. But it's a bit tricker to do...
-		 */
-		rollback_lock_file(&lock_file);
-	}
-
-	read_ref_full("HEAD", 0, &rev, NULL);
-	head = lookup_commit_reference_gently(the_repository, &rev, 1);
-
-	errs |= post_checkout_hook(head, head, 0);
-	return errs;
-}
-
-static void show_local_changes(struct object *head,
-			       const struct diff_options *opts)
-{
-	struct rev_info rev;
-	/* I think we want full paths, even if we're in a subdirectory. */
-	repo_init_revisions(the_repository, &rev, NULL);
-	rev.diffopt.flags = opts->flags;
-	rev.diffopt.output_format |= DIFF_FORMAT_NAME_STATUS;
-	diff_setup_done(&rev.diffopt);
-	add_pending_object(&rev, head, NULL);
-	run_diff_index(&rev, 0);
-}
-
-static void describe_detached_head(const char *msg, struct commit *commit)
-{
-	struct strbuf sb = STRBUF_INIT;
-
-	if (!parse_commit(commit))
-		pp_commit_easy(CMIT_FMT_ONELINE, commit, &sb);
-	if (print_sha1_ellipsis()) {
-		fprintf(stderr, "%s %s... %s\n", msg,
-			find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV), sb.buf);
-	} else {
-		fprintf(stderr, "%s %s %s\n", msg,
-			find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV), sb.buf);
-	}
-	strbuf_release(&sb);
-}
-
-static int reset_tree(struct tree *tree, const struct checkout_opts *o,
-		      int worktree, int *writeout_error,
-		      struct branch_info *info)
-{
-	struct unpack_trees_options opts;
-	struct tree_desc tree_desc;
-
-	memset(&opts, 0, sizeof(opts));
-	opts.head_idx = -1;
-	opts.update = worktree;
-	opts.skip_unmerged = !worktree;
-	opts.reset = 1;
-	opts.merge = 1;
-	opts.fn = oneway_merge;
-	opts.verbose_update = o->show_progress;
-	opts.src_index = &the_index;
-	opts.dst_index = &the_index;
-	init_checkout_metadata(&opts.meta, info->refname,
-			       info->commit ? &info->commit->object.oid : &null_oid,
-			       NULL);
-	parse_tree(tree);
-	init_tree_desc(&tree_desc, tree->buffer, tree->size);
-	switch (unpack_trees(1, &tree_desc, &opts)) {
-	case -2:
-		*writeout_error = 1;
-		/*
-		 * We return 0 nevertheless, as the index is all right
-		 * and more importantly we have made best efforts to
-		 * update paths in the work tree, and we cannot revert
-		 * them.
-		 */
-		/* fallthrough */
-	case 0:
-		return 0;
-	default:
-		return 128;
-	}
-}
-
-static void setup_branch_path(struct branch_info *branch)
-{
-	struct strbuf buf = STRBUF_INIT;
-
-	/*
-	 * If this is a ref, resolve it; otherwise, look up the OID for our
-	 * expression.  Failure here is okay.
-	 */
-	if (!dwim_ref(branch->name, strlen(branch->name), &branch->oid, &branch->refname, 0))
-		repo_get_oid_committish(the_repository, branch->name, &branch->oid);
-
-	strbuf_branchname(&buf, branch->name, INTERPRET_BRANCH_LOCAL);
-	if (strcmp(buf.buf, branch->name))
-		branch->name = xstrdup(buf.buf);
-	strbuf_splice(&buf, 0, 0, "refs/heads/", 11);
-	branch->path = strbuf_detach(&buf, NULL);
-}
-
-static int merge_working_tree(const struct checkout_opts *opts,
-			      struct branch_info *old_branch_info,
-			      struct branch_info *new_branch_info,
-			      int *writeout_error)
-{
-	int ret;
-	struct lock_file lock_file = LOCK_INIT;
-	struct tree *new_tree;
-
-	hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
-	if (read_cache_preload(NULL) < 0)
-		return error(_("index file corrupt"));
-
-	resolve_undo_clear();
-	if (opts->new_orphan_branch && opts->orphan_from_empty_tree) {
-		if (new_branch_info->commit)
-			BUG("'switch --orphan' should never accept a commit as starting point");
-		new_tree = parse_tree_indirect(the_hash_algo->empty_tree);
-	} else
-		new_tree = get_commit_tree(new_branch_info->commit);
-	if (opts->discard_changes) {
-		ret = reset_tree(new_tree, opts, 1, writeout_error, new_branch_info);
-		if (ret)
-			return ret;
-	} else {
-		struct tree_desc trees[2];
-		struct tree *tree;
-		struct unpack_trees_options topts;
-
-		memset(&topts, 0, sizeof(topts));
-		topts.head_idx = -1;
-		topts.src_index = &the_index;
-		topts.dst_index = &the_index;
-
-		setup_unpack_trees_porcelain(&topts, "checkout");
-
-		refresh_cache(REFRESH_QUIET);
-
-		if (unmerged_cache()) {
-			error(_("you need to resolve your current index first"));
-			return 1;
-		}
-
-		/* 2-way merge to the new branch */
-		topts.initial_checkout = is_cache_unborn();
-		topts.update = 1;
-		topts.merge = 1;
-		topts.quiet = opts->merge && old_branch_info->commit;
-		topts.verbose_update = opts->show_progress;
-		topts.fn = twoway_merge;
-		init_checkout_metadata(&topts.meta, new_branch_info->refname,
-				       new_branch_info->commit ?
-				       &new_branch_info->commit->object.oid :
-				       &new_branch_info->oid, NULL);
-		if (opts->overwrite_ignore) {
-			topts.dir = xcalloc(1, sizeof(*topts.dir));
-			topts.dir->flags |= DIR_SHOW_IGNORED;
-			setup_standard_excludes(topts.dir);
-		}
-		tree = parse_tree_indirect(old_branch_info->commit ?
-					   &old_branch_info->commit->object.oid :
-					   the_hash_algo->empty_tree);
-		init_tree_desc(&trees[0], tree->buffer, tree->size);
-		parse_tree(new_tree);
-		tree = new_tree;
-		init_tree_desc(&trees[1], tree->buffer, tree->size);
-
-		ret = unpack_trees(2, trees, &topts);
-		clear_unpack_trees_porcelain(&topts);
-		if (ret == -1) {
-			/*
-			 * Unpack couldn't do a trivial merge; either
-			 * give up or do a real merge, depending on
-			 * whether the merge flag was used.
-			 */
-			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;
-
-			/*
-			 * Without old_branch_info->commit, the below is the same as
-			 * the two-tree unpack we already tried and failed.
-			 */
-			if (!old_branch_info->commit)
-				return 1;
-			old_tree = get_commit_tree(old_branch_info->commit);
-
-			if (repo_index_has_changes(the_repository, old_tree, &sb))
-				die(_("cannot continue with staged changes in "
-				      "the following files:\n%s"), sb.buf);
-			strbuf_release(&sb);
-
-			/* Do more real merge */
-
-			/*
-			 * We update the index fully, then write the
-			 * tree from the index, then merge the new
-			 * branch with the current tree, with the old
-			 * branch as the base. Then we reset the index
-			 * (but not the working tree) to the new
-			 * branch, leaving the working tree as the
-			 * merged version, but skipping unmerged
-			 * entries in the index.
-			 */
-
-			add_files_to_cache(NULL, NULL, 0);
-			init_merge_options(&o, the_repository);
-			o.verbosity = 0;
-			work = write_in_core_index_as_tree(the_repository);
-
-			ret = reset_tree(new_tree,
-					 opts, 1,
-					 writeout_error, new_branch_info);
-			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);
-			if (ret < 0)
-				exit(128);
-			ret = reset_tree(new_tree,
-					 opts, 0,
-					 writeout_error, new_branch_info);
-			strbuf_release(&o.obuf);
-			strbuf_release(&old_commit_shortname);
-			if (ret)
-				return ret;
-		}
-	}
-
-	if (!active_cache_tree)
-		active_cache_tree = cache_tree();
-
-	if (!cache_tree_fully_valid(active_cache_tree))
-		cache_tree_update(&the_index, WRITE_TREE_SILENT | WRITE_TREE_REPAIR);
-
-	if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
-		die(_("unable to write new index file"));
-
-	if (!opts->discard_changes && !opts->quiet && new_branch_info->commit)
-		show_local_changes(&new_branch_info->commit->object, &opts->diff_options);
-
-	return 0;
-}
-
-static void report_tracking(struct branch_info *new_branch_info)
-{
-	struct strbuf sb = STRBUF_INIT;
-	struct branch *branch = branch_get(new_branch_info->name);
-
-	if (!format_tracking_info(branch, &sb, AHEAD_BEHIND_FULL))
-		return;
-	fputs(sb.buf, stdout);
-	strbuf_release(&sb);
-}
-
-static void update_refs_for_switch(const struct checkout_opts *opts,
-				   struct branch_info *old_branch_info,
-				   struct branch_info *new_branch_info)
-{
-	struct strbuf msg = STRBUF_INIT;
-	const char *old_desc, *reflog_msg;
-	if (opts->new_branch) {
-		if (opts->new_orphan_branch) {
-			char *refname;
-
-			refname = mkpathdup("refs/heads/%s", opts->new_orphan_branch);
-			if (opts->new_branch_log &&
-			    !should_autocreate_reflog(refname)) {
-				int ret;
-				struct strbuf err = STRBUF_INIT;
-
-				ret = safe_create_reflog(refname, 1, &err);
-				if (ret) {
-					fprintf(stderr, _("Can not do reflog for '%s': %s\n"),
-						opts->new_orphan_branch, err.buf);
-					strbuf_release(&err);
-					free(refname);
-					return;
-				}
-				strbuf_release(&err);
-			}
-			free(refname);
-		}
-		else
-			create_branch(the_repository,
-				      opts->new_branch, new_branch_info->name,
-				      opts->new_branch_force ? 1 : 0,
-				      opts->new_branch_force ? 1 : 0,
-				      opts->new_branch_log,
-				      opts->quiet,
-				      opts->track);
-		new_branch_info->name = opts->new_branch;
-		setup_branch_path(new_branch_info);
-	}
-
-	old_desc = old_branch_info->name;
-	if (!old_desc && old_branch_info->commit)
-		old_desc = oid_to_hex(&old_branch_info->commit->object.oid);
-
-	reflog_msg = getenv("GIT_REFLOG_ACTION");
-	if (!reflog_msg)
-		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);
-
-	if (!strcmp(new_branch_info->name, "HEAD") && !new_branch_info->path && !opts->force_detach) {
-		/* Nothing to do. */
-	} else if (opts->force_detach || !new_branch_info->path) {	/* No longer on any branch. */
-		update_ref(msg.buf, "HEAD", &new_branch_info->commit->object.oid, NULL,
-			   REF_NO_DEREF, UPDATE_REFS_DIE_ON_ERR);
-		if (!opts->quiet) {
-			if (old_branch_info->path &&
-			    advice_detached_head && !opts->force_detach)
-				detach_advice(new_branch_info->name);
-			describe_detached_head(_("HEAD is now at"), new_branch_info->commit);
-		}
-	} else if (new_branch_info->path) {	/* Switch branches. */
-		if (create_symref("HEAD", new_branch_info->path, msg.buf) < 0)
-			die(_("unable to update HEAD"));
-		if (!opts->quiet) {
-			if (old_branch_info->path && !strcmp(new_branch_info->path, old_branch_info->path)) {
-				if (opts->new_branch_force)
-					fprintf(stderr, _("Reset branch '%s'\n"),
-						new_branch_info->name);
-				else
-					fprintf(stderr, _("Already on '%s'\n"),
-						new_branch_info->name);
-			} else if (opts->new_branch) {
-				if (opts->branch_exists)
-					fprintf(stderr, _("Switched to and reset branch '%s'\n"), new_branch_info->name);
-				else
-					fprintf(stderr, _("Switched to a new branch '%s'\n"), new_branch_info->name);
-			} else {
-				fprintf(stderr, _("Switched to branch '%s'\n"),
-					new_branch_info->name);
-			}
-		}
-		if (old_branch_info->path && old_branch_info->name) {
-			if (!ref_exists(old_branch_info->path) && reflog_exists(old_branch_info->path))
-				delete_reflog(old_branch_info->path);
-		}
-	}
-	remove_branch_state(the_repository, !opts->quiet);
-	strbuf_release(&msg);
-	if (!opts->quiet &&
-	    (new_branch_info->path || (!opts->force_detach && !strcmp(new_branch_info->name, "HEAD"))))
-		report_tracking(new_branch_info);
-}
-
-static int add_pending_uninteresting_ref(const char *refname,
-					 const struct object_id *oid,
-					 int flags, void *cb_data)
-{
-	add_pending_oid(cb_data, refname, oid, UNINTERESTING);
-	return 0;
-}
-
-static void describe_one_orphan(struct strbuf *sb, struct commit *commit)
-{
-	strbuf_addstr(sb, "  ");
-	strbuf_add_unique_abbrev(sb, &commit->object.oid, DEFAULT_ABBREV);
-	strbuf_addch(sb, ' ');
-	if (!parse_commit(commit))
-		pp_commit_easy(CMIT_FMT_ONELINE, commit, sb);
-	strbuf_addch(sb, '\n');
-}
-
-#define ORPHAN_CUTOFF 4
-static void suggest_reattach(struct commit *commit, struct rev_info *revs)
-{
-	struct commit *c, *last = NULL;
-	struct strbuf sb = STRBUF_INIT;
-	int lost = 0;
-	while ((c = get_revision(revs)) != NULL) {
-		if (lost < ORPHAN_CUTOFF)
-			describe_one_orphan(&sb, c);
-		last = c;
-		lost++;
-	}
-	if (ORPHAN_CUTOFF < lost) {
-		int more = lost - ORPHAN_CUTOFF;
-		if (more == 1)
-			describe_one_orphan(&sb, last);
-		else
-			strbuf_addf(&sb, _(" ... and %d more.\n"), more);
-	}
-
-	fprintf(stderr,
-		Q_(
-		/* The singular version */
-		"Warning: you are leaving %d commit behind, "
-		"not connected to\n"
-		"any of your branches:\n\n"
-		"%s\n",
-		/* The plural version */
-		"Warning: you are leaving %d commits behind, "
-		"not connected to\n"
-		"any of your branches:\n\n"
-		"%s\n",
-		/* Give ngettext() the count */
-		lost),
-		lost,
-		sb.buf);
-	strbuf_release(&sb);
-
-	if (advice_detached_head)
-		fprintf(stderr,
-			Q_(
-			/* The singular version */
-			"If you want to keep it by creating a new branch, "
-			"this may be a good time\nto do so with:\n\n"
-			" git branch <new-branch-name> %s\n\n",
-			/* The plural version */
-			"If you want to keep them by creating a new branch, "
-			"this may be a good time\nto do so with:\n\n"
-			" git branch <new-branch-name> %s\n\n",
-			/* Give ngettext() the count */
-			lost),
-			find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV));
-}
-
-/*
- * We are about to leave commit that was at the tip of a detached
- * HEAD.  If it is not reachable from any ref, this is the last chance
- * for the user to do so without resorting to reflog.
- */
-static void orphaned_commit_warning(struct commit *old_commit, struct commit *new_commit)
-{
-	struct rev_info revs;
-	struct object *object = &old_commit->object;
-
-	repo_init_revisions(the_repository, &revs, NULL);
-	setup_revisions(0, NULL, &revs, NULL);
-
-	object->flags &= ~UNINTERESTING;
-	add_pending_object(&revs, object, oid_to_hex(&object->oid));
-
-	for_each_ref(add_pending_uninteresting_ref, &revs);
-	if (new_commit)
-		add_pending_oid(&revs, "HEAD",
-				&new_commit->object.oid,
-				UNINTERESTING);
-
-	if (prepare_revision_walk(&revs))
-		die(_("internal error in revision walk"));
-	if (!(old_commit->object.flags & UNINTERESTING))
-		suggest_reattach(old_commit, &revs);
-	else
-		describe_detached_head(_("Previous HEAD position was"), old_commit);
-
-	/* Clean up objects used, as they will be reused. */
-	clear_commit_marks_all(ALL_REV_FLAGS);
-}
-
-static int switch_branches(const struct checkout_opts *opts,
-			   struct branch_info *new_branch_info)
-{
-	int ret = 0;
-	struct branch_info old_branch_info;
-	void *path_to_free;
-	struct object_id rev;
-	int flag, writeout_error = 0;
-	int do_merge = 1;
-
-	trace2_cmd_mode("branch");
-
-	memset(&old_branch_info, 0, sizeof(old_branch_info));
-	old_branch_info.path = path_to_free = resolve_refdup("HEAD", 0, &rev, &flag);
-	if (old_branch_info.path)
-		old_branch_info.commit = lookup_commit_reference_gently(the_repository, &rev, 1);
-	if (!(flag & REF_ISSYMREF))
-		old_branch_info.path = NULL;
-
-	if (old_branch_info.path)
-		skip_prefix(old_branch_info.path, "refs/heads/", &old_branch_info.name);
-
-	if (opts->new_orphan_branch && opts->orphan_from_empty_tree) {
-		if (new_branch_info->name)
-			BUG("'switch --orphan' should never accept a commit as starting point");
-		new_branch_info->commit = NULL;
-		new_branch_info->name = "(empty)";
-		do_merge = 1;
-	}
-
-	if (!new_branch_info->name) {
-		new_branch_info->name = "HEAD";
-		new_branch_info->commit = old_branch_info.commit;
-		if (!new_branch_info->commit)
-			die(_("You are on a branch yet to be born"));
-		parse_commit_or_die(new_branch_info->commit);
-
-		if (opts->only_merge_on_switching_branches)
-			do_merge = 0;
-	}
-
-	if (do_merge) {
-		ret = merge_working_tree(opts, &old_branch_info, new_branch_info, &writeout_error);
-		if (ret) {
-			free(path_to_free);
-			return ret;
-		}
-	}
-
-	if (!opts->quiet && !old_branch_info.path && old_branch_info.commit && new_branch_info->commit != old_branch_info.commit)
-		orphaned_commit_warning(old_branch_info.commit, new_branch_info->commit);
-
-	update_refs_for_switch(opts, &old_branch_info, new_branch_info);
-
-	ret = post_checkout_hook(old_branch_info.commit, new_branch_info->commit, 1);
-	free(path_to_free);
-	return ret || writeout_error;
-}
-
-static int git_checkout_config(const char *var, const char *value, void *cb)
-{
-	if (!strcmp(var, "diff.ignoresubmodules")) {
-		struct checkout_opts *opts = cb;
-		handle_ignore_submodules_arg(&opts->diff_options, value);
-		return 0;
-	}
-
-	if (starts_with(var, "submodule."))
-		return git_default_submodule_config(var, value, NULL);
-
-	return git_xmerge_config(var, value, NULL);
-}
-
-static void setup_new_branch_info_and_source_tree(
-	struct branch_info *new_branch_info,
-	struct checkout_opts *opts,
-	struct object_id *rev,
-	const char *arg)
-{
-	struct tree **source_tree = &opts->source_tree;
-	struct object_id branch_rev;
-
-	new_branch_info->name = arg;
-	setup_branch_path(new_branch_info);
-
-	if (!check_refname_format(new_branch_info->path, 0) &&
-	    !read_ref(new_branch_info->path, &branch_rev))
-		oidcpy(rev, &branch_rev);
-	else {
-		free((char *)new_branch_info->path);
-		new_branch_info->path = NULL; /* not an existing branch */
-	}
-
-	new_branch_info->commit = lookup_commit_reference_gently(the_repository, rev, 1);
-	if (!new_branch_info->commit) {
-		/* not a commit */
-		*source_tree = parse_tree_indirect(rev);
-	} else {
-		parse_commit_or_die(new_branch_info->commit);
-		*source_tree = get_commit_tree(new_branch_info->commit);
-	}
-}
-
-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)
-{
-	const char **new_branch = &opts->new_branch;
-	int argcount = 0;
-	const char *arg;
-	int dash_dash_pos;
-	int has_dash_dash = 0;
-	int i;
-
-	/*
-	 * case 1: git checkout <ref> -- [<paths>]
-	 *
-	 *   <ref> must be a valid tree, everything after the '--' must be
-	 *   a path.
-	 *
-	 * case 2: git checkout -- [<paths>]
-	 *
-	 *   everything after the '--' must be paths.
-	 *
-	 * case 3: git checkout <something> [--]
-	 *
-	 *   (a) If <something> is a commit, that is to
-	 *       switch to the branch or detach HEAD at it.  As a special case,
-	 *       if <something> is A...B (missing A or B means HEAD but you can
-	 *       omit at most one side), and if there is a unique merge base
-	 *       between A and B, A...B names that merge base.
-	 *
-	 *   (b) If <something> is _not_ a commit, either "--" is present
-	 *       or <something> is not a path, no -t or -b was given, and
-	 *       and there is a tracking branch whose name is <something>
-	 *       in one and only one remote (or if the branch exists on the
-	 *       remote named in checkout.defaultRemote), then this is a
-	 *       short-hand to fork local <something> from that
-	 *       remote-tracking branch.
-	 *
-	 *   (c) Otherwise, if "--" is present, treat it like case (1).
-	 *
-	 *   (d) Otherwise :
-	 *       - if it's a reference, treat it like case (1)
-	 *       - else if it's a path, treat it like case (2)
-	 *       - else: fail.
-	 *
-	 * case 4: git checkout <something> <paths>
-	 *
-	 *   The first argument must not be ambiguous.
-	 *   - If it's *only* a reference, treat it like case (1).
-	 *   - If it's only a path, treat it like case (2).
-	 *   - else: fail.
-	 *
-	 */
-	if (!argc)
-		return 0;
-
-	if (!opts->accept_pathspec) {
-		if (argc > 1)
-			die(_("only one reference expected"));
-		has_dash_dash = 1; /* helps disambiguate */
-	}
-
-	arg = argv[0];
-	dash_dash_pos = -1;
-	for (i = 0; i < argc; i++) {
-		if (opts->accept_pathspec && !strcmp(argv[i], "--")) {
-			dash_dash_pos = i;
-			break;
-		}
-	}
-	if (dash_dash_pos == 0)
-		return 1; /* case (2) */
-	else if (dash_dash_pos == 1)
-		has_dash_dash = 1; /* case (3) or (1) */
-	else if (dash_dash_pos >= 2)
-		die(_("only one reference expected, %d given."), dash_dash_pos);
-	opts->count_checkout_paths = !opts->quiet && !has_dash_dash;
-
-	if (!strcmp(arg, "-"))
-		arg = "@{-1}";
-
-	if (get_oid_mb(arg, rev)) {
-		/*
-		 * Either case (3) or (4), with <something> not being
-		 * a commit, or an attempt to use case (1) with an
-		 * invalid ref.
-		 *
-		 * It's likely an error, but we need to find out if
-		 * we should auto-create the branch, case (3).(b).
-		 */
-		int recover_with_dwim = dwim_new_local_branch_ok;
-
-		int could_be_checkout_paths = !has_dash_dash &&
-			check_filename(opts->prefix, arg);
-
-		if (!has_dash_dash && !no_wildcard(arg))
-			recover_with_dwim = 0;
-
-		/*
-		 * Accept "git checkout foo", "git checkout foo --"
-		 * and "git switch foo" as candidates for dwim.
-		 */
-		if (!(argc == 1 && !has_dash_dash) &&
-		    !(argc == 2 && has_dash_dash) &&
-		    opts->accept_pathspec)
-			recover_with_dwim = 0;
-
-		if (recover_with_dwim) {
-			const char *remote = parse_remote_branch(arg, rev,
-								 could_be_checkout_paths);
-			if (remote) {
-				*new_branch = arg;
-				arg = remote;
-				/* DWIMmed to create local branch, case (3).(b) */
-			} else {
-				recover_with_dwim = 0;
-			}
-		}
-
-		if (!recover_with_dwim) {
-			if (has_dash_dash)
-				die(_("invalid reference: %s"), arg);
-			return argcount;
-		}
-	}
-
-	/* we can't end up being in (2) anymore, eat the argument */
-	argcount++;
-	argv++;
-	argc--;
-
-	setup_new_branch_info_and_source_tree(new_branch_info, opts, rev, arg);
-
-	if (!opts->source_tree)                   /* case (1): want a tree */
-		die(_("reference is not a tree: %s"), arg);
-
-	if (!has_dash_dash) {	/* case (3).(d) -> (1) */
-		/*
-		 * Do not complain the most common case
-		 *	git checkout branch
-		 * even if there happen to be a file called 'branch';
-		 * it would be extremely annoying.
-		 */
-		if (argc)
-			verify_non_filename(opts->prefix, arg);
-	} else if (opts->accept_pathspec) {
-		argcount++;
-		argv++;
-		argc--;
-	}
-
-	return argcount;
-}
-
-static int switch_unborn_to_new_branch(const struct checkout_opts *opts)
-{
-	int status;
-	struct strbuf branch_ref = STRBUF_INIT;
-
-	trace2_cmd_mode("unborn");
-
-	if (!opts->new_branch)
-		die(_("You are on a branch yet to be born"));
-	strbuf_addf(&branch_ref, "refs/heads/%s", opts->new_branch);
-	status = create_symref("HEAD", branch_ref.buf, "checkout -b");
-	strbuf_release(&branch_ref);
-	if (!opts->quiet)
-		fprintf(stderr, _("Switched to a new branch '%s'\n"),
-			opts->new_branch);
-	return status;
-}
-
-static void die_expecting_a_branch(const struct branch_info *branch_info)
-{
-	struct object_id oid;
-	char *to_free;
-
-	if (dwim_ref(branch_info->name, strlen(branch_info->name), &oid, &to_free, 0) == 1) {
-		const char *ref = to_free;
-
-		if (skip_prefix(ref, "refs/tags/", &ref))
-			die(_("a branch is expected, got tag '%s'"), ref);
-		if (skip_prefix(ref, "refs/remotes/", &ref))
-			die(_("a branch is expected, got remote branch '%s'"), ref);
-		die(_("a branch is expected, got '%s'"), ref);
-	}
-	if (branch_info->commit)
-		die(_("a branch is expected, got commit '%s'"), branch_info->name);
-	/*
-	 * This case should never happen because we already die() on
-	 * non-commit, but just in case.
-	 */
-	die(_("a branch is expected, got '%s'"), branch_info->name);
-}
-
-static void die_if_some_operation_in_progress(void)
-{
-	struct wt_status_state state;
-
-	memset(&state, 0, sizeof(state));
-	wt_status_get_state(the_repository, &state, 0);
-
-	if (state.merge_in_progress)
-		die(_("cannot switch branch while merging\n"
-		      "Consider \"git merge --quit\" "
-		      "or \"git worktree add\"."));
-	if (state.am_in_progress)
-		die(_("cannot switch branch in the middle of an am session\n"
-		      "Consider \"git am --quit\" "
-		      "or \"git worktree add\"."));
-	if (state.rebase_interactive_in_progress || state.rebase_in_progress)
-		die(_("cannot switch branch while rebasing\n"
-		      "Consider \"git rebase --quit\" "
-		      "or \"git worktree add\"."));
-	if (state.cherry_pick_in_progress)
-		die(_("cannot switch branch while cherry-picking\n"
-		      "Consider \"git cherry-pick --quit\" "
-		      "or \"git worktree add\"."));
-	if (state.revert_in_progress)
-		die(_("cannot switch branch while reverting\n"
-		      "Consider \"git revert --quit\" "
-		      "or \"git worktree add\"."));
-	if (state.bisect_in_progress)
-		warning(_("you are switching branch while bisecting"));
-}
-
-static int checkout_branch(struct checkout_opts *opts,
-			   struct branch_info *new_branch_info)
-{
-	if (opts->pathspec.nr)
-		die(_("paths cannot be used with switching branches"));
-
-	if (opts->patch_mode)
-		die(_("'%s' cannot be used with switching branches"),
-		    "--patch");
-
-	if (opts->overlay_mode != -1)
-		die(_("'%s' cannot be used with switching branches"),
-		    "--[no]-overlay");
-
-	if (opts->writeout_stage)
-		die(_("'%s' cannot be used with switching branches"),
-		    "--ours/--theirs");
-
-	if (opts->force && opts->merge)
-		die(_("'%s' cannot be used with '%s'"), "-f", "-m");
-
-	if (opts->discard_changes && opts->merge)
-		die(_("'%s' cannot be used with '%s'"), "--discard-changes", "--merge");
-
-	if (opts->force_detach && opts->new_branch)
-		die(_("'%s' cannot be used with '%s'"),
-		    "--detach", "-b/-B/--orphan");
-
-	if (opts->new_orphan_branch) {
-		if (opts->track != BRANCH_TRACK_UNSPECIFIED)
-			die(_("'%s' cannot be used with '%s'"), "--orphan", "-t");
-		if (opts->orphan_from_empty_tree && new_branch_info->name)
-			die(_("'%s' cannot take <start-point>"), "--orphan");
-	} else if (opts->force_detach) {
-		if (opts->track != BRANCH_TRACK_UNSPECIFIED)
-			die(_("'%s' cannot be used with '%s'"), "--detach", "-t");
-	} else if (opts->track == BRANCH_TRACK_UNSPECIFIED)
-		opts->track = git_branch_track;
-
-	if (new_branch_info->name && !new_branch_info->commit)
-		die(_("Cannot switch branch to a non-commit '%s'"),
-		    new_branch_info->name);
-
-	if (!opts->switch_branch_doing_nothing_is_ok &&
-	    !new_branch_info->name &&
-	    !opts->new_branch &&
-	    !opts->force_detach)
-		die(_("missing branch or commit argument"));
-
-	if (!opts->implicit_detach &&
-	    !opts->force_detach &&
-	    !opts->new_branch &&
-	    !opts->new_branch_force &&
-	    new_branch_info->name &&
-	    !new_branch_info->path)
-		die_expecting_a_branch(new_branch_info);
-
-	if (!opts->can_switch_when_in_progress)
-		die_if_some_operation_in_progress();
-
-	if (new_branch_info->path && !opts->force_detach && !opts->new_branch &&
-	    !opts->ignore_other_worktrees) {
-		int flag;
-		char *head_ref = resolve_refdup("HEAD", 0, NULL, &flag);
-		if (head_ref &&
-		    (!(flag & REF_ISSYMREF) || strcmp(head_ref, new_branch_info->path)))
-			die_if_checked_out(new_branch_info->path, 1);
-		free(head_ref);
-	}
-
-	if (!new_branch_info->commit && opts->new_branch) {
-		struct object_id rev;
-		int flag;
-
-		if (!read_ref_full("HEAD", 0, &rev, &flag) &&
-		    (flag & REF_ISSYMREF) && is_null_oid(&rev))
-			return switch_unborn_to_new_branch(opts);
-	}
-	return switch_branches(opts, new_branch_info);
-}
-
-static struct option *add_common_options(struct checkout_opts *opts,
-					 struct option *prevopts)
-{
-	struct option options[] = {
-		OPT__QUIET(&opts->quiet, N_("suppress progress reporting")),
-		OPT_CALLBACK_F(0, "recurse-submodules", NULL,
-			    "checkout", "control recursive updating of submodules",
-			    PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater),
-		OPT_BOOL(0, "progress", &opts->show_progress, N_("force progress reporting")),
-		OPT_BOOL('m', "merge", &opts->merge, N_("perform a 3-way merge with the new branch")),
-		OPT_STRING(0, "conflict", &opts->conflict_style, N_("style"),
-			   N_("conflict style (merge or diff3)")),
-		OPT_END()
-	};
-	struct option *newopts = parse_options_concat(prevopts, options);
-	free(prevopts);
-	return newopts;
-}
-
-static struct option *add_common_switch_branch_options(
-	struct checkout_opts *opts, struct option *prevopts)
-{
-	struct option options[] = {
-		OPT_BOOL('d', "detach", &opts->force_detach, N_("detach HEAD at named commit")),
-		OPT_SET_INT('t', "track",  &opts->track, N_("set upstream info for new branch"),
-			BRANCH_TRACK_EXPLICIT),
-		OPT__FORCE(&opts->force, N_("force checkout (throw away local modifications)"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT_STRING(0, "orphan", &opts->new_orphan_branch, N_("new-branch"), N_("new unparented branch")),
-		OPT_BOOL_F(0, "overwrite-ignore", &opts->overwrite_ignore,
-			   N_("update ignored files (default)"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT_BOOL(0, "ignore-other-worktrees", &opts->ignore_other_worktrees,
-			 N_("do not check if another worktree is holding the given ref")),
-		OPT_END()
-	};
-	struct option *newopts = parse_options_concat(prevopts, options);
-	free(prevopts);
-	return newopts;
-}
-
-static struct option *add_checkout_path_options(struct checkout_opts *opts,
-						struct option *prevopts)
-{
-	struct option options[] = {
-		OPT_SET_INT_F('2', "ours", &opts->writeout_stage,
-			      N_("checkout our version for unmerged files"),
-			      2, PARSE_OPT_NONEG),
-		OPT_SET_INT_F('3', "theirs", &opts->writeout_stage,
-			      N_("checkout their version for unmerged files"),
-			      3, PARSE_OPT_NONEG),
-		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);
-	free(prevopts);
-	return newopts;
-}
-
-/* create-branch option (either b or c) */
-static char cb_option = 'b';
-
-static int checkout_main(int argc, const char **argv, const char *prefix,
-			 struct checkout_opts *opts, struct option *options,
-			 const char * const usagestr[])
-{
-	struct branch_info new_branch_info;
-	int parseopt_flags = 0;
-
-	memset(&new_branch_info, 0, sizeof(new_branch_info));
-	opts->overwrite_ignore = 1;
-	opts->prefix = prefix;
-	opts->show_progress = -1;
-
-	git_config(git_checkout_config, opts);
-
-	opts->track = BRANCH_TRACK_UNSPECIFIED;
-
-	if (!opts->accept_pathspec && !opts->accept_ref)
-		BUG("make up your mind, you need to take _something_");
-	if (opts->accept_pathspec && opts->accept_ref)
-		parseopt_flags = PARSE_OPT_KEEP_DASHDASH;
-
-	argc = parse_options(argc, argv, prefix, options,
-			     usagestr, parseopt_flags);
-
-	if (opts->show_progress < 0) {
-		if (opts->quiet)
-			opts->show_progress = 0;
-		else
-			opts->show_progress = isatty(2);
-	}
-
-	if (opts->conflict_style) {
-		opts->merge = 1; /* implied */
-		git_xmerge_config("merge.conflictstyle", opts->conflict_style, NULL);
-	}
-	if (opts->force) {
-		opts->discard_changes = 1;
-		opts->ignore_unmerged_opt = "--force";
-		opts->ignore_unmerged = 1;
-	}
-
-	if ((!!opts->new_branch + !!opts->new_branch_force + !!opts->new_orphan_branch) > 1)
-		die(_("-%c, -%c and --orphan are mutually exclusive"),
-				cb_option, toupper(cb_option));
-
-	if (opts->overlay_mode == 1 && opts->patch_mode)
-		die(_("-p and --overlay are mutually exclusive"));
-
-	if (opts->checkout_index >= 0 || opts->checkout_worktree >= 0) {
-		if (opts->checkout_index < 0)
-			opts->checkout_index = 0;
-		if (opts->checkout_worktree < 0)
-			opts->checkout_worktree = 0;
-	} else {
-		if (opts->checkout_index < 0)
-			opts->checkout_index = -opts->checkout_index - 1;
-		if (opts->checkout_worktree < 0)
-			opts->checkout_worktree = -opts->checkout_worktree - 1;
-	}
-	if (opts->checkout_index < 0 || opts->checkout_worktree < 0)
-		BUG("these flags should be non-negative by now");
-	/*
-	 * convenient shortcut: "git restore --staged [--worktree]" equals
-	 * "git restore --staged [--worktree] --source HEAD"
-	 */
-	if (!opts->from_treeish && opts->checkout_index)
-		opts->from_treeish = "HEAD";
-
-	/*
-	 * From here on, new_branch will contain the branch to be checked out,
-	 * and new_branch_force and new_orphan_branch will tell us which one of
-	 * -b/-B/-c/-C/--orphan is being used.
-	 */
-	if (opts->new_branch_force)
-		opts->new_branch = opts->new_branch_force;
-
-	if (opts->new_orphan_branch)
-		opts->new_branch = opts->new_orphan_branch;
-
-	/* --track without -c/-C/-b/-B/--orphan should DWIM */
-	if (opts->track != BRANCH_TRACK_UNSPECIFIED && !opts->new_branch) {
-		const char *argv0 = argv[0];
-		if (!argc || !strcmp(argv0, "--"))
-			die(_("--track needs a branch name"));
-		skip_prefix(argv0, "refs/", &argv0);
-		skip_prefix(argv0, "remotes/", &argv0);
-		argv0 = strchr(argv0, '/');
-		if (!argv0 || !argv0[1])
-			die(_("missing branch name; try -%c"), cb_option);
-		opts->new_branch = argv0 + 1;
-	}
-
-	/*
-	 * Extract branch name from command line arguments, so
-	 * all that is left is pathspecs.
-	 *
-	 * Handle
-	 *
-	 *  1) git checkout <tree> -- [<paths>]
-	 *  2) git checkout -- [<paths>]
-	 *  3) git checkout <something> [<paths>]
-	 *
-	 * including "last branch" syntax and DWIM-ery for names of
-	 * remote branches, erroring out for invalid or ambiguous cases.
-	 */
-	if (argc && opts->accept_ref) {
-		struct object_id rev;
-		int dwim_ok =
-			!opts->patch_mode &&
-			opts->dwim_new_local_branch &&
-			opts->track == BRANCH_TRACK_UNSPECIFIED &&
-			!opts->new_branch;
-		int n = parse_branchname_arg(argc, argv, dwim_ok,
-					     &new_branch_info, opts, &rev);
-		argv += n;
-		argc -= n;
-	} else if (!opts->accept_ref && opts->from_treeish) {
-		struct object_id rev;
-
-		if (get_oid_mb(opts->from_treeish, &rev))
-			die(_("could not resolve %s"), opts->from_treeish);
-
-		setup_new_branch_info_and_source_tree(&new_branch_info,
-						      opts, &rev,
-						      opts->from_treeish);
-
-		if (!opts->source_tree)
-			die(_("reference is not a tree: %s"), opts->from_treeish);
-	}
-
-	if (argc) {
-		parse_pathspec(&opts->pathspec, 0,
-			       opts->patch_mode ? PATHSPEC_PREFIX_ORIGIN : 0,
-			       prefix, argv);
-
-		if (!opts->pathspec.nr)
-			die(_("invalid path specification"));
-
-		/*
-		 * Try to give more helpful suggestion.
-		 * new_branch && argc > 1 will be caught later.
-		 */
-		if (opts->new_branch && argc == 1 && !new_branch_info.commit)
-			die(_("'%s' is not a commit and a branch '%s' cannot be created from it"),
-				argv[0], opts->new_branch);
-
-		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"));
-	}
-
-	opts->pathspec.recursive = 1;
-
-	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) {
-		struct strbuf buf = STRBUF_INIT;
-
-		if (opts->new_branch_force)
-			opts->branch_exists = validate_branchname(opts->new_branch, &buf);
-		else
-			opts->branch_exists =
-				validate_new_branchname(opts->new_branch, &buf, 0);
-		strbuf_release(&buf);
-	}
-
-	UNLEAK(opts);
-	if (opts->patch_mode || opts->pathspec.nr)
-		return checkout_paths(opts, &new_branch_info);
-	else
-		return checkout_branch(opts, &new_branch_info);
-}
-
-int cmd_checkout(int argc, const char **argv, const char *prefix)
-{
-	struct checkout_opts opts;
-	struct option *options;
-	struct option checkout_options[] = {
-		OPT_STRING('b', NULL, &opts.new_branch, N_("branch"),
-			   N_("create and checkout a new branch")),
-		OPT_STRING('B', NULL, &opts.new_branch_force, N_("branch"),
-			   N_("create/reset and checkout a branch")),
-		OPT_BOOL('l', NULL, &opts.new_branch_log, N_("create reflog for new branch")),
-		OPT_BOOL(0, "guess", &opts.dwim_new_local_branch,
-			 N_("second guess 'git checkout <no-such-branch>' (default)")),
-		OPT_BOOL(0, "overlay", &opts.overlay_mode, N_("use overlay mode (default)")),
-		OPT_END()
-	};
-	int ret;
-
-	memset(&opts, 0, sizeof(opts));
-	opts.dwim_new_local_branch = 1;
-	opts.switch_branch_doing_nothing_is_ok = 1;
-	opts.only_merge_on_switching_branches = 0;
-	opts.accept_ref = 1;
-	opts.accept_pathspec = 1;
-	opts.implicit_detach = 1;
-	opts.can_switch_when_in_progress = 1;
-	opts.orphan_from_empty_tree = 0;
-	opts.empty_pathspec_ok = 1;
-	opts.overlay_mode = -1;
-	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);
-	options = add_checkout_path_options(&opts, options);
-
-	ret = checkout_main(argc, argv, prefix, &opts,
-			    options, checkout_usage);
-	FREE_AND_NULL(options);
-	return ret;
-}
-
-int cmd_switch(int argc, const char **argv, const char *prefix)
-{
-	struct checkout_opts opts;
-	struct option *options = NULL;
-	struct option switch_options[] = {
-		OPT_STRING('c', "create", &opts.new_branch, N_("branch"),
-			   N_("create and switch to a new branch")),
-		OPT_STRING('C', "force-create", &opts.new_branch_force, N_("branch"),
-			   N_("create/reset and switch to a branch")),
-		OPT_BOOL(0, "guess", &opts.dwim_new_local_branch,
-			 N_("second guess 'git switch <no-such-branch>'")),
-		OPT_BOOL(0, "discard-changes", &opts.discard_changes,
-			 N_("throw away local modifications")),
-		OPT_END()
-	};
-	int ret;
-
-	memset(&opts, 0, sizeof(opts));
-	opts.dwim_new_local_branch = 1;
-	opts.accept_ref = 1;
-	opts.accept_pathspec = 0;
-	opts.switch_branch_doing_nothing_is_ok = 0;
-	opts.only_merge_on_switching_branches = 1;
-	opts.implicit_detach = 0;
-	opts.can_switch_when_in_progress = 0;
-	opts.orphan_from_empty_tree = 1;
-	opts.overlay_mode = -1;
-
-	options = parse_options_dup(switch_options);
-	options = add_common_options(&opts, options);
-	options = add_common_switch_branch_options(&opts, options);
-
-	cb_option = 'c';
-
-	ret = checkout_main(argc, argv, prefix, &opts,
-			    options, switch_branch_usage);
-	FREE_AND_NULL(options);
-	return ret;
-}
-
-int cmd_restore(int argc, const char **argv, const char *prefix)
-{
-	struct checkout_opts opts;
-	struct option *options;
-	struct option restore_options[] = {
-		OPT_STRING('s', "source", &opts.from_treeish, "<tree-ish>",
-			   N_("which tree-ish to checkout from")),
-		OPT_BOOL('S', "staged", &opts.checkout_index,
-			   N_("restore the index")),
-		OPT_BOOL('W', "worktree", &opts.checkout_worktree,
-			   N_("restore the working tree (default)")),
-		OPT_BOOL(0, "ignore-unmerged", &opts.ignore_unmerged,
-			 N_("ignore unmerged entries")),
-		OPT_BOOL(0, "overlay", &opts.overlay_mode, N_("use overlay mode")),
-		OPT_END()
-	};
-	int ret;
-
-	memset(&opts, 0, sizeof(opts));
-	opts.accept_ref = 0;
-	opts.accept_pathspec = 1;
-	opts.empty_pathspec_ok = 0;
-	opts.overlay_mode = 0;
-	opts.checkout_index = -1;    /* default off */
-	opts.checkout_worktree = -2; /* default on */
-	opts.ignore_unmerged_opt = "--ignore-unmerged";
-
-	options = parse_options_dup(restore_options);
-	options = add_common_options(&opts, options);
-	options = add_checkout_path_options(&opts, options);
-
-	ret = checkout_main(argc, argv, prefix, &opts,
-			    options, restore_usage);
-	FREE_AND_NULL(options);
-	return ret;
-}
diff --git a/third_party/git/builtin/clean.c b/third_party/git/builtin/clean.c
deleted file mode 100644
index 687ab473c20c..000000000000
--- a/third_party/git/builtin/clean.c
+++ /dev/null
@@ -1,1073 +0,0 @@
-/*
- * "git clean" builtin command
- *
- * Copyright (C) 2007 Shawn Bohrer
- *
- * Based on git-clean.sh by Pavel Roskin
- */
-
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "dir.h"
-#include "parse-options.h"
-#include "string-list.h"
-#include "quote.h"
-#include "column.h"
-#include "color.h"
-#include "pathspec.h"
-#include "help.h"
-#include "prompt.h"
-
-static int force = -1; /* unset */
-static int interactive;
-static struct string_list del_list = STRING_LIST_INIT_DUP;
-static unsigned int colopts;
-
-static const char *const builtin_clean_usage[] = {
-	N_("git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."),
-	NULL
-};
-
-static const char *msg_remove = N_("Removing %s\n");
-static const char *msg_would_remove = N_("Would remove %s\n");
-static const char *msg_skip_git_dir = N_("Skipping repository %s\n");
-static const char *msg_would_skip_git_dir = N_("Would skip repository %s\n");
-static const char *msg_warn_remove_failed = N_("failed to remove %s");
-static const char *msg_warn_lstat_failed = N_("could not lstat %s\n");
-
-enum color_clean {
-	CLEAN_COLOR_RESET = 0,
-	CLEAN_COLOR_PLAIN = 1,
-	CLEAN_COLOR_PROMPT = 2,
-	CLEAN_COLOR_HEADER = 3,
-	CLEAN_COLOR_HELP = 4,
-	CLEAN_COLOR_ERROR = 5
-};
-
-static const char *color_interactive_slots[] = {
-	[CLEAN_COLOR_ERROR]  = "error",
-	[CLEAN_COLOR_HEADER] = "header",
-	[CLEAN_COLOR_HELP]   = "help",
-	[CLEAN_COLOR_PLAIN]  = "plain",
-	[CLEAN_COLOR_PROMPT] = "prompt",
-	[CLEAN_COLOR_RESET]  = "reset",
-};
-
-static int clean_use_color = -1;
-static char clean_colors[][COLOR_MAXLEN] = {
-	[CLEAN_COLOR_ERROR] = GIT_COLOR_BOLD_RED,
-	[CLEAN_COLOR_HEADER] = GIT_COLOR_BOLD,
-	[CLEAN_COLOR_HELP] = GIT_COLOR_BOLD_RED,
-	[CLEAN_COLOR_PLAIN] = GIT_COLOR_NORMAL,
-	[CLEAN_COLOR_PROMPT] = GIT_COLOR_BOLD_BLUE,
-	[CLEAN_COLOR_RESET] = GIT_COLOR_RESET,
-};
-
-#define MENU_OPTS_SINGLETON		01
-#define MENU_OPTS_IMMEDIATE		02
-#define MENU_OPTS_LIST_ONLY		04
-
-struct menu_opts {
-	const char *header;
-	const char *prompt;
-	int flags;
-};
-
-#define MENU_RETURN_NO_LOOP		10
-
-struct menu_item {
-	char hotkey;
-	const char *title;
-	int selected;
-	int (*fn)(void);
-};
-
-enum menu_stuff_type {
-	MENU_STUFF_TYPE_STRING_LIST = 1,
-	MENU_STUFF_TYPE_MENU_ITEM
-};
-
-struct menu_stuff {
-	enum menu_stuff_type type;
-	int nr;
-	void *stuff;
-};
-
-define_list_config_array(color_interactive_slots);
-
-static int git_clean_config(const char *var, const char *value, void *cb)
-{
-	const char *slot_name;
-
-	if (starts_with(var, "column."))
-		return git_column_config(var, value, "clean", &colopts);
-
-	/* honors the color.interactive* config variables which also
-	   applied in git-add--interactive and git-stash */
-	if (!strcmp(var, "color.interactive")) {
-		clean_use_color = git_config_colorbool(var, value);
-		return 0;
-	}
-	if (skip_prefix(var, "color.interactive.", &slot_name)) {
-		int slot = LOOKUP_CONFIG(color_interactive_slots, slot_name);
-		if (slot < 0)
-			return 0;
-		if (!value)
-			return config_error_nonbool(var);
-		return color_parse(value, clean_colors[slot]);
-	}
-
-	if (!strcmp(var, "clean.requireforce")) {
-		force = !git_config_bool(var, value);
-		return 0;
-	}
-
-	/* inspect the color.ui config variable and others */
-	return git_color_default_config(var, value, cb);
-}
-
-static const char *clean_get_color(enum color_clean ix)
-{
-	if (want_color(clean_use_color))
-		return clean_colors[ix];
-	return "";
-}
-
-static void clean_print_color(enum color_clean ix)
-{
-	printf("%s", clean_get_color(ix));
-}
-
-static int exclude_cb(const struct option *opt, const char *arg, int unset)
-{
-	struct string_list *exclude_list = opt->value;
-	BUG_ON_OPT_NEG(unset);
-	string_list_append(exclude_list, arg);
-	return 0;
-}
-
-static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
-		int dry_run, int quiet, int *dir_gone)
-{
-	DIR *dir;
-	struct strbuf quoted = STRBUF_INIT;
-	struct dirent *e;
-	int res = 0, ret = 0, gone = 1, original_len = path->len, len;
-	struct string_list dels = STRING_LIST_INIT_DUP;
-
-	*dir_gone = 1;
-
-	if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) &&
-	    is_nonbare_repository_dir(path)) {
-		if (!quiet) {
-			quote_path(path->buf, prefix, &quoted, 0);
-			printf(dry_run ?  _(msg_would_skip_git_dir) : _(msg_skip_git_dir),
-					quoted.buf);
-		}
-
-		*dir_gone = 0;
-		goto out;
-	}
-
-	dir = opendir(path->buf);
-	if (!dir) {
-		/* an empty dir could be removed even if it is unreadble */
-		res = dry_run ? 0 : rmdir(path->buf);
-		if (res) {
-			int saved_errno = errno;
-			quote_path(path->buf, prefix, &quoted, 0);
-			errno = saved_errno;
-			warning_errno(_(msg_warn_remove_failed), quoted.buf);
-			*dir_gone = 0;
-		}
-		ret = res;
-		goto out;
-	}
-
-	strbuf_complete(path, '/');
-
-	len = path->len;
-	while ((e = readdir(dir)) != NULL) {
-		struct stat st;
-		if (is_dot_or_dotdot(e->d_name))
-			continue;
-
-		strbuf_setlen(path, len);
-		strbuf_addstr(path, e->d_name);
-		if (lstat(path->buf, &st))
-			warning_errno(_(msg_warn_lstat_failed), path->buf);
-		else if (S_ISDIR(st.st_mode)) {
-			if (remove_dirs(path, prefix, force_flag, dry_run, quiet, &gone))
-				ret = 1;
-			if (gone) {
-				quote_path(path->buf, prefix, &quoted, 0);
-				string_list_append(&dels, quoted.buf);
-			} else
-				*dir_gone = 0;
-			continue;
-		} else {
-			res = dry_run ? 0 : unlink(path->buf);
-			if (!res) {
-				quote_path(path->buf, prefix, &quoted, 0);
-				string_list_append(&dels, quoted.buf);
-			} else {
-				int saved_errno = errno;
-				quote_path(path->buf, prefix, &quoted, 0);
-				errno = saved_errno;
-				warning_errno(_(msg_warn_remove_failed), quoted.buf);
-				*dir_gone = 0;
-				ret = 1;
-			}
-			continue;
-		}
-
-		/* path too long, stat fails, or non-directory still exists */
-		*dir_gone = 0;
-		ret = 1;
-		break;
-	}
-	closedir(dir);
-
-	strbuf_setlen(path, original_len);
-
-	if (*dir_gone) {
-		res = dry_run ? 0 : rmdir(path->buf);
-		if (!res)
-			*dir_gone = 1;
-		else {
-			int saved_errno = errno;
-			quote_path(path->buf, prefix, &quoted, 0);
-			errno = saved_errno;
-			warning_errno(_(msg_warn_remove_failed), quoted.buf);
-			*dir_gone = 0;
-			ret = 1;
-		}
-	}
-
-	if (!*dir_gone && !quiet) {
-		int i;
-		for (i = 0; i < dels.nr; i++)
-			printf(dry_run ?  _(msg_would_remove) : _(msg_remove), dels.items[i].string);
-	}
-out:
-	strbuf_release(&quoted);
-	string_list_clear(&dels, 0);
-	return ret;
-}
-
-static void pretty_print_dels(void)
-{
-	struct string_list list = STRING_LIST_INIT_DUP;
-	struct string_list_item *item;
-	struct strbuf buf = STRBUF_INIT;
-	const char *qname;
-	struct column_options copts;
-
-	for_each_string_list_item(item, &del_list) {
-		qname = quote_path(item->string, NULL, &buf, 0);
-		string_list_append(&list, qname);
-	}
-
-	/*
-	 * always enable column display, we only consult column.*
-	 * about layout strategy and stuff
-	 */
-	colopts = (colopts & ~COL_ENABLE_MASK) | COL_ENABLED;
-	memset(&copts, 0, sizeof(copts));
-	copts.indent = "  ";
-	copts.padding = 2;
-	print_columns(&list, colopts, &copts);
-	strbuf_release(&buf);
-	string_list_clear(&list, 0);
-}
-
-static void pretty_print_menus(struct string_list *menu_list)
-{
-	unsigned int local_colopts = 0;
-	struct column_options copts;
-
-	local_colopts = COL_ENABLED | COL_ROW;
-	memset(&copts, 0, sizeof(copts));
-	copts.indent = "  ";
-	copts.padding = 2;
-	print_columns(menu_list, local_colopts, &copts);
-}
-
-static void prompt_help_cmd(int singleton)
-{
-	clean_print_color(CLEAN_COLOR_HELP);
-	printf(singleton ?
-		  _("Prompt help:\n"
-		    "1          - select a numbered item\n"
-		    "foo        - select item based on unique prefix\n"
-		    "           - (empty) select nothing\n") :
-		  _("Prompt help:\n"
-		    "1          - select a single item\n"
-		    "3-5        - select a range of items\n"
-		    "2-3,6-9    - select multiple ranges\n"
-		    "foo        - select item based on unique prefix\n"
-		    "-...       - unselect specified items\n"
-		    "*          - choose all items\n"
-		    "           - (empty) finish selecting\n"));
-	clean_print_color(CLEAN_COLOR_RESET);
-}
-
-/*
- * display menu stuff with number prefix and hotkey highlight
- */
-static void print_highlight_menu_stuff(struct menu_stuff *stuff, int **chosen)
-{
-	struct string_list menu_list = STRING_LIST_INIT_DUP;
-	struct strbuf menu = STRBUF_INIT;
-	struct menu_item *menu_item;
-	struct string_list_item *string_list_item;
-	int i;
-
-	switch (stuff->type) {
-	default:
-		die("Bad type of menu_stuff when print menu");
-	case MENU_STUFF_TYPE_MENU_ITEM:
-		menu_item = (struct menu_item *)stuff->stuff;
-		for (i = 0; i < stuff->nr; i++, menu_item++) {
-			const char *p;
-			int highlighted = 0;
-
-			p = menu_item->title;
-			if ((*chosen)[i] < 0)
-				(*chosen)[i] = menu_item->selected ? 1 : 0;
-			strbuf_addf(&menu, "%s%2d: ", (*chosen)[i] ? "*" : " ", i+1);
-			for (; *p; p++) {
-				if (!highlighted && *p == menu_item->hotkey) {
-					strbuf_addstr(&menu, clean_get_color(CLEAN_COLOR_PROMPT));
-					strbuf_addch(&menu, *p);
-					strbuf_addstr(&menu, clean_get_color(CLEAN_COLOR_RESET));
-					highlighted = 1;
-				} else {
-					strbuf_addch(&menu, *p);
-				}
-			}
-			string_list_append(&menu_list, menu.buf);
-			strbuf_reset(&menu);
-		}
-		break;
-	case MENU_STUFF_TYPE_STRING_LIST:
-		i = 0;
-		for_each_string_list_item(string_list_item, (struct string_list *)stuff->stuff) {
-			if ((*chosen)[i] < 0)
-				(*chosen)[i] = 0;
-			strbuf_addf(&menu, "%s%2d: %s",
-				    (*chosen)[i] ? "*" : " ", i+1, string_list_item->string);
-			string_list_append(&menu_list, menu.buf);
-			strbuf_reset(&menu);
-			i++;
-		}
-		break;
-	}
-
-	pretty_print_menus(&menu_list);
-
-	strbuf_release(&menu);
-	string_list_clear(&menu_list, 0);
-}
-
-static int find_unique(const char *choice, struct menu_stuff *menu_stuff)
-{
-	struct menu_item *menu_item;
-	struct string_list_item *string_list_item;
-	int i, len, found = 0;
-
-	len = strlen(choice);
-	switch (menu_stuff->type) {
-	default:
-		die("Bad type of menu_stuff when parse choice");
-	case MENU_STUFF_TYPE_MENU_ITEM:
-
-		menu_item = (struct menu_item *)menu_stuff->stuff;
-		for (i = 0; i < menu_stuff->nr; i++, menu_item++) {
-			if (len == 1 && *choice == menu_item->hotkey) {
-				found = i + 1;
-				break;
-			}
-			if (!strncasecmp(choice, menu_item->title, len)) {
-				if (found) {
-					if (len == 1) {
-						/* continue for hotkey matching */
-						found = -1;
-					} else {
-						found = 0;
-						break;
-					}
-				} else {
-					found = i + 1;
-				}
-			}
-		}
-		break;
-	case MENU_STUFF_TYPE_STRING_LIST:
-		string_list_item = ((struct string_list *)menu_stuff->stuff)->items;
-		for (i = 0; i < menu_stuff->nr; i++, string_list_item++) {
-			if (!strncasecmp(choice, string_list_item->string, len)) {
-				if (found) {
-					found = 0;
-					break;
-				}
-				found = i + 1;
-			}
-		}
-		break;
-	}
-	return found;
-}
-
-/*
- * Parse user input, and return choice(s) for menu (menu_stuff).
- *
- * Input
- *     (for single choice)
- *         1          - select a numbered item
- *         foo        - select item based on menu title
- *                    - (empty) select nothing
- *
- *     (for multiple choice)
- *         1          - select a single item
- *         3-5        - select a range of items
- *         2-3,6-9    - select multiple ranges
- *         foo        - select item based on menu title
- *         -...       - unselect specified items
- *         *          - choose all items
- *                    - (empty) finish selecting
- *
- * The parse result will be saved in array **chosen, and
- * return number of total selections.
- */
-static int parse_choice(struct menu_stuff *menu_stuff,
-			int is_single,
-			struct strbuf input,
-			int **chosen)
-{
-	struct strbuf **choice_list, **ptr;
-	int nr = 0;
-	int i;
-
-	if (is_single) {
-		choice_list = strbuf_split_max(&input, '\n', 0);
-	} else {
-		char *p = input.buf;
-		do {
-			if (*p == ',')
-				*p = ' ';
-		} while (*p++);
-		choice_list = strbuf_split_max(&input, ' ', 0);
-	}
-
-	for (ptr = choice_list; *ptr; ptr++) {
-		char *p;
-		int choose = 1;
-		int bottom = 0, top = 0;
-		int is_range, is_number;
-
-		strbuf_trim(*ptr);
-		if (!(*ptr)->len)
-			continue;
-
-		/* Input that begins with '-'; unchoose */
-		if (*(*ptr)->buf == '-') {
-			choose = 0;
-			strbuf_remove((*ptr), 0, 1);
-		}
-
-		is_range = 0;
-		is_number = 1;
-		for (p = (*ptr)->buf; *p; p++) {
-			if ('-' == *p) {
-				if (!is_range) {
-					is_range = 1;
-					is_number = 0;
-				} else {
-					is_number = 0;
-					is_range = 0;
-					break;
-				}
-			} else if (!isdigit(*p)) {
-				is_number = 0;
-				is_range = 0;
-				break;
-			}
-		}
-
-		if (is_number) {
-			bottom = atoi((*ptr)->buf);
-			top = bottom;
-		} else if (is_range) {
-			bottom = atoi((*ptr)->buf);
-			/* a range can be specified like 5-7 or 5- */
-			if (!*(strchr((*ptr)->buf, '-') + 1))
-				top = menu_stuff->nr;
-			else
-				top = atoi(strchr((*ptr)->buf, '-') + 1);
-		} else if (!strcmp((*ptr)->buf, "*")) {
-			bottom = 1;
-			top = menu_stuff->nr;
-		} else {
-			bottom = find_unique((*ptr)->buf, menu_stuff);
-			top = bottom;
-		}
-
-		if (top <= 0 || bottom <= 0 || top > menu_stuff->nr || bottom > top ||
-		    (is_single && bottom != top)) {
-			clean_print_color(CLEAN_COLOR_ERROR);
-			printf(_("Huh (%s)?\n"), (*ptr)->buf);
-			clean_print_color(CLEAN_COLOR_RESET);
-			continue;
-		}
-
-		for (i = bottom; i <= top; i++)
-			(*chosen)[i-1] = choose;
-	}
-
-	strbuf_list_free(choice_list);
-
-	for (i = 0; i < menu_stuff->nr; i++)
-		nr += (*chosen)[i];
-	return nr;
-}
-
-/*
- * Implement a git-add-interactive compatible UI, which is borrowed
- * from git-add--interactive.perl.
- *
- * Return value:
- *
- *   - Return an array of integers
- *   - , and it is up to you to free the allocated memory.
- *   - The array ends with EOF.
- *   - If user pressed CTRL-D (i.e. EOF), no selection returned.
- */
-static int *list_and_choose(struct menu_opts *opts, struct menu_stuff *stuff)
-{
-	struct strbuf choice = STRBUF_INIT;
-	int *chosen, *result;
-	int nr = 0;
-	int eof = 0;
-	int i;
-
-	ALLOC_ARRAY(chosen, stuff->nr);
-	/* set chosen as uninitialized */
-	for (i = 0; i < stuff->nr; i++)
-		chosen[i] = -1;
-
-	for (;;) {
-		if (opts->header) {
-			printf_ln("%s%s%s",
-				  clean_get_color(CLEAN_COLOR_HEADER),
-				  _(opts->header),
-				  clean_get_color(CLEAN_COLOR_RESET));
-		}
-
-		/* chosen will be initialized by print_highlight_menu_stuff */
-		print_highlight_menu_stuff(stuff, &chosen);
-
-		if (opts->flags & MENU_OPTS_LIST_ONLY)
-			break;
-
-		if (opts->prompt) {
-			printf("%s%s%s%s",
-			       clean_get_color(CLEAN_COLOR_PROMPT),
-			       _(opts->prompt),
-			       opts->flags & MENU_OPTS_SINGLETON ? "> " : ">> ",
-			       clean_get_color(CLEAN_COLOR_RESET));
-		}
-
-		if (git_read_line_interactively(&choice) == EOF) {
-			eof = 1;
-			break;
-		}
-
-		/* help for prompt */
-		if (!strcmp(choice.buf, "?")) {
-			prompt_help_cmd(opts->flags & MENU_OPTS_SINGLETON);
-			continue;
-		}
-
-		/* for a multiple-choice menu, press ENTER (empty) will return back */
-		if (!(opts->flags & MENU_OPTS_SINGLETON) && !choice.len)
-			break;
-
-		nr = parse_choice(stuff,
-				  opts->flags & MENU_OPTS_SINGLETON,
-				  choice,
-				  &chosen);
-
-		if (opts->flags & MENU_OPTS_SINGLETON) {
-			if (nr)
-				break;
-		} else if (opts->flags & MENU_OPTS_IMMEDIATE) {
-			break;
-		}
-	}
-
-	if (eof) {
-		result = xmalloc(sizeof(int));
-		*result = EOF;
-	} else {
-		int j = 0;
-
-		/*
-		 * recalculate nr, if return back from menu directly with
-		 * default selections.
-		 */
-		if (!nr) {
-			for (i = 0; i < stuff->nr; i++)
-				nr += chosen[i];
-		}
-
-		result = xcalloc(st_add(nr, 1), sizeof(int));
-		for (i = 0; i < stuff->nr && j < nr; i++) {
-			if (chosen[i])
-				result[j++] = i;
-		}
-		result[j] = EOF;
-	}
-
-	free(chosen);
-	strbuf_release(&choice);
-	return result;
-}
-
-static int clean_cmd(void)
-{
-	return MENU_RETURN_NO_LOOP;
-}
-
-static int filter_by_patterns_cmd(void)
-{
-	struct dir_struct dir;
-	struct strbuf confirm = STRBUF_INIT;
-	struct strbuf **ignore_list;
-	struct string_list_item *item;
-	struct pattern_list *pl;
-	int changed = -1, i;
-
-	for (;;) {
-		if (!del_list.nr)
-			break;
-
-		if (changed)
-			pretty_print_dels();
-
-		clean_print_color(CLEAN_COLOR_PROMPT);
-		printf(_("Input ignore patterns>> "));
-		clean_print_color(CLEAN_COLOR_RESET);
-		if (git_read_line_interactively(&confirm) == EOF)
-			putchar('\n');
-
-		/* quit filter_by_pattern mode if press ENTER or Ctrl-D */
-		if (!confirm.len)
-			break;
-
-		dir_init(&dir);
-		pl = add_pattern_list(&dir, EXC_CMDL, "manual exclude");
-		ignore_list = strbuf_split_max(&confirm, ' ', 0);
-
-		for (i = 0; ignore_list[i]; i++) {
-			strbuf_trim(ignore_list[i]);
-			if (!ignore_list[i]->len)
-				continue;
-
-			add_pattern(ignore_list[i]->buf, "", 0, pl, -(i+1));
-		}
-
-		changed = 0;
-		for_each_string_list_item(item, &del_list) {
-			int dtype = DT_UNKNOWN;
-
-			if (is_excluded(&dir, &the_index, item->string, &dtype)) {
-				*item->string = '\0';
-				changed++;
-			}
-		}
-
-		if (changed) {
-			string_list_remove_empty_items(&del_list, 0);
-		} else {
-			clean_print_color(CLEAN_COLOR_ERROR);
-			printf_ln(_("WARNING: Cannot find items matched by: %s"), confirm.buf);
-			clean_print_color(CLEAN_COLOR_RESET);
-		}
-
-		strbuf_list_free(ignore_list);
-		dir_clear(&dir);
-	}
-
-	strbuf_release(&confirm);
-	return 0;
-}
-
-static int select_by_numbers_cmd(void)
-{
-	struct menu_opts menu_opts;
-	struct menu_stuff menu_stuff;
-	struct string_list_item *items;
-	int *chosen;
-	int i, j;
-
-	menu_opts.header = NULL;
-	menu_opts.prompt = N_("Select items to delete");
-	menu_opts.flags = 0;
-
-	menu_stuff.type = MENU_STUFF_TYPE_STRING_LIST;
-	menu_stuff.stuff = &del_list;
-	menu_stuff.nr = del_list.nr;
-
-	chosen = list_and_choose(&menu_opts, &menu_stuff);
-	items = del_list.items;
-	for (i = 0, j = 0; i < del_list.nr; i++) {
-		if (i < chosen[j]) {
-			*(items[i].string) = '\0';
-		} else if (i == chosen[j]) {
-			/* delete selected item */
-			j++;
-			continue;
-		} else {
-			/* end of chosen (chosen[j] == EOF), won't delete */
-			*(items[i].string) = '\0';
-		}
-	}
-
-	string_list_remove_empty_items(&del_list, 0);
-
-	free(chosen);
-	return 0;
-}
-
-static int ask_each_cmd(void)
-{
-	struct strbuf confirm = STRBUF_INIT;
-	struct strbuf buf = STRBUF_INIT;
-	struct string_list_item *item;
-	const char *qname;
-	int changed = 0, eof = 0;
-
-	for_each_string_list_item(item, &del_list) {
-		/* Ctrl-D should stop removing files */
-		if (!eof) {
-			qname = quote_path(item->string, NULL, &buf, 0);
-			/* TRANSLATORS: Make sure to keep [y/N] as is */
-			printf(_("Remove %s [y/N]? "), qname);
-			if (git_read_line_interactively(&confirm) == EOF) {
-				putchar('\n');
-				eof = 1;
-			}
-		}
-		if (!confirm.len || strncasecmp(confirm.buf, "yes", confirm.len)) {
-			*item->string = '\0';
-			changed++;
-		}
-	}
-
-	if (changed)
-		string_list_remove_empty_items(&del_list, 0);
-
-	strbuf_release(&buf);
-	strbuf_release(&confirm);
-	return MENU_RETURN_NO_LOOP;
-}
-
-static int quit_cmd(void)
-{
-	string_list_clear(&del_list, 0);
-	printf(_("Bye.\n"));
-	return MENU_RETURN_NO_LOOP;
-}
-
-static int help_cmd(void)
-{
-	clean_print_color(CLEAN_COLOR_HELP);
-	printf_ln(_(
-		    "clean               - start cleaning\n"
-		    "filter by pattern   - exclude items from deletion\n"
-		    "select by numbers   - select items to be deleted by numbers\n"
-		    "ask each            - confirm each deletion (like \"rm -i\")\n"
-		    "quit                - stop cleaning\n"
-		    "help                - this screen\n"
-		    "?                   - help for prompt selection"
-		   ));
-	clean_print_color(CLEAN_COLOR_RESET);
-	return 0;
-}
-
-static void interactive_main_loop(void)
-{
-	while (del_list.nr) {
-		struct menu_opts menu_opts;
-		struct menu_stuff menu_stuff;
-		struct menu_item menus[] = {
-			{'c', "clean",			0, clean_cmd},
-			{'f', "filter by pattern",	0, filter_by_patterns_cmd},
-			{'s', "select by numbers",	0, select_by_numbers_cmd},
-			{'a', "ask each",		0, ask_each_cmd},
-			{'q', "quit",			0, quit_cmd},
-			{'h', "help",			0, help_cmd},
-		};
-		int *chosen;
-
-		menu_opts.header = N_("*** Commands ***");
-		menu_opts.prompt = N_("What now");
-		menu_opts.flags = MENU_OPTS_SINGLETON;
-
-		menu_stuff.type = MENU_STUFF_TYPE_MENU_ITEM;
-		menu_stuff.stuff = menus;
-		menu_stuff.nr = sizeof(menus) / sizeof(struct menu_item);
-
-		clean_print_color(CLEAN_COLOR_HEADER);
-		printf_ln(Q_("Would remove the following item:",
-			     "Would remove the following items:",
-			     del_list.nr));
-		clean_print_color(CLEAN_COLOR_RESET);
-
-		pretty_print_dels();
-
-		chosen = list_and_choose(&menu_opts, &menu_stuff);
-
-		if (*chosen != EOF) {
-			int ret;
-			ret = menus[*chosen].fn();
-			if (ret != MENU_RETURN_NO_LOOP) {
-				FREE_AND_NULL(chosen);
-				if (!del_list.nr) {
-					clean_print_color(CLEAN_COLOR_ERROR);
-					printf_ln(_("No more files to clean, exiting."));
-					clean_print_color(CLEAN_COLOR_RESET);
-					break;
-				}
-				continue;
-			}
-		} else {
-			quit_cmd();
-		}
-
-		FREE_AND_NULL(chosen);
-		break;
-	}
-}
-
-static void correct_untracked_entries(struct dir_struct *dir)
-{
-	int src, dst, ign;
-
-	for (src = dst = ign = 0; src < dir->nr; src++) {
-		/* skip paths in ignored[] that cannot be inside entries[src] */
-		while (ign < dir->ignored_nr &&
-		       0 <= cmp_dir_entry(&dir->entries[src], &dir->ignored[ign]))
-			ign++;
-
-		if (ign < dir->ignored_nr &&
-		    check_dir_entry_contains(dir->entries[src], dir->ignored[ign])) {
-			/* entries[src] contains an ignored path, so we drop it */
-			free(dir->entries[src]);
-		} else {
-			struct dir_entry *ent = dir->entries[src++];
-
-			/* entries[src] does not contain an ignored path, so we keep it */
-			dir->entries[dst++] = ent;
-
-			/* then discard paths in entries[] contained inside entries[src] */
-			while (src < dir->nr &&
-			       check_dir_entry_contains(ent, dir->entries[src]))
-				free(dir->entries[src++]);
-
-			/* compensate for the outer loop's loop control */
-			src--;
-		}
-	}
-	dir->nr = dst;
-}
-
-int cmd_clean(int argc, const char **argv, const char *prefix)
-{
-	int i, res;
-	int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0;
-	int ignored_only = 0, config_set = 0, errors = 0, gone = 1;
-	int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT;
-	struct strbuf abs_path = STRBUF_INIT;
-	struct dir_struct dir;
-	struct pathspec pathspec;
-	struct strbuf buf = STRBUF_INIT;
-	struct string_list exclude_list = STRING_LIST_INIT_NODUP;
-	struct pattern_list *pl;
-	struct string_list_item *item;
-	const char *qname;
-	struct option options[] = {
-		OPT__QUIET(&quiet, N_("do not print names of files removed")),
-		OPT__DRY_RUN(&dry_run, N_("dry run")),
-		OPT__FORCE(&force, N_("force"), PARSE_OPT_NOCOMPLETE),
-		OPT_BOOL('i', "interactive", &interactive, N_("interactive cleaning")),
-		OPT_BOOL('d', NULL, &remove_directories,
-				N_("remove whole directories")),
-		OPT_CALLBACK_F('e', "exclude", &exclude_list, N_("pattern"),
-		  N_("add <pattern> to ignore rules"), PARSE_OPT_NONEG, exclude_cb),
-		OPT_BOOL('x', NULL, &ignored, N_("remove ignored files, too")),
-		OPT_BOOL('X', NULL, &ignored_only,
-				N_("remove only ignored files")),
-		OPT_END()
-	};
-
-	git_config(git_clean_config, NULL);
-	if (force < 0)
-		force = 0;
-	else
-		config_set = 1;
-
-	argc = parse_options(argc, argv, prefix, options, builtin_clean_usage,
-			     0);
-
-	dir_init(&dir);
-	if (!interactive && !dry_run && !force) {
-		if (config_set)
-			die(_("clean.requireForce set to true and neither -i, -n, nor -f given; "
-				  "refusing to clean"));
-		else
-			die(_("clean.requireForce defaults to true and neither -i, -n, nor -f given;"
-				  " refusing to clean"));
-	}
-
-	if (force > 1)
-		rm_flags = 0;
-	else
-		dir.flags |= DIR_SKIP_NESTED_GIT;
-
-	dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
-
-	if (ignored && ignored_only)
-		die(_("-x and -X cannot be used together"));
-	if (!ignored)
-		setup_standard_excludes(&dir);
-	if (ignored_only)
-		dir.flags |= DIR_SHOW_IGNORED;
-
-	if (argc) {
-		/*
-		 * Remaining args implies pathspecs specified, and we should
-		 * recurse within those.
-		 */
-		remove_directories = 1;
-	}
-
-	if (remove_directories && !ignored_only) {
-		/*
-		 * We need to know about ignored files too:
-		 *
-		 * If (ignored), then we will delete ignored files as well.
-		 *
-		 * If (!ignored), then even though we not are doing
-		 * anything with ignored files, we need to know about them
-		 * so that we can avoid deleting a directory of untracked
-		 * files that also contains an ignored file within it.
-		 *
-		 * For the (!ignored) case, since we only need to avoid
-		 * deleting ignored files, we can set
-		 * DIR_SHOW_IGNORED_TOO_MODE_MATCHING in order to avoid
-		 * recursing into a directory which is itself ignored.
-		 */
-		dir.flags |= DIR_SHOW_IGNORED_TOO;
-		if (!ignored)
-			dir.flags |= DIR_SHOW_IGNORED_TOO_MODE_MATCHING;
-
-		/*
-		 * Let the fill_directory() machinery know that we aren't
-		 * just recursing to collect the ignored files; we want all
-		 * the untracked ones so that we can delete them.  (Note:
-		 * we could also set DIR_KEEP_UNTRACKED_CONTENTS when
-		 * ignored_only is true, since DIR_KEEP_UNTRACKED_CONTENTS
-		 * only has effect in combination with DIR_SHOW_IGNORED_TOO.  It makes
-		 * the code clearer to exclude it, though.
-		 */
-		dir.flags |= DIR_KEEP_UNTRACKED_CONTENTS;
-	}
-
-	if (read_cache() < 0)
-		die(_("index file corrupt"));
-
-	pl = add_pattern_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));
-
-	parse_pathspec(&pathspec, 0,
-		       PATHSPEC_PREFER_CWD,
-		       prefix, argv);
-
-	fill_directory(&dir, &the_index, &pathspec);
-	correct_untracked_entries(&dir);
-
-	for (i = 0; i < dir.nr; i++) {
-		struct dir_entry *ent = dir.entries[i];
-		int matches = 0;
-		struct stat st;
-		const char *rel;
-
-		if (!cache_name_is_other(ent->name, ent->len))
-			continue;
-
-		if (lstat(ent->name, &st))
-			die_errno("Cannot lstat '%s'", ent->name);
-
-		if (S_ISDIR(st.st_mode) && !remove_directories &&
-		    matches != MATCHED_EXACTLY)
-			continue;
-
-		rel = relative_path(ent->name, prefix, &buf);
-		string_list_append(&del_list, rel);
-	}
-
-	dir_clear(&dir);
-
-	if (interactive && del_list.nr > 0)
-		interactive_main_loop();
-
-	for_each_string_list_item(item, &del_list) {
-		struct stat st;
-
-		strbuf_reset(&abs_path);
-		if (prefix)
-			strbuf_addstr(&abs_path, prefix);
-
-		strbuf_addstr(&abs_path, item->string);
-
-		/*
-		 * we might have removed this as part of earlier
-		 * recursive directory removal, so lstat() here could
-		 * fail with ENOENT.
-		 */
-		if (lstat(abs_path.buf, &st))
-			continue;
-
-		if (S_ISDIR(st.st_mode)) {
-			if (remove_dirs(&abs_path, prefix, rm_flags, dry_run, quiet, &gone))
-				errors++;
-			if (gone && !quiet) {
-				qname = quote_path(item->string, NULL, &buf, 0);
-				printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
-			}
-		} else {
-			res = dry_run ? 0 : unlink(abs_path.buf);
-			if (res) {
-				int saved_errno = errno;
-				qname = quote_path(item->string, NULL, &buf, 0);
-				errno = saved_errno;
-				warning_errno(_(msg_warn_remove_failed), qname);
-				errors++;
-			} else if (!quiet) {
-				qname = quote_path(item->string, NULL, &buf, 0);
-				printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
-			}
-		}
-	}
-
-	strbuf_release(&abs_path);
-	strbuf_release(&buf);
-	string_list_clear(&del_list, 0);
-	string_list_clear(&exclude_list, 0);
-	return (errors != 0);
-}
diff --git a/third_party/git/builtin/clone.c b/third_party/git/builtin/clone.c
deleted file mode 100644
index 391aa41075ee..000000000000
--- a/third_party/git/builtin/clone.c
+++ /dev/null
@@ -1,1337 +0,0 @@
-/*
- * Builtin "git clone"
- *
- * Copyright (c) 2007 Kristian Hรธgsberg <krh@redhat.com>,
- *		 2008 Daniel Barkalow <barkalow@iabervon.org>
- * Based on git-commit.sh by Junio C Hamano and Linus Torvalds
- *
- * Clone a repository into a different directory that does not yet exist.
- */
-
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "config.h"
-#include "lockfile.h"
-#include "parse-options.h"
-#include "fetch-pack.h"
-#include "refs.h"
-#include "refspec.h"
-#include "object-store.h"
-#include "tree.h"
-#include "tree-walk.h"
-#include "unpack-trees.h"
-#include "transport.h"
-#include "strbuf.h"
-#include "dir.h"
-#include "dir-iterator.h"
-#include "iterator.h"
-#include "sigchain.h"
-#include "branch.h"
-#include "remote.h"
-#include "run-command.h"
-#include "connected.h"
-#include "packfile.h"
-#include "list-objects-filter-options.h"
-
-/*
- * Overall FIXMEs:
- *  - respect DB_ENVIRONMENT for .git/objects.
- *
- * Implementation notes:
- *  - dropping use-separate-remote and no-separate-remote compatibility
- *
- */
-static const char * const builtin_clone_usage[] = {
-	N_("git clone [<options>] [--] <repo> [<dir>]"),
-	NULL
-};
-
-static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;
-static int option_local = -1, option_no_hardlinks, option_shared;
-static int option_no_tags;
-static int option_shallow_submodules;
-static int deepen;
-static char *option_template, *option_depth, *option_since;
-static char *option_origin = NULL;
-static char *option_branch = NULL;
-static struct string_list option_not = STRING_LIST_INIT_NODUP;
-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;
-static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;
-static int option_dissociate;
-static int max_jobs = -1;
-static struct string_list option_recurse_submodules = STRING_LIST_INIT_NODUP;
-static struct list_objects_filter_options filter_options;
-static struct string_list server_options = STRING_LIST_INIT_NODUP;
-static int option_remote_submodules;
-
-static int recurse_submodules_cb(const struct option *opt,
-				 const char *arg, int unset)
-{
-	if (unset)
-		string_list_clear((struct string_list *)opt->value, 0);
-	else if (arg)
-		string_list_append((struct string_list *)opt->value, arg);
-	else
-		string_list_append((struct string_list *)opt->value,
-				   (const char *)opt->defval);
-
-	return 0;
-}
-
-static struct option builtin_clone_options[] = {
-	OPT__VERBOSITY(&option_verbosity),
-	OPT_BOOL(0, "progress", &option_progress,
-		 N_("force progress reporting")),
-	OPT_BOOL('n', "no-checkout", &option_no_checkout,
-		 N_("don't create a checkout")),
-	OPT_BOOL(0, "bare", &option_bare, N_("create a bare repository")),
-	OPT_HIDDEN_BOOL(0, "naked", &option_bare,
-			N_("create a bare repository")),
-	OPT_BOOL(0, "mirror", &option_mirror,
-		 N_("create a mirror repository (implies bare)")),
-	OPT_BOOL('l', "local", &option_local,
-		N_("to clone from a local repository")),
-	OPT_BOOL(0, "no-hardlinks", &option_no_hardlinks,
-		    N_("don't use local hardlinks, always copy")),
-	OPT_BOOL('s', "shared", &option_shared,
-		    N_("setup as shared repository")),
-	{ OPTION_CALLBACK, 0, "recurse-submodules", &option_recurse_submodules,
-	  N_("pathspec"), N_("initialize submodules in the clone"),
-	  PARSE_OPT_OPTARG, recurse_submodules_cb, (intptr_t)"." },
-	OPT_ALIAS(0, "recursive", "recurse-submodules"),
-	OPT_INTEGER('j', "jobs", &max_jobs,
-		    N_("number of submodules cloned in parallel")),
-	OPT_STRING(0, "template", &option_template, N_("template-directory"),
-		   N_("directory from which templates will be used")),
-	OPT_STRING_LIST(0, "reference", &option_required_reference, N_("repo"),
-			N_("reference repository")),
-	OPT_STRING_LIST(0, "reference-if-able", &option_optional_reference,
-			N_("repo"), N_("reference repository")),
-	OPT_BOOL(0, "dissociate", &option_dissociate,
-		 N_("use --reference only while cloning")),
-	OPT_STRING('o', "origin", &option_origin, N_("name"),
-		   N_("use <name> instead of 'origin' to track upstream")),
-	OPT_STRING('b', "branch", &option_branch, N_("branch"),
-		   N_("checkout <branch> instead of the remote's HEAD")),
-	OPT_STRING('u', "upload-pack", &option_upload_pack, N_("path"),
-		   N_("path to git-upload-pack on the remote")),
-	OPT_STRING(0, "depth", &option_depth, N_("depth"),
-		    N_("create a shallow clone of that depth")),
-	OPT_STRING(0, "shallow-since", &option_since, N_("time"),
-		    N_("create a shallow clone since a specific time")),
-	OPT_STRING_LIST(0, "shallow-exclude", &option_not, N_("revision"),
-			N_("deepen history of shallow clone, excluding rev")),
-	OPT_BOOL(0, "single-branch", &option_single_branch,
-		    N_("clone only one branch, HEAD or --branch")),
-	OPT_BOOL(0, "no-tags", &option_no_tags,
-		 N_("don't clone any tags, and make later fetches not to follow them")),
-	OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules,
-		    N_("any cloned submodules will be shallow")),
-	OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
-		   N_("separate git dir from working tree")),
-	OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
-			N_("set config inside the new repository")),
-	OPT_STRING_LIST(0, "server-option", &server_options,
-			N_("server-specific"), N_("option to transmit")),
-	OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
-			TRANSPORT_FAMILY_IPV4),
-	OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
-			TRANSPORT_FAMILY_IPV6),
-	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()
-};
-
-static const char *get_repo_path_1(struct strbuf *path, int *is_bundle)
-{
-	static char *suffix[] = { "/.git", "", ".git/.git", ".git" };
-	static char *bundle_suffix[] = { ".bundle", "" };
-	size_t baselen = path->len;
-	struct stat st;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(suffix); i++) {
-		strbuf_setlen(path, baselen);
-		strbuf_addstr(path, suffix[i]);
-		if (stat(path->buf, &st))
-			continue;
-		if (S_ISDIR(st.st_mode) && is_git_directory(path->buf)) {
-			*is_bundle = 0;
-			return path->buf;
-		} else if (S_ISREG(st.st_mode) && st.st_size > 8) {
-			/* Is it a "gitfile"? */
-			char signature[8];
-			const char *dst;
-			int len, fd = open(path->buf, O_RDONLY);
-			if (fd < 0)
-				continue;
-			len = read_in_full(fd, signature, 8);
-			close(fd);
-			if (len != 8 || strncmp(signature, "gitdir: ", 8))
-				continue;
-			dst = read_gitfile(path->buf);
-			if (dst) {
-				*is_bundle = 0;
-				return dst;
-			}
-		}
-	}
-
-	for (i = 0; i < ARRAY_SIZE(bundle_suffix); i++) {
-		strbuf_setlen(path, baselen);
-		strbuf_addstr(path, bundle_suffix[i]);
-		if (!stat(path->buf, &st) && S_ISREG(st.st_mode)) {
-			*is_bundle = 1;
-			return path->buf;
-		}
-	}
-
-	return NULL;
-}
-
-static char *get_repo_path(const char *repo, int *is_bundle)
-{
-	struct strbuf path = STRBUF_INIT;
-	const char *raw;
-	char *canon;
-
-	strbuf_addstr(&path, repo);
-	raw = get_repo_path_1(&path, is_bundle);
-	canon = raw ? absolute_pathdup(raw) : NULL;
-	strbuf_release(&path);
-	return canon;
-}
-
-static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
-{
-	const char *end = repo + strlen(repo), *start, *ptr;
-	size_t len;
-	char *dir;
-
-	/*
-	 * Skip scheme.
-	 */
-	start = strstr(repo, "://");
-	if (start == NULL)
-		start = repo;
-	else
-		start += 3;
-
-	/*
-	 * Skip authentication data. The stripping does happen
-	 * greedily, such that we strip up to the last '@' inside
-	 * the host part.
-	 */
-	for (ptr = start; ptr < end && !is_dir_sep(*ptr); ptr++) {
-		if (*ptr == '@')
-			start = ptr + 1;
-	}
-
-	/*
-	 * Strip trailing spaces, slashes and /.git
-	 */
-	while (start < end && (is_dir_sep(end[-1]) || isspace(end[-1])))
-		end--;
-	if (end - start > 5 && is_dir_sep(end[-5]) &&
-	    !strncmp(end - 4, ".git", 4)) {
-		end -= 5;
-		while (start < end && is_dir_sep(end[-1]))
-			end--;
-	}
-
-	/*
-	 * Strip trailing port number if we've got only a
-	 * hostname (that is, there is no dir separator but a
-	 * colon). This check is required such that we do not
-	 * strip URI's like '/foo/bar:2222.git', which should
-	 * result in a dir '2222' being guessed due to backwards
-	 * compatibility.
-	 */
-	if (memchr(start, '/', end - start) == NULL
-	    && memchr(start, ':', end - start) != NULL) {
-		ptr = end;
-		while (start < ptr && isdigit(ptr[-1]) && ptr[-1] != ':')
-			ptr--;
-		if (start < ptr && ptr[-1] == ':')
-			end = ptr - 1;
-	}
-
-	/*
-	 * Find last component. To remain backwards compatible we
-	 * also regard colons as path separators, such that
-	 * cloning a repository 'foo:bar.git' would result in a
-	 * directory 'bar' being guessed.
-	 */
-	ptr = end;
-	while (start < ptr && !is_dir_sep(ptr[-1]) && ptr[-1] != ':')
-		ptr--;
-	start = ptr;
-
-	/*
-	 * Strip .{bundle,git}.
-	 */
-	len = end - start;
-	strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
-
-	if (!len || (len == 1 && *start == '/'))
-		die(_("No directory name could be guessed.\n"
-		      "Please specify a directory on the command line"));
-
-	if (is_bare)
-		dir = xstrfmt("%.*s.git", (int)len, start);
-	else
-		dir = xstrndup(start, len);
-	/*
-	 * Replace sequences of 'control' characters and whitespace
-	 * with one ascii space, remove leading and trailing spaces.
-	 */
-	if (*dir) {
-		char *out = dir;
-		int prev_space = 1 /* strip leading whitespace */;
-		for (end = dir; *end; ++end) {
-			char ch = *end;
-			if ((unsigned char)ch < '\x20')
-				ch = '\x20';
-			if (isspace(ch)) {
-				if (prev_space)
-					continue;
-				prev_space = 1;
-			} else
-				prev_space = 0;
-			*out++ = ch;
-		}
-		*out = '\0';
-		if (out > dir && prev_space)
-			out[-1] = '\0';
-	}
-	return dir;
-}
-
-static void strip_trailing_slashes(char *dir)
-{
-	char *end = dir + strlen(dir);
-
-	while (dir < end - 1 && is_dir_sep(end[-1]))
-		end--;
-	*end = '\0';
-}
-
-static int add_one_reference(struct string_list_item *item, void *cb_data)
-{
-	struct strbuf err = STRBUF_INIT;
-	int *required = cb_data;
-	char *ref_git = compute_alternate_path(item->string, &err);
-
-	if (!ref_git) {
-		if (*required)
-			die("%s", err.buf);
-		else
-			fprintf(stderr,
-				_("info: Could not add alternate for '%s': %s\n"),
-				item->string, err.buf);
-	} else {
-		struct strbuf sb = STRBUF_INIT;
-		strbuf_addf(&sb, "%s/objects", ref_git);
-		add_to_alternates_file(sb.buf);
-		strbuf_release(&sb);
-	}
-
-	strbuf_release(&err);
-	free(ref_git);
-	return 0;
-}
-
-static void setup_reference(void)
-{
-	int required = 1;
-	for_each_string_list(&option_required_reference,
-			     add_one_reference, &required);
-	required = 0;
-	for_each_string_list(&option_optional_reference,
-			     add_one_reference, &required);
-}
-
-static void copy_alternates(struct strbuf *src, const char *src_repo)
-{
-	/*
-	 * Read from the source objects/info/alternates file
-	 * and copy the entries to corresponding file in the
-	 * destination repository with add_to_alternates_file().
-	 * Both src and dst have "$path/objects/info/alternates".
-	 *
-	 * Instead of copying bit-for-bit from the original,
-	 * we need to append to existing one so that the already
-	 * created entry via "clone -s" is not lost, and also
-	 * to turn entries with paths relative to the original
-	 * absolute, so that they can be used in the new repository.
-	 */
-	FILE *in = xfopen(src->buf, "r");
-	struct strbuf line = STRBUF_INIT;
-
-	while (strbuf_getline(&line, in) != EOF) {
-		char *abs_path;
-		if (!line.len || line.buf[0] == '#')
-			continue;
-		if (is_absolute_path(line.buf)) {
-			add_to_alternates_file(line.buf);
-			continue;
-		}
-		abs_path = mkpathdup("%s/objects/%s", src_repo, line.buf);
-		if (!normalize_path_copy(abs_path, abs_path))
-			add_to_alternates_file(abs_path);
-		else
-			warning("skipping invalid relative alternate: %s/%s",
-				src_repo, line.buf);
-		free(abs_path);
-	}
-	strbuf_release(&line);
-	fclose(in);
-}
-
-static void mkdir_if_missing(const char *pathname, mode_t mode)
-{
-	struct stat st;
-
-	if (!mkdir(pathname, mode))
-		return;
-
-	if (errno != EEXIST)
-		die_errno(_("failed to create directory '%s'"), pathname);
-	else if (stat(pathname, &st))
-		die_errno(_("failed to stat '%s'"), pathname);
-	else if (!S_ISDIR(st.st_mode))
-		die(_("%s exists and is not a directory"), pathname);
-}
-
-static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
-				   const char *src_repo)
-{
-	int src_len, dest_len;
-	struct dir_iterator *iter;
-	int iter_status;
-	unsigned int flags;
-	struct strbuf realpath = STRBUF_INIT;
-
-	mkdir_if_missing(dest->buf, 0777);
-
-	flags = DIR_ITERATOR_PEDANTIC | DIR_ITERATOR_FOLLOW_SYMLINKS;
-	iter = dir_iterator_begin(src->buf, flags);
-
-	if (!iter)
-		die_errno(_("failed to start iterator over '%s'"), src->buf);
-
-	strbuf_addch(src, '/');
-	src_len = src->len;
-	strbuf_addch(dest, '/');
-	dest_len = dest->len;
-
-	while ((iter_status = dir_iterator_advance(iter)) == ITER_OK) {
-		strbuf_setlen(src, src_len);
-		strbuf_addstr(src, iter->relative_path);
-		strbuf_setlen(dest, dest_len);
-		strbuf_addstr(dest, iter->relative_path);
-
-		if (S_ISDIR(iter->st.st_mode)) {
-			mkdir_if_missing(dest->buf, 0777);
-			continue;
-		}
-
-		/* Files that cannot be copied bit-for-bit... */
-		if (!fspathcmp(iter->relative_path, "info/alternates")) {
-			copy_alternates(src, src_repo);
-			continue;
-		}
-
-		if (unlink(dest->buf) && errno != ENOENT)
-			die_errno(_("failed to unlink '%s'"), dest->buf);
-		if (!option_no_hardlinks) {
-			strbuf_realpath(&realpath, src->buf, 1);
-			if (!link(realpath.buf, dest->buf))
-				continue;
-			if (option_local > 0)
-				die_errno(_("failed to create link '%s'"), dest->buf);
-			option_no_hardlinks = 1;
-		}
-		if (copy_file_with_time(dest->buf, src->buf, 0666))
-			die_errno(_("failed to copy file to '%s'"), dest->buf);
-	}
-
-	if (iter_status != ITER_DONE) {
-		strbuf_setlen(src, src_len);
-		die(_("failed to iterate over '%s'"), src->buf);
-	}
-
-	strbuf_release(&realpath);
-}
-
-static void clone_local(const char *src_repo, const char *dest_repo)
-{
-	if (option_shared) {
-		struct strbuf alt = STRBUF_INIT;
-		get_common_dir(&alt, src_repo);
-		strbuf_addstr(&alt, "/objects");
-		add_to_alternates_file(alt.buf);
-		strbuf_release(&alt);
-	} else {
-		struct strbuf src = STRBUF_INIT;
-		struct strbuf dest = STRBUF_INIT;
-		get_common_dir(&src, src_repo);
-		get_common_dir(&dest, dest_repo);
-		strbuf_addstr(&src, "/objects");
-		strbuf_addstr(&dest, "/objects");
-		copy_or_link_directory(&src, &dest, src_repo);
-		strbuf_release(&src);
-		strbuf_release(&dest);
-	}
-
-	if (0 <= option_verbosity)
-		fprintf(stderr, _("done.\n"));
-}
-
-static const char *junk_work_tree;
-static int junk_work_tree_flags;
-static const char *junk_git_dir;
-static int junk_git_dir_flags;
-static enum {
-	JUNK_LEAVE_NONE,
-	JUNK_LEAVE_REPO,
-	JUNK_LEAVE_ALL
-} junk_mode = JUNK_LEAVE_NONE;
-
-static const char junk_leave_repo_msg[] =
-N_("Clone succeeded, but checkout failed.\n"
-   "You can inspect what was checked out with 'git status'\n"
-   "and retry with 'git restore --source=HEAD :/'\n");
-
-static void remove_junk(void)
-{
-	struct strbuf sb = STRBUF_INIT;
-
-	switch (junk_mode) {
-	case JUNK_LEAVE_REPO:
-		warning("%s", _(junk_leave_repo_msg));
-		/* fall-through */
-	case JUNK_LEAVE_ALL:
-		return;
-	default:
-		/* proceed to removal */
-		break;
-	}
-
-	if (junk_git_dir) {
-		strbuf_addstr(&sb, junk_git_dir);
-		remove_dir_recursively(&sb, junk_git_dir_flags);
-		strbuf_reset(&sb);
-	}
-	if (junk_work_tree) {
-		strbuf_addstr(&sb, junk_work_tree);
-		remove_dir_recursively(&sb, junk_work_tree_flags);
-	}
-	strbuf_release(&sb);
-}
-
-static void remove_junk_on_signal(int signo)
-{
-	remove_junk();
-	sigchain_pop(signo);
-	raise(signo);
-}
-
-static struct ref *find_remote_branch(const struct ref *refs, const char *branch)
-{
-	struct ref *ref;
-	struct strbuf head = STRBUF_INIT;
-	strbuf_addstr(&head, "refs/heads/");
-	strbuf_addstr(&head, branch);
-	ref = find_ref_by_name(refs, head.buf);
-	strbuf_release(&head);
-
-	if (ref)
-		return ref;
-
-	strbuf_addstr(&head, "refs/tags/");
-	strbuf_addstr(&head, branch);
-	ref = find_ref_by_name(refs, head.buf);
-	strbuf_release(&head);
-
-	return ref;
-}
-
-static struct ref *wanted_peer_refs(const struct ref *refs,
-		struct refspec *refspec)
-{
-	struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
-	struct ref *local_refs = head;
-	struct ref **tail = head ? &head->next : &local_refs;
-
-	if (option_single_branch) {
-		struct ref *remote_head = NULL;
-
-		if (!option_branch)
-			remote_head = guess_remote_head(head, refs, 0);
-		else {
-			local_refs = NULL;
-			tail = &local_refs;
-			remote_head = copy_ref(find_remote_branch(refs, option_branch));
-		}
-
-		if (!remote_head && option_branch)
-			warning(_("Could not find remote branch %s to clone."),
-				option_branch);
-		else {
-			int i;
-			for (i = 0; i < refspec->nr; i++)
-				get_fetch_map(remote_head, &refspec->items[i],
-					      &tail, 0);
-
-			/* if --branch=tag, pull the requested tag explicitly */
-			get_fetch_map(remote_head, tag_refspec, &tail, 0);
-		}
-	} else {
-		int i;
-		for (i = 0; i < refspec->nr; i++)
-			get_fetch_map(refs, &refspec->items[i], &tail, 0);
-	}
-
-	if (!option_mirror && !option_single_branch && !option_no_tags)
-		get_fetch_map(refs, tag_refspec, &tail, 0);
-
-	return local_refs;
-}
-
-static void write_remote_refs(const struct ref *local_refs)
-{
-	const struct ref *r;
-
-	struct ref_transaction *t;
-	struct strbuf err = STRBUF_INIT;
-
-	t = ref_transaction_begin(&err);
-	if (!t)
-		die("%s", err.buf);
-
-	for (r = local_refs; r; r = r->next) {
-		if (!r->peer_ref)
-			continue;
-		if (ref_transaction_create(t, r->peer_ref->name, &r->old_oid,
-					   0, NULL, &err))
-			die("%s", err.buf);
-	}
-
-	if (initial_ref_transaction_commit(t, &err))
-		die("%s", err.buf);
-
-	strbuf_release(&err);
-	ref_transaction_free(t);
-}
-
-static void write_followtags(const struct ref *refs, const char *msg)
-{
-	const struct ref *ref;
-	for (ref = refs; ref; ref = ref->next) {
-		if (!starts_with(ref->name, "refs/tags/"))
-			continue;
-		if (ends_with(ref->name, "^{}"))
-			continue;
-		if (!has_object_file_with_flags(&ref->old_oid,
-						OBJECT_INFO_QUICK |
-						OBJECT_INFO_SKIP_FETCH_OBJECT))
-			continue;
-		update_ref(msg, ref->name, &ref->old_oid, NULL, 0,
-			   UPDATE_REFS_DIE_ON_ERR);
-	}
-}
-
-static int iterate_ref_map(void *cb_data, struct object_id *oid)
-{
-	struct ref **rm = cb_data;
-	struct ref *ref = *rm;
-
-	/*
-	 * Skip anything missing a peer_ref, which we are not
-	 * actually going to write a ref for.
-	 */
-	while (ref && !ref->peer_ref)
-		ref = ref->next;
-	/* Returning -1 notes "end of list" to the caller. */
-	if (!ref)
-		return -1;
-
-	oidcpy(oid, &ref->old_oid);
-	*rm = ref->next;
-	return 0;
-}
-
-static void update_remote_refs(const struct ref *refs,
-			       const struct ref *mapped_refs,
-			       const struct ref *remote_head_points_at,
-			       const char *branch_top,
-			       const char *msg,
-			       struct transport *transport,
-			       int check_connectivity)
-{
-	const struct ref *rm = mapped_refs;
-
-	if (check_connectivity) {
-		struct check_connected_options opt = CHECK_CONNECTED_INIT;
-
-		opt.transport = transport;
-		opt.progress = transport->progress;
-
-		if (check_connected(iterate_ref_map, &rm, &opt))
-			die(_("remote did not send all necessary objects"));
-	}
-
-	if (refs) {
-		write_remote_refs(mapped_refs);
-		if (option_single_branch && !option_no_tags)
-			write_followtags(refs, msg);
-	}
-
-	if (remote_head_points_at && !option_bare) {
-		struct strbuf head_ref = STRBUF_INIT;
-		strbuf_addstr(&head_ref, branch_top);
-		strbuf_addstr(&head_ref, "HEAD");
-		if (create_symref(head_ref.buf,
-				  remote_head_points_at->peer_ref->name,
-				  msg) < 0)
-			die(_("unable to update %s"), head_ref.buf);
-		strbuf_release(&head_ref);
-	}
-}
-
-static void update_head(const struct ref *our, const struct ref *remote,
-			const char *msg)
-{
-	const char *head;
-	if (our && skip_prefix(our->name, "refs/heads/", &head)) {
-		/* Local default branch link */
-		if (create_symref("HEAD", our->name, NULL) < 0)
-			die(_("unable to update HEAD"));
-		if (!option_bare) {
-			update_ref(msg, "HEAD", &our->old_oid, NULL, 0,
-				   UPDATE_REFS_DIE_ON_ERR);
-			install_branch_config(0, head, option_origin, our->name);
-		}
-	} else if (our) {
-		struct commit *c = lookup_commit_reference(the_repository,
-							   &our->old_oid);
-		/* --branch specifies a non-branch (i.e. tags), detach HEAD */
-		update_ref(msg, "HEAD", &c->object.oid, NULL, REF_NO_DEREF,
-			   UPDATE_REFS_DIE_ON_ERR);
-	} else if (remote) {
-		/*
-		 * We know remote HEAD points to a non-branch, or
-		 * HEAD points to a branch but we don't know which one.
-		 * Detach HEAD in all these cases.
-		 */
-		update_ref(msg, "HEAD", &remote->old_oid, NULL, REF_NO_DEREF,
-			   UPDATE_REFS_DIE_ON_ERR);
-	}
-}
-
-static int git_sparse_checkout_init(const char *repo)
-{
-	struct strvec argv = STRVEC_INIT;
-	int result = 0;
-	strvec_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.v, RUN_GIT_CMD)) {
-		error(_("failed to initialize sparse-checkout"));
-		result = 1;
-	}
-
-	strvec_clear(&argv);
-	return result;
-}
-
-static int checkout(int submodule_progress)
-{
-	struct object_id oid;
-	char *head;
-	struct lock_file lock_file = LOCK_INIT;
-	struct unpack_trees_options opts;
-	struct tree *tree;
-	struct tree_desc t;
-	int err = 0;
-
-	if (option_no_checkout)
-		return 0;
-
-	head = resolve_refdup("HEAD", RESOLVE_REF_READING, &oid, NULL);
-	if (!head) {
-		warning(_("remote HEAD refers to nonexistent ref, "
-			  "unable to checkout.\n"));
-		return 0;
-	}
-	if (!strcmp(head, "HEAD")) {
-		if (advice_detached_head)
-			detach_advice(oid_to_hex(&oid));
-		FREE_AND_NULL(head);
-	} else {
-		if (!starts_with(head, "refs/heads/"))
-			die(_("HEAD not found below refs/heads!"));
-	}
-
-	/* We need to be in the new work tree for the checkout */
-	setup_work_tree();
-
-	hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
-
-	memset(&opts, 0, sizeof opts);
-	opts.update = 1;
-	opts.merge = 1;
-	opts.clone = 1;
-	opts.fn = oneway_merge;
-	opts.verbose_update = (option_verbosity >= 0);
-	opts.src_index = &the_index;
-	opts.dst_index = &the_index;
-	init_checkout_metadata(&opts.meta, head, &oid, NULL);
-
-	tree = parse_tree_indirect(&oid);
-	parse_tree(tree);
-	init_tree_desc(&t, tree->buffer, tree->size);
-	if (unpack_trees(1, &t, &opts) < 0)
-		die(_("unable to checkout working tree"));
-
-	free(head);
-
-	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),
-			   oid_to_hex(&oid), "1", NULL);
-
-	if (!err && (option_recurse_submodules.nr > 0)) {
-		struct strvec args = STRVEC_INIT;
-		strvec_pushl(&args, "submodule", "update", "--require-init", "--recursive", NULL);
-
-		if (option_shallow_submodules == 1)
-			strvec_push(&args, "--depth=1");
-
-		if (max_jobs != -1)
-			strvec_pushf(&args, "--jobs=%d", max_jobs);
-
-		if (submodule_progress)
-			strvec_push(&args, "--progress");
-
-		if (option_verbosity < 0)
-			strvec_push(&args, "--quiet");
-
-		if (option_remote_submodules) {
-			strvec_push(&args, "--remote");
-			strvec_push(&args, "--no-fetch");
-		}
-
-		if (option_single_branch >= 0)
-			strvec_push(&args, option_single_branch ?
-					       "--single-branch" :
-					       "--no-single-branch");
-
-		err = run_command_v_opt(args.v, RUN_GIT_CMD);
-		strvec_clear(&args);
-	}
-
-	return err;
-}
-
-static int write_one_config(const char *key, const char *value, void *data)
-{
-	return git_config_set_multivar_gently(key,
-					      value ? value : "true",
-					      CONFIG_REGEX_NONE, 0);
-}
-
-static void write_config(struct string_list *config)
-{
-	int i;
-
-	for (i = 0; i < config->nr; i++) {
-		if (git_config_parse_parameter(config->items[i].string,
-					       write_one_config, NULL) < 0)
-			die(_("unable to write parameters to config file"));
-	}
-}
-
-static void write_refspec_config(const char *src_ref_prefix,
-		const struct ref *our_head_points_at,
-		const struct ref *remote_head_points_at,
-		struct strbuf *branch_top)
-{
-	struct strbuf key = STRBUF_INIT;
-	struct strbuf value = STRBUF_INIT;
-
-	if (option_mirror || !option_bare) {
-		if (option_single_branch && !option_mirror) {
-			if (option_branch) {
-				if (starts_with(our_head_points_at->name, "refs/tags/"))
-					strbuf_addf(&value, "+%s:%s", our_head_points_at->name,
-						our_head_points_at->name);
-				else
-					strbuf_addf(&value, "+%s:%s%s", our_head_points_at->name,
-						branch_top->buf, option_branch);
-			} else if (remote_head_points_at) {
-				const char *head = remote_head_points_at->name;
-				if (!skip_prefix(head, "refs/heads/", &head))
-					BUG("remote HEAD points at non-head?");
-
-				strbuf_addf(&value, "+%s:%s%s", remote_head_points_at->name,
-						branch_top->buf, head);
-			}
-			/*
-			 * otherwise, the next "git fetch" will
-			 * simply fetch from HEAD without updating
-			 * any remote-tracking branch, which is what
-			 * we want.
-			 */
-		} else {
-			strbuf_addf(&value, "+%s*:%s*", src_ref_prefix, branch_top->buf);
-		}
-		/* Configure the remote */
-		if (value.len) {
-			strbuf_addf(&key, "remote.%s.fetch", option_origin);
-			git_config_set_multivar(key.buf, value.buf, "^$", 0);
-			strbuf_reset(&key);
-
-			if (option_mirror) {
-				strbuf_addf(&key, "remote.%s.mirror", option_origin);
-				git_config_set(key.buf, "true");
-				strbuf_reset(&key);
-			}
-		}
-	}
-
-	strbuf_release(&key);
-	strbuf_release(&value);
-}
-
-static void dissociate_from_references(void)
-{
-	static const char* argv[] = { "repack", "-a", "-d", NULL };
-	char *alternates = git_pathdup("objects/info/alternates");
-
-	if (!access(alternates, F_OK)) {
-		if (run_command_v_opt(argv, RUN_GIT_CMD|RUN_COMMAND_NO_STDIN))
-			die(_("cannot repack to clean up"));
-		if (unlink(alternates) && errno != ENOENT)
-			die_errno(_("cannot unlink temporary alternates file"));
-	}
-	free(alternates);
-}
-
-static int path_exists(const char *path)
-{
-	struct stat sb;
-	return !stat(path, &sb);
-}
-
-int cmd_clone(int argc, const char **argv, const char *prefix)
-{
-	int is_bundle = 0, is_local;
-	const char *repo_name, *repo, *work_tree, *git_dir;
-	char *path, *dir, *display_repo = NULL;
-	int dest_exists, real_dest_exists = 0;
-	const struct ref *refs, *remote_head;
-	const struct ref *remote_head_points_at;
-	const struct ref *our_head_points_at;
-	struct ref *mapped_refs;
-	const struct ref *ref;
-	struct strbuf key = STRBUF_INIT;
-	struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;
-	struct transport *transport = NULL;
-	const char *src_ref_prefix = "refs/heads/";
-	struct remote *remote;
-	int err = 0, complete_refs_before_fetch = 1;
-	int submodule_progress;
-
-	struct strvec ref_prefixes = STRVEC_INIT;
-
-	packet_trace_identity("clone");
-	argc = parse_options(argc, argv, prefix, builtin_clone_options,
-			     builtin_clone_usage, 0);
-
-	if (argc > 2)
-		usage_msg_opt(_("Too many arguments."),
-			builtin_clone_usage, builtin_clone_options);
-
-	if (argc == 0)
-		usage_msg_opt(_("You must specify a repository to clone."),
-			builtin_clone_usage, builtin_clone_options);
-
-	if (option_depth || option_since || option_not.nr)
-		deepen = 1;
-	if (option_single_branch == -1)
-		option_single_branch = deepen ? 1 : 0;
-
-	if (option_mirror)
-		option_bare = 1;
-
-	if (option_bare) {
-		if (option_origin)
-			die(_("--bare and --origin %s options are incompatible."),
-			    option_origin);
-		if (real_git_dir)
-			die(_("--bare and --separate-git-dir are incompatible."));
-		option_no_checkout = 1;
-	}
-
-	if (!option_origin)
-		option_origin = "origin";
-
-	repo_name = argv[0];
-
-	path = get_repo_path(repo_name, &is_bundle);
-	if (path)
-		repo = absolute_pathdup(repo_name);
-	else if (strchr(repo_name, ':')) {
-		repo = repo_name;
-		display_repo = transport_anonymize_url(repo);
-	} else
-		die(_("repository '%s' does not exist"), repo_name);
-
-	/* no need to be strict, transport_set_option() will validate it again */
-	if (option_depth && atoi(option_depth) < 1)
-		die(_("depth %s is not a positive number"), option_depth);
-
-	if (argc == 2)
-		dir = xstrdup(argv[1]);
-	else
-		dir = guess_dir_name(repo_name, is_bundle, option_bare);
-	strip_trailing_slashes(dir);
-
-	dest_exists = path_exists(dir);
-	if (dest_exists && !is_empty_dir(dir))
-		die(_("destination path '%s' already exists and is not "
-			"an empty directory."), dir);
-
-	if (real_git_dir) {
-		real_dest_exists = path_exists(real_git_dir);
-		if (real_dest_exists && !is_empty_dir(real_git_dir))
-			die(_("repository path '%s' already exists and is not "
-				"an empty directory."), real_git_dir);
-	}
-
-
-	strbuf_addf(&reflog_msg, "clone: from %s",
-		    display_repo ? display_repo : repo);
-	free(display_repo);
-
-	if (option_bare)
-		work_tree = NULL;
-	else {
-		work_tree = getenv("GIT_WORK_TREE");
-		if (work_tree && path_exists(work_tree))
-			die(_("working tree '%s' already exists."), work_tree);
-	}
-
-	if (option_bare || work_tree)
-		git_dir = xstrdup(dir);
-	else {
-		work_tree = dir;
-		git_dir = mkpathdup("%s/.git", dir);
-	}
-
-	atexit(remove_junk);
-	sigchain_push_common(remove_junk_on_signal);
-
-	if (!option_bare) {
-		if (safe_create_leading_directories_const(work_tree) < 0)
-			die_errno(_("could not create leading directories of '%s'"),
-				  work_tree);
-		if (dest_exists)
-			junk_work_tree_flags |= REMOVE_DIR_KEEP_TOPLEVEL;
-		else if (mkdir(work_tree, 0777))
-			die_errno(_("could not create work tree dir '%s'"),
-				  work_tree);
-		junk_work_tree = work_tree;
-		set_git_work_tree(work_tree);
-	}
-
-	if (real_git_dir) {
-		if (real_dest_exists)
-			junk_git_dir_flags |= REMOVE_DIR_KEEP_TOPLEVEL;
-		junk_git_dir = real_git_dir;
-	} else {
-		if (dest_exists)
-			junk_git_dir_flags |= REMOVE_DIR_KEEP_TOPLEVEL;
-		junk_git_dir = git_dir;
-	}
-	if (safe_create_leading_directories_const(git_dir) < 0)
-		die(_("could not create leading directories of '%s'"), git_dir);
-
-	if (0 <= option_verbosity) {
-		if (option_bare)
-			fprintf(stderr, _("Cloning into bare repository '%s'...\n"), dir);
-		else
-			fprintf(stderr, _("Cloning into '%s'...\n"), dir);
-	}
-
-	if (option_recurse_submodules.nr > 0) {
-		struct string_list_item *item;
-		struct strbuf sb = STRBUF_INIT;
-
-		/* remove duplicates */
-		string_list_sort(&option_recurse_submodules);
-		string_list_remove_duplicates(&option_recurse_submodules, 0);
-
-		/*
-		 * NEEDSWORK: In a multi-working-tree world, this needs to be
-		 * set in the per-worktree config.
-		 */
-		for_each_string_list_item(item, &option_recurse_submodules) {
-			strbuf_addf(&sb, "submodule.active=%s",
-				    item->string);
-			string_list_append(&option_config,
-					   strbuf_detach(&sb, NULL));
-		}
-
-		if (option_required_reference.nr &&
-		    option_optional_reference.nr)
-			die(_("clone --recursive is not compatible with "
-			      "both --reference and --reference-if-able"));
-		else if (option_required_reference.nr) {
-			string_list_append(&option_config,
-				"submodule.alternateLocation=superproject");
-			string_list_append(&option_config,
-				"submodule.alternateErrorStrategy=die");
-		} else if (option_optional_reference.nr) {
-			string_list_append(&option_config,
-				"submodule.alternateLocation=superproject");
-			string_list_append(&option_config,
-				"submodule.alternateErrorStrategy=info");
-		}
-	}
-
-	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
-		INIT_DB_QUIET);
-
-	if (real_git_dir)
-		git_dir = real_git_dir;
-
-	write_config(&option_config);
-
-	git_config(git_default_config, NULL);
-
-	if (option_bare) {
-		if (option_mirror)
-			src_ref_prefix = "refs/";
-		strbuf_addstr(&branch_top, src_ref_prefix);
-
-		git_config_set("core.bare", "true");
-	} else {
-		strbuf_addf(&branch_top, "refs/remotes/%s/", option_origin);
-	}
-
-	strbuf_addf(&key, "remote.%s.url", option_origin);
-	git_config_set(key.buf, repo);
-	strbuf_reset(&key);
-
-	if (option_no_tags) {
-		strbuf_addf(&key, "remote.%s.tagOpt", option_origin);
-		git_config_set(key.buf, "--no-tags");
-		strbuf_reset(&key);
-	}
-
-	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);
-
-	refspec_appendf(&remote->fetch, "+%s*:%s*", src_ref_prefix,
-			branch_top.buf);
-
-	transport = transport_get(remote, remote->url[0]);
-	transport_set_verbosity(transport, option_verbosity, option_progress);
-	transport->family = family;
-
-	path = get_repo_path(remote->url[0], &is_bundle);
-	is_local = option_local != 0 && path && !is_bundle;
-	if (is_local) {
-		if (option_depth)
-			warning(_("--depth is ignored in local clones; use file:// instead."));
-		if (option_since)
-			warning(_("--shallow-since is ignored in local clones; use file:// instead."));
-		if (option_not.nr)
-			warning(_("--shallow-exclude is ignored in local clones; use file:// instead."));
-		if (filter_options.choice)
-			warning(_("--filter is ignored in local clones; use file:// instead."));
-		if (!access(mkpath("%s/shallow", path), F_OK)) {
-			if (option_local > 0)
-				warning(_("source repository is shallow, ignoring --local"));
-			is_local = 0;
-		}
-	}
-	if (option_local > 0 && !is_local)
-		warning(_("--local is ignored"));
-	transport->cloning = 1;
-
-	transport_set_option(transport, TRANS_OPT_KEEP, "yes");
-
-	if (option_depth)
-		transport_set_option(transport, TRANS_OPT_DEPTH,
-				     option_depth);
-	if (option_since)
-		transport_set_option(transport, TRANS_OPT_DEEPEN_SINCE,
-				     option_since);
-	if (option_not.nr)
-		transport_set_option(transport, TRANS_OPT_DEEPEN_NOT,
-				     (const char *)&option_not);
-	if (option_single_branch)
-		transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1");
-
-	if (option_upload_pack)
-		transport_set_option(transport, TRANS_OPT_UPLOADPACK,
-				     option_upload_pack);
-
-	if (server_options.nr)
-		transport->server_options = &server_options;
-
-	if (filter_options.choice) {
-		const char *spec =
-			expand_list_objects_filter_spec(&filter_options);
-		transport_set_option(transport, TRANS_OPT_LIST_OBJECTS_FILTER,
-				     spec);
-		transport_set_option(transport, TRANS_OPT_FROM_PROMISOR, "1");
-	}
-
-	if (transport->smart_options && !deepen && !filter_options.choice)
-		transport->smart_options->check_self_contained_and_connected = 1;
-
-
-	strvec_push(&ref_prefixes, "HEAD");
-	refspec_ref_prefixes(&remote->fetch, &ref_prefixes);
-	if (option_branch)
-		expand_ref_prefix(&ref_prefixes, option_branch);
-	if (!option_no_tags)
-		strvec_push(&ref_prefixes, "refs/tags/");
-
-	refs = transport_get_remote_refs(transport, &ref_prefixes);
-
-	if (refs) {
-		int hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
-
-		/*
-		 * Now that we know what algorithm the remote side is using,
-		 * let's set ours to the same thing.
-		 */
-		initialize_repository_version(hash_algo, 1);
-		repo_set_hash_algo(the_repository, hash_algo);
-
-		mapped_refs = wanted_peer_refs(refs, &remote->fetch);
-		/*
-		 * transport_get_remote_refs() may return refs with null sha-1
-		 * in mapped_refs (see struct transport->get_refs_list
-		 * comment). In that case we need fetch it early because
-		 * remote_head code below relies on it.
-		 *
-		 * for normal clones, transport_get_remote_refs() should
-		 * return reliable ref set, we can delay cloning until after
-		 * remote HEAD check.
-		 */
-		for (ref = refs; ref; ref = ref->next)
-			if (is_null_oid(&ref->old_oid)) {
-				complete_refs_before_fetch = 0;
-				break;
-			}
-
-		if (!is_local && !complete_refs_before_fetch)
-			transport_fetch_refs(transport, mapped_refs);
-
-		remote_head = find_ref_by_name(refs, "HEAD");
-		remote_head_points_at =
-			guess_remote_head(remote_head, mapped_refs, 0);
-
-		if (option_branch) {
-			our_head_points_at =
-				find_remote_branch(mapped_refs, option_branch);
-
-			if (!our_head_points_at)
-				die(_("Remote branch %s not found in upstream %s"),
-				    option_branch, option_origin);
-		}
-		else
-			our_head_points_at = remote_head_points_at;
-	}
-	else {
-		if (option_branch)
-			die(_("Remote branch %s not found in upstream %s"),
-					option_branch, option_origin);
-
-		warning(_("You appear to have cloned an empty repository."));
-		mapped_refs = NULL;
-		our_head_points_at = NULL;
-		remote_head_points_at = NULL;
-		remote_head = NULL;
-		option_no_checkout = 1;
-		if (!option_bare) {
-			const char *branch = git_default_branch_name();
-			char *ref = xstrfmt("refs/heads/%s", branch);
-
-			install_branch_config(0, branch, option_origin, ref);
-			free(ref);
-		}
-	}
-
-	write_refspec_config(src_ref_prefix, our_head_points_at,
-			remote_head_points_at, &branch_top);
-
-	if (filter_options.choice)
-		partial_clone_register(option_origin, &filter_options);
-
-	if (is_local)
-		clone_local(path, git_dir);
-	else if (refs && complete_refs_before_fetch)
-		transport_fetch_refs(transport, mapped_refs);
-
-	update_remote_refs(refs, mapped_refs, remote_head_points_at,
-			   branch_top.buf, reflog_msg.buf, transport,
-			   !is_local);
-
-	update_head(our_head_points_at, remote_head, reflog_msg.buf);
-
-	/*
-	 * We want to show progress for recursive submodule clones iff
-	 * we did so for the main clone. But only the transport knows
-	 * the final decision for this flag, so we need to rescue the value
-	 * before we free the transport.
-	 */
-	submodule_progress = transport->progress;
-
-	transport_unlock_pack(transport);
-	transport_disconnect(transport);
-
-	if (option_dissociate) {
-		close_object_store(the_repository->objects);
-		dissociate_from_references();
-	}
-
-	junk_mode = JUNK_LEAVE_REPO;
-	err = checkout(submodule_progress);
-
-	strbuf_release(&reflog_msg);
-	strbuf_release(&branch_top);
-	strbuf_release(&key);
-	junk_mode = JUNK_LEAVE_ALL;
-
-	strvec_clear(&ref_prefixes);
-	return err;
-}
diff --git a/third_party/git/builtin/column.c b/third_party/git/builtin/column.c
deleted file mode 100644
index e815e148aa18..000000000000
--- a/third_party/git/builtin/column.c
+++ /dev/null
@@ -1,59 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "strbuf.h"
-#include "parse-options.h"
-#include "string-list.h"
-#include "column.h"
-
-static const char * const builtin_column_usage[] = {
-	N_("git column [<options>]"),
-	NULL
-};
-static unsigned int colopts;
-
-static int column_config(const char *var, const char *value, void *cb)
-{
-	return git_column_config(var, value, cb, &colopts);
-}
-
-int cmd_column(int argc, const char **argv, const char *prefix)
-{
-	struct string_list list = STRING_LIST_INIT_DUP;
-	struct strbuf sb = STRBUF_INIT;
-	struct column_options copts;
-	const char *command = NULL, *real_command = NULL;
-	struct option options[] = {
-		OPT_STRING(0, "command", &real_command, N_("name"), N_("lookup config vars")),
-		OPT_COLUMN(0, "mode", &colopts, N_("layout to use")),
-		OPT_INTEGER(0, "raw-mode", &colopts, N_("layout to use")),
-		OPT_INTEGER(0, "width", &copts.width, N_("Maximum width")),
-		OPT_STRING(0, "indent", &copts.indent, N_("string"), N_("Padding space on left border")),
-		OPT_INTEGER(0, "nl", &copts.nl, N_("Padding space on right border")),
-		OPT_INTEGER(0, "padding", &copts.padding, N_("Padding space between columns")),
-		OPT_END()
-	};
-
-	/* This one is special and must be the first one */
-	if (argc > 1 && starts_with(argv[1], "--command=")) {
-		command = argv[1] + 10;
-		git_config(column_config, (void *)command);
-	} else
-		git_config(column_config, NULL);
-
-	memset(&copts, 0, sizeof(copts));
-	copts.padding = 1;
-	argc = parse_options(argc, argv, prefix, options, builtin_column_usage, 0);
-	if (argc)
-		usage_with_options(builtin_column_usage, options);
-	if (real_command || command) {
-		if (!real_command || !command || strcmp(real_command, command))
-			die(_("--command must be the first argument"));
-	}
-	finalize_colopts(&colopts, -1);
-	while (!strbuf_getline(&sb, stdin))
-		string_list_append(&list, sb.buf);
-
-	print_columns(&list, colopts, &copts);
-	return 0;
-}
diff --git a/third_party/git/builtin/commit-graph.c b/third_party/git/builtin/commit-graph.c
deleted file mode 100644
index 78fa08f43af5..000000000000
--- a/third_party/git/builtin/commit-graph.c
+++ /dev/null
@@ -1,342 +0,0 @@
-#include "builtin.h"
-#include "config.h"
-#include "dir.h"
-#include "lockfile.h"
-#include "parse-options.h"
-#include "repository.h"
-#include "commit-graph.h"
-#include "object-store.h"
-#include "progress.h"
-#include "tag.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[=<strategy>]] [--reachable|--stdin-packs|--stdin-commits] "
-	   "[--changed-paths] [--[no-]max-new-filters <n>] [--[no-]progress] "
-	   "<split options>"),
-	NULL
-};
-
-static const char * const builtin_commit_graph_verify_usage[] = {
-	N_("git commit-graph verify [--object-dir <objdir>] [--shallow] [--[no-]progress]"),
-	NULL
-};
-
-static const char * const builtin_commit_graph_write_usage[] = {
-	N_("git commit-graph write [--object-dir <objdir>] [--append] "
-	   "[--split[=<strategy>]] [--reachable|--stdin-packs|--stdin-commits] "
-	   "[--changed-paths] [--[no-]max-new-filters <n>] [--[no-]progress] "
-	   "<split options>"),
-	NULL
-};
-
-static struct opts_commit_graph {
-	const char *obj_dir;
-	int reachable;
-	int stdin_packs;
-	int stdin_commits;
-	int append;
-	int split;
-	int shallow;
-	int progress;
-	int enable_changed_paths;
-} 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);
-	struct strbuf odb_path_real = STRBUF_INIT;
-
-	prepare_alt_odb(r);
-	for (odb = r->objects->odb; odb; odb = odb->next) {
-		strbuf_realpath(&odb_path_real, odb->path, 1);
-		if (!strcmp(obj_dir_real, odb_path_real.buf))
-			break;
-	}
-
-	free(obj_dir_real);
-	strbuf_release(&odb_path_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;
-	struct stat st;
-	int flags = 0;
-
-	static struct option builtin_commit_graph_verify_options[] = {
-		OPT_STRING(0, "object-dir", &opts.obj_dir,
-			   N_("dir"),
-			   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);
-
-	if (!opts.obj_dir)
-		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);
-	open_ok = open_commit_graph(graph_name, &fd, &st);
-	if (!open_ok && errno != ENOENT)
-		die_errno(_("Could not open commit-graph '%s'"), graph_name);
-
-	FREE_AND_NULL(graph_name);
-
-	if (open_ok)
-		graph = load_commit_graph_one_fd_st(the_repository, fd, &st, odb);
-	else
-		graph = read_commit_graph_one(the_repository, odb);
-
-	/* Return failure if open_ok predicted success */
-	if (!graph)
-		return !!open_ok;
-
-	UNLEAK(graph);
-	return verify_commit_graph(the_repository, graph, flags);
-}
-
-extern int read_replace_refs;
-static struct commit_graph_opts write_opts;
-
-static int write_option_parse_split(const struct option *opt, const char *arg,
-				    int unset)
-{
-	enum commit_graph_split_flags *flags = opt->value;
-
-	BUG_ON_OPT_NEG(unset);
-
-	opts.split = 1;
-	if (!arg)
-		return 0;
-
-	if (!strcmp(arg, "no-merge"))
-		*flags = COMMIT_GRAPH_SPLIT_MERGE_PROHIBITED;
-	else if (!strcmp(arg, "replace"))
-		*flags = COMMIT_GRAPH_SPLIT_REPLACE;
-	else
-		die(_("unrecognized --split argument, %s"), arg);
-
-	return 0;
-}
-
-static int read_one_commit(struct oidset *commits, struct progress *progress,
-			   const char *hash)
-{
-	struct object *result;
-	struct object_id oid;
-	const char *end;
-
-	if (parse_oid_hex(hash, &oid, &end))
-		return error(_("unexpected non-hex object ID: %s"), hash);
-
-	result = deref_tag(the_repository, parse_object(the_repository, &oid),
-			   NULL, 0);
-	if (!result)
-		return error(_("invalid object: %s"), hash);
-	else if (object_as_type(result, OBJ_COMMIT, 1))
-		oidset_insert(commits, &result->oid);
-
-	display_progress(progress, oidset_size(commits));
-
-	return 0;
-}
-
-static int write_option_max_new_filters(const struct option *opt,
-					const char *arg,
-					int unset)
-{
-	int *to = opt->value;
-	if (unset)
-		*to = -1;
-	else {
-		const char *s;
-		*to = strtol(arg, (char **)&s, 10);
-		if (*s)
-			return error(_("%s expects a numerical value"),
-				     optname(opt, opt->flags));
-	}
-	return 0;
-}
-
-static int git_commit_graph_write_config(const char *var, const char *value,
-					 void *cb)
-{
-	if (!strcmp(var, "commitgraph.maxnewfilters"))
-		write_opts.max_new_filters = git_config_int(var, value);
-	/*
-	 * No need to fall-back to 'git_default_config', since this was already
-	 * called in 'cmd_commit_graph()'.
-	 */
-	return 0;
-}
-
-static int graph_write(int argc, const char **argv)
-{
-	struct string_list pack_indexes = STRING_LIST_INIT_NODUP;
-	struct strbuf buf = STRBUF_INIT;
-	struct oidset commits = OIDSET_INIT;
-	struct object_directory *odb = NULL;
-	int result = 0;
-	enum commit_graph_write_flags flags = 0;
-	struct progress *progress = NULL;
-
-	static struct option builtin_commit_graph_write_options[] = {
-		OPT_STRING(0, "object-dir", &opts.obj_dir,
-			N_("dir"),
-			N_("The object directory to store the graph")),
-		OPT_BOOL(0, "reachable", &opts.reachable,
-			N_("start walk at all refs")),
-		OPT_BOOL(0, "stdin-packs", &opts.stdin_packs,
-			N_("scan pack-indexes listed by stdin for commits")),
-		OPT_BOOL(0, "stdin-commits", &opts.stdin_commits,
-			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, "changed-paths", &opts.enable_changed_paths,
-			N_("enable computation for changed paths")),
-		OPT_BOOL(0, "progress", &opts.progress, N_("force progress reporting")),
-		OPT_CALLBACK_F(0, "split", &write_opts.split_flags, NULL,
-			N_("allow writing an incremental commit-graph file"),
-			PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
-			write_option_parse_split),
-		OPT_INTEGER(0, "max-commits", &write_opts.max_commits,
-			N_("maximum number of commits in a non-base split commit-graph")),
-		OPT_INTEGER(0, "size-multiple", &write_opts.size_multiple,
-			N_("maximum ratio between two levels of a split commit-graph")),
-		OPT_EXPIRY_DATE(0, "expire-time", &write_opts.expire_time,
-			N_("only expire files older than a given date-time")),
-		OPT_CALLBACK_F(0, "max-new-filters", &write_opts.max_new_filters,
-			NULL, N_("maximum number of changed-path Bloom filters to compute"),
-			0, write_option_max_new_filters),
-		OPT_END(),
-	};
-
-	opts.progress = isatty(2);
-	opts.enable_changed_paths = -1;
-	write_opts.size_multiple = 2;
-	write_opts.max_commits = 0;
-	write_opts.expire_time = 0;
-	write_opts.max_new_filters = -1;
-
-	trace2_cmd_mode("write");
-
-	git_config(git_commit_graph_write_config, &opts);
-
-	argc = parse_options(argc, argv, NULL,
-			     builtin_commit_graph_write_options,
-			     builtin_commit_graph_write_usage, 0);
-
-	if (opts.reachable + opts.stdin_packs + opts.stdin_commits > 1)
-		die(_("use at most one of --reachable, --stdin-commits, or --stdin-packs"));
-	if (!opts.obj_dir)
-		opts.obj_dir = get_object_directory();
-	if (opts.append)
-		flags |= COMMIT_GRAPH_WRITE_APPEND;
-	if (opts.split)
-		flags |= COMMIT_GRAPH_WRITE_SPLIT;
-	if (opts.progress)
-		flags |= COMMIT_GRAPH_WRITE_PROGRESS;
-	if (!opts.enable_changed_paths)
-		flags |= COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS;
-	if (opts.enable_changed_paths == 1 ||
-	    git_env_bool(GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS, 0))
-		flags |= COMMIT_GRAPH_WRITE_BLOOM_FILTERS;
-
-	read_replace_refs = 0;
-	odb = find_odb(the_repository, opts.obj_dir);
-
-	if (opts.reachable) {
-		if (write_commit_graph_reachable(odb, flags, &write_opts))
-			return 1;
-		return 0;
-	}
-
-	if (opts.stdin_packs) {
-		while (strbuf_getline(&buf, stdin) != EOF)
-			string_list_append(&pack_indexes,
-					   strbuf_detach(&buf, NULL));
-	} else if (opts.stdin_commits) {
-		oidset_init(&commits, 0);
-		if (opts.progress)
-			progress = start_delayed_progress(
-				_("Collecting commits from input"), 0);
-
-		while (strbuf_getline(&buf, stdin) != EOF) {
-			if (read_one_commit(&commits, progress, buf.buf)) {
-				result = 1;
-				goto cleanup;
-			}
-		}
-
-		stop_progress(&progress);
-	}
-
-	if (write_commit_graph(odb,
-			       opts.stdin_packs ? &pack_indexes : NULL,
-			       opts.stdin_commits ? &commits : NULL,
-			       flags,
-			       &write_opts))
-		result = 1;
-
-cleanup:
-	string_list_clear(&pack_indexes, 0);
-	strbuf_release(&buf);
-	return result;
-}
-
-int cmd_commit_graph(int argc, const char **argv, const char *prefix)
-{
-	static struct option builtin_commit_graph_options[] = {
-		OPT_STRING(0, "object-dir", &opts.obj_dir,
-			N_("dir"),
-			N_("The object directory to store the graph")),
-		OPT_END(),
-	};
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage_with_options(builtin_commit_graph_usage,
-				   builtin_commit_graph_options);
-
-	git_config(git_default_config, NULL);
-	argc = parse_options(argc, argv, prefix,
-			     builtin_commit_graph_options,
-			     builtin_commit_graph_usage,
-			     PARSE_OPT_STOP_AT_NON_OPTION);
-
-	save_commit_buffer = 0;
-
-	if (argc > 0) {
-		if (!strcmp(argv[0], "verify"))
-			return graph_verify(argc, argv);
-		if (!strcmp(argv[0], "write"))
-			return graph_write(argc, argv);
-	}
-
-	usage_with_options(builtin_commit_graph_usage,
-			   builtin_commit_graph_options);
-}
diff --git a/third_party/git/builtin/commit-tree.c b/third_party/git/builtin/commit-tree.c
deleted file mode 100644
index 1031b9a491c5..000000000000
--- a/third_party/git/builtin/commit-tree.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * GIT - The information manager from hell
- *
- * Copyright (C) Linus Torvalds, 2005
- */
-#include "cache.h"
-#include "config.h"
-#include "object-store.h"
-#include "repository.h"
-#include "commit.h"
-#include "tree.h"
-#include "builtin.h"
-#include "utf8.h"
-#include "gpg-interface.h"
-#include "parse-options.h"
-
-static const char * const commit_tree_usage[] = {
-	N_("git commit-tree [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...] "
-		"[(-F <file>)...] <tree>"),
-	NULL
-};
-
-static const char *sign_commit;
-
-static void new_parent(struct commit *parent, struct commit_list **parents_p)
-{
-	struct object_id *oid = &parent->object.oid;
-	struct commit_list *parents;
-	for (parents = *parents_p; parents; parents = parents->next) {
-		if (parents->item == parent) {
-			error(_("duplicate parent %s ignored"), oid_to_hex(oid));
-			return;
-		}
-		parents_p = &parents->next;
-	}
-	commit_list_insert(parent, parents_p);
-}
-
-static int commit_tree_config(const char *var, const char *value, void *cb)
-{
-	int status = git_gpg_config(var, value, NULL);
-	if (status)
-		return status;
-	return git_default_config(var, value, cb);
-}
-
-static int parse_parent_arg_callback(const struct option *opt,
-		const char *arg, int unset)
-{
-	struct object_id oid;
-	struct commit_list **parents = opt->value;
-
-	BUG_ON_OPT_NEG_NOARG(unset, arg);
-
-	if (get_oid_commit(arg, &oid))
-		die(_("not a valid object name %s"), arg);
-
-	assert_oid_type(&oid, OBJ_COMMIT);
-	new_parent(lookup_commit(the_repository, &oid), parents);
-	return 0;
-}
-
-static int parse_message_arg_callback(const struct option *opt,
-		const char *arg, int unset)
-{
-	struct strbuf *buf = opt->value;
-
-	BUG_ON_OPT_NEG_NOARG(unset, arg);
-
-	if (buf->len)
-		strbuf_addch(buf, '\n');
-	strbuf_addstr(buf, arg);
-	strbuf_complete_line(buf);
-
-	return 0;
-}
-
-static int parse_file_arg_callback(const struct option *opt,
-		const char *arg, int unset)
-{
-	int fd;
-	struct strbuf *buf = opt->value;
-
-	BUG_ON_OPT_NEG_NOARG(unset, arg);
-
-	if (buf->len)
-		strbuf_addch(buf, '\n');
-	if (!strcmp(arg, "-"))
-		fd = 0;
-	else {
-		fd = open(arg, O_RDONLY);
-		if (fd < 0)
-			die_errno(_("git commit-tree: failed to open '%s'"), arg);
-	}
-	if (strbuf_read(buf, fd, 0) < 0)
-		die_errno(_("git commit-tree: failed to read '%s'"), arg);
-	if (fd && close(fd))
-		die_errno(_("git commit-tree: failed to close '%s'"), arg);
-
-	return 0;
-}
-
-int cmd_commit_tree(int argc, const char **argv, const char *prefix)
-{
-	static struct strbuf buffer = STRBUF_INIT;
-	struct commit_list *parents = NULL;
-	struct object_id tree_oid;
-	struct object_id commit_oid;
-
-	struct option options[] = {
-		OPT_CALLBACK_F('p', NULL, &parents, N_("parent"),
-			N_("id of a parent commit object"), PARSE_OPT_NONEG,
-			parse_parent_arg_callback),
-		OPT_CALLBACK_F('m', NULL, &buffer, N_("message"),
-			N_("commit message"), PARSE_OPT_NONEG,
-			parse_message_arg_callback),
-		OPT_CALLBACK_F('F', NULL, &buffer, N_("file"),
-			N_("read commit log message from file"), PARSE_OPT_NONEG,
-			parse_file_arg_callback),
-		{ OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
-			N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
-		OPT_END()
-	};
-
-	git_config(commit_tree_config, NULL);
-
-	if (argc < 2 || !strcmp(argv[1], "-h"))
-		usage_with_options(commit_tree_usage, options);
-
-	argc = parse_options(argc, argv, prefix, options, commit_tree_usage, 0);
-
-	if (argc != 1)
-		die(_("must give exactly one tree"));
-
-	if (get_oid_tree(argv[0], &tree_oid))
-		die(_("not a valid object name %s"), argv[0]);
-
-	if (!buffer.len) {
-		if (strbuf_read(&buffer, 0, 0) < 0)
-			die_errno(_("git commit-tree: failed to read"));
-	}
-
-	if (commit_tree(buffer.buf, buffer.len, &tree_oid, parents, &commit_oid,
-			NULL, sign_commit)) {
-		strbuf_release(&buffer);
-		return 1;
-	}
-
-	printf("%s\n", oid_to_hex(&commit_oid));
-	strbuf_release(&buffer);
-	return 0;
-}
diff --git a/third_party/git/builtin/commit.c b/third_party/git/builtin/commit.c
deleted file mode 100644
index 1dfd799ec518..000000000000
--- a/third_party/git/builtin/commit.c
+++ /dev/null
@@ -1,1724 +0,0 @@
-/*
- * Builtin "git commit"
- *
- * Copyright (c) 2007 Kristian Hรธgsberg <krh@redhat.com>
- * Based on git-commit.sh by Junio C Hamano and Linus Torvalds
- */
-
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "config.h"
-#include "lockfile.h"
-#include "cache-tree.h"
-#include "color.h"
-#include "dir.h"
-#include "builtin.h"
-#include "diff.h"
-#include "diffcore.h"
-#include "commit.h"
-#include "revision.h"
-#include "wt-status.h"
-#include "run-command.h"
-#include "refs.h"
-#include "log-tree.h"
-#include "strbuf.h"
-#include "utf8.h"
-#include "parse-options.h"
-#include "string-list.h"
-#include "rerere.h"
-#include "unpack-trees.h"
-#include "quote.h"
-#include "submodule.h"
-#include "gpg-interface.h"
-#include "column.h"
-#include "sequencer.h"
-#include "mailmap.h"
-#include "help.h"
-#include "commit-reach.h"
-#include "commit-graph.h"
-
-static const char * const builtin_commit_usage[] = {
-	N_("git commit [<options>] [--] <pathspec>..."),
-	NULL
-};
-
-static const char * const builtin_status_usage[] = {
-	N_("git status [<options>] [--] <pathspec>..."),
-	NULL
-};
-
-static const char empty_amend_advice[] =
-N_("You asked to amend the most recent commit, but doing so would make\n"
-"it empty. You can repeat your command with --allow-empty, or you can\n"
-"remove the commit entirely with \"git reset HEAD^\".\n");
-
-static const char empty_cherry_pick_advice[] =
-N_("The previous cherry-pick is now empty, possibly due to conflict resolution.\n"
-"If you wish to commit it anyway, use:\n"
-"\n"
-"    git commit --allow-empty\n"
-"\n");
-
-static const char empty_rebase_pick_advice[] =
-N_("Otherwise, please use 'git rebase --skip'\n");
-
-static const char empty_cherry_pick_advice_single[] =
-N_("Otherwise, please use 'git cherry-pick --skip'\n");
-
-static const char empty_cherry_pick_advice_multi[] =
-N_("and then use:\n"
-"\n"
-"    git cherry-pick --continue\n"
-"\n"
-"to resume cherry-picking the remaining commits.\n"
-"If you wish to skip this commit, use:\n"
-"\n"
-"    git cherry-pick --skip\n"
-"\n");
-
-static const char *color_status_slots[] = {
-	[WT_STATUS_HEADER]	  = "header",
-	[WT_STATUS_UPDATED]	  = "updated",
-	[WT_STATUS_CHANGED]	  = "changed",
-	[WT_STATUS_UNTRACKED]	  = "untracked",
-	[WT_STATUS_NOBRANCH]	  = "noBranch",
-	[WT_STATUS_UNMERGED]	  = "unmerged",
-	[WT_STATUS_LOCAL_BRANCH]  = "localBranch",
-	[WT_STATUS_REMOTE_BRANCH] = "remoteBranch",
-	[WT_STATUS_ONBRANCH]	  = "branch",
-};
-
-static const char *use_message_buffer;
-static struct lock_file index_lock; /* real index */
-static struct lock_file false_lock; /* used only for partial commits */
-static enum {
-	COMMIT_AS_IS = 1,
-	COMMIT_NORMAL,
-	COMMIT_PARTIAL
-} commit_style;
-
-static const char *logfile, *force_author;
-static const char *template_file;
-/*
- * The _message variables are commit names from which to take
- * the commit message and/or authorship.
- */
-static const char *author_message, *author_message_buffer;
-static char *edit_message, *use_message;
-static char *fixup_message, *squash_message;
-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 char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;
-static char *sign_commit, *pathspec_from_file;
-
-/*
- * The default commit message cleanup mode will remove the lines
- * beginning with # (shell comments) and leading and trailing
- * whitespaces (empty lines or containing only whitespaces)
- * if editor is used, and only the whitespaces if the message
- * is specified explicitly.
- */
-static enum commit_msg_cleanup_mode cleanup_mode;
-static const char *cleanup_arg;
-
-static enum commit_whence whence;
-static int use_editor = 1, include_status = 1;
-static int have_option_m;
-static struct strbuf message = STRBUF_INIT;
-
-static enum wt_status_format status_format = STATUS_FORMAT_UNSPECIFIED;
-
-static int opt_parse_porcelain(const struct option *opt, const char *arg, int unset)
-{
-	enum wt_status_format *value = (enum wt_status_format *)opt->value;
-	if (unset)
-		*value = STATUS_FORMAT_NONE;
-	else if (!arg)
-		*value = STATUS_FORMAT_PORCELAIN;
-	else if (!strcmp(arg, "v1") || !strcmp(arg, "1"))
-		*value = STATUS_FORMAT_PORCELAIN;
-	else if (!strcmp(arg, "v2") || !strcmp(arg, "2"))
-		*value = STATUS_FORMAT_PORCELAIN_V2;
-	else
-		die("unsupported porcelain version '%s'", arg);
-
-	return 0;
-}
-
-static int opt_parse_m(const struct option *opt, const char *arg, int unset)
-{
-	struct strbuf *buf = opt->value;
-	if (unset) {
-		have_option_m = 0;
-		strbuf_setlen(buf, 0);
-	} else {
-		have_option_m = 1;
-		if (buf->len)
-			strbuf_addch(buf, '\n');
-		strbuf_addstr(buf, arg);
-		strbuf_complete_line(buf);
-	}
-	return 0;
-}
-
-static int opt_parse_rename_score(const struct option *opt, const char *arg, int unset)
-{
-	const char **value = opt->value;
-
-	BUG_ON_OPT_NEG(unset);
-
-	if (arg != NULL && *arg == '=')
-		arg = arg + 1;
-
-	*value = arg;
-	return 0;
-}
-
-static void determine_whence(struct wt_status *s)
-{
-	if (file_exists(git_path_merge_head(the_repository)))
-		whence = FROM_MERGE;
-	else if (!sequencer_determine_whence(the_repository, &whence))
-		whence = FROM_COMMIT;
-	if (s)
-		s->whence = whence;
-}
-
-static void status_init_config(struct wt_status *s, config_fn_t fn)
-{
-	wt_status_prepare(the_repository, s);
-	init_diff_ui_defaults();
-	git_config(fn, s);
-	determine_whence(s);
-	s->hints = advice_status_hints; /* must come after git_config() */
-}
-
-static void rollback_index_files(void)
-{
-	switch (commit_style) {
-	case COMMIT_AS_IS:
-		break; /* nothing to do */
-	case COMMIT_NORMAL:
-		rollback_lock_file(&index_lock);
-		break;
-	case COMMIT_PARTIAL:
-		rollback_lock_file(&index_lock);
-		rollback_lock_file(&false_lock);
-		break;
-	}
-}
-
-static int commit_index_files(void)
-{
-	int err = 0;
-
-	switch (commit_style) {
-	case COMMIT_AS_IS:
-		break; /* nothing to do */
-	case COMMIT_NORMAL:
-		err = commit_lock_file(&index_lock);
-		break;
-	case COMMIT_PARTIAL:
-		err = commit_lock_file(&index_lock);
-		rollback_lock_file(&false_lock);
-		break;
-	}
-
-	return err;
-}
-
-/*
- * Take a union of paths in the index and the named tree (typically, "HEAD"),
- * and return the paths that match the given pattern in list.
- */
-static int list_paths(struct string_list *list, const char *with_tree,
-		      const struct pathspec *pattern)
-{
-	int i, ret;
-	char *m;
-
-	if (!pattern->nr)
-		return 0;
-
-	m = xcalloc(1, pattern->nr);
-
-	if (with_tree) {
-		char *max_prefix = common_prefix(pattern);
-		overlay_tree_on_index(&the_index, with_tree, max_prefix);
-		free(max_prefix);
-	}
-
-	for (i = 0; i < active_nr; i++) {
-		const struct cache_entry *ce = active_cache[i];
-		struct string_list_item *item;
-
-		if (ce->ce_flags & CE_UPDATE)
-			continue;
-		if (!ce_path_match(&the_index, ce, pattern, m))
-			continue;
-		item = string_list_insert(list, ce->name);
-		if (ce_skip_worktree(ce))
-			item->util = item; /* better a valid pointer than a fake one */
-	}
-
-	ret = report_path_error(m, pattern);
-	free(m);
-	return ret;
-}
-
-static void add_remove_files(struct string_list *list)
-{
-	int i;
-	for (i = 0; i < list->nr; i++) {
-		struct stat st;
-		struct string_list_item *p = &(list->items[i]);
-
-		/* p->util is skip-worktree */
-		if (p->util)
-			continue;
-
-		if (!lstat(p->string, &st)) {
-			if (add_to_cache(p->string, &st, 0))
-				die(_("updating files failed"));
-		} else
-			remove_file_from_cache(p->string);
-	}
-}
-
-static void create_base_index(const struct commit *current_head)
-{
-	struct tree *tree;
-	struct unpack_trees_options opts;
-	struct tree_desc t;
-
-	if (!current_head) {
-		discard_cache();
-		return;
-	}
-
-	memset(&opts, 0, sizeof(opts));
-	opts.head_idx = 1;
-	opts.index_only = 1;
-	opts.merge = 1;
-	opts.src_index = &the_index;
-	opts.dst_index = &the_index;
-
-	opts.fn = oneway_merge;
-	tree = parse_tree_indirect(&current_head->object.oid);
-	if (!tree)
-		die(_("failed to unpack HEAD tree object"));
-	parse_tree(tree);
-	init_tree_desc(&t, tree->buffer, tree->size);
-	if (unpack_trees(1, &t, &opts))
-		exit(128); /* We've already reported the error, finish dying */
-}
-
-static void refresh_cache_or_die(int refresh_flags)
-{
-	/*
-	 * refresh_flags contains REFRESH_QUIET, so the only errors
-	 * are for unmerged entries.
-	 */
-	if (refresh_cache(refresh_flags | REFRESH_IN_PORCELAIN))
-		die_resolve_conflict("commit");
-}
-
-static const char *prepare_index(const char **argv, const char *prefix,
-				 const struct commit *current_head, int is_status)
-{
-	struct string_list partial = STRING_LIST_INIT_DUP;
-	struct pathspec pathspec;
-	int refresh_flags = REFRESH_QUIET;
-	const char *ret;
-
-	if (is_status)
-		refresh_flags |= REFRESH_UNMERGED;
-	parse_pathspec(&pathspec, 0,
-		       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;
-		hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
-
-		refresh_cache_or_die(refresh_flags);
-
-		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);
-
-		if (interactive_add(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
-			unsetenv(INDEX_ENVIRONMENT);
-		FREE_AND_NULL(old_index_env);
-
-		discard_cache();
-		read_cache_from(get_lock_file_path(&index_lock));
-		if (update_main_cache_tree(WRITE_TREE_SILENT) == 0) {
-			if (reopen_lock_file(&index_lock) < 0)
-				die(_("unable to write index file"));
-			if (write_locked_index(&the_index, &index_lock, 0))
-				die(_("unable to update temporary index"));
-		} else
-			warning(_("Failed to update main cache tree"));
-
-		commit_style = COMMIT_NORMAL;
-		ret = get_lock_file_path(&index_lock);
-		goto out;
-	}
-
-	/*
-	 * Non partial, non as-is commit.
-	 *
-	 * (1) get the real index;
-	 * (2) update the_index as necessary;
-	 * (3) write the_index out to the real index (still locked);
-	 * (4) return the name of the locked index file.
-	 *
-	 * The caller should run hooks on the locked real index, and
-	 * (A) if all goes well, commit the real index;
-	 * (B) on failure, rollback the real index.
-	 */
-	if (all || (also && pathspec.nr)) {
-		hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
-		add_files_to_cache(also ? prefix : NULL, &pathspec, 0);
-		refresh_cache_or_die(refresh_flags);
-		update_main_cache_tree(WRITE_TREE_SILENT);
-		if (write_locked_index(&the_index, &index_lock, 0))
-			die(_("unable to write new_index file"));
-		commit_style = COMMIT_NORMAL;
-		ret = get_lock_file_path(&index_lock);
-		goto out;
-	}
-
-	/*
-	 * As-is commit.
-	 *
-	 * (1) return the name of the real index file.
-	 *
-	 * The caller should run hooks on the real index,
-	 * and create commit from the_index.
-	 * We still need to refresh the index here.
-	 */
-	if (!only && !pathspec.nr) {
-		hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
-		refresh_cache_or_die(refresh_flags);
-		if (active_cache_changed
-		    || !cache_tree_fully_valid(active_cache_tree))
-			update_main_cache_tree(WRITE_TREE_SILENT);
-		if (write_locked_index(&the_index, &index_lock,
-				       COMMIT_LOCK | SKIP_IF_UNCHANGED))
-			die(_("unable to write new_index file"));
-		commit_style = COMMIT_AS_IS;
-		ret = get_index_file();
-		goto out;
-	}
-
-	/*
-	 * A partial commit.
-	 *
-	 * (0) find the set of affected paths;
-	 * (1) get lock on the real index file;
-	 * (2) update the_index with the given paths;
-	 * (3) write the_index out to the real index (still locked);
-	 * (4) get lock on the false index file;
-	 * (5) reset the_index from HEAD;
-	 * (6) update the_index the same way as (2);
-	 * (7) write the_index out to the false index file;
-	 * (8) return the name of the false index file (still locked);
-	 *
-	 * The caller should run hooks on the locked false index, and
-	 * create commit from it.  Then
-	 * (A) if all goes well, commit the real index;
-	 * (B) on failure, rollback the real index;
-	 * In either case, rollback the false index.
-	 */
-	commit_style = COMMIT_PARTIAL;
-
-	if (whence != FROM_COMMIT) {
-		if (whence == FROM_MERGE)
-			die(_("cannot do a partial commit during a merge."));
-		else if (is_from_cherry_pick(whence))
-			die(_("cannot do a partial commit during a cherry-pick."));
-		else if (is_from_rebase(whence))
-			die(_("cannot do a partial commit during a rebase."));
-	}
-
-	if (list_paths(&partial, !current_head ? NULL : "HEAD", &pathspec))
-		exit(1);
-
-	discard_cache();
-	if (read_cache() < 0)
-		die(_("cannot read the index"));
-
-	hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
-	add_remove_files(&partial);
-	refresh_cache(REFRESH_QUIET);
-	update_main_cache_tree(WRITE_TREE_SILENT);
-	if (write_locked_index(&the_index, &index_lock, 0))
-		die(_("unable to write new_index file"));
-
-	hold_lock_file_for_update(&false_lock,
-				  git_path("next-index-%"PRIuMAX,
-					   (uintmax_t) getpid()),
-				  LOCK_DIE_ON_ERROR);
-
-	create_base_index(current_head);
-	add_remove_files(&partial);
-	refresh_cache(REFRESH_QUIET);
-
-	if (write_locked_index(&the_index, &false_lock, 0))
-		die(_("unable to write temporary index file"));
-
-	discard_cache();
-	ret = get_lock_file_path(&false_lock);
-	read_cache_from(ret);
-out:
-	string_list_clear(&partial, 0);
-	clear_pathspec(&pathspec);
-	return ret;
-}
-
-static int run_status(FILE *fp, const char *index_file, const char *prefix, int nowarn,
-		      struct wt_status *s)
-{
-	struct object_id oid;
-
-	if (s->relative_paths)
-		s->prefix = prefix;
-
-	if (amend) {
-		s->amend = 1;
-		s->reference = "HEAD^1";
-	}
-	s->verbose = verbose;
-	s->index_file = index_file;
-	s->fp = fp;
-	s->nowarn = nowarn;
-	s->is_initial = get_oid(s->reference, &oid) ? 1 : 0;
-	if (!s->is_initial)
-		oidcpy(&s->oid_commit, &oid);
-	s->status_format = status_format;
-	s->ignore_submodule_arg = ignore_submodule_arg;
-
-	wt_status_collect(s);
-	wt_status_print(s);
-	wt_status_collect_free_buffers(s);
-
-	return s->committable;
-}
-
-static int is_a_merge(const struct commit *current_head)
-{
-	return !!(current_head->parents && current_head->parents->next);
-}
-
-static void assert_split_ident(struct ident_split *id, const struct strbuf *buf)
-{
-	if (split_ident_line(id, buf->buf, buf->len) || !id->date_begin)
-		BUG("unable to parse our own ident: %s", buf->buf);
-}
-
-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);
-	setenv(var, buf.buf, 1);
-	strbuf_release(&buf);
-}
-
-static int parse_force_date(const char *in, struct strbuf *out)
-{
-	strbuf_addch(out, '@');
-
-	if (parse_date(in, out) < 0) {
-		int errors = 0;
-		unsigned long t = approxidate_careful(in, &errors);
-		if (errors)
-			return -1;
-		strbuf_addf(out, "%lu", t);
-	}
-
-	return 0;
-}
-
-static void set_ident_var(char **buf, char *val)
-{
-	free(*buf);
-	*buf = val;
-}
-
-static void determine_author_info(struct strbuf *author_ident)
-{
-	char *name, *email, *date;
-	struct ident_split author;
-
-	name = xstrdup_or_null(getenv("GIT_AUTHOR_NAME"));
-	email = xstrdup_or_null(getenv("GIT_AUTHOR_EMAIL"));
-	date = xstrdup_or_null(getenv("GIT_AUTHOR_DATE"));
-
-	if (author_message) {
-		struct ident_split ident;
-		size_t len;
-		const char *a;
-
-		a = find_commit_header(author_message_buffer, "author", &len);
-		if (!a)
-			die(_("commit '%s' lacks author header"), author_message);
-		if (split_ident_line(&ident, a, len) < 0)
-			die(_("commit '%s' has malformed author line"), author_message);
-
-		set_ident_var(&name, xmemdupz(ident.name_begin, ident.name_end - ident.name_begin));
-		set_ident_var(&email, xmemdupz(ident.mail_begin, ident.mail_end - ident.mail_begin));
-
-		if (ident.date_begin) {
-			struct strbuf date_buf = STRBUF_INIT;
-			strbuf_addch(&date_buf, '@');
-			strbuf_add(&date_buf, ident.date_begin, ident.date_end - ident.date_begin);
-			strbuf_addch(&date_buf, ' ');
-			strbuf_add(&date_buf, ident.tz_begin, ident.tz_end - ident.tz_begin);
-			set_ident_var(&date, strbuf_detach(&date_buf, NULL));
-		}
-	}
-
-	if (force_author) {
-		struct ident_split ident;
-
-		if (split_ident_line(&ident, force_author, strlen(force_author)) < 0)
-			die(_("malformed --author parameter"));
-		set_ident_var(&name, xmemdupz(ident.name_begin, ident.name_end - ident.name_begin));
-		set_ident_var(&email, xmemdupz(ident.mail_begin, ident.mail_end - ident.mail_begin));
-	}
-
-	if (force_date) {
-		struct strbuf date_buf = STRBUF_INIT;
-		if (parse_force_date(force_date, &date_buf))
-			die(_("invalid date format: %s"), force_date);
-		set_ident_var(&date, strbuf_detach(&date_buf, NULL));
-	}
-
-	strbuf_addstr(author_ident, fmt_ident(name, email, WANT_AUTHOR_IDENT, date,
-				IDENT_STRICT));
-	assert_split_ident(&author, author_ident);
-	export_one("GIT_AUTHOR_NAME", author.name_begin, author.name_end, 0);
-	export_one("GIT_AUTHOR_EMAIL", author.mail_begin, author.mail_end, 0);
-	export_one("GIT_AUTHOR_DATE", author.date_begin, author.tz_end, '@');
-	free(name);
-	free(email);
-	free(date);
-}
-
-static int author_date_is_interesting(void)
-{
-	return author_message || force_date;
-}
-
-static void adjust_comment_line_char(const struct strbuf *sb)
-{
-	char candidates[] = "#;@!$%^&|:";
-	char *candidate;
-	const char *p;
-
-	comment_line_char = candidates[0];
-	if (!memchr(sb->buf, comment_line_char, sb->len))
-		return;
-
-	p = sb->buf;
-	candidate = strchr(candidates, *p);
-	if (candidate)
-		*candidate = ' ';
-	for (p = sb->buf; *p; p++) {
-		if ((p[0] == '\n' || p[0] == '\r') && p[1]) {
-			candidate = strchr(candidates, p[1]);
-			if (candidate)
-				*candidate = ' ';
-		}
-	}
-
-	for (p = candidates; *p == ' '; p++)
-		;
-	if (!*p)
-		die(_("unable to select a comment character that is not used\n"
-		      "in the current commit message"));
-	comment_line_char = *p;
-}
-
-static int prepare_to_commit(const char *index_file, const char *prefix,
-			     struct commit *current_head,
-			     struct wt_status *s,
-			     struct strbuf *author_ident)
-{
-	struct stat statbuf;
-	struct strbuf committer_ident = STRBUF_INIT;
-	int committable;
-	struct strbuf sb = STRBUF_INIT;
-	const char *hook_arg1 = NULL;
-	const char *hook_arg2 = NULL;
-	int clean_message_contents = (cleanup_mode != COMMIT_MSG_CLEANUP_NONE);
-	int old_display_comment_prefix;
-	int merge_contains_scissors = 0;
-
-	/* This checks and barfs if author is badly specified */
-	determine_author_info(author_ident);
-
-	if (!no_verify && run_commit_hook(use_editor, index_file, "pre-commit", NULL))
-		return 0;
-
-	if (squash_message) {
-		/*
-		 * Insert the proper subject line before other commit
-		 * message options add their content.
-		 */
-		if (use_message && !strcmp(use_message, squash_message))
-			strbuf_addstr(&sb, "squash! ");
-		else {
-			struct pretty_print_context ctx = {0};
-			struct commit *c;
-			c = lookup_commit_reference_by_name(squash_message);
-			if (!c)
-				die(_("could not lookup commit %s"), squash_message);
-			ctx.output_encoding = get_commit_output_encoding();
-			format_commit_message(c, "squash! %s\n\n", &sb,
-					      &ctx);
-		}
-	}
-
-	if (have_option_m && !fixup_message) {
-		strbuf_addbuf(&sb, &message);
-		hook_arg1 = "message";
-	} else if (logfile && !strcmp(logfile, "-")) {
-		if (isatty(0))
-			fprintf(stderr, _("(reading log message from standard input)\n"));
-		if (strbuf_read(&sb, 0, 0) < 0)
-			die_errno(_("could not read log from standard input"));
-		hook_arg1 = "message";
-	} else if (logfile) {
-		if (strbuf_read_file(&sb, logfile, 0) < 0)
-			die_errno(_("could not read log file '%s'"),
-				  logfile);
-		hook_arg1 = "message";
-	} else if (use_message) {
-		char *buffer;
-		buffer = strstr(use_message_buffer, "\n\n");
-		if (buffer)
-			strbuf_addstr(&sb, skip_blank_lines(buffer + 2));
-		hook_arg1 = "commit";
-		hook_arg2 = use_message;
-	} else if (fixup_message) {
-		struct pretty_print_context ctx = {0};
-		struct commit *commit;
-		commit = lookup_commit_reference_by_name(fixup_message);
-		if (!commit)
-			die(_("could not lookup commit %s"), fixup_message);
-		ctx.output_encoding = get_commit_output_encoding();
-		format_commit_message(commit, "fixup! %s\n\n",
-				      &sb, &ctx);
-		if (have_option_m)
-			strbuf_addbuf(&sb, &message);
-		hook_arg1 = "message";
-	} else if (!stat(git_path_merge_msg(the_repository), &statbuf)) {
-		size_t merge_msg_start;
-
-		/*
-		 * prepend SQUASH_MSG here if it exists and a
-		 * "merge --squash" was originally performed
-		 */
-		if (!stat(git_path_squash_msg(the_repository), &statbuf)) {
-			if (strbuf_read_file(&sb, git_path_squash_msg(the_repository), 0) < 0)
-				die_errno(_("could not read SQUASH_MSG"));
-			hook_arg1 = "squash";
-		} else
-			hook_arg1 = "merge";
-
-		merge_msg_start = sb.len;
-		if (strbuf_read_file(&sb, git_path_merge_msg(the_repository), 0) < 0)
-			die_errno(_("could not read MERGE_MSG"));
-
-		if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS &&
-		    wt_status_locate_end(sb.buf + merge_msg_start,
-					 sb.len - merge_msg_start) <
-				sb.len - merge_msg_start)
-			merge_contains_scissors = 1;
-	} else if (!stat(git_path_squash_msg(the_repository), &statbuf)) {
-		if (strbuf_read_file(&sb, git_path_squash_msg(the_repository), 0) < 0)
-			die_errno(_("could not read SQUASH_MSG"));
-		hook_arg1 = "squash";
-	} else if (template_file) {
-		if (strbuf_read_file(&sb, template_file, 0) < 0)
-			die_errno(_("could not read '%s'"), template_file);
-		hook_arg1 = "template";
-		clean_message_contents = 0;
-	}
-
-	/*
-	 * The remaining cases don't modify the template message, but
-	 * just set the argument(s) to the prepare-commit-msg hook.
-	 */
-	else if (whence == FROM_MERGE)
-		hook_arg1 = "merge";
-	else if (is_from_cherry_pick(whence) || whence == FROM_REBASE_PICK) {
-		hook_arg1 = "commit";
-		hook_arg2 = "CHERRY_PICK_HEAD";
-	}
-
-	if (squash_message) {
-		/*
-		 * If squash_commit was used for the commit subject,
-		 * then we're possibly hijacking other commit log options.
-		 * Reset the hook args to tell the real story.
-		 */
-		hook_arg1 = "message";
-		hook_arg2 = "";
-	}
-
-	s->fp = fopen_for_writing(git_path_commit_editmsg());
-	if (s->fp == NULL)
-		die_errno(_("could not open '%s'"), git_path_commit_editmsg());
-
-	/* Ignore status.displayCommentPrefix: we do need comments in COMMIT_EDITMSG. */
-	old_display_comment_prefix = s->display_comment_prefix;
-	s->display_comment_prefix = 1;
-
-	/*
-	 * Most hints are counter-productive when the commit has
-	 * already started.
-	 */
-	s->hints = 0;
-
-	if (clean_message_contents)
-		strbuf_stripspace(&sb, 0);
-
-	if (signoff)
-		append_signoff(&sb, ignore_non_trailer(sb.buf, sb.len), 0);
-
-	if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len)
-		die_errno(_("could not write commit template"));
-
-	if (auto_comment_line_char)
-		adjust_comment_line_char(&sb);
-	strbuf_release(&sb);
-
-	/* This checks if committer ident is explicitly given */
-	strbuf_addstr(&committer_ident, git_committer_info(IDENT_STRICT));
-	if (use_editor && include_status) {
-		int ident_shown = 0;
-		int saved_color_setting;
-		struct ident_split ci, ai;
-
-		if (whence != FROM_COMMIT) {
-			if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS &&
-				!merge_contains_scissors)
-				wt_status_add_cut_line(s->fp);
-			status_printf_ln(
-				s, GIT_COLOR_NORMAL,
-				whence == FROM_MERGE ?
-					      _("\n"
-					  "It looks like you may be committing a merge.\n"
-					  "If this is not correct, please run\n"
-					  "	git update-ref -d MERGE_HEAD\n"
-					  "and try again.\n") :
-					      _("\n"
-					  "It looks like you may be committing a cherry-pick.\n"
-					  "If this is not correct, please run\n"
-					  "	git update-ref -d CHERRY_PICK_HEAD\n"
-					  "and try again.\n"));
-		}
-
-		fprintf(s->fp, "\n");
-		if (cleanup_mode == COMMIT_MSG_CLEANUP_ALL)
-			status_printf(s, GIT_COLOR_NORMAL,
-				_("Please enter the commit message for your changes."
-				  " Lines starting\nwith '%c' will be ignored, and an empty"
-				  " message aborts the commit.\n"), comment_line_char);
-		else if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) {
-			if (whence == FROM_COMMIT && !merge_contains_scissors)
-				wt_status_add_cut_line(s->fp);
-		} else /* COMMIT_MSG_CLEANUP_SPACE, that is. */
-			status_printf(s, GIT_COLOR_NORMAL,
-				_("Please enter the commit message for your changes."
-				  " Lines starting\n"
-				  "with '%c' will be kept; you may remove them"
-				  " yourself if you want to.\n"
-				  "An empty message aborts the commit.\n"), comment_line_char);
-
-		/*
-		 * These should never fail because they come from our own
-		 * fmt_ident. They may fail the sane_ident test, but we know
-		 * that the name and mail pointers will at least be valid,
-		 * which is enough for our tests and printing here.
-		 */
-		assert_split_ident(&ai, author_ident);
-		assert_split_ident(&ci, &committer_ident);
-
-		if (ident_cmp(&ai, &ci))
-			status_printf_ln(s, GIT_COLOR_NORMAL,
-				_("%s"
-				"Author:    %.*s <%.*s>"),
-				ident_shown++ ? "" : "\n",
-				(int)(ai.name_end - ai.name_begin), ai.name_begin,
-				(int)(ai.mail_end - ai.mail_begin), ai.mail_begin);
-
-		if (author_date_is_interesting())
-			status_printf_ln(s, GIT_COLOR_NORMAL,
-				_("%s"
-				"Date:      %s"),
-				ident_shown++ ? "" : "\n",
-				show_ident_date(&ai, DATE_MODE(NORMAL)));
-
-		if (!committer_ident_sufficiently_given())
-			status_printf_ln(s, GIT_COLOR_NORMAL,
-				_("%s"
-				"Committer: %.*s <%.*s>"),
-				ident_shown++ ? "" : "\n",
-				(int)(ci.name_end - ci.name_begin), ci.name_begin,
-				(int)(ci.mail_end - ci.mail_begin), ci.mail_begin);
-
-		status_printf_ln(s, GIT_COLOR_NORMAL, "%s", ""); /* Add new line for clarity */
-
-		saved_color_setting = s->use_color;
-		s->use_color = 0;
-		committable = run_status(s->fp, index_file, prefix, 1, s);
-		s->use_color = saved_color_setting;
-		string_list_clear(&s->change, 1);
-	} else {
-		struct object_id oid;
-		const char *parent = "HEAD";
-
-		if (!active_nr && read_cache() < 0)
-			die(_("Cannot read index"));
-
-		if (amend)
-			parent = "HEAD^1";
-
-		if (get_oid(parent, &oid)) {
-			int i, ita_nr = 0;
-
-			for (i = 0; i < active_nr; i++)
-				if (ce_intent_to_add(active_cache[i]))
-					ita_nr++;
-			committable = active_nr - ita_nr > 0;
-		} else {
-			/*
-			 * Unless the user did explicitly request a submodule
-			 * ignore mode by passing a command line option we do
-			 * not ignore any changed submodule SHA-1s when
-			 * comparing index and parent, no matter what is
-			 * configured. Otherwise we won't commit any
-			 * submodules which were manually staged, which would
-			 * be really confusing.
-			 */
-			struct diff_flags flags = DIFF_FLAGS_INIT;
-			flags.override_submodule_config = 1;
-			if (ignore_submodule_arg &&
-			    !strcmp(ignore_submodule_arg, "all"))
-				flags.ignore_submodules = 1;
-			committable = index_differs_from(the_repository,
-							 parent, &flags, 1);
-		}
-	}
-	strbuf_release(&committer_ident);
-
-	fclose(s->fp);
-
-	/*
-	 * Reject an attempt to record a non-merge empty commit without
-	 * explicit --allow-empty. In the cherry-pick case, it may be
-	 * empty due to conflict resolution, which the user should okay.
-	 */
-	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)
-			fputs(_(empty_amend_advice), stderr);
-		else if (is_from_cherry_pick(whence) ||
-			 whence == FROM_REBASE_PICK) {
-			fputs(_(empty_cherry_pick_advice), stderr);
-			if (whence == FROM_CHERRY_PICK_SINGLE)
-				fputs(_(empty_cherry_pick_advice_single), stderr);
-			else if (whence == FROM_CHERRY_PICK_MULTI)
-				fputs(_(empty_cherry_pick_advice_multi), stderr);
-			else
-				fputs(_(empty_rebase_pick_advice), stderr);
-		}
-		return 0;
-	}
-
-	if (!no_verify && find_hook("pre-commit")) {
-		/*
-		 * Re-read the index as pre-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.
-		 */
-		discard_cache();
-	}
-	read_cache_from(index_file);
-
-	if (update_main_cache_tree(0)) {
-		error(_("Error building trees"));
-		return 0;
-	}
-
-	if (run_commit_hook(use_editor, index_file, "prepare-commit-msg",
-			    git_path_commit_editmsg(), hook_arg1, hook_arg2, NULL))
-		return 0;
-
-	if (use_editor) {
-		struct strvec env = STRVEC_INIT;
-
-		strvec_pushf(&env, "GIT_INDEX_FILE=%s", index_file);
-		if (launch_editor(git_path_commit_editmsg(), NULL, env.v)) {
-			fprintf(stderr,
-			_("Please supply the message using either -m or -F option.\n"));
-			exit(1);
-		}
-		strvec_clear(&env);
-	}
-
-	if (!no_verify &&
-	    run_commit_hook(use_editor, index_file, "commit-msg", git_path_commit_editmsg(), NULL)) {
-		return 0;
-	}
-
-	return 1;
-}
-
-static const char *find_author_by_nickname(const char *name)
-{
-	struct rev_info revs;
-	struct commit *commit;
-	struct strbuf buf = STRBUF_INIT;
-	struct string_list mailmap = STRING_LIST_INIT_NODUP;
-	const char *av[20];
-	int ac = 0;
-
-	repo_init_revisions(the_repository, &revs, NULL);
-	strbuf_addf(&buf, "--author=%s", name);
-	av[++ac] = "--all";
-	av[++ac] = "-i";
-	av[++ac] = buf.buf;
-	av[++ac] = NULL;
-	setup_revisions(ac, av, &revs, NULL);
-	revs.mailmap = &mailmap;
-	read_mailmap(revs.mailmap, NULL);
-
-	if (prepare_revision_walk(&revs))
-		die(_("revision walk setup failed"));
-	commit = get_revision(&revs);
-	if (commit) {
-		struct pretty_print_context ctx = {0};
-		ctx.date_mode.type = DATE_NORMAL;
-		strbuf_release(&buf);
-		format_commit_message(commit, "%aN <%aE>", &buf, &ctx);
-		clear_mailmap(&mailmap);
-		return strbuf_detach(&buf, NULL);
-	}
-	die(_("--author '%s' is not 'Name <email>' and matches no existing author"), name);
-}
-
-static void handle_ignored_arg(struct wt_status *s)
-{
-	if (!ignored_arg)
-		; /* default already initialized */
-	else if (!strcmp(ignored_arg, "traditional"))
-		s->show_ignored_mode = SHOW_TRADITIONAL_IGNORED;
-	else if (!strcmp(ignored_arg, "no"))
-		s->show_ignored_mode = SHOW_NO_IGNORED;
-	else if (!strcmp(ignored_arg, "matching"))
-		s->show_ignored_mode = SHOW_MATCHING_IGNORED;
-	else
-		die(_("Invalid ignored mode '%s'"), ignored_arg);
-}
-
-static void handle_untracked_files_arg(struct wt_status *s)
-{
-	if (!untracked_files_arg)
-		; /* default already initialized */
-	else if (!strcmp(untracked_files_arg, "no"))
-		s->show_untracked_files = SHOW_NO_UNTRACKED_FILES;
-	else if (!strcmp(untracked_files_arg, "normal"))
-		s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
-	else if (!strcmp(untracked_files_arg, "all"))
-		s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
-	/*
-	 * Please update $__git_untracked_file_modes in
-	 * git-completion.bash when you add new options
-	 */
-	else
-		die(_("Invalid untracked files mode '%s'"), untracked_files_arg);
-}
-
-static const char *read_commit_message(const char *name)
-{
-	const char *out_enc;
-	struct commit *commit;
-
-	commit = lookup_commit_reference_by_name(name);
-	if (!commit)
-		die(_("could not lookup commit %s"), name);
-	out_enc = get_commit_output_encoding();
-	return logmsg_reencode(commit, NULL, out_enc);
-}
-
-/*
- * Enumerate what needs to be propagated when --porcelain
- * is not in effect here.
- */
-static struct status_deferred_config {
-	enum wt_status_format status_format;
-	int show_branch;
-	enum ahead_behind_flags ahead_behind;
-} status_deferred_config = {
-	STATUS_FORMAT_UNSPECIFIED,
-	-1, /* unspecified */
-	AHEAD_BEHIND_UNSPECIFIED,
-};
-
-static void finalize_deferred_config(struct wt_status *s)
-{
-	int use_deferred_config = (status_format != STATUS_FORMAT_PORCELAIN &&
-				   status_format != STATUS_FORMAT_PORCELAIN_V2 &&
-				   !s->null_termination);
-
-	if (s->null_termination) {
-		if (status_format == STATUS_FORMAT_NONE ||
-		    status_format == STATUS_FORMAT_UNSPECIFIED)
-			status_format = STATUS_FORMAT_PORCELAIN;
-		else if (status_format == STATUS_FORMAT_LONG)
-			die(_("--long and -z are incompatible"));
-	}
-
-	if (use_deferred_config && status_format == STATUS_FORMAT_UNSPECIFIED)
-		status_format = status_deferred_config.status_format;
-	if (status_format == STATUS_FORMAT_UNSPECIFIED)
-		status_format = STATUS_FORMAT_NONE;
-
-	if (use_deferred_config && s->show_branch < 0)
-		s->show_branch = status_deferred_config.show_branch;
-	if (s->show_branch < 0)
-		s->show_branch = 0;
-
-	/*
-	 * If the user did not give a "--[no]-ahead-behind" command
-	 * line argument *AND* we will print in a human-readable format
-	 * (short, long etc.) then we inherit from the status.aheadbehind
-	 * config setting.  In all other cases (and porcelain V[12] formats
-	 * in particular), we inherit _FULL for backwards compatibility.
-	 */
-	if (use_deferred_config &&
-	    s->ahead_behind_flags == AHEAD_BEHIND_UNSPECIFIED)
-		s->ahead_behind_flags = status_deferred_config.ahead_behind;
-
-	if (s->ahead_behind_flags == AHEAD_BEHIND_UNSPECIFIED)
-		s->ahead_behind_flags = AHEAD_BEHIND_FULL;
-}
-
-static int parse_and_validate_options(int argc, const char *argv[],
-				      const struct option *options,
-				      const char * const usage[],
-				      const char *prefix,
-				      struct commit *current_head,
-				      struct wt_status *s)
-{
-	int f = 0;
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-	finalize_deferred_config(s);
-
-	if (force_author && !strchr(force_author, '>'))
-		force_author = find_author_by_nickname(force_author);
-
-	if (force_author && renew_authorship)
-		die(_("Using both --reset-author and --author does not make sense"));
-
-	if (logfile || have_option_m || use_message || fixup_message)
-		use_editor = 0;
-	if (0 <= edit_flag)
-		use_editor = edit_flag;
-
-	/* Sanity check options */
-	if (amend && !current_head)
-		die(_("You have nothing to amend."));
-	if (amend && whence != FROM_COMMIT) {
-		if (whence == FROM_MERGE)
-			die(_("You are in the middle of a merge -- cannot amend."));
-		else if (is_from_cherry_pick(whence))
-			die(_("You are in the middle of a cherry-pick -- cannot amend."));
-		else if (whence == FROM_REBASE_PICK)
-			die(_("You are in the middle of a rebase -- cannot amend."));
-	}
-	if (fixup_message && squash_message)
-		die(_("Options --squash and --fixup cannot be used together"));
-	if (use_message)
-		f++;
-	if (edit_message)
-		f++;
-	if (fixup_message)
-		f++;
-	if (logfile)
-		f++;
-	if (f > 1)
-		die(_("Only one of -c/-C/-F/--fixup can be used."));
-	if (have_option_m && (edit_message || use_message || logfile))
-		die((_("Option -m cannot be combined with -c/-C/-F.")));
-	if (f || have_option_m)
-		template_file = NULL;
-	if (edit_message)
-		use_message = edit_message;
-	if (amend && !use_message && !fixup_message)
-		use_message = "HEAD";
-	if (!use_message && !is_from_cherry_pick(whence) &&
-	    !is_from_rebase(whence) && renew_authorship)
-		die(_("--reset-author can be used only with -C, -c or --amend."));
-	if (use_message) {
-		use_message_buffer = read_commit_message(use_message);
-		if (!renew_authorship) {
-			author_message = use_message;
-			author_message_buffer = use_message_buffer;
-		}
-	}
-	if ((is_from_cherry_pick(whence) || whence == FROM_REBASE_PICK) &&
-	    !renew_authorship) {
-		author_message = "CHERRY_PICK_HEAD";
-		author_message_buffer = read_commit_message(author_message);
-	}
-
-	if (patch_interactive)
-		interactive = 1;
-
-	if (also + only + all + interactive > 1)
-		die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
-	cleanup_mode = get_cleanup_mode(cleanup_arg, use_editor);
-
-	handle_untracked_files_arg(s);
-
-	if (all && argc > 0)
-		die(_("paths '%s ...' with -a does not make sense"),
-		    argv[0]);
-
-	if (status_format != STATUS_FORMAT_NONE)
-		dry_run = 1;
-
-	return argc;
-}
-
-static int dry_run_commit(const char **argv, const char *prefix,
-			  const struct commit *current_head, struct wt_status *s)
-{
-	int committable;
-	const char *index_file;
-
-	index_file = prepare_index(argv, prefix, current_head, 1);
-	committable = run_status(stdout, index_file, prefix, 0, s);
-	rollback_index_files();
-
-	return committable ? 0 : 1;
-}
-
-define_list_config_array_extra(color_status_slots, {"added"});
-
-static int parse_status_slot(const char *slot)
-{
-	if (!strcasecmp(slot, "added"))
-		return WT_STATUS_UPDATED;
-
-	return LOOKUP_CONFIG(color_status_slots, slot);
-}
-
-static int git_status_config(const char *k, const char *v, void *cb)
-{
-	struct wt_status *s = cb;
-	const char *slot_name;
-
-	if (starts_with(k, "column."))
-		return git_column_config(k, v, "status", &s->colopts);
-	if (!strcmp(k, "status.submodulesummary")) {
-		int is_bool;
-		s->submodule_summary = git_config_bool_or_int(k, v, &is_bool);
-		if (is_bool && s->submodule_summary)
-			s->submodule_summary = -1;
-		return 0;
-	}
-	if (!strcmp(k, "status.short")) {
-		if (git_config_bool(k, v))
-			status_deferred_config.status_format = STATUS_FORMAT_SHORT;
-		else
-			status_deferred_config.status_format = STATUS_FORMAT_NONE;
-		return 0;
-	}
-	if (!strcmp(k, "status.branch")) {
-		status_deferred_config.show_branch = git_config_bool(k, v);
-		return 0;
-	}
-	if (!strcmp(k, "status.aheadbehind")) {
-		status_deferred_config.ahead_behind = git_config_bool(k, v);
-		return 0;
-	}
-	if (!strcmp(k, "status.showstash")) {
-		s->show_stash = git_config_bool(k, v);
-		return 0;
-	}
-	if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
-		s->use_color = git_config_colorbool(k, v);
-		return 0;
-	}
-	if (!strcmp(k, "status.displaycommentprefix")) {
-		s->display_comment_prefix = git_config_bool(k, v);
-		return 0;
-	}
-	if (skip_prefix(k, "status.color.", &slot_name) ||
-	    skip_prefix(k, "color.status.", &slot_name)) {
-		int slot = parse_status_slot(slot_name);
-		if (slot < 0)
-			return 0;
-		if (!v)
-			return config_error_nonbool(k);
-		return color_parse(v, s->color_palette[slot]);
-	}
-	if (!strcmp(k, "status.relativepaths")) {
-		s->relative_paths = git_config_bool(k, v);
-		return 0;
-	}
-	if (!strcmp(k, "status.showuntrackedfiles")) {
-		if (!v)
-			return config_error_nonbool(k);
-		else if (!strcmp(v, "no"))
-			s->show_untracked_files = SHOW_NO_UNTRACKED_FILES;
-		else if (!strcmp(v, "normal"))
-			s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
-		else if (!strcmp(v, "all"))
-			s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
-		else
-			return error(_("Invalid untracked files mode '%s'"), v);
-		return 0;
-	}
-	if (!strcmp(k, "diff.renamelimit")) {
-		if (s->rename_limit == -1)
-			s->rename_limit = git_config_int(k, v);
-		return 0;
-	}
-	if (!strcmp(k, "status.renamelimit")) {
-		s->rename_limit = git_config_int(k, v);
-		return 0;
-	}
-	if (!strcmp(k, "diff.renames")) {
-		if (s->detect_rename == -1)
-			s->detect_rename = git_config_rename(k, v);
-		return 0;
-	}
-	if (!strcmp(k, "status.renames")) {
-		s->detect_rename = git_config_rename(k, v);
-		return 0;
-	}
-	return git_diff_ui_config(k, v, NULL);
-}
-
-int cmd_status(int argc, const char **argv, const char *prefix)
-{
-	static int no_renames = -1;
-	static const char *rename_score_arg = (const char *)-1;
-	static struct wt_status s;
-	unsigned int progress_flag = 0;
-	int fd;
-	struct object_id oid;
-	static struct option builtin_status_options[] = {
-		OPT__VERBOSE(&verbose, N_("be verbose")),
-		OPT_SET_INT('s', "short", &status_format,
-			    N_("show status concisely"), STATUS_FORMAT_SHORT),
-		OPT_BOOL('b', "branch", &s.show_branch,
-			 N_("show branch information")),
-		OPT_BOOL(0, "show-stash", &s.show_stash,
-			 N_("show stash information")),
-		OPT_BOOL(0, "ahead-behind", &s.ahead_behind_flags,
-			 N_("compute full ahead/behind values")),
-		OPT_CALLBACK_F(0, "porcelain", &status_format,
-		  N_("version"), N_("machine-readable output"),
-		  PARSE_OPT_OPTARG, opt_parse_porcelain),
-		OPT_SET_INT(0, "long", &status_format,
-			    N_("show status in long format (default)"),
-			    STATUS_FORMAT_LONG),
-		OPT_BOOL('z', "null", &s.null_termination,
-			 N_("terminate entries with NUL")),
-		{ 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" },
-		{ OPTION_STRING, 0, "ignored", &ignored_arg,
-		  N_("mode"),
-		  N_("show ignored files, optional modes: traditional, matching, no. (Default: traditional)"),
-		  PARSE_OPT_OPTARG, NULL, (intptr_t)"traditional" },
-		{ OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"),
-		  N_("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)"),
-		  PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
-		OPT_COLUMN(0, "column", &s.colopts, N_("list untracked files in columns")),
-		OPT_BOOL(0, "no-renames", &no_renames, N_("do not detect renames")),
-		OPT_CALLBACK_F('M', "find-renames", &rename_score_arg,
-		  N_("n"), N_("detect renames, optionally set similarity index"),
-		  PARSE_OPT_OPTARG | PARSE_OPT_NONEG, opt_parse_rename_score),
-		OPT_END(),
-	};
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage_with_options(builtin_status_usage, builtin_status_options);
-
-	status_init_config(&s, git_status_config);
-	argc = parse_options(argc, argv, prefix,
-			     builtin_status_options,
-			     builtin_status_usage, 0);
-	finalize_colopts(&s.colopts, -1);
-	finalize_deferred_config(&s);
-
-	handle_untracked_files_arg(&s);
-	handle_ignored_arg(&s);
-
-	if (s.show_ignored_mode == SHOW_MATCHING_IGNORED &&
-	    s.show_untracked_files == SHOW_NO_UNTRACKED_FILES)
-		die(_("Unsupported combination of ignored and untracked-files arguments"));
-
-	parse_pathspec(&s.pathspec, 0,
-		       PATHSPEC_PREFER_FULL,
-		       prefix, argv);
-
-	if (status_format != STATUS_FORMAT_PORCELAIN &&
-	    status_format != STATUS_FORMAT_PORCELAIN_V2)
-		progress_flag = REFRESH_PROGRESS;
-	repo_read_index(the_repository);
-	refresh_index(&the_index,
-		      REFRESH_QUIET|REFRESH_UNMERGED|progress_flag,
-		      &s.pathspec, NULL, NULL);
-
-	if (use_optional_locks())
-		fd = hold_locked_index(&index_lock, 0);
-	else
-		fd = -1;
-
-	s.is_initial = get_oid(s.reference, &oid) ? 1 : 0;
-	if (!s.is_initial)
-		oidcpy(&s.oid_commit, &oid);
-
-	s.ignore_submodule_arg = ignore_submodule_arg;
-	s.status_format = status_format;
-	s.verbose = verbose;
-	if (no_renames != -1)
-		s.detect_rename = !no_renames;
-	if ((intptr_t)rename_score_arg != -1) {
-		if (s.detect_rename < DIFF_DETECT_RENAME)
-			s.detect_rename = DIFF_DETECT_RENAME;
-		if (rename_score_arg)
-			s.rename_score = parse_rename_score(&rename_score_arg);
-	}
-
-	wt_status_collect(&s);
-
-	if (0 <= fd)
-		repo_update_index_if_able(the_repository, &index_lock);
-
-	if (s.relative_paths)
-		s.prefix = prefix;
-
-	wt_status_print(&s);
-	wt_status_collect_free_buffers(&s);
-
-	return 0;
-}
-
-static int git_commit_config(const char *k, const char *v, void *cb)
-{
-	struct wt_status *s = cb;
-	int status;
-
-	if (!strcmp(k, "commit.template"))
-		return git_config_pathname(&template_file, k, v);
-	if (!strcmp(k, "commit.status")) {
-		include_status = git_config_bool(k, v);
-		return 0;
-	}
-	if (!strcmp(k, "commit.cleanup"))
-		return git_config_string(&cleanup_arg, k, v);
-	if (!strcmp(k, "commit.gpgsign")) {
-		sign_commit = git_config_bool(k, v) ? "" : NULL;
-		return 0;
-	}
-	if (!strcmp(k, "commit.verbose")) {
-		int is_bool;
-		config_commit_verbose = git_config_bool_or_int(k, v, &is_bool);
-		return 0;
-	}
-
-	status = git_gpg_config(k, v, NULL);
-	if (status)
-		return status;
-	return git_status_config(k, v, s);
-}
-
-int cmd_commit(int argc, const char **argv, const char *prefix)
-{
-	static struct wt_status s;
-	static struct option builtin_commit_options[] = {
-		OPT__QUIET(&quiet, N_("suppress summary after successful commit")),
-		OPT__VERBOSE(&verbose, N_("show diff in commit message template")),
-
-		OPT_GROUP(N_("Commit message options")),
-		OPT_FILENAME('F', "file", &logfile, N_("read message from file")),
-		OPT_STRING(0, "author", &force_author, N_("author"), N_("override author for commit")),
-		OPT_STRING(0, "date", &force_date, N_("date"), N_("override date for commit")),
-		OPT_CALLBACK('m', "message", &message, N_("message"), N_("commit message"), opt_parse_m),
-		OPT_STRING('c', "reedit-message", &edit_message, N_("commit"), N_("reuse and edit message from specified commit")),
-		OPT_STRING('C', "reuse-message", &use_message, N_("commit"), N_("reuse message from specified commit")),
-		OPT_STRING(0, "fixup", &fixup_message, N_("commit"), N_("use autosquash formatted message to fixup specified commit")),
-		OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")),
-		OPT_BOOL(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
-		OPT_BOOL('s', "signoff", &signoff, N_("add Signed-off-by:")),
-		OPT_FILENAME('t', "template", &template_file, N_("use specified template file")),
-		OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
-		OPT_CLEANUP(&cleanup_arg),
-		OPT_BOOL(0, "status", &include_status, N_("include status in commit message template")),
-		{ OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
-		  N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
-		/* end commit message options */
-
-		OPT_GROUP(N_("Commit contents options")),
-		OPT_BOOL('a', "all", &all, N_("commit all changed files")),
-		OPT_BOOL('i', "include", &also, N_("add specified files to index for commit")),
-		OPT_BOOL(0, "interactive", &interactive, N_("interactively add files")),
-		OPT_BOOL('p', "patch", &patch_interactive, N_("interactively add changes")),
-		OPT_BOOL('o', "only", &only, N_("commit only specified files")),
-		OPT_BOOL('n', "no-verify", &no_verify, N_("bypass pre-commit and commit-msg hooks")),
-		OPT_BOOL(0, "dry-run", &dry_run, N_("show what would be committed")),
-		OPT_SET_INT(0, "short", &status_format, N_("show status concisely"),
-			    STATUS_FORMAT_SHORT),
-		OPT_BOOL(0, "branch", &s.show_branch, N_("show branch information")),
-		OPT_BOOL(0, "ahead-behind", &s.ahead_behind_flags,
-			 N_("compute full ahead/behind values")),
-		OPT_SET_INT(0, "porcelain", &status_format,
-			    N_("machine-readable output"), STATUS_FORMAT_PORCELAIN),
-		OPT_SET_INT(0, "long", &status_format,
-			    N_("show status in long format (default)"),
-			    STATUS_FORMAT_LONG),
-		OPT_BOOL('z', "null", &s.null_termination,
-			 N_("terminate entries with NUL")),
-		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,
-				N_("ok to record an empty change")),
-		OPT_HIDDEN_BOOL(0, "allow-empty-message", &allow_empty_message,
-				N_("ok to record a change with an empty message")),
-
-		OPT_END()
-	};
-
-	struct strbuf sb = STRBUF_INIT;
-	struct strbuf author_ident = STRBUF_INIT;
-	const char *index_file, *reflog_msg;
-	struct object_id oid;
-	struct commit_list *parents = NULL;
-	struct stat statbuf;
-	struct commit *current_head = NULL;
-	struct commit_extra_header *extra = NULL;
-	struct strbuf err = STRBUF_INIT;
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage_with_options(builtin_commit_usage, builtin_commit_options);
-
-	status_init_config(&s, git_commit_config);
-	s.commit_template = 1;
-	status_format = STATUS_FORMAT_NONE; /* Ignore status.short */
-	s.colopts = 0;
-
-	if (get_oid("HEAD", &oid))
-		current_head = NULL;
-	else {
-		current_head = lookup_commit_or_die(&oid, "HEAD");
-		if (parse_commit(current_head))
-			die(_("could not parse HEAD commit"));
-	}
-	verbose = -1; /* unspecified */
-	argc = parse_and_validate_options(argc, argv, builtin_commit_options,
-					  builtin_commit_usage,
-					  prefix, current_head, &s);
-	if (verbose == -1)
-		verbose = (config_commit_verbose < 0) ? 0 : config_commit_verbose;
-
-	if (dry_run)
-		return dry_run_commit(argv, prefix, current_head, &s);
-	index_file = prepare_index(argv, prefix, current_head, 0);
-
-	/* Set up everything for writing the commit object.  This includes
-	   running hooks, writing the trees, and interacting with the user.  */
-	if (!prepare_to_commit(index_file, prefix,
-			       current_head, &s, &author_ident)) {
-		rollback_index_files();
-		return 1;
-	}
-
-	/* Determine parents */
-	reflog_msg = getenv("GIT_REFLOG_ACTION");
-	if (!current_head) {
-		if (!reflog_msg)
-			reflog_msg = "commit (initial)";
-	} else if (amend) {
-		if (!reflog_msg)
-			reflog_msg = "commit (amend)";
-		parents = copy_commit_list(current_head->parents);
-	} else if (whence == FROM_MERGE) {
-		struct strbuf m = STRBUF_INIT;
-		FILE *fp;
-		int allow_fast_forward = 1;
-		struct commit_list **pptr = &parents;
-
-		if (!reflog_msg)
-			reflog_msg = "commit (merge)";
-		pptr = commit_list_append(current_head, pptr);
-		fp = xfopen(git_path_merge_head(the_repository), "r");
-		while (strbuf_getline_lf(&m, fp) != EOF) {
-			struct commit *parent;
-
-			parent = get_merge_parent(m.buf);
-			if (!parent)
-				die(_("Corrupt MERGE_HEAD file (%s)"), m.buf);
-			pptr = commit_list_append(parent, pptr);
-		}
-		fclose(fp);
-		strbuf_release(&m);
-		if (!stat(git_path_merge_mode(the_repository), &statbuf)) {
-			if (strbuf_read_file(&sb, git_path_merge_mode(the_repository), 0) < 0)
-				die_errno(_("could not read MERGE_MODE"));
-			if (!strcmp(sb.buf, "no-ff"))
-				allow_fast_forward = 0;
-		}
-		if (allow_fast_forward)
-			reduce_heads_replace(&parents);
-	} else {
-		if (!reflog_msg)
-			reflog_msg = is_from_cherry_pick(whence)
-					? "commit (cherry-pick)"
-					: is_from_rebase(whence)
-					? "commit (rebase)"
-					: "commit";
-		commit_list_insert(current_head, &parents);
-	}
-
-	/* Finally, get the commit message */
-	strbuf_reset(&sb);
-	if (strbuf_read_file(&sb, git_path_commit_editmsg(), 0) < 0) {
-		int saved_errno = errno;
-		rollback_index_files();
-		die(_("could not read commit message: %s"), strerror(saved_errno));
-	}
-
-	cleanup_message(&sb, cleanup_mode, verbose);
-
-	if (message_is_empty(&sb, cleanup_mode) && !allow_empty_message) {
-		rollback_index_files();
-		fprintf(stderr, _("Aborting commit due to empty commit message.\n"));
-		exit(1);
-	}
-	if (template_untouched(&sb, template_file, cleanup_mode) && !allow_empty_message) {
-		rollback_index_files();
-		fprintf(stderr, _("Aborting commit; you did not edit the message.\n"));
-		exit(1);
-	}
-
-	if (amend) {
-		const char *exclude_gpgsig[3] = { "gpgsig", "gpgsig-sha256", NULL };
-		extra = read_commit_extra_headers(current_head, exclude_gpgsig);
-	} else {
-		struct commit_extra_header **tail = &extra;
-		append_merge_tag_headers(parents, &tail);
-	}
-
-	if (commit_tree_extended(sb.buf, sb.len, &active_cache_tree->oid,
-				 parents, &oid, author_ident.buf, NULL,
-				 sign_commit, extra)) {
-		rollback_index_files();
-		die(_("failed to write commit object"));
-	}
-	strbuf_release(&author_ident);
-	free_commit_extra_headers(extra);
-
-	if (update_head_with_reflog(current_head, &oid, reflog_msg, &sb,
-				    &err)) {
-		rollback_index_files();
-		die("%s", err.buf);
-	}
-
-	sequencer_post_commit_cleanup(the_repository, 0);
-	unlink(git_path_merge_head(the_repository));
-	unlink(git_path_merge_msg(the_repository));
-	unlink(git_path_merge_mode(the_repository));
-	unlink(git_path_squash_msg(the_repository));
-
-	if (commit_index_files())
-		die(_("repository has been updated, but unable to write\n"
-		      "new_index file. Check that disk is not full and quota is\n"
-		      "not exceeded, and then \"git restore --staged :/\" to recover."));
-
-	git_test_write_commit_graph_or_die();
-
-	repo_rerere(the_repository, 0);
-	run_auto_maintenance(quiet);
-	run_commit_hook(use_editor, get_index_file(), "post-commit", NULL);
-	if (amend && !no_post_rewrite) {
-		commit_post_rewrite(the_repository, current_head, &oid);
-	}
-	if (!quiet) {
-		unsigned int flags = 0;
-
-		if (!current_head)
-			flags |= SUMMARY_INITIAL_COMMIT;
-		if (author_date_is_interesting())
-			flags |= SUMMARY_SHOW_AUTHOR_DATE;
-		print_commit_summary(the_repository, prefix,
-				     &oid, flags);
-	}
-
-	apply_autostash(git_path_merge_autostash(the_repository));
-
-	UNLEAK(err);
-	UNLEAK(sb);
-	return 0;
-}
diff --git a/third_party/git/builtin/config.c b/third_party/git/builtin/config.c
deleted file mode 100644
index 963d65fd3fc1..000000000000
--- a/third_party/git/builtin/config.c
+++ /dev/null
@@ -1,919 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "color.h"
-#include "parse-options.h"
-#include "urlmatch.h"
-#include "quote.h"
-#include "worktree.h"
-
-static const char *const builtin_config_usage[] = {
-	N_("git config [<options>]"),
-	NULL
-};
-
-static char *key;
-static regex_t *key_regexp;
-static regex_t *regexp;
-static int show_keys;
-static int omit_values;
-static int use_key_regexp;
-static int do_all;
-static int do_not_match;
-static char delim = '=';
-static char key_delim = ' ';
-static char term = '\n';
-
-static int use_global_config, use_system_config, use_local_config;
-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 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)
-#define ACTION_GET_REGEXP (1<<2)
-#define ACTION_REPLACE_ALL (1<<3)
-#define ACTION_ADD (1<<4)
-#define ACTION_UNSET (1<<5)
-#define ACTION_UNSET_ALL (1<<6)
-#define ACTION_RENAME_SECTION (1<<7)
-#define ACTION_REMOVE_SECTION (1<<8)
-#define ACTION_LIST (1<<9)
-#define ACTION_EDIT (1<<10)
-#define ACTION_SET (1<<11)
-#define ACTION_SET_ALL (1<<12)
-#define ACTION_GET_COLOR (1<<13)
-#define ACTION_GET_COLORBOOL (1<<14)
-#define ACTION_GET_URLMATCH (1<<15)
-
-/*
- * The actions "ACTION_LIST | ACTION_GET_*" which may produce more than
- * one line of output and which should therefore be paged.
- */
-#define PAGING_ACTIONS (ACTION_LIST | ACTION_GET_ALL | \
-			ACTION_GET_REGEXP | ACTION_GET_URLMATCH)
-
-#define TYPE_BOOL		1
-#define TYPE_INT		2
-#define TYPE_BOOL_OR_INT	3
-#define TYPE_PATH		4
-#define TYPE_EXPIRY_DATE	5
-#define TYPE_COLOR		6
-#define TYPE_BOOL_OR_STR	7
-
-#define OPT_CALLBACK_VALUE(s, l, v, h, i) \
-	{ OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \
-	PARSE_OPT_NONEG, option_parse_type, (i) }
-
-static NORETURN void usage_builtin_config(void);
-
-static int option_parse_type(const struct option *opt, const char *arg,
-			     int unset)
-{
-	int new_type, *to_type;
-
-	if (unset) {
-		*((int *) opt->value) = 0;
-		return 0;
-	}
-
-	/*
-	 * To support '--<type>' style flags, begin with new_type equal to
-	 * opt->defval.
-	 */
-	new_type = opt->defval;
-	if (!new_type) {
-		if (!strcmp(arg, "bool"))
-			new_type = TYPE_BOOL;
-		else if (!strcmp(arg, "int"))
-			new_type = TYPE_INT;
-		else if (!strcmp(arg, "bool-or-int"))
-			new_type = TYPE_BOOL_OR_INT;
-		else if (!strcmp(arg, "bool-or-str"))
-			new_type = TYPE_BOOL_OR_STR;
-		else if (!strcmp(arg, "path"))
-			new_type = TYPE_PATH;
-		else if (!strcmp(arg, "expiry-date"))
-			new_type = TYPE_EXPIRY_DATE;
-		else if (!strcmp(arg, "color"))
-			new_type = TYPE_COLOR;
-		else
-			die(_("unrecognized --type argument, %s"), arg);
-	}
-
-	to_type = opt->value;
-	if (*to_type && *to_type != new_type) {
-		/*
-		 * Complain when there is a new type not equal to the old type.
-		 * This allows for combinations like '--int --type=int' and
-		 * '--type=int --type=int', but disallows ones like '--type=bool
-		 * --int' and '--type=bool
-		 * --type=int'.
-		 */
-		error(_("only one type at a time"));
-		usage_builtin_config();
-	}
-	*to_type = new_type;
-
-	return 0;
-}
-
-static struct option builtin_config_options[] = {
-	OPT_GROUP(N_("Config file location")),
-	OPT_BOOL(0, "global", &use_global_config, N_("use global config file")),
-	OPT_BOOL(0, "system", &use_system_config, N_("use system config file")),
-	OPT_BOOL(0, "local", &use_local_config, N_("use repository config file")),
-	OPT_BOOL(0, "worktree", &use_worktree_config, N_("use per-worktree config file")),
-	OPT_STRING('f', "file", &given_config_source.file, N_("file"), N_("use given config file")),
-	OPT_STRING(0, "blob", &given_config_source.blob, N_("blob-id"), N_("read config from given blob object")),
-	OPT_GROUP(N_("Action")),
-	OPT_BIT(0, "get", &actions, N_("get value: name [value-regex]"), ACTION_GET),
-	OPT_BIT(0, "get-all", &actions, N_("get all values: key [value-regex]"), ACTION_GET_ALL),
-	OPT_BIT(0, "get-regexp", &actions, N_("get values for regexp: name-regex [value-regex]"), ACTION_GET_REGEXP),
-	OPT_BIT(0, "get-urlmatch", &actions, N_("get value specific for the URL: section[.var] URL"), ACTION_GET_URLMATCH),
-	OPT_BIT(0, "replace-all", &actions, N_("replace all matching variables: name value [value_regex]"), ACTION_REPLACE_ALL),
-	OPT_BIT(0, "add", &actions, N_("add a new variable: name value"), ACTION_ADD),
-	OPT_BIT(0, "unset", &actions, N_("remove a variable: name [value-regex]"), ACTION_UNSET),
-	OPT_BIT(0, "unset-all", &actions, N_("remove all matches: name [value-regex]"), ACTION_UNSET_ALL),
-	OPT_BIT(0, "rename-section", &actions, N_("rename section: old-name new-name"), ACTION_RENAME_SECTION),
-	OPT_BIT(0, "remove-section", &actions, N_("remove a section: name"), ACTION_REMOVE_SECTION),
-	OPT_BIT('l', "list", &actions, N_("list all"), ACTION_LIST),
-	OPT_BIT('e', "edit", &actions, N_("open an editor"), ACTION_EDIT),
-	OPT_BIT(0, "get-color", &actions, N_("find the color configured: slot [default]"), ACTION_GET_COLOR),
-	OPT_BIT(0, "get-colorbool", &actions, N_("find the color setting: slot [stdout-is-tty]"), ACTION_GET_COLORBOOL),
-	OPT_GROUP(N_("Type")),
-	OPT_CALLBACK('t', "type", &type, "", N_("value is given this type"), option_parse_type),
-	OPT_CALLBACK_VALUE(0, "bool", &type, N_("value is \"true\" or \"false\""), TYPE_BOOL),
-	OPT_CALLBACK_VALUE(0, "int", &type, N_("value is decimal number"), TYPE_INT),
-	OPT_CALLBACK_VALUE(0, "bool-or-int", &type, N_("value is --bool or --int"), TYPE_BOOL_OR_INT),
-	OPT_CALLBACK_VALUE(0, "bool-or-str", &type, N_("value is --bool or string"), TYPE_BOOL_OR_STR),
-	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(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(),
-};
-
-static NORETURN void usage_builtin_config(void)
-{
-	usage_with_options(builtin_config_usage, builtin_config_options);
-}
-
-static void check_argc(int argc, int min, int max)
-{
-	if (argc >= min && argc <= max)
-		return;
-	if (min == max)
-		error(_("wrong number of arguments, should be %d"), min);
-	else
-		error(_("wrong number of arguments, should be from %d to %d"),
-		      min, max);
-	usage_builtin_config();
-}
-
-static void show_config_origin(struct strbuf *buf)
-{
-	const char term = end_nul ? '\0' : '\t';
-
-	strbuf_addstr(buf, current_config_origin_type());
-	strbuf_addch(buf, ':');
-	if (end_nul)
-		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) {
-		struct strbuf buf = STRBUF_INIT;
-		if (show_scope)
-			show_config_scope(&buf);
-		if (show_origin)
-			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);
-	}
-	if (!omit_values && value_)
-		printf("%s%c%s%c", key_, delim, value_, term);
-	else
-		printf("%s%c", key_, term);
-	return 0;
-}
-
-struct strbuf_list {
-	struct strbuf *items;
-	int nr;
-	int alloc;
-};
-
-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)
-		strbuf_addstr(buf, key_);
-	if (!omit_values) {
-		if (show_keys)
-			strbuf_addch(buf, key_delim);
-
-		if (type == TYPE_INT)
-			strbuf_addf(buf, "%"PRId64,
-				    git_config_int64(key_, value_ ? value_ : ""));
-		else if (type == TYPE_BOOL)
-			strbuf_addstr(buf, git_config_bool(key_, value_) ?
-				      "true" : "false");
-		else if (type == TYPE_BOOL_OR_INT) {
-			int is_bool, v;
-			v = git_config_bool_or_int(key_, value_, &is_bool);
-			if (is_bool)
-				strbuf_addstr(buf, v ? "true" : "false");
-			else
-				strbuf_addf(buf, "%d", v);
-		} else if (type == TYPE_BOOL_OR_STR) {
-			int v = git_parse_maybe_bool(value_);
-			if (v < 0)
-				strbuf_addstr(buf, value_);
-			else
-				strbuf_addstr(buf, v ? "true" : "false");
-		} else if (type == TYPE_PATH) {
-			const char *v;
-			if (git_config_pathname(&v, key_, value_) < 0)
-				return -1;
-			strbuf_addstr(buf, v);
-			free((char *)v);
-		} else if (type == TYPE_EXPIRY_DATE) {
-			timestamp_t t;
-			if (git_config_expiry_date(&t, key_, value_) < 0)
-				return -1;
-			strbuf_addf(buf, "%"PRItime, t);
-		} else if (type == TYPE_COLOR) {
-			char v[COLOR_MAXLEN];
-			if (git_config_color(v, key_, value_) < 0)
-				return -1;
-			strbuf_addstr(buf, v);
-		} else if (value_) {
-			strbuf_addstr(buf, value_);
-		} else {
-			/* Just show the key name; back out delimiter */
-			if (show_keys)
-				strbuf_setlen(buf, buf->len - 1);
-		}
-	}
-	strbuf_addch(buf, term);
-	return 0;
-}
-
-static int collect_config(const char *key_, const char *value_, void *cb)
-{
-	struct strbuf_list *values = cb;
-
-	if (!use_key_regexp && strcmp(key_, key))
-		return 0;
-	if (use_key_regexp && regexec(key_regexp, key_, 0, NULL, 0))
-		return 0;
-	if (regexp != NULL &&
-	    (do_not_match ^ !!regexec(regexp, (value_?value_:""), 0, NULL, 0)))
-		return 0;
-
-	ALLOC_GROW(values->items, values->nr + 1, values->alloc);
-	strbuf_init(&values->items[values->nr], 0);
-
-	return format_config(&values->items[values->nr++], key_, value_);
-}
-
-static int get_value(const char *key_, const char *regex_)
-{
-	int ret = CONFIG_GENERIC_ERROR;
-	struct strbuf_list values = {NULL};
-	int i;
-
-	if (use_key_regexp) {
-		char *tl;
-
-		/*
-		 * NEEDSWORK: this naive pattern lowercasing obviously does not
-		 * work for more complex patterns like "^[^.]*Foo.*bar".
-		 * Perhaps we should deprecate this altogether someday.
-		 */
-
-		key = xstrdup(key_);
-		for (tl = key + strlen(key) - 1;
-		     tl >= key && *tl != '.';
-		     tl--)
-			*tl = tolower(*tl);
-		for (tl = key; *tl && *tl != '.'; tl++)
-			*tl = tolower(*tl);
-
-		key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
-		if (regcomp(key_regexp, key, REG_EXTENDED)) {
-			error(_("invalid key pattern: %s"), key_);
-			FREE_AND_NULL(key_regexp);
-			ret = CONFIG_INVALID_PATTERN;
-			goto free_strings;
-		}
-	} else {
-		if (git_config_parse_key(key_, &key, NULL)) {
-			ret = CONFIG_INVALID_KEY;
-			goto free_strings;
-		}
-	}
-
-	if (regex_) {
-		if (regex_[0] == '!') {
-			do_not_match = 1;
-			regex_++;
-		}
-
-		regexp = (regex_t*)xmalloc(sizeof(regex_t));
-		if (regcomp(regexp, regex_, REG_EXTENDED)) {
-			error(_("invalid pattern: %s"), regex_);
-			FREE_AND_NULL(regexp);
-			ret = CONFIG_INVALID_PATTERN;
-			goto free_strings;
-		}
-	}
-
-	config_with_options(collect_config, &values,
-			    &given_config_source, &config_options);
-
-	if (!values.nr && default_value) {
-		struct strbuf *item;
-		ALLOC_GROW(values.items, values.nr + 1, values.alloc);
-		item = &values.items[values.nr++];
-		strbuf_init(item, 0);
-		if (format_config(item, key_, default_value) < 0)
-			die(_("failed to format default config value: %s"),
-				default_value);
-	}
-
-	ret = !values.nr;
-
-	for (i = 0; i < values.nr; i++) {
-		struct strbuf *buf = values.items + i;
-		if (do_all || i == values.nr - 1)
-			fwrite(buf->buf, 1, buf->len, stdout);
-		strbuf_release(buf);
-	}
-	free(values.items);
-
-free_strings:
-	free(key);
-	if (key_regexp) {
-		regfree(key_regexp);
-		free(key_regexp);
-	}
-	if (regexp) {
-		regfree(regexp);
-		free(regexp);
-	}
-
-	return ret;
-}
-
-static char *normalize_value(const char *key, const char *value)
-{
-	if (!value)
-		return NULL;
-
-	if (type == 0 || type == TYPE_PATH || type == TYPE_EXPIRY_DATE)
-		/*
-		 * We don't do normalization for TYPE_PATH here: If
-		 * the path is like ~/foobar/, we prefer to store
-		 * "~/foobar/" in the config file, and to expand the ~
-		 * when retrieving the value.
-		 * Also don't do normalization for expiry dates.
-		 */
-		return xstrdup(value);
-	if (type == TYPE_INT)
-		return xstrfmt("%"PRId64, git_config_int64(key, value));
-	if (type == TYPE_BOOL)
-		return xstrdup(git_config_bool(key, value) ?  "true" : "false");
-	if (type == TYPE_BOOL_OR_INT) {
-		int is_bool, v;
-		v = git_config_bool_or_int(key, value, &is_bool);
-		if (!is_bool)
-			return xstrfmt("%d", v);
-		else
-			return xstrdup(v ? "true" : "false");
-	}
-	if (type == TYPE_BOOL_OR_STR) {
-		int v = git_parse_maybe_bool(value);
-		if (v < 0)
-			return xstrdup(value);
-		else
-			return xstrdup(v ? "true" : "false");
-	}
-	if (type == TYPE_COLOR) {
-		char v[COLOR_MAXLEN];
-		if (git_config_color(v, key, value))
-			die(_("cannot parse color '%s'"), value);
-
-		/*
-		 * The contents of `v` now contain an ANSI escape
-		 * sequence, not suitable for including within a
-		 * configuration file. Treat the above as a
-		 * "sanity-check", and return the given value, which we
-		 * know is representable as valid color code.
-		 */
-		return xstrdup(value);
-	}
-
-	BUG("cannot normalize type %d", type);
-}
-
-static int get_color_found;
-static const char *get_color_slot;
-static const char *get_colorbool_slot;
-static char parsed_color[COLOR_MAXLEN];
-
-static int git_get_color_config(const char *var, const char *value, void *cb)
-{
-	if (!strcmp(var, get_color_slot)) {
-		if (!value)
-			config_error_nonbool(var);
-		if (color_parse(value, parsed_color) < 0)
-			return -1;
-		get_color_found = 1;
-	}
-	return 0;
-}
-
-static void get_color(const char *var, const char *def_color)
-{
-	get_color_slot = var;
-	get_color_found = 0;
-	parsed_color[0] = '\0';
-	config_with_options(git_get_color_config, NULL,
-			    &given_config_source, &config_options);
-
-	if (!get_color_found && def_color) {
-		if (color_parse(def_color, parsed_color) < 0)
-			die(_("unable to parse default color value"));
-	}
-
-	fputs(parsed_color, stdout);
-}
-
-static int get_colorbool_found;
-static int get_diff_color_found;
-static int get_color_ui_found;
-static int git_get_colorbool_config(const char *var, const char *value,
-		void *cb)
-{
-	if (!strcmp(var, get_colorbool_slot))
-		get_colorbool_found = git_config_colorbool(var, value);
-	else if (!strcmp(var, "diff.color"))
-		get_diff_color_found = git_config_colorbool(var, value);
-	else if (!strcmp(var, "color.ui"))
-		get_color_ui_found = git_config_colorbool(var, value);
-	return 0;
-}
-
-static int get_colorbool(const char *var, int print)
-{
-	get_colorbool_slot = var;
-	get_colorbool_found = -1;
-	get_diff_color_found = -1;
-	get_color_ui_found = -1;
-	config_with_options(git_get_colorbool_config, NULL,
-			    &given_config_source, &config_options);
-
-	if (get_colorbool_found < 0) {
-		if (!strcmp(get_colorbool_slot, "color.diff"))
-			get_colorbool_found = get_diff_color_found;
-		if (get_colorbool_found < 0)
-			get_colorbool_found = get_color_ui_found;
-	}
-
-	if (get_colorbool_found < 0)
-		/* default value if none found in config */
-		get_colorbool_found = GIT_COLOR_AUTO;
-
-	get_colorbool_found = want_color(get_colorbool_found);
-
-	if (print) {
-		printf("%s\n", get_colorbool_found ? "true" : "false");
-		return 0;
-	} else
-		return get_colorbool_found ? 0 : 1;
-}
-
-static void check_write(void)
-{
-	if (!given_config_source.file && !startup_info->have_repository)
-		die(_("not in a git directory"));
-
-	if (given_config_source.use_stdin)
-		die(_("writing to stdin is not supported"));
-
-	if (given_config_source.blob)
-		die(_("writing config blobs is not supported"));
-}
-
-struct urlmatch_current_candidate_value {
-	char value_is_null;
-	struct strbuf value;
-};
-
-static int urlmatch_collect_fn(const char *var, const char *value, void *cb)
-{
-	struct string_list *values = cb;
-	struct string_list_item *item = string_list_insert(values, var);
-	struct urlmatch_current_candidate_value *matched = item->util;
-
-	if (!matched) {
-		matched = xmalloc(sizeof(*matched));
-		strbuf_init(&matched->value, 0);
-		item->util = matched;
-	} else {
-		strbuf_reset(&matched->value);
-	}
-
-	if (value) {
-		strbuf_addstr(&matched->value, value);
-		matched->value_is_null = 0;
-	} else {
-		matched->value_is_null = 1;
-	}
-	return 0;
-}
-
-static int get_urlmatch(const char *var, const char *url)
-{
-	int ret;
-	char *section_tail;
-	struct string_list_item *item;
-	struct urlmatch_config config = { STRING_LIST_INIT_DUP };
-	struct string_list values = STRING_LIST_INIT_DUP;
-
-	config.collect_fn = urlmatch_collect_fn;
-	config.cascade_fn = NULL;
-	config.cb = &values;
-
-	if (!url_normalize(url, &config.url))
-		die("%s", config.url.err);
-
-	config.section = xstrdup_tolower(var);
-	section_tail = strchr(config.section, '.');
-	if (section_tail) {
-		*section_tail = '\0';
-		config.key = section_tail + 1;
-		show_keys = 0;
-	} else {
-		config.key = NULL;
-		show_keys = 1;
-	}
-
-	config_with_options(urlmatch_config_entry, &config,
-			    &given_config_source, &config_options);
-
-	ret = !values.nr;
-
-	for_each_string_list_item(item, &values) {
-		struct urlmatch_current_candidate_value *matched = item->util;
-		struct strbuf buf = STRBUF_INIT;
-
-		format_config(&buf, item->string,
-			      matched->value_is_null ? NULL : matched->value.buf);
-		fwrite(buf.buf, 1, buf.len, stdout);
-		strbuf_release(&buf);
-
-		strbuf_release(&matched->value);
-	}
-	string_list_clear(&config.vars, 1);
-	string_list_clear(&values, 1);
-	free(config.url.url);
-
-	free((void *)config.section);
-	return ret;
-}
-
-static char *default_user_config(void)
-{
-	struct strbuf buf = STRBUF_INIT;
-	strbuf_addf(&buf,
-		    _("# This is Git's per-user configuration file.\n"
-		      "[user]\n"
-		      "# Please adapt and uncomment the following lines:\n"
-		      "#	name = %s\n"
-		      "#	email = %s\n"),
-		    ident_default_name(),
-		    ident_default_email());
-	return strbuf_detach(&buf, NULL);
-}
-
-int cmd_config(int argc, const char **argv, const char *prefix)
-{
-	int nongit = !startup_info->have_repository;
-	char *value;
-
-	given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));
-
-	argc = parse_options(argc, argv, prefix, builtin_config_options,
-			     builtin_config_usage,
-			     PARSE_OPT_STOP_AT_NON_OPTION);
-
-	if (use_global_config + use_system_config + use_local_config +
-	    use_worktree_config +
-	    !!given_config_source.file + !!given_config_source.blob > 1) {
-		error(_("only one config file at a time"));
-		usage_builtin_config();
-	}
-
-	if (nongit) {
-		if (use_local_config)
-			die(_("--local can only be used inside a git repository"));
-		if (given_config_source.blob)
-			die(_("--blob can only be used inside a git repository"));
-		if (use_worktree_config)
-			die(_("--worktree can only be used inside a git repository"));
-
-	}
-
-	if (given_config_source.file &&
-			!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) {
-		char *user_config = expand_user_path("~/.gitconfig", 0);
-		char *xdg_config = xdg_config_home("config");
-
-		if (!user_config)
-			/*
-			 * It is unknown if HOME/.gitconfig exists, so
-			 * we do not know if we should write to XDG
-			 * location; error out even if XDG_CONFIG_HOME
-			 * is set and points at a sane location.
-			 */
-			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;
-			free(user_config);
-		} else {
-			given_config_source.file = user_config;
-			free(xdg_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) {
-		given_config_source.file = git_pathdup("config");
-		given_config_source.scope = CONFIG_SCOPE_LOCAL;
-	} else if (use_worktree_config) {
-		struct worktree **worktrees = get_worktrees();
-		if (repository_format_worktree_config)
-			given_config_source.file = git_pathdup("config.worktree");
-		else if (worktrees[0] && worktrees[1])
-			die(_("--worktree cannot be used with multiple "
-			      "working trees unless the config\n"
-			      "extension worktreeConfig is enabled. "
-			      "Please read \"CONFIGURATION FILE\"\n"
-			      "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
-		config_options.respect_includes = respect_includes_opt;
-	if (!nongit) {
-		config_options.commondir = get_git_common_dir();
-		config_options.git_dir = get_git_dir();
-	}
-
-	if (end_nul) {
-		term = '\0';
-		delim = '\n';
-		key_delim = '\n';
-	}
-
-	if ((actions & (ACTION_GET_COLOR|ACTION_GET_COLORBOOL)) && type) {
-		error(_("--get-color and variable type are incoherent"));
-		usage_builtin_config();
-	}
-
-	if (HAS_MULTI_BITS(actions)) {
-		error(_("only one action at a time"));
-		usage_builtin_config();
-	}
-	if (actions == 0)
-		switch (argc) {
-		case 1: actions = ACTION_GET; break;
-		case 2: actions = ACTION_SET; break;
-		case 3: actions = ACTION_SET_ALL; break;
-		default:
-			usage_builtin_config();
-		}
-	if (omit_values &&
-	    !(actions == ACTION_LIST || actions == ACTION_GET_REGEXP)) {
-		error(_("--name-only is only applicable to --list or --get-regexp"));
-		usage_builtin_config();
-	}
-
-	if (show_origin && !(actions &
-		(ACTION_GET|ACTION_GET_ALL|ACTION_GET_REGEXP|ACTION_LIST))) {
-		error(_("--show-origin is only applicable to --get, --get-all, "
-			"--get-regexp, and --list"));
-		usage_builtin_config();
-	}
-
-	if (default_value && !(actions & ACTION_GET)) {
-		error(_("--default is only applicable to --get"));
-		usage_builtin_config();
-	}
-
-	if (actions & PAGING_ACTIONS)
-		setup_auto_pager("config", 1);
-
-	if (actions == ACTION_LIST) {
-		check_argc(argc, 0, 0);
-		if (config_with_options(show_all_config, NULL,
-					&given_config_source,
-					&config_options) < 0) {
-			if (given_config_source.file)
-				die_errno(_("unable to read config file '%s'"),
-					  given_config_source.file);
-			else
-				die(_("error processing config file(s)"));
-		}
-	}
-	else if (actions == ACTION_EDIT) {
-		char *config_file;
-
-		check_argc(argc, 0, 0);
-		if (!given_config_source.file && nongit)
-			die(_("not in a git directory"));
-		if (given_config_source.use_stdin)
-			die(_("editing stdin is not supported"));
-		if (given_config_source.blob)
-			die(_("editing blobs is not supported"));
-		git_config(git_default_config, NULL);
-		config_file = given_config_source.file ?
-				xstrdup(given_config_source.file) :
-				git_pathdup("config");
-		if (use_global_config) {
-			int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666);
-			if (fd >= 0) {
-				char *content = default_user_config();
-				write_str_in_full(fd, content);
-				free(content);
-				close(fd);
-			}
-			else if (errno != EEXIST)
-				die_errno(_("cannot create configuration file %s"), config_file);
-		}
-		launch_editor(config_file, NULL, NULL);
-		free(config_file);
-	}
-	else if (actions == ACTION_SET) {
-		int ret;
-		check_write();
-		check_argc(argc, 2, 2);
-		value = normalize_value(argv[0], argv[1]);
-		UNLEAK(value);
-		ret = git_config_set_in_file_gently(given_config_source.file, argv[0], value);
-		if (ret == CONFIG_NOTHING_SET)
-			error(_("cannot overwrite multiple values with a single value\n"
-			"       Use a regexp, --add or --replace-all to change %s."), argv[0]);
-		return ret;
-	}
-	else if (actions == ACTION_SET_ALL) {
-		check_write();
-		check_argc(argc, 2, 3);
-		value = normalize_value(argv[0], argv[1]);
-		UNLEAK(value);
-		return git_config_set_multivar_in_file_gently(given_config_source.file,
-							      argv[0], value, argv[2], 0);
-	}
-	else if (actions == ACTION_ADD) {
-		check_write();
-		check_argc(argc, 2, 2);
-		value = normalize_value(argv[0], argv[1]);
-		UNLEAK(value);
-		return git_config_set_multivar_in_file_gently(given_config_source.file,
-							      argv[0], value,
-							      CONFIG_REGEX_NONE, 0);
-	}
-	else if (actions == ACTION_REPLACE_ALL) {
-		check_write();
-		check_argc(argc, 2, 3);
-		value = normalize_value(argv[0], argv[1]);
-		UNLEAK(value);
-		return git_config_set_multivar_in_file_gently(given_config_source.file,
-							      argv[0], value, argv[2], 1);
-	}
-	else if (actions == ACTION_GET) {
-		check_argc(argc, 1, 2);
-		return get_value(argv[0], argv[1]);
-	}
-	else if (actions == ACTION_GET_ALL) {
-		do_all = 1;
-		check_argc(argc, 1, 2);
-		return get_value(argv[0], argv[1]);
-	}
-	else if (actions == ACTION_GET_REGEXP) {
-		show_keys = 1;
-		use_key_regexp = 1;
-		do_all = 1;
-		check_argc(argc, 1, 2);
-		return get_value(argv[0], argv[1]);
-	}
-	else if (actions == ACTION_GET_URLMATCH) {
-		check_argc(argc, 2, 2);
-		return get_urlmatch(argv[0], argv[1]);
-	}
-	else if (actions == ACTION_UNSET) {
-		check_write();
-		check_argc(argc, 1, 2);
-		if (argc == 2)
-			return git_config_set_multivar_in_file_gently(given_config_source.file,
-								      argv[0], NULL, argv[1], 0);
-		else
-			return git_config_set_in_file_gently(given_config_source.file,
-							     argv[0], NULL);
-	}
-	else if (actions == ACTION_UNSET_ALL) {
-		check_write();
-		check_argc(argc, 1, 2);
-		return git_config_set_multivar_in_file_gently(given_config_source.file,
-							      argv[0], NULL, argv[1], 1);
-	}
-	else if (actions == ACTION_RENAME_SECTION) {
-		int ret;
-		check_write();
-		check_argc(argc, 2, 2);
-		ret = git_config_rename_section_in_file(given_config_source.file,
-							argv[0], argv[1]);
-		if (ret < 0)
-			return ret;
-		if (ret == 0)
-			die(_("no such section: %s"), argv[0]);
-	}
-	else if (actions == ACTION_REMOVE_SECTION) {
-		int ret;
-		check_write();
-		check_argc(argc, 1, 1);
-		ret = git_config_rename_section_in_file(given_config_source.file,
-							argv[0], NULL);
-		if (ret < 0)
-			return ret;
-		if (ret == 0)
-			die(_("no such section: %s"), argv[0]);
-	}
-	else if (actions == ACTION_GET_COLOR) {
-		check_argc(argc, 1, 2);
-		get_color(argv[0], argv[1]);
-	}
-	else if (actions == ACTION_GET_COLORBOOL) {
-		check_argc(argc, 1, 2);
-		if (argc == 2)
-			color_stdout_is_tty = git_config_bool("command line", argv[1]);
-		return get_colorbool(argv[0], argc == 2);
-	}
-
-	return 0;
-}
diff --git a/third_party/git/builtin/count-objects.c b/third_party/git/builtin/count-objects.c
deleted file mode 100644
index 3fae474f6f1f..000000000000
--- a/third_party/git/builtin/count-objects.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Builtin "git count-objects".
- *
- * Copyright (c) 2006 Junio C Hamano
- */
-
-#include "cache.h"
-#include "config.h"
-#include "dir.h"
-#include "repository.h"
-#include "builtin.h"
-#include "parse-options.h"
-#include "quote.h"
-#include "packfile.h"
-#include "object-store.h"
-
-static unsigned long garbage;
-static off_t size_garbage;
-static int verbose;
-static unsigned long loose, packed, packed_loose;
-static off_t loose_size;
-
-static const char *bits_to_msg(unsigned seen_bits)
-{
-	switch (seen_bits) {
-	case 0:
-		return "no corresponding .idx or .pack";
-	case PACKDIR_FILE_GARBAGE:
-		return "garbage found";
-	case PACKDIR_FILE_PACK:
-		return "no corresponding .idx";
-	case PACKDIR_FILE_IDX:
-		return "no corresponding .pack";
-	case PACKDIR_FILE_PACK|PACKDIR_FILE_IDX:
-	default:
-		return NULL;
-	}
-}
-
-static void real_report_garbage(unsigned seen_bits, const char *path)
-{
-	struct stat st;
-	const char *desc = bits_to_msg(seen_bits);
-
-	if (!desc)
-		return;
-
-	if (!stat(path, &st))
-		size_garbage += st.st_size;
-	warning("%s: %s", desc, path);
-	garbage++;
-}
-
-static void loose_garbage(const char *path)
-{
-	if (verbose)
-		report_garbage(PACKDIR_FILE_GARBAGE, path);
-}
-
-static int count_loose(const struct object_id *oid, const char *path, void *data)
-{
-	struct stat st;
-
-	if (lstat(path, &st) || !S_ISREG(st.st_mode))
-		loose_garbage(path);
-	else {
-		loose_size += on_disk_bytes(st);
-		loose++;
-		if (verbose && has_object_pack(oid))
-			packed_loose++;
-	}
-	return 0;
-}
-
-static int count_cruft(const char *basename, const char *path, void *data)
-{
-	loose_garbage(path);
-	return 0;
-}
-
-static int print_alternate(struct object_directory *odb, void *data)
-{
-	printf("alternate: ");
-	quote_c_style(odb->path, NULL, stdout, 0);
-	putchar('\n');
-	return 0;
-}
-
-static char const * const count_objects_usage[] = {
-	N_("git count-objects [-v] [-H | --human-readable]"),
-	NULL
-};
-
-int cmd_count_objects(int argc, const char **argv, const char *prefix)
-{
-	int human_readable = 0;
-	struct option opts[] = {
-		OPT__VERBOSE(&verbose, N_("be verbose")),
-		OPT_BOOL('H', "human-readable", &human_readable,
-			 N_("print sizes in human readable format")),
-		OPT_END(),
-	};
-
-	git_config(git_default_config, NULL);
-
-	argc = parse_options(argc, argv, prefix, opts, count_objects_usage, 0);
-	/* we do not take arguments other than flags for now */
-	if (argc)
-		usage_with_options(count_objects_usage, opts);
-	if (verbose) {
-		report_garbage = real_report_garbage;
-		report_linked_checkout_garbage();
-	}
-
-	for_each_loose_file_in_objdir(get_object_directory(),
-				      count_loose, count_cruft, NULL, NULL);
-
-	if (verbose) {
-		struct packed_git *p;
-		unsigned long num_pack = 0;
-		off_t size_pack = 0;
-		struct strbuf loose_buf = STRBUF_INIT;
-		struct strbuf pack_buf = STRBUF_INIT;
-		struct strbuf garbage_buf = STRBUF_INIT;
-
-		for (p = get_all_packs(the_repository); p; p = p->next) {
-			if (!p->pack_local)
-				continue;
-			if (open_pack_index(p))
-				continue;
-			packed += p->num_objects;
-			size_pack += p->pack_size + p->index_size;
-			num_pack++;
-		}
-
-		if (human_readable) {
-			strbuf_humanise_bytes(&loose_buf, loose_size);
-			strbuf_humanise_bytes(&pack_buf, size_pack);
-			strbuf_humanise_bytes(&garbage_buf, size_garbage);
-		} else {
-			strbuf_addf(&loose_buf, "%lu",
-				    (unsigned long)(loose_size / 1024));
-			strbuf_addf(&pack_buf, "%lu",
-				    (unsigned long)(size_pack / 1024));
-			strbuf_addf(&garbage_buf, "%lu",
-				    (unsigned long)(size_garbage / 1024));
-		}
-
-		printf("count: %lu\n", loose);
-		printf("size: %s\n", loose_buf.buf);
-		printf("in-pack: %lu\n", packed);
-		printf("packs: %lu\n", num_pack);
-		printf("size-pack: %s\n", pack_buf.buf);
-		printf("prune-packable: %lu\n", packed_loose);
-		printf("garbage: %lu\n", garbage);
-		printf("size-garbage: %s\n", garbage_buf.buf);
-		foreach_alt_odb(print_alternate, NULL);
-		strbuf_release(&loose_buf);
-		strbuf_release(&pack_buf);
-		strbuf_release(&garbage_buf);
-	} else {
-		struct strbuf buf = STRBUF_INIT;
-		if (human_readable)
-			strbuf_humanise_bytes(&buf, loose_size);
-		else
-			strbuf_addf(&buf, "%lu kilobytes",
-				    (unsigned long)(loose_size / 1024));
-		printf("%lu objects, %s\n", loose, buf.buf);
-		strbuf_release(&buf);
-	}
-	return 0;
-}
diff --git a/third_party/git/builtin/credential-cache--daemon.c b/third_party/git/builtin/credential-cache--daemon.c
deleted file mode 100644
index c61f123a3b81..000000000000
--- a/third_party/git/builtin/credential-cache--daemon.c
+++ /dev/null
@@ -1,318 +0,0 @@
-#include "builtin.h"
-#include "parse-options.h"
-
-#ifndef NO_UNIX_SOCKETS
-
-#include "config.h"
-#include "tempfile.h"
-#include "credential.h"
-#include "unix-socket.h"
-
-struct credential_cache_entry {
-	struct credential item;
-	timestamp_t expiration;
-};
-static struct credential_cache_entry *entries;
-static int entries_nr;
-static int entries_alloc;
-
-static void cache_credential(struct credential *c, int timeout)
-{
-	struct credential_cache_entry *e;
-
-	ALLOC_GROW(entries, entries_nr + 1, entries_alloc);
-	e = &entries[entries_nr++];
-
-	/* take ownership of pointers */
-	memcpy(&e->item, c, sizeof(*c));
-	memset(c, 0, sizeof(*c));
-	e->expiration = time(NULL) + timeout;
-}
-
-static struct credential_cache_entry *lookup_credential(const struct credential *c)
-{
-	int i;
-	for (i = 0; i < entries_nr; i++) {
-		struct credential *e = &entries[i].item;
-		if (credential_match(c, e))
-			return &entries[i];
-	}
-	return NULL;
-}
-
-static void remove_credential(const struct credential *c)
-{
-	struct credential_cache_entry *e;
-
-	e = lookup_credential(c);
-	if (e)
-		e->expiration = 0;
-}
-
-static timestamp_t check_expirations(void)
-{
-	static timestamp_t wait_for_entry_until;
-	int i = 0;
-	timestamp_t now = time(NULL);
-	timestamp_t next = TIME_MAX;
-
-	/*
-	 * Initially give the client 30 seconds to actually contact us
-	 * and store a credential before we decide there's no point in
-	 * keeping the daemon around.
-	 */
-	if (!wait_for_entry_until)
-		wait_for_entry_until = now + 30;
-
-	while (i < entries_nr) {
-		if (entries[i].expiration <= now) {
-			entries_nr--;
-			credential_clear(&entries[i].item);
-			if (i != entries_nr)
-				memcpy(&entries[i], &entries[entries_nr], sizeof(*entries));
-			/*
-			 * Stick around 30 seconds in case a new credential
-			 * shows up (e.g., because we just removed a failed
-			 * one, and we will soon get the correct one).
-			 */
-			wait_for_entry_until = now + 30;
-		}
-		else {
-			if (entries[i].expiration < next)
-				next = entries[i].expiration;
-			i++;
-		}
-	}
-
-	if (!entries_nr) {
-		if (wait_for_entry_until <= now)
-			return 0;
-		next = wait_for_entry_until;
-	}
-
-	return next - now;
-}
-
-static int read_request(FILE *fh, struct credential *c,
-			struct strbuf *action, int *timeout)
-{
-	static struct strbuf item = STRBUF_INIT;
-	const char *p;
-
-	strbuf_getline_lf(&item, fh);
-	if (!skip_prefix(item.buf, "action=", &p))
-		return error("client sent bogus action line: %s", item.buf);
-	strbuf_addstr(action, p);
-
-	strbuf_getline_lf(&item, fh);
-	if (!skip_prefix(item.buf, "timeout=", &p))
-		return error("client sent bogus timeout line: %s", item.buf);
-	*timeout = atoi(p);
-
-	if (credential_read(c, fh) < 0)
-		return -1;
-	return 0;
-}
-
-static void serve_one_client(FILE *in, FILE *out)
-{
-	struct credential c = CREDENTIAL_INIT;
-	struct strbuf action = STRBUF_INIT;
-	int timeout = -1;
-
-	if (read_request(in, &c, &action, &timeout) < 0)
-		/* ignore error */ ;
-	else if (!strcmp(action.buf, "get")) {
-		struct credential_cache_entry *e = lookup_credential(&c);
-		if (e) {
-			fprintf(out, "username=%s\n", e->item.username);
-			fprintf(out, "password=%s\n", e->item.password);
-		}
-	}
-	else if (!strcmp(action.buf, "exit")) {
-		/*
-		 * It's important that we clean up our socket first, and then
-		 * signal the client only once we have finished the cleanup.
-		 * Calling exit() directly does this, because we clean up in
-		 * our atexit() handler, and then signal the client when our
-		 * process actually ends, which closes the socket and gives
-		 * them EOF.
-		 */
-		exit(0);
-	}
-	else if (!strcmp(action.buf, "erase"))
-		remove_credential(&c);
-	else if (!strcmp(action.buf, "store")) {
-		if (timeout < 0)
-			warning("cache client didn't specify a timeout");
-		else if (!c.username || !c.password)
-			warning("cache client gave us a partial credential");
-		else {
-			remove_credential(&c);
-			cache_credential(&c, timeout);
-		}
-	}
-	else
-		warning("cache client sent unknown action: %s", action.buf);
-
-	credential_clear(&c);
-	strbuf_release(&action);
-}
-
-static int serve_cache_loop(int fd)
-{
-	struct pollfd pfd;
-	timestamp_t wakeup;
-
-	wakeup = check_expirations();
-	if (!wakeup)
-		return 0;
-
-	pfd.fd = fd;
-	pfd.events = POLLIN;
-	if (poll(&pfd, 1, 1000 * wakeup) < 0) {
-		if (errno != EINTR)
-			die_errno("poll failed");
-		return 1;
-	}
-
-	if (pfd.revents & POLLIN) {
-		int client, client2;
-		FILE *in, *out;
-
-		client = accept(fd, NULL, NULL);
-		if (client < 0) {
-			warning_errno("accept failed");
-			return 1;
-		}
-		client2 = dup(client);
-		if (client2 < 0) {
-			warning_errno("dup failed");
-			close(client);
-			return 1;
-		}
-
-		in = xfdopen(client, "r");
-		out = xfdopen(client2, "w");
-		serve_one_client(in, out);
-		fclose(in);
-		fclose(out);
-	}
-	return 1;
-}
-
-static void serve_cache(const char *socket_path, int debug)
-{
-	int fd;
-
-	fd = unix_stream_listen(socket_path);
-	if (fd < 0)
-		die_errno("unable to bind to '%s'", socket_path);
-
-	printf("ok\n");
-	fclose(stdout);
-	if (!debug) {
-		if (!freopen("/dev/null", "w", stderr))
-			die_errno("unable to point stderr to /dev/null");
-	}
-
-	while (serve_cache_loop(fd))
-		; /* nothing */
-
-	close(fd);
-}
-
-static const char permissions_advice[] = N_(
-"The permissions on your socket directory are too loose; other\n"
-"users may be able to read your cached credentials. Consider running:\n"
-"\n"
-"	chmod 0700 %s");
-static void init_socket_directory(const char *path)
-{
-	struct stat st;
-	char *path_copy = xstrdup(path);
-	char *dir = dirname(path_copy);
-
-	if (!stat(dir, &st)) {
-		if (st.st_mode & 077)
-			die(_(permissions_advice), dir);
-	} else {
-		/*
-		 * We must be sure to create the directory with the correct mode,
-		 * not just chmod it after the fact; otherwise, there is a race
-		 * condition in which somebody can chdir to it, sleep, then try to open
-		 * our protected socket.
-		 */
-		if (safe_create_leading_directories_const(dir) < 0)
-			die_errno("unable to create directories for '%s'", dir);
-		if (mkdir(dir, 0700) < 0)
-			die_errno("unable to mkdir '%s'", dir);
-	}
-
-	if (chdir(dir))
-		/*
-		 * We don't actually care what our cwd is; we chdir here just to
-		 * be a friendly daemon and avoid tying up our original cwd.
-		 * If this fails, it's OK to just continue without that benefit.
-		 */
-		;
-
-	free(path_copy);
-}
-
-int cmd_credential_cache_daemon(int argc, const char **argv, const char *prefix)
-{
-	struct tempfile *socket_file;
-	const char *socket_path;
-	int ignore_sighup = 0;
-	static const char *usage[] = {
-		"git-credential-cache--daemon [opts] <socket_path>",
-		NULL
-	};
-	int debug = 0;
-	const struct option options[] = {
-		OPT_BOOL(0, "debug", &debug,
-			 N_("print debugging messages to stderr")),
-		OPT_END()
-	};
-
-	git_config_get_bool("credentialcache.ignoresighup", &ignore_sighup);
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-	socket_path = argv[0];
-
-	if (!socket_path)
-		usage_with_options(usage, options);
-
-	if (!is_absolute_path(socket_path))
-		die("socket directory must be an absolute path");
-
-	init_socket_directory(socket_path);
-	socket_file = register_tempfile(socket_path);
-
-	if (ignore_sighup)
-		signal(SIGHUP, SIG_IGN);
-
-	serve_cache(socket_path, debug);
-	delete_tempfile(&socket_file);
-
-	return 0;
-}
-
-#else
-
-int cmd_credential_cache_daemon(int argc, const char **argv, const char *prefix)
-{
-	const char * const usage[] = {
-		"git credential-cache--daemon [options] <action>",
-		"",
-		"credential-cache--daemon is disabled in this build of Git",
-		NULL
-	};
-	struct option options[] = { OPT_END() };
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-	die(_("credential-cache--daemon unavailable; no unix socket support"));
-}
-
-#endif /* NO_UNIX_SOCKET */
diff --git a/third_party/git/builtin/credential-cache.c b/third_party/git/builtin/credential-cache.c
deleted file mode 100644
index 9b3f70990597..000000000000
--- a/third_party/git/builtin/credential-cache.c
+++ /dev/null
@@ -1,157 +0,0 @@
-#include "builtin.h"
-#include "parse-options.h"
-
-#ifndef NO_UNIX_SOCKETS
-
-#include "credential.h"
-#include "string-list.h"
-#include "unix-socket.h"
-#include "run-command.h"
-
-#define FLAG_SPAWN 0x1
-#define FLAG_RELAY 0x2
-
-static int send_request(const char *socket, const struct strbuf *out)
-{
-	int got_data = 0;
-	int fd = unix_stream_connect(socket);
-
-	if (fd < 0)
-		return -1;
-
-	if (write_in_full(fd, out->buf, out->len) < 0)
-		die_errno("unable to write to cache daemon");
-	shutdown(fd, SHUT_WR);
-
-	while (1) {
-		char in[1024];
-		int r;
-
-		r = read_in_full(fd, in, sizeof(in));
-		if (r == 0 || (r < 0 && errno == ECONNRESET))
-			break;
-		if (r < 0)
-			die_errno("read error from cache daemon");
-		write_or_die(1, in, r);
-		got_data = 1;
-	}
-	close(fd);
-	return got_data;
-}
-
-static void spawn_daemon(const char *socket)
-{
-	struct child_process daemon = CHILD_PROCESS_INIT;
-	char buf[128];
-	int r;
-
-	strvec_pushl(&daemon.args,
-		     "credential-cache--daemon", socket,
-		     NULL);
-	daemon.git_cmd = 1;
-	daemon.no_stdin = 1;
-	daemon.out = -1;
-
-	if (start_command(&daemon))
-		die_errno("unable to start cache daemon");
-	r = read_in_full(daemon.out, buf, sizeof(buf));
-	if (r < 0)
-		die_errno("unable to read result code from cache daemon");
-	if (r != 3 || memcmp(buf, "ok\n", 3))
-		die("cache daemon did not start: %.*s", r, buf);
-	close(daemon.out);
-}
-
-static void do_cache(const char *socket, const char *action, int timeout,
-		     int flags)
-{
-	struct strbuf buf = STRBUF_INIT;
-
-	strbuf_addf(&buf, "action=%s\n", action);
-	strbuf_addf(&buf, "timeout=%d\n", timeout);
-	if (flags & FLAG_RELAY) {
-		if (strbuf_read(&buf, 0, 0) < 0)
-			die_errno("unable to relay credential");
-	}
-
-	if (send_request(socket, &buf) < 0) {
-		if (errno != ENOENT && errno != ECONNREFUSED)
-			die_errno("unable to connect to cache daemon");
-		if (flags & FLAG_SPAWN) {
-			spawn_daemon(socket);
-			if (send_request(socket, &buf) < 0)
-				die_errno("unable to connect to cache daemon");
-		}
-	}
-	strbuf_release(&buf);
-}
-
-static char *get_socket_path(void)
-{
-	struct stat sb;
-	char *old_dir, *socket;
-	old_dir = expand_user_path("~/.git-credential-cache", 0);
-	if (old_dir && !stat(old_dir, &sb) && S_ISDIR(sb.st_mode))
-		socket = xstrfmt("%s/socket", old_dir);
-	else
-		socket = xdg_cache_home("credential/socket");
-	free(old_dir);
-	return socket;
-}
-
-int cmd_credential_cache(int argc, const char **argv, const char *prefix)
-{
-	char *socket_path = NULL;
-	int timeout = 900;
-	const char *op;
-	const char * const usage[] = {
-		"git credential-cache [<options>] <action>",
-		NULL
-	};
-	struct option options[] = {
-		OPT_INTEGER(0, "timeout", &timeout,
-			    "number of seconds to cache credentials"),
-		OPT_STRING(0, "socket", &socket_path, "path",
-			   "path of cache-daemon socket"),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-	if (!argc)
-		usage_with_options(usage, options);
-	op = argv[0];
-
-	if (!socket_path)
-		socket_path = get_socket_path();
-	if (!socket_path)
-		die("unable to find a suitable socket path; use --socket");
-
-	if (!strcmp(op, "exit"))
-		do_cache(socket_path, op, timeout, 0);
-	else if (!strcmp(op, "get") || !strcmp(op, "erase"))
-		do_cache(socket_path, op, timeout, FLAG_RELAY);
-	else if (!strcmp(op, "store"))
-		do_cache(socket_path, op, timeout, FLAG_RELAY|FLAG_SPAWN);
-	else
-		; /* ignore unknown operation */
-
-	return 0;
-}
-
-#else
-
-int cmd_credential_cache(int argc, const char **argv, const char *prefix)
-{
-	const char * const usage[] = {
-		"git credential-cache [options] <action>",
-		"",
-		"credential-cache is disabled in this build of Git",
-		NULL
-	};
-	struct option options[] = { OPT_END() };
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-	die(_("credential-cache unavailable; no unix socket support"));
-}
-
-#endif /* NO_UNIX_SOCKETS */
diff --git a/third_party/git/builtin/credential-store.c b/third_party/git/builtin/credential-store.c
deleted file mode 100644
index 5331ab151a6f..000000000000
--- a/third_party/git/builtin/credential-store.c
+++ /dev/null
@@ -1,195 +0,0 @@
-#include "builtin.h"
-#include "lockfile.h"
-#include "credential.h"
-#include "string-list.h"
-#include "parse-options.h"
-
-static struct lock_file credential_lock;
-
-static int parse_credential_file(const char *fn,
-				  struct credential *c,
-				  void (*match_cb)(struct credential *),
-				  void (*other_cb)(struct strbuf *))
-{
-	FILE *fh;
-	struct strbuf line = STRBUF_INIT;
-	struct credential entry = CREDENTIAL_INIT;
-	int found_credential = 0;
-
-	fh = fopen(fn, "r");
-	if (!fh) {
-		if (errno != ENOENT && errno != EACCES)
-			die_errno("unable to open %s", fn);
-		return found_credential;
-	}
-
-	while (strbuf_getline_lf(&line, fh) != EOF) {
-		if (!credential_from_url_gently(&entry, line.buf, 1) &&
-		    entry.username && entry.password &&
-		    credential_match(c, &entry)) {
-			found_credential = 1;
-			if (match_cb) {
-				match_cb(&entry);
-				break;
-			}
-		}
-		else if (other_cb)
-			other_cb(&line);
-	}
-
-	credential_clear(&entry);
-	strbuf_release(&line);
-	fclose(fh);
-	return found_credential;
-}
-
-static void print_entry(struct credential *c)
-{
-	printf("username=%s\n", c->username);
-	printf("password=%s\n", c->password);
-}
-
-static void print_line(struct strbuf *buf)
-{
-	strbuf_addch(buf, '\n');
-	write_or_die(get_lock_file_fd(&credential_lock), buf->buf, buf->len);
-}
-
-static void rewrite_credential_file(const char *fn, struct credential *c,
-				    struct strbuf *extra)
-{
-	if (hold_lock_file_for_update(&credential_lock, fn, 0) < 0)
-		die_errno("unable to get credential storage lock");
-	if (extra)
-		print_line(extra);
-	parse_credential_file(fn, c, NULL, print_line);
-	if (commit_lock_file(&credential_lock) < 0)
-		die_errno("unable to write credential store");
-}
-
-static void store_credential_file(const char *fn, struct credential *c)
-{
-	struct strbuf buf = STRBUF_INIT;
-
-	strbuf_addf(&buf, "%s://", c->protocol);
-	strbuf_addstr_urlencode(&buf, c->username, is_rfc3986_unreserved);
-	strbuf_addch(&buf, ':');
-	strbuf_addstr_urlencode(&buf, c->password, is_rfc3986_unreserved);
-	strbuf_addch(&buf, '@');
-	if (c->host)
-		strbuf_addstr_urlencode(&buf, c->host, is_rfc3986_unreserved);
-	if (c->path) {
-		strbuf_addch(&buf, '/');
-		strbuf_addstr_urlencode(&buf, c->path,
-					is_rfc3986_reserved_or_unreserved);
-	}
-
-	rewrite_credential_file(fn, c, &buf);
-	strbuf_release(&buf);
-}
-
-static void store_credential(const struct string_list *fns, struct credential *c)
-{
-	struct string_list_item *fn;
-
-	/*
-	 * Sanity check that what we are storing is actually sensible.
-	 * In particular, we can't make a URL without a protocol field.
-	 * Without either a host or pathname (depending on the scheme),
-	 * we have no primary key. And without a username and password,
-	 * we are not actually storing a credential.
-	 */
-	if (!c->protocol || !(c->host || c->path) || !c->username || !c->password)
-		return;
-
-	for_each_string_list_item(fn, fns)
-		if (!access(fn->string, F_OK)) {
-			store_credential_file(fn->string, c);
-			return;
-		}
-	/*
-	 * Write credential to the filename specified by fns->items[0], thus
-	 * creating it
-	 */
-	if (fns->nr)
-		store_credential_file(fns->items[0].string, c);
-}
-
-static void remove_credential(const struct string_list *fns, struct credential *c)
-{
-	struct string_list_item *fn;
-
-	/*
-	 * Sanity check that we actually have something to match
-	 * against. The input we get is a restrictive pattern,
-	 * so technically a blank credential means "erase everything".
-	 * But it is too easy to accidentally send this, since it is equivalent
-	 * to empty input. So explicitly disallow it, and require that the
-	 * pattern have some actual content to match.
-	 */
-	if (!c->protocol && !c->host && !c->path && !c->username)
-		return;
-	for_each_string_list_item(fn, fns)
-		if (!access(fn->string, F_OK))
-			rewrite_credential_file(fn->string, c, NULL);
-}
-
-static void lookup_credential(const struct string_list *fns, struct credential *c)
-{
-	struct string_list_item *fn;
-
-	for_each_string_list_item(fn, fns)
-		if (parse_credential_file(fn->string, c, print_entry, NULL))
-			return; /* Found credential */
-}
-
-int cmd_credential_store(int argc, const char **argv, const char *prefix)
-{
-	const char * const usage[] = {
-		"git credential-store [<options>] <action>",
-		NULL
-	};
-	const char *op;
-	struct credential c = CREDENTIAL_INIT;
-	struct string_list fns = STRING_LIST_INIT_DUP;
-	char *file = NULL;
-	struct option options[] = {
-		OPT_STRING(0, "file", &file, "path",
-			   "fetch and store credentials in <path>"),
-		OPT_END()
-	};
-
-	umask(077);
-
-	argc = parse_options(argc, (const char **)argv, prefix, options, usage, 0);
-	if (argc != 1)
-		usage_with_options(usage, options);
-	op = argv[0];
-
-	if (file) {
-		string_list_append(&fns, file);
-	} else {
-		if ((file = expand_user_path("~/.git-credentials", 0)))
-			string_list_append_nodup(&fns, file);
-		file = xdg_config_home("credentials");
-		if (file)
-			string_list_append_nodup(&fns, file);
-	}
-	if (!fns.nr)
-		die("unable to set up default path; use --file");
-
-	if (credential_read(&c, stdin) < 0)
-		die("unable to read credential");
-
-	if (!strcmp(op, "get"))
-		lookup_credential(&fns, &c);
-	else if (!strcmp(op, "erase"))
-		remove_credential(&fns, &c);
-	else if (!strcmp(op, "store"))
-		store_credential(&fns, &c);
-	else
-		; /* Ignore unknown operation. */
-
-	string_list_clear(&fns, 0);
-	return 0;
-}
diff --git a/third_party/git/builtin/credential.c b/third_party/git/builtin/credential.c
deleted file mode 100644
index 879acfbcda75..000000000000
--- a/third_party/git/builtin/credential.c
+++ /dev/null
@@ -1,31 +0,0 @@
-#include "git-compat-util.h"
-#include "credential.h"
-#include "builtin.h"
-
-static const char usage_msg[] =
-	"git credential [fill|approve|reject]";
-
-int cmd_credential(int argc, const char **argv, const char *prefix)
-{
-	const char *op;
-	struct credential c = CREDENTIAL_INIT;
-
-	if (argc != 2 || !strcmp(argv[1], "-h"))
-		usage(usage_msg);
-	op = argv[1];
-
-	if (credential_read(&c, stdin) < 0)
-		die("unable to read credential from stdin");
-
-	if (!strcmp(op, "fill")) {
-		credential_fill(&c);
-		credential_write(&c, stdout);
-	} else if (!strcmp(op, "approve")) {
-		credential_approve(&c);
-	} else if (!strcmp(op, "reject")) {
-		credential_reject(&c);
-	} else {
-		usage(usage_msg);
-	}
-	return 0;
-}
diff --git a/third_party/git/builtin/describe.c b/third_party/git/builtin/describe.c
deleted file mode 100644
index 7668591d575a..000000000000
--- a/third_party/git/builtin/describe.c
+++ /dev/null
@@ -1,681 +0,0 @@
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "config.h"
-#include "lockfile.h"
-#include "commit.h"
-#include "tag.h"
-#include "blob.h"
-#include "refs.h"
-#include "builtin.h"
-#include "exec-cmd.h"
-#include "parse-options.h"
-#include "revision.h"
-#include "diff.h"
-#include "hashmap.h"
-#include "strvec.h"
-#include "run-command.h"
-#include "object-store.h"
-#include "list-objects.h"
-#include "commit-slab.h"
-
-#define MAX_TAGS	(FLAG_BITS - 1)
-
-define_commit_slab(commit_names, struct commit_name *);
-
-static const char * const describe_usage[] = {
-	N_("git describe [<options>] [<commit-ish>...]"),
-	N_("git describe [<options>] --dirty"),
-	NULL
-};
-
-static int debug;	/* Display lots of verbose info */
-static int all;	/* Any valid ref can be used */
-static int tags;	/* Allow lightweight tags */
-static int longformat;
-static int first_parent;
-static int abbrev = -1; /* unspecified */
-static int max_candidates = 10;
-static struct hashmap names;
-static int have_util;
-static struct string_list patterns = STRING_LIST_INIT_NODUP;
-static struct string_list exclude_patterns = STRING_LIST_INIT_NODUP;
-static int always;
-static const char *suffix, *dirty, *broken;
-static struct commit_names commit_names;
-
-/* diff-index command arguments to check if working tree is dirty. */
-static const char *diff_index_args[] = {
-	"diff-index", "--quiet", "HEAD", "--", NULL
-};
-
-struct commit_name {
-	struct hashmap_entry entry;
-	struct object_id peeled;
-	struct tag *tag;
-	unsigned prio:2; /* annotated tag = 2, tag = 1, head = 0 */
-	unsigned name_checked:1;
-	unsigned misnamed:1;
-	struct object_id oid;
-	char *path;
-};
-
-static const char *prio_names[] = {
-	N_("head"), N_("lightweight"), N_("annotated"),
-};
-
-static int commit_name_neq(const void *unused_cmp_data,
-			   const struct hashmap_entry *eptr,
-			   const struct hashmap_entry *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);
-
-	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);
-}
-
-static int replace_name(struct commit_name *e,
-			       int prio,
-			       const struct object_id *oid,
-			       struct tag **tag)
-{
-	if (!e || e->prio < prio)
-		return 1;
-
-	if (e->prio == 2 && prio == 2) {
-		/* Multiple annotated tags point to the same commit.
-		 * Select one to keep based upon their tagger date.
-		 */
-		struct tag *t;
-
-		if (!e->tag) {
-			t = lookup_tag(the_repository, &e->oid);
-			if (!t || parse_tag(t))
-				return 1;
-			e->tag = t;
-		}
-
-		t = lookup_tag(the_repository, oid);
-		if (!t || parse_tag(t))
-			return 0;
-		*tag = t;
-
-		if (e->tag->date < t->date)
-			return 1;
-	}
-
-	return 0;
-}
-
-static void add_to_known_names(const char *path,
-			       const struct object_id *peeled,
-			       int prio,
-			       const struct object_id *oid)
-{
-	struct commit_name *e = find_commit_name(peeled);
-	struct tag *tag = NULL;
-	if (replace_name(e, prio, oid, &tag)) {
-		if (!e) {
-			e = xmalloc(sizeof(struct commit_name));
-			oidcpy(&e->peeled, peeled);
-			hashmap_entry_init(&e->entry, oidhash(peeled));
-			hashmap_add(&names, &e->entry);
-			e->path = NULL;
-		}
-		e->tag = tag;
-		e->prio = prio;
-		e->name_checked = 0;
-		e->misnamed = 0;
-		oidcpy(&e->oid, oid);
-		free(e->path);
-		e->path = xstrdup(path);
-	}
-}
-
-static int get_name(const char *path, const struct object_id *oid, int flag, void *cb_data)
-{
-	int is_tag = 0;
-	struct object_id peeled;
-	int is_annotated, prio;
-	const char *path_to_match = NULL;
-
-	if (skip_prefix(path, "refs/tags/", &path_to_match)) {
-		is_tag = 1;
-	} else if (all) {
-		if ((exclude_patterns.nr || patterns.nr) &&
-		    !skip_prefix(path, "refs/heads/", &path_to_match) &&
-		    !skip_prefix(path, "refs/remotes/", &path_to_match)) {
-			/* Only accept reference of known type if there are match/exclude patterns */
-			return 0;
-		}
-	} else {
-		/* Reject anything outside refs/tags/ unless --all */
-		return 0;
-	}
-
-	/*
-	 * If we're given exclude patterns, first exclude any tag which match
-	 * any of the exclude pattern.
-	 */
-	if (exclude_patterns.nr) {
-		struct string_list_item *item;
-
-		for_each_string_list_item(item, &exclude_patterns) {
-			if (!wildmatch(item->string, path_to_match, 0))
-				return 0;
-		}
-	}
-
-	/*
-	 * If we're given patterns, accept only tags which match at least one
-	 * pattern.
-	 */
-	if (patterns.nr) {
-		int found = 0;
-		struct string_list_item *item;
-
-		for_each_string_list_item(item, &patterns) {
-			if (!wildmatch(item->string, path_to_match, 0)) {
-				found = 1;
-				break;
-			}
-		}
-
-		if (!found)
-			return 0;
-	}
-
-	/* Is it annotated? */
-	if (!peel_ref(path, &peeled)) {
-		is_annotated = !oideq(oid, &peeled);
-	} else {
-		oidcpy(&peeled, oid);
-		is_annotated = 0;
-	}
-
-	/*
-	 * By default, we only use annotated tags, but with --tags
-	 * we fall back to lightweight ones (even without --tags,
-	 * we still remember lightweight ones, only to give hints
-	 * in an error message).  --all allows any refs to be used.
-	 */
-	if (is_annotated)
-		prio = 2;
-	else if (is_tag)
-		prio = 1;
-	else
-		prio = 0;
-
-	add_to_known_names(all ? path + 5 : path + 10, &peeled, prio, oid);
-	return 0;
-}
-
-struct possible_tag {
-	struct commit_name *name;
-	int depth;
-	int found_order;
-	unsigned flag_within;
-};
-
-static int compare_pt(const void *a_, const void *b_)
-{
-	struct possible_tag *a = (struct possible_tag *)a_;
-	struct possible_tag *b = (struct possible_tag *)b_;
-	if (a->depth != b->depth)
-		return a->depth - b->depth;
-	if (a->found_order != b->found_order)
-		return a->found_order - b->found_order;
-	return 0;
-}
-
-static unsigned long finish_depth_computation(
-	struct commit_list **list,
-	struct possible_tag *best)
-{
-	unsigned long seen_commits = 0;
-	while (*list) {
-		struct commit *c = pop_commit(list);
-		struct commit_list *parents = c->parents;
-		seen_commits++;
-		if (c->object.flags & best->flag_within) {
-			struct commit_list *a = *list;
-			while (a) {
-				struct commit *i = a->item;
-				if (!(i->object.flags & best->flag_within))
-					break;
-				a = a->next;
-			}
-			if (!a)
-				break;
-		} else
-			best->depth++;
-		while (parents) {
-			struct commit *p = parents->item;
-			parse_commit(p);
-			if (!(p->object.flags & SEEN))
-				commit_list_insert_by_date(p, list);
-			p->object.flags |= c->object.flags;
-			parents = parents->next;
-		}
-	}
-	return seen_commits;
-}
-
-static void append_name(struct commit_name *n, struct strbuf *dst)
-{
-	if (n->prio == 2 && !n->tag) {
-		n->tag = lookup_tag(the_repository, &n->oid);
-		if (!n->tag || parse_tag(n->tag))
-			die(_("annotated tag %s not available"), n->path);
-	}
-	if (n->tag && !n->name_checked) {
-		if (strcmp(n->tag->tag, all ? n->path + 5 : n->path)) {
-			warning(_("tag '%s' is externally known as '%s'"),
-				n->path, n->tag->tag);
-			n->misnamed = 1;
-		}
-		n->name_checked = 1;
-	}
-
-	if (n->tag) {
-		if (all)
-			strbuf_addstr(dst, "tags/");
-		strbuf_addstr(dst, n->tag->tag);
-	} else {
-		strbuf_addstr(dst, n->path);
-	}
-}
-
-static void append_suffix(int depth, const struct object_id *oid, struct strbuf *dst)
-{
-	strbuf_addf(dst, "-%d-g%s", depth, find_unique_abbrev(oid, abbrev));
-}
-
-static void describe_commit(struct object_id *oid, struct strbuf *dst)
-{
-	struct commit *cmit, *gave_up_on = NULL;
-	struct commit_list *list;
-	struct commit_name *n;
-	struct possible_tag all_matches[MAX_TAGS];
-	unsigned int match_cnt = 0, annotated_cnt = 0, cur_match;
-	unsigned long seen_commits = 0;
-	unsigned int unannotated_cnt = 0;
-
-	cmit = lookup_commit_reference(the_repository, oid);
-
-	n = find_commit_name(&cmit->object.oid);
-	if (n && (tags || all || n->prio == 2)) {
-		/*
-		 * Exact match to an existing ref.
-		 */
-		append_name(n, dst);
-		if (n->misnamed || longformat)
-			append_suffix(0, n->tag ? get_tagged_oid(n->tag) : oid, dst);
-		if (suffix)
-			strbuf_addstr(dst, suffix);
-		return;
-	}
-
-	if (!max_candidates)
-		die(_("no tag exactly matches '%s'"), oid_to_hex(&cmit->object.oid));
-	if (debug)
-		fprintf(stderr, _("No exact match on refs or tags, searching to describe\n"));
-
-	if (!have_util) {
-		struct hashmap_iter iter;
-		struct commit *c;
-		struct commit_name *n;
-
-		init_commit_names(&commit_names);
-		hashmap_for_each_entry(&names, &iter, n,
-					entry /* member name */) {
-			c = lookup_commit_reference_gently(the_repository,
-							   &n->peeled, 1);
-			if (c)
-				*commit_names_at(&commit_names, c) = n;
-		}
-		have_util = 1;
-	}
-
-	list = NULL;
-	cmit->object.flags = SEEN;
-	commit_list_insert(cmit, &list);
-	while (list) {
-		struct commit *c = pop_commit(&list);
-		struct commit_list *parents = c->parents;
-		struct commit_name **slot;
-
-		seen_commits++;
-		slot = commit_names_peek(&commit_names, c);
-		n = slot ? *slot : NULL;
-		if (n) {
-			if (!tags && !all && n->prio < 2) {
-				unannotated_cnt++;
-			} else if (match_cnt < max_candidates) {
-				struct possible_tag *t = &all_matches[match_cnt++];
-				t->name = n;
-				t->depth = seen_commits - 1;
-				t->flag_within = 1u << match_cnt;
-				t->found_order = match_cnt;
-				c->object.flags |= t->flag_within;
-				if (n->prio == 2)
-					annotated_cnt++;
-			}
-			else {
-				gave_up_on = c;
-				break;
-			}
-		}
-		for (cur_match = 0; cur_match < match_cnt; cur_match++) {
-			struct possible_tag *t = &all_matches[cur_match];
-			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;
-			}
-		}
-		while (parents) {
-			struct commit *p = parents->item;
-			parse_commit(p);
-			if (!(p->object.flags & SEEN))
-				commit_list_insert_by_date(p, &list);
-			p->object.flags |= c->object.flags;
-			parents = parents->next;
-
-			if (first_parent)
-				break;
-		}
-	}
-
-	if (!match_cnt) {
-		struct object_id *cmit_oid = &cmit->object.oid;
-		if (always) {
-			strbuf_add_unique_abbrev(dst, cmit_oid, abbrev);
-			if (suffix)
-				strbuf_addstr(dst, suffix);
-			return;
-		}
-		if (unannotated_cnt)
-			die(_("No annotated tags can describe '%s'.\n"
-			    "However, there were unannotated tags: try --tags."),
-			    oid_to_hex(cmit_oid));
-		else
-			die(_("No tags can describe '%s'.\n"
-			    "Try --always, or create some tags."),
-			    oid_to_hex(cmit_oid));
-	}
-
-	QSORT(all_matches, match_cnt, compare_pt);
-
-	if (gave_up_on) {
-		commit_list_insert_by_date(gave_up_on, &list);
-		seen_commits--;
-	}
-	seen_commits += finish_depth_computation(&list, &all_matches[0]);
-	free_commit_list(list);
-
-	if (debug) {
-		static int label_width = -1;
-		if (label_width < 0) {
-			int i, w;
-			for (i = 0; i < ARRAY_SIZE(prio_names); i++) {
-				w = strlen(_(prio_names[i]));
-				if (label_width < w)
-					label_width = w;
-			}
-		}
-		for (cur_match = 0; cur_match < match_cnt; cur_match++) {
-			struct possible_tag *t = &all_matches[cur_match];
-			fprintf(stderr, " %-*s %8d %s\n",
-				label_width, _(prio_names[t->name->prio]),
-				t->depth, t->name->path);
-		}
-		fprintf(stderr, _("traversed %lu commits\n"), seen_commits);
-		if (gave_up_on) {
-			fprintf(stderr,
-				_("more than %i tags found; listed %i most recent\n"
-				"gave up search at %s\n"),
-				max_candidates, max_candidates,
-				oid_to_hex(&gave_up_on->object.oid));
-		}
-	}
-
-	append_name(all_matches[0].name, dst);
-	if (all_matches[0].name->misnamed || abbrev)
-		append_suffix(all_matches[0].depth, &cmit->object.oid, dst);
-	if (suffix)
-		strbuf_addstr(dst, suffix);
-}
-
-struct process_commit_data {
-	struct object_id current_commit;
-	struct object_id looking_for;
-	struct strbuf *dst;
-	struct rev_info *revs;
-};
-
-static void process_commit(struct commit *commit, void *data)
-{
-	struct process_commit_data *pcd = data;
-	pcd->current_commit = commit->object.oid;
-}
-
-static void process_object(struct object *obj, const char *path, void *data)
-{
-	struct process_commit_data *pcd = data;
-
-	if (oideq(&pcd->looking_for, &obj->oid) && !pcd->dst->len) {
-		reset_revision_walk();
-		describe_commit(&pcd->current_commit, pcd->dst);
-		strbuf_addf(pcd->dst, ":%s", path);
-		free_commit_list(pcd->revs->commits);
-		pcd->revs->commits = NULL;
-	}
-}
-
-static void describe_blob(struct object_id oid, struct strbuf *dst)
-{
-	struct rev_info revs;
-	struct strvec args = STRVEC_INIT;
-	struct process_commit_data pcd = { null_oid, oid, dst, &revs};
-
-	strvec_pushl(&args, "internal: The first arg is not parsed",
-		     "--objects", "--in-commit-order", "--reverse", "HEAD",
-		     NULL);
-
-	repo_init_revisions(the_repository, &revs, NULL);
-	if (setup_revisions(args.nr, args.v, &revs, NULL) > 1)
-		BUG("setup_revisions could not handle all args?");
-
-	if (prepare_revision_walk(&revs))
-		die("revision walk setup failed");
-
-	traverse_commit_list(&revs, process_commit, process_object, &pcd);
-	reset_revision_walk();
-}
-
-static void describe(const char *arg, int last_one)
-{
-	struct object_id oid;
-	struct commit *cmit;
-	struct strbuf sb = STRBUF_INIT;
-
-	if (debug)
-		fprintf(stderr, _("describe %s\n"), arg);
-
-	if (get_oid(arg, &oid))
-		die(_("Not a valid object name %s"), arg);
-	cmit = lookup_commit_reference_gently(the_repository, &oid, 1);
-
-	if (cmit)
-		describe_commit(&oid, &sb);
-	else if (oid_object_info(the_repository, &oid, NULL) == OBJ_BLOB)
-		describe_blob(oid, &sb);
-	else
-		die(_("%s is neither a commit nor blob"), arg);
-
-	puts(sb.buf);
-
-	if (!last_one)
-		clear_commit_marks(cmit, -1);
-
-	strbuf_release(&sb);
-}
-
-int cmd_describe(int argc, const char **argv, const char *prefix)
-{
-	int contains = 0;
-	struct option options[] = {
-		OPT_BOOL(0, "contains",   &contains, N_("find the tag that comes after the commit")),
-		OPT_BOOL(0, "debug",      &debug, N_("debug search strategy on stderr")),
-		OPT_BOOL(0, "all",        &all, N_("use any ref")),
-		OPT_BOOL(0, "tags",       &tags, N_("use any tag, even unannotated")),
-		OPT_BOOL(0, "long",       &longformat, N_("always use long format")),
-		OPT_BOOL(0, "first-parent", &first_parent, N_("only follow first parent")),
-		OPT__ABBREV(&abbrev),
-		OPT_SET_INT(0, "exact-match", &max_candidates,
-			    N_("only output exact matches"), 0),
-		OPT_INTEGER(0, "candidates", &max_candidates,
-			    N_("consider <n> most recent tags (default: 10)")),
-		OPT_STRING_LIST(0, "match", &patterns, N_("pattern"),
-			   N_("only consider tags matching <pattern>")),
-		OPT_STRING_LIST(0, "exclude", &exclude_patterns, N_("pattern"),
-			   N_("do not consider tags matching <pattern>")),
-		OPT_BOOL(0, "always",        &always,
-			N_("show abbreviated commit object as fallback")),
-		{OPTION_STRING, 0, "dirty",  &dirty, N_("mark"),
-			N_("append <mark> on dirty working tree (default: \"-dirty\")"),
-			PARSE_OPT_OPTARG, NULL, (intptr_t) "-dirty"},
-		{OPTION_STRING, 0, "broken",  &broken, N_("mark"),
-			N_("append <mark> on broken working tree (default: \"-broken\")"),
-			PARSE_OPT_OPTARG, NULL, (intptr_t) "-broken"},
-		OPT_END(),
-	};
-
-	git_config(git_default_config, NULL);
-	argc = parse_options(argc, argv, prefix, options, describe_usage, 0);
-	if (abbrev < 0)
-		abbrev = DEFAULT_ABBREV;
-
-	if (max_candidates < 0)
-		max_candidates = 0;
-	else if (max_candidates > MAX_TAGS)
-		max_candidates = MAX_TAGS;
-
-	save_commit_buffer = 0;
-
-	if (longformat && abbrev == 0)
-		die(_("--long is incompatible with --abbrev=0"));
-
-	if (contains) {
-		struct string_list_item *item;
-		struct strvec args;
-
-		strvec_init(&args);
-		strvec_pushl(&args, "name-rev",
-			     "--peel-tag", "--name-only", "--no-undefined",
-			     NULL);
-		if (always)
-			strvec_push(&args, "--always");
-		if (!all) {
-			strvec_push(&args, "--tags");
-			for_each_string_list_item(item, &patterns)
-				strvec_pushf(&args, "--refs=refs/tags/%s", item->string);
-			for_each_string_list_item(item, &exclude_patterns)
-				strvec_pushf(&args, "--exclude=refs/tags/%s", item->string);
-		}
-		if (argc)
-			strvec_pushv(&args, argv);
-		else
-			strvec_push(&args, "HEAD");
-		return cmd_name_rev(args.nr, args.v, prefix);
-	}
-
-	hashmap_init(&names, commit_name_neq, NULL, 0);
-	for_each_rawref(get_name, NULL);
-	if (!hashmap_get_size(&names) && !always)
-		die(_("No names found, cannot describe anything."));
-
-	if (argc == 0) {
-		if (broken) {
-			struct child_process cp = CHILD_PROCESS_INIT;
-			strvec_pushv(&cp.args, diff_index_args);
-			cp.git_cmd = 1;
-			cp.no_stdin = 1;
-			cp.no_stdout = 1;
-
-			if (!dirty)
-				dirty = "-dirty";
-
-			switch (run_command(&cp)) {
-			case 0:
-				suffix = NULL;
-				break;
-			case 1:
-				suffix = dirty;
-				break;
-			default:
-				/* diff-index aborted abnormally */
-				suffix = broken;
-			}
-		} else if (dirty) {
-			struct lock_file index_lock = LOCK_INIT;
-			struct rev_info revs;
-			struct strvec args = STRVEC_INIT;
-			int fd, result;
-
-			setup_work_tree();
-			read_cache();
-			refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED,
-				      NULL, NULL, NULL);
-			fd = hold_locked_index(&index_lock, 0);
-			if (0 <= fd)
-				repo_update_index_if_able(the_repository, &index_lock);
-
-			repo_init_revisions(the_repository, &revs, prefix);
-			strvec_pushv(&args, diff_index_args);
-			if (setup_revisions(args.nr, args.v, &revs, NULL) != 1)
-				BUG("malformed internal diff-index command line");
-			result = run_diff_index(&revs, 0);
-
-			if (!diff_result_code(&revs.diffopt, result))
-				suffix = NULL;
-			else
-				suffix = dirty;
-		}
-		describe("HEAD", 1);
-	} else if (dirty) {
-		die(_("--dirty is incompatible with commit-ishes"));
-	} else if (broken) {
-		die(_("--broken is incompatible with commit-ishes"));
-	} else {
-		while (argc-- > 0)
-			describe(*argv++, argc == 0);
-	}
-	return 0;
-}
diff --git a/third_party/git/builtin/diff-files.c b/third_party/git/builtin/diff-files.c
deleted file mode 100644
index 1e352dd8f77c..000000000000
--- a/third_party/git/builtin/diff-files.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * GIT - The information manager from hell
- *
- * Copyright (C) Linus Torvalds, 2005
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "config.h"
-#include "diff.h"
-#include "commit.h"
-#include "revision.h"
-#include "builtin.h"
-#include "submodule.h"
-
-static const char diff_files_usage[] =
-"git diff-files [-q] [-0 | -1 | -2 | -3 | -c | --cc] [<common-diff-options>] [<path>...]"
-COMMON_DIFF_OPTIONS_HELP;
-
-int cmd_diff_files(int argc, const char **argv, const char *prefix)
-{
-	struct rev_info rev;
-	int result;
-	unsigned options = 0;
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage(diff_files_usage);
-
-	git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
-	repo_init_revisions(the_repository, &rev, prefix);
-	rev.abbrev = 0;
-
-	/*
-	 * Consider "intent-to-add" files as new by default, unless
-	 * explicitly specified in the command line or anywhere else.
-	 */
-	rev.diffopt.ita_invisible_in_index = 1;
-
-	precompose_argv(argc, argv);
-
-	argc = setup_revisions(argc, argv, &rev, NULL);
-	while (1 < argc && argv[1][0] == '-') {
-		if (!strcmp(argv[1], "--base"))
-			rev.max_count = 1;
-		else if (!strcmp(argv[1], "--ours"))
-			rev.max_count = 2;
-		else if (!strcmp(argv[1], "--theirs"))
-			rev.max_count = 3;
-		else if (!strcmp(argv[1], "-q"))
-			options |= DIFF_SILENT_ON_REMOVED;
-		else
-			usage(diff_files_usage);
-		argv++; argc--;
-	}
-	if (!rev.diffopt.output_format)
-		rev.diffopt.output_format = DIFF_FORMAT_RAW;
-
-	/*
-	 * Make sure there are NO revision (i.e. pending object) parameter,
-	 * rev.max_count is reasonable (0 <= n <= 3), and
-	 * there is no other revision filtering parameters.
-	 */
-	if (rev.pending.nr ||
-	    rev.min_age != -1 || rev.max_age != -1 ||
-	    3 < rev.max_count)
-		usage(diff_files_usage);
-
-	/*
-	 * "diff-files --base -p" should not combine merges because it
-	 * was not asked to.  "diff-files -c -p" should not densify
-	 * (the user should ask with "diff-files --cc" explicitly).
-	 */
-	if (rev.max_count == -1 && !rev.combine_merges &&
-	    (rev.diffopt.output_format & DIFF_FORMAT_PATCH))
-		rev.combine_merges = rev.dense_combined_merges = 1;
-
-	if (read_cache_preload(&rev.diffopt.pathspec) < 0) {
-		perror("read_cache_preload");
-		return -1;
-	}
-	result = run_diff_files(&rev, options);
-	return diff_result_code(&rev.diffopt, result);
-}
diff --git a/third_party/git/builtin/diff-index.c b/third_party/git/builtin/diff-index.c
deleted file mode 100644
index 93ec6424234c..000000000000
--- a/third_party/git/builtin/diff-index.c
+++ /dev/null
@@ -1,62 +0,0 @@
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "config.h"
-#include "diff.h"
-#include "commit.h"
-#include "revision.h"
-#include "builtin.h"
-#include "submodule.h"
-
-static const char diff_cache_usage[] =
-"git diff-index [-m] [--cached] "
-"[<common-diff-options>] <tree-ish> [<path>...]"
-COMMON_DIFF_OPTIONS_HELP;
-
-int cmd_diff_index(int argc, const char **argv, const char *prefix)
-{
-	struct rev_info rev;
-	int cached = 0;
-	int i;
-	int result;
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage(diff_cache_usage);
-
-	git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
-	repo_init_revisions(the_repository, &rev, prefix);
-	rev.abbrev = 0;
-	precompose_argv(argc, argv);
-
-	argc = setup_revisions(argc, argv, &rev, NULL);
-	for (i = 1; i < argc; i++) {
-		const char *arg = argv[i];
-
-		if (!strcmp(arg, "--cached"))
-			cached = 1;
-		else
-			usage(diff_cache_usage);
-	}
-	if (!rev.diffopt.output_format)
-		rev.diffopt.output_format = DIFF_FORMAT_RAW;
-
-	/*
-	 * Make sure there is one revision (i.e. pending object),
-	 * and there is no revision filtering parameters.
-	 */
-	if (rev.pending.nr != 1 ||
-	    rev.max_count != -1 || rev.min_age != -1 || rev.max_age != -1)
-		usage(diff_cache_usage);
-	if (!cached) {
-		setup_work_tree();
-		if (read_cache_preload(&rev.diffopt.pathspec) < 0) {
-			perror("read_cache_preload");
-			return -1;
-		}
-	} else if (read_cache() < 0) {
-		perror("read_cache");
-		return -1;
-	}
-	result = run_diff_index(&rev, cached);
-	UNLEAK(rev);
-	return diff_result_code(&rev.diffopt, result);
-}
diff --git a/third_party/git/builtin/diff-tree.c b/third_party/git/builtin/diff-tree.c
deleted file mode 100644
index 802363d0a229..000000000000
--- a/third_party/git/builtin/diff-tree.c
+++ /dev/null
@@ -1,205 +0,0 @@
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "config.h"
-#include "diff.h"
-#include "commit.h"
-#include "log-tree.h"
-#include "builtin.h"
-#include "submodule.h"
-#include "repository.h"
-
-static struct rev_info log_tree_opt;
-
-static int diff_tree_commit_oid(const struct object_id *oid)
-{
-	struct commit *commit = lookup_commit_reference(the_repository, oid);
-	if (!commit)
-		return -1;
-	return log_tree_commit(&log_tree_opt, commit);
-}
-
-/* Diff one or more commits. */
-static int stdin_diff_commit(struct commit *commit, const char *p)
-{
-	struct object_id oid;
-	struct commit_list **pptr = NULL;
-
-	/* Graft the fake parents locally to the commit */
-	while (isspace(*p++) && !parse_oid_hex(p, &oid, &p)) {
-		struct commit *parent = lookup_commit(the_repository, &oid);
-		if (!pptr) {
-			/* Free the real parent list */
-			free_commit_list(commit->parents);
-			commit->parents = NULL;
-			pptr = &(commit->parents);
-		}
-		if (parent) {
-			pptr = &commit_list_insert(parent, pptr)->next;
-		}
-	}
-	return log_tree_commit(&log_tree_opt, commit);
-}
-
-/* Diff two trees. */
-static int stdin_diff_trees(struct tree *tree1, const char *p)
-{
-	struct object_id oid;
-	struct tree *tree2;
-	if (!isspace(*p++) || parse_oid_hex(p, &oid, &p) || *p)
-		return error("Need exactly two trees, separated by a space");
-	tree2 = lookup_tree(the_repository, &oid);
-	if (!tree2 || parse_tree(tree2))
-		return -1;
-	printf("%s %s\n", oid_to_hex(&tree1->object.oid),
-			  oid_to_hex(&tree2->object.oid));
-	diff_tree_oid(&tree1->object.oid, &tree2->object.oid,
-		      "", &log_tree_opt.diffopt);
-	log_tree_diff_flush(&log_tree_opt);
-	return 0;
-}
-
-static int diff_tree_stdin(char *line)
-{
-	int len = strlen(line);
-	struct object_id oid;
-	struct object *obj;
-	const char *p;
-
-	if (!len || line[len-1] != '\n')
-		return -1;
-	line[len-1] = 0;
-	if (parse_oid_hex(line, &oid, &p))
-		return -1;
-	obj = parse_object(the_repository, &oid);
-	if (!obj)
-		return -1;
-	if (obj->type == OBJ_COMMIT)
-		return stdin_diff_commit((struct commit *)obj, p);
-	if (obj->type == OBJ_TREE)
-		return stdin_diff_trees((struct tree *)obj, p);
-	error("Object %s is a %s, not a commit or tree",
-	      oid_to_hex(&oid), type_name(obj->type));
-	return -1;
-}
-
-static const char diff_tree_usage[] =
-"git diff-tree [--stdin] [-m] [-c | --cc] [-s] [-v] [--pretty] [-t] [-r] [--root] "
-"[<common-diff-options>] <tree-ish> [<tree-ish>] [<path>...]\n"
-"  -r            diff recursively\n"
-"  -c            show combined diff for merge commits\n"
-"  --cc          show combined diff for merge commits removing uninteresting hunks\n"
-"  --combined-all-paths\n"
-"                show name of file in all parents for combined diffs\n"
-"  --root        include the initial commit as diff against /dev/null\n"
-COMMON_DIFF_OPTIONS_HELP;
-
-static void diff_tree_tweak_rev(struct rev_info *rev, struct setup_revision_opt *opt)
-{
-	if (!rev->diffopt.output_format) {
-		if (rev->dense_combined_merges)
-			rev->diffopt.output_format = DIFF_FORMAT_PATCH;
-		else
-			rev->diffopt.output_format = DIFF_FORMAT_RAW;
-	}
-}
-
-int cmd_diff_tree(int argc, const char **argv, const char *prefix)
-{
-	char line[1000];
-	struct object *tree1, *tree2;
-	static struct rev_info *opt = &log_tree_opt;
-	struct setup_revision_opt s_r_opt;
-	struct userformat_want w;
-	int read_stdin = 0;
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage(diff_tree_usage);
-
-	git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
-	repo_init_revisions(the_repository, opt, prefix);
-	if (read_cache() < 0)
-		die(_("index file corrupt"));
-	opt->abbrev = 0;
-	opt->diff = 1;
-	opt->disable_stdin = 1;
-	memset(&s_r_opt, 0, sizeof(s_r_opt));
-	s_r_opt.tweak = diff_tree_tweak_rev;
-
-	precompose_argv(argc, argv);
-	argc = setup_revisions(argc, argv, opt, &s_r_opt);
-
-	memset(&w, 0, sizeof(w));
-	userformat_find_requirements(NULL, &w);
-
-	if (!opt->show_notes_given && w.notes)
-		opt->show_notes = 1;
-	if (opt->show_notes)
-		load_display_notes(&opt->notes_opt);
-
-	while (--argc > 0) {
-		const char *arg = *++argv;
-
-		if (!strcmp(arg, "--stdin")) {
-			read_stdin = 1;
-			continue;
-		}
-		usage(diff_tree_usage);
-	}
-
-	/*
-	 * NOTE!  We expect "a..b" to expand to "^a b" but it is
-	 * perfectly valid for revision range parser to yield "b ^a",
-	 * which means the same thing. If we get the latter, i.e. the
-	 * second one is marked UNINTERESTING, we recover the original
-	 * order the user gave, i.e. "a..b", by swapping the trees.
-	 */
-	switch (opt->pending.nr) {
-	case 0:
-		if (!read_stdin)
-			usage(diff_tree_usage);
-		break;
-	case 1:
-		tree1 = opt->pending.objects[0].item;
-		diff_tree_commit_oid(&tree1->oid);
-		break;
-	case 2:
-		tree1 = opt->pending.objects[0].item;
-		tree2 = opt->pending.objects[1].item;
-		if (tree2->flags & UNINTERESTING) {
-			SWAP(tree2, tree1);
-		}
-		diff_tree_oid(&tree1->oid, &tree2->oid, "", &opt->diffopt);
-		log_tree_diff_flush(opt);
-		break;
-	}
-
-	if (read_stdin) {
-		int saved_nrl = 0;
-		int saved_dcctc = 0;
-
-		if (opt->diffopt.detect_rename) {
-			if (!the_index.cache)
-				repo_read_index(the_repository);
-			opt->diffopt.setup |= DIFF_SETUP_USE_SIZE_CACHE;
-		}
-		while (fgets(line, sizeof(line), stdin)) {
-			struct object_id oid;
-
-			if (get_oid_hex(line, &oid)) {
-				fputs(line, stdout);
-				fflush(stdout);
-			}
-			else {
-				diff_tree_stdin(line);
-				if (saved_nrl < opt->diffopt.needed_rename_limit)
-					saved_nrl = opt->diffopt.needed_rename_limit;
-				if (opt->diffopt.degraded_cc_to_c)
-					saved_dcctc = 1;
-			}
-		}
-		opt->diffopt.degraded_cc_to_c = saved_dcctc;
-		opt->diffopt.needed_rename_limit = saved_nrl;
-	}
-
-	return diff_result_code(&opt->diffopt, 0);
-}
diff --git a/third_party/git/builtin/diff.c b/third_party/git/builtin/diff.c
deleted file mode 100644
index cd4083fed96e..000000000000
--- a/third_party/git/builtin/diff.c
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- * Builtin "git diff"
- *
- * Copyright (c) 2006 Junio C Hamano
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "config.h"
-#include "ewah/ewok.h"
-#include "lockfile.h"
-#include "color.h"
-#include "commit.h"
-#include "blob.h"
-#include "tag.h"
-#include "diff.h"
-#include "diffcore.h"
-#include "revision.h"
-#include "log-tree.h"
-#include "builtin.h"
-#include "submodule.h"
-#include "oid-array.h"
-
-#define DIFF_NO_INDEX_EXPLICIT 1
-#define DIFF_NO_INDEX_IMPLICIT 2
-
-static const char builtin_diff_usage[] =
-"git diff [<options>] [<commit>] [--] [<path>...]\n"
-"   or: git diff [<options>] --cached [<commit>] [--] [<path>...]\n"
-"   or: git diff [<options>] <commit> [<commit>...] <commit> [--] [<path>...]\n"
-"   or: git diff [<options>] <commit>...<commit>] [--] [<path>...]\n"
-"   or: git diff [<options>] <blob> <blob>]\n"
-"   or: git diff [<options>] --no-index [--] <path> <path>]\n"
-COMMON_DIFF_OPTIONS_HELP;
-
-static const char *blob_path(struct object_array_entry *entry)
-{
-	return entry->path ? entry->path : entry->name;
-}
-
-static void stuff_change(struct diff_options *opt,
-			 unsigned old_mode, unsigned new_mode,
-			 const struct object_id *old_oid,
-			 const struct object_id *new_oid,
-			 int old_oid_valid,
-			 int new_oid_valid,
-			 const char *old_path,
-			 const char *new_path)
-{
-	struct diff_filespec *one, *two;
-
-	if (!is_null_oid(old_oid) && !is_null_oid(new_oid) &&
-	    oideq(old_oid, new_oid) && (old_mode == new_mode))
-		return;
-
-	if (opt->flags.reverse_diff) {
-		SWAP(old_mode, new_mode);
-		SWAP(old_oid, new_oid);
-		SWAP(old_path, new_path);
-	}
-
-	if (opt->prefix &&
-	    (strncmp(old_path, opt->prefix, opt->prefix_length) ||
-	     strncmp(new_path, opt->prefix, opt->prefix_length)))
-		return;
-
-	one = alloc_filespec(old_path);
-	two = alloc_filespec(new_path);
-	fill_filespec(one, old_oid, old_oid_valid, old_mode);
-	fill_filespec(two, new_oid, new_oid_valid, new_mode);
-
-	diff_queue(&diff_queued_diff, one, two);
-}
-
-static int builtin_diff_b_f(struct rev_info *revs,
-			    int argc, const char **argv,
-			    struct object_array_entry **blob)
-{
-	/* Blob vs file in the working tree*/
-	struct stat st;
-	const char *path;
-
-	if (argc > 1)
-		usage(builtin_diff_usage);
-
-	GUARD_PATHSPEC(&revs->prune_data, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);
-	path = revs->prune_data.items[0].match;
-
-	if (lstat(path, &st))
-		die_errno(_("failed to stat '%s'"), path);
-	if (!(S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)))
-		die(_("'%s': not a regular file or symlink"), path);
-
-	diff_set_mnemonic_prefix(&revs->diffopt, "o/", "w/");
-
-	if (blob[0]->mode == S_IFINVALID)
-		blob[0]->mode = canon_mode(st.st_mode);
-
-	stuff_change(&revs->diffopt,
-		     blob[0]->mode, canon_mode(st.st_mode),
-		     &blob[0]->item->oid, &null_oid,
-		     1, 0,
-		     blob[0]->path ? blob[0]->path : path,
-		     path);
-	diffcore_std(&revs->diffopt);
-	diff_flush(&revs->diffopt);
-	return 0;
-}
-
-static int builtin_diff_blobs(struct rev_info *revs,
-			      int argc, const char **argv,
-			      struct object_array_entry **blob)
-{
-	const unsigned mode = canon_mode(S_IFREG | 0644);
-
-	if (argc > 1)
-		usage(builtin_diff_usage);
-
-	if (blob[0]->mode == S_IFINVALID)
-		blob[0]->mode = mode;
-
-	if (blob[1]->mode == S_IFINVALID)
-		blob[1]->mode = mode;
-
-	stuff_change(&revs->diffopt,
-		     blob[0]->mode, blob[1]->mode,
-		     &blob[0]->item->oid, &blob[1]->item->oid,
-		     1, 1,
-		     blob_path(blob[0]), blob_path(blob[1]));
-	diffcore_std(&revs->diffopt);
-	diff_flush(&revs->diffopt);
-	return 0;
-}
-
-static int builtin_diff_index(struct rev_info *revs,
-			      int argc, const char **argv)
-{
-	int cached = 0;
-	while (1 < argc) {
-		const char *arg = argv[1];
-		if (!strcmp(arg, "--cached") || !strcmp(arg, "--staged"))
-			cached = 1;
-		else
-			usage(builtin_diff_usage);
-		argv++; argc--;
-	}
-	/*
-	 * Make sure there is one revision (i.e. pending object),
-	 * and there is no revision filtering parameters.
-	 */
-	if (revs->pending.nr != 1 ||
-	    revs->max_count != -1 || revs->min_age != -1 ||
-	    revs->max_age != -1)
-		usage(builtin_diff_usage);
-	if (!cached) {
-		setup_work_tree();
-		if (read_cache_preload(&revs->diffopt.pathspec) < 0) {
-			perror("read_cache_preload");
-			return -1;
-		}
-	} else if (read_cache() < 0) {
-		perror("read_cache");
-		return -1;
-	}
-	return run_diff_index(revs, cached);
-}
-
-static int builtin_diff_tree(struct rev_info *revs,
-			     int argc, const char **argv,
-			     struct object_array_entry *ent0,
-			     struct object_array_entry *ent1)
-{
-	const struct object_id *(oid[2]);
-	int swap = 0;
-
-	if (argc > 1)
-		usage(builtin_diff_usage);
-
-	/*
-	 * We saw two trees, ent0 and ent1.  If ent1 is uninteresting,
-	 * swap them.
-	 */
-	if (ent1->item->flags & UNINTERESTING)
-		swap = 1;
-	oid[swap] = &ent0->item->oid;
-	oid[1 - swap] = &ent1->item->oid;
-	diff_tree_oid(oid[0], oid[1], "", &revs->diffopt);
-	log_tree_diff_flush(revs);
-	return 0;
-}
-
-static int builtin_diff_combined(struct rev_info *revs,
-				 int argc, const char **argv,
-				 struct object_array_entry *ent,
-				 int ents)
-{
-	struct oid_array parents = OID_ARRAY_INIT;
-	int i;
-
-	if (argc > 1)
-		usage(builtin_diff_usage);
-
-	if (!revs->dense_combined_merges && !revs->combine_merges)
-		revs->dense_combined_merges = revs->combine_merges = 1;
-	for (i = 1; i < ents; i++)
-		oid_array_append(&parents, &ent[i].item->oid);
-	diff_tree_combined(&ent[0].item->oid, &parents, revs);
-	oid_array_clear(&parents);
-	return 0;
-}
-
-static void refresh_index_quietly(void)
-{
-	struct lock_file lock_file = LOCK_INIT;
-	int fd;
-
-	fd = hold_locked_index(&lock_file, 0);
-	if (fd < 0)
-		return;
-	discard_cache();
-	read_cache();
-	refresh_cache(REFRESH_QUIET|REFRESH_UNMERGED);
-	repo_update_index_if_able(the_repository, &lock_file);
-}
-
-static int builtin_diff_files(struct rev_info *revs, int argc, const char **argv)
-{
-	unsigned int options = 0;
-
-	while (1 < argc && argv[1][0] == '-') {
-		if (!strcmp(argv[1], "--base"))
-			revs->max_count = 1;
-		else if (!strcmp(argv[1], "--ours"))
-			revs->max_count = 2;
-		else if (!strcmp(argv[1], "--theirs"))
-			revs->max_count = 3;
-		else if (!strcmp(argv[1], "-q"))
-			options |= DIFF_SILENT_ON_REMOVED;
-		else if (!strcmp(argv[1], "-h"))
-			usage(builtin_diff_usage);
-		else
-			return error(_("invalid option: %s"), argv[1]);
-		argv++; argc--;
-	}
-
-	/*
-	 * "diff --base" should not combine merges because it was not
-	 * asked to.  "diff -c" should not densify (if the user wants
-	 * dense one, --cc can be explicitly asked for, or just rely
-	 * on the default).
-	 */
-	if (revs->max_count == -1 && !revs->combine_merges &&
-	    (revs->diffopt.output_format & DIFF_FORMAT_PATCH))
-		revs->combine_merges = revs->dense_combined_merges = 1;
-
-	setup_work_tree();
-	if (read_cache_preload(&revs->diffopt.pathspec) < 0) {
-		perror("read_cache_preload");
-		return -1;
-	}
-	return run_diff_files(revs, options);
-}
-
-struct symdiff {
-	struct bitmap *skip;
-	int warn;
-	const char *base, *left, *right;
-};
-
-/*
- * Check for symmetric-difference arguments, and if present, arrange
- * everything we need to know to handle them correctly.  As a bonus,
- * weed out all bogus range-based revision specifications, e.g.,
- * "git diff A..B C..D" or "git diff A..B C" get rejected.
- *
- * For an actual symmetric diff, *symdiff is set this way:
- *
- *  - its skip is non-NULL and marks *all* rev->pending.objects[i]
- *    indices that the caller should ignore (extra merge bases, of
- *    which there might be many, and A in A...B).  Note that the
- *    chosen merge base and right side are NOT marked.
- *  - warn is set if there are multiple merge bases.
- *  - base, left, and right point to the names to use in a
- *    warning about multiple merge bases.
- *
- * If there is no symmetric diff argument, sym->skip is NULL and
- * sym->warn is cleared.  The remaining fields are not set.
- */
-static void symdiff_prepare(struct rev_info *rev, struct symdiff *sym)
-{
-	int i, is_symdiff = 0, basecount = 0, othercount = 0;
-	int lpos = -1, rpos = -1, basepos = -1;
-	struct bitmap *map = NULL;
-
-	/*
-	 * Use the whence fields to find merge bases and left and
-	 * right parts of symmetric difference, so that we do not
-	 * depend on the order that revisions are parsed.  If there
-	 * are any revs that aren't from these sources, we have a
-	 * "git diff C A...B" or "git diff A...B C" case.  Or we
-	 * could even get "git diff A...B C...E", for instance.
-	 *
-	 * If we don't have just one merge base, we pick one
-	 * at random.
-	 *
-	 * NB: REV_CMD_LEFT, REV_CMD_RIGHT are also used for A..B,
-	 * so we must check for SYMMETRIC_LEFT too.  The two arrays
-	 * rev->pending.objects and rev->cmdline.rev are parallel.
-	 */
-	for (i = 0; i < rev->cmdline.nr; i++) {
-		struct object *obj = rev->pending.objects[i].item;
-		switch (rev->cmdline.rev[i].whence) {
-		case REV_CMD_MERGE_BASE:
-			if (basepos < 0)
-				basepos = i;
-			basecount++;
-			break;		/* do mark all bases */
-		case REV_CMD_LEFT:
-			if (lpos >= 0)
-				usage(builtin_diff_usage);
-			lpos = i;
-			if (obj->flags & SYMMETRIC_LEFT) {
-				is_symdiff = 1;
-				break;	/* do mark A */
-			}
-			continue;
-		case REV_CMD_RIGHT:
-			if (rpos >= 0)
-				usage(builtin_diff_usage);
-			rpos = i;
-			continue;	/* don't mark B */
-		case REV_CMD_PARENTS_ONLY:
-		case REV_CMD_REF:
-		case REV_CMD_REV:
-			othercount++;
-			continue;
-		}
-		if (map == NULL)
-			map = bitmap_new();
-		bitmap_set(map, i);
-	}
-
-	/*
-	 * Forbid any additional revs for both A...B and A..B.
-	 */
-	if (lpos >= 0 && othercount > 0)
-		usage(builtin_diff_usage);
-
-	if (!is_symdiff) {
-		bitmap_free(map);
-		sym->warn = 0;
-		sym->skip = NULL;
-		return;
-	}
-
-	sym->left = rev->pending.objects[lpos].name;
-	sym->right = rev->pending.objects[rpos].name;
-	if (basecount == 0)
-		die(_("%s...%s: no merge base"), sym->left, sym->right);
-	sym->base = rev->pending.objects[basepos].name;
-	bitmap_unset(map, basepos);	/* unmark the base we want */
-	sym->warn = basecount > 1;
-	sym->skip = map;
-}
-
-int cmd_diff(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	struct rev_info rev;
-	struct object_array ent = OBJECT_ARRAY_INIT;
-	int blobs = 0, paths = 0;
-	struct object_array_entry *blob[2];
-	int nongit = 0, no_index = 0;
-	int result = 0;
-	struct symdiff sdiff;
-
-	/*
-	 * We could get N tree-ish in the rev.pending_objects list.
-	 * Also there could be M blobs there, and P pathspecs. --cached may
-	 * also be present.
-	 *
-	 * N=0, M=0:
-	 *      cache vs files (diff-files)
-	 *
-	 * N=0, M=0, --cached:
-	 *      HEAD vs cache (diff-index --cached)
-	 *
-	 * N=0, M=2:
-	 *      compare two random blobs.  P must be zero.
-	 *
-	 * N=0, M=1, P=1:
-	 *      compare a blob with a working tree file.
-	 *
-	 * N=1, M=0:
-	 *      tree vs files (diff-index)
-	 *
-	 * N=1, M=0, --cached:
-	 *      tree vs cache (diff-index --cached)
-	 *
-	 * N=2, M=0:
-	 *      tree vs tree (diff-tree)
-	 *
-	 * N=0, M=0, P=2:
-	 *      compare two filesystem entities (aka --no-index).
-	 *
-	 * Other cases are errors.
-	 */
-
-	/* Were we asked to do --no-index explicitly? */
-	for (i = 1; i < argc; i++) {
-		if (!strcmp(argv[i], "--")) {
-			i++;
-			break;
-		}
-		if (!strcmp(argv[i], "--no-index"))
-			no_index = DIFF_NO_INDEX_EXPLICIT;
-		if (argv[i][0] != '-')
-			break;
-	}
-
-	prefix = setup_git_directory_gently(&nongit);
-
-	if (!no_index) {
-		/*
-		 * Treat git diff with at least one path outside of the
-		 * repo the same as if the command would have been executed
-		 * outside of a git repository.  In this case it behaves
-		 * the same way as "git diff --no-index <a> <b>", which acts
-		 * as a colourful "diff" replacement.
-		 */
-		if (nongit || ((argc == i + 2) &&
-			       (!path_inside_repo(prefix, argv[i]) ||
-				!path_inside_repo(prefix, argv[i + 1]))))
-			no_index = DIFF_NO_INDEX_IMPLICIT;
-	}
-
-	init_diff_ui_defaults();
-	git_config(git_diff_ui_config, NULL);
-	precompose_argv(argc, argv);
-
-	repo_init_revisions(the_repository, &rev, prefix);
-
-	/* Set up defaults that will apply to both no-index and regular diffs. */
-	rev.diffopt.stat_width = -1;
-	rev.diffopt.stat_graph_width = -1;
-	rev.diffopt.flags.allow_external = 1;
-	rev.diffopt.flags.allow_textconv = 1;
-
-	/* If this is a no-index diff, just run it and exit there. */
-	if (no_index)
-		exit(diff_no_index(&rev, no_index == DIFF_NO_INDEX_IMPLICIT,
-				   argc, argv));
-
-
-	/*
-	 * Otherwise, we are doing the usual "git" diff; set up any
-	 * further defaults that apply to regular diffs.
-	 */
-	rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
-
-	/*
-	 * Default to intent-to-add entries invisible in the
-	 * index. This makes them show up as new files in diff-files
-	 * and not at all in diff-cached.
-	 */
-	rev.diffopt.ita_invisible_in_index = 1;
-
-	if (nongit)
-		die(_("Not a git repository"));
-	argc = setup_revisions(argc, argv, &rev, NULL);
-	if (!rev.diffopt.output_format) {
-		rev.diffopt.output_format = DIFF_FORMAT_PATCH;
-		diff_setup_done(&rev.diffopt);
-	}
-
-	rev.diffopt.flags.recursive = 1;
-
-	setup_diff_pager(&rev.diffopt);
-
-	/*
-	 * Do we have --cached and not have a pending object, then
-	 * default to HEAD by hand.  Eek.
-	 */
-	if (!rev.pending.nr) {
-		int i;
-		for (i = 1; i < argc; i++) {
-			const char *arg = argv[i];
-			if (!strcmp(arg, "--"))
-				break;
-			else if (!strcmp(arg, "--cached") ||
-				 !strcmp(arg, "--staged")) {
-				add_head_to_pending(&rev);
-				if (!rev.pending.nr) {
-					struct tree *tree;
-					tree = lookup_tree(the_repository,
-							   the_repository->hash_algo->empty_tree);
-					add_pending_object(&rev, &tree->object, "HEAD");
-				}
-				break;
-			}
-		}
-	}
-
-	symdiff_prepare(&rev, &sdiff);
-	for (i = 0; i < rev.pending.nr; i++) {
-		struct object_array_entry *entry = &rev.pending.objects[i];
-		struct object *obj = entry->item;
-		const char *name = entry->name;
-		int flags = (obj->flags & UNINTERESTING);
-		if (!obj->parsed)
-			obj = parse_object(the_repository, &obj->oid);
-		obj = deref_tag(the_repository, obj, NULL, 0);
-		if (!obj)
-			die(_("invalid object '%s' given."), name);
-		if (obj->type == OBJ_COMMIT)
-			obj = &get_commit_tree(((struct commit *)obj))->object;
-
-		if (obj->type == OBJ_TREE) {
-			if (sdiff.skip && bitmap_get(sdiff.skip, i))
-				continue;
-			obj->flags |= flags;
-			add_object_array(obj, name, &ent);
-		} else if (obj->type == OBJ_BLOB) {
-			if (2 <= blobs)
-				die(_("more than two blobs given: '%s'"), name);
-			blob[blobs] = entry;
-			blobs++;
-
-		} else {
-			die(_("unhandled object '%s' given."), name);
-		}
-	}
-	if (rev.prune_data.nr)
-		paths += rev.prune_data.nr;
-
-	/*
-	 * Now, do the arguments look reasonable?
-	 */
-	if (!ent.nr) {
-		switch (blobs) {
-		case 0:
-			result = builtin_diff_files(&rev, argc, argv);
-			break;
-		case 1:
-			if (paths != 1)
-				usage(builtin_diff_usage);
-			result = builtin_diff_b_f(&rev, argc, argv, blob);
-			break;
-		case 2:
-			if (paths)
-				usage(builtin_diff_usage);
-			result = builtin_diff_blobs(&rev, argc, argv, blob);
-			break;
-		default:
-			usage(builtin_diff_usage);
-		}
-	}
-	else if (blobs)
-		usage(builtin_diff_usage);
-	else if (ent.nr == 1)
-		result = builtin_diff_index(&rev, argc, argv);
-	else if (ent.nr == 2) {
-		if (sdiff.warn)
-			warning(_("%s...%s: multiple merge bases, using %s"),
-				sdiff.left, sdiff.right, sdiff.base);
-		result = builtin_diff_tree(&rev, argc, argv,
-					   &ent.objects[0], &ent.objects[1]);
-	} else
-		result = builtin_diff_combined(&rev, argc, argv,
-					       ent.objects, ent.nr);
-	result = diff_result_code(&rev.diffopt, result);
-	if (1 < rev.diffopt.skip_stat_unmatch)
-		refresh_index_quietly();
-	UNLEAK(rev);
-	UNLEAK(ent);
-	UNLEAK(blob);
-	return result;
-}
diff --git a/third_party/git/builtin/difftool.c b/third_party/git/builtin/difftool.c
deleted file mode 100644
index 7ac432b88193..000000000000
--- a/third_party/git/builtin/difftool.c
+++ /dev/null
@@ -1,772 +0,0 @@
-/*
- * "git difftool" builtin command
- *
- * This is a wrapper around the GIT_EXTERNAL_DIFF-compatible
- * git-difftool--helper script.
- *
- * This script exports GIT_EXTERNAL_DIFF and GIT_PAGER for use by git.
- * The GIT_DIFF* variables are exported for use by git-difftool--helper.
- *
- * Any arguments that are unknown to this script are forwarded to 'git diff'.
- *
- * Copyright (C) 2016 Johannes Schindelin
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "config.h"
-#include "builtin.h"
-#include "run-command.h"
-#include "exec-cmd.h"
-#include "parse-options.h"
-#include "strvec.h"
-#include "strbuf.h"
-#include "lockfile.h"
-#include "object-store.h"
-#include "dir.h"
-
-static int trust_exit_code;
-
-static const char *const builtin_difftool_usage[] = {
-	N_("git difftool [<options>] [<commit> [<commit>]] [--] [<path>...]"),
-	NULL
-};
-
-static int difftool_config(const char *var, const char *value, void *cb)
-{
-	if (!strcmp(var, "difftool.trustexitcode")) {
-		trust_exit_code = git_config_bool(var, value);
-		return 0;
-	}
-
-	return git_default_config(var, value, cb);
-}
-
-static int print_tool_help(void)
-{
-	const char *argv[] = { "mergetool", "--tool-help=diff", NULL };
-	return run_command_v_opt(argv, RUN_GIT_CMD);
-}
-
-static int parse_index_info(char *p, int *mode1, int *mode2,
-			    struct object_id *oid1, struct object_id *oid2,
-			    char *status)
-{
-	if (*p != ':')
-		return error("expected ':', got '%c'", *p);
-	*mode1 = (int)strtol(p + 1, &p, 8);
-	if (*p != ' ')
-		return error("expected ' ', got '%c'", *p);
-	*mode2 = (int)strtol(p + 1, &p, 8);
-	if (*p != ' ')
-		return error("expected ' ', got '%c'", *p);
-	if (parse_oid_hex(++p, oid1, (const char **)&p))
-		return error("expected object ID, got '%s'", p);
-	if (*p != ' ')
-		return error("expected ' ', got '%c'", *p);
-	if (parse_oid_hex(++p, oid2, (const char **)&p))
-		return error("expected object ID, got '%s'", p);
-	if (*p != ' ')
-		return error("expected ' ', got '%c'", *p);
-	*status = *++p;
-	if (!*status)
-		return error("missing status");
-	if (p[1] && !isdigit(p[1]))
-		return error("unexpected trailer: '%s'", p + 1);
-	return 0;
-}
-
-/*
- * Remove any trailing slash from $workdir
- * before starting to avoid double slashes in symlink targets.
- */
-static void add_path(struct strbuf *buf, size_t base_len, const char *path)
-{
-	strbuf_setlen(buf, base_len);
-	if (buf->len && buf->buf[buf->len - 1] != '/')
-		strbuf_addch(buf, '/');
-	strbuf_addstr(buf, path);
-}
-
-/*
- * Determine whether we can simply reuse the file in the worktree.
- */
-static int use_wt_file(const char *workdir, const char *name,
-		       struct object_id *oid)
-{
-	struct strbuf buf = STRBUF_INIT;
-	struct stat st;
-	int use = 0;
-
-	strbuf_addstr(&buf, workdir);
-	add_path(&buf, buf.len, name);
-
-	if (!lstat(buf.buf, &st) && !S_ISLNK(st.st_mode)) {
-		struct object_id wt_oid;
-		int fd = open(buf.buf, O_RDONLY);
-
-		if (fd >= 0 &&
-		    !index_fd(&the_index, &wt_oid, fd, &st, OBJ_BLOB, name, 0)) {
-			if (is_null_oid(oid)) {
-				oidcpy(oid, &wt_oid);
-				use = 1;
-			} else if (oideq(oid, &wt_oid))
-				use = 1;
-		}
-	}
-
-	strbuf_release(&buf);
-
-	return use;
-}
-
-struct working_tree_entry {
-	struct hashmap_entry entry;
-	char path[FLEX_ARRAY];
-};
-
-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 *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);
-
-	return strcmp(a->path, b->path);
-}
-
-/*
- * The `left` and `right` entries hold paths for the symlinks hashmap,
- * and a SHA-1 surrounded by brief text for submodules.
- */
-struct pair_entry {
-	struct hashmap_entry entry;
-	char left[PATH_MAX], right[PATH_MAX];
-	const char path[FLEX_ARRAY];
-};
-
-static int pair_cmp(const void *unused_cmp_data,
-		    const struct hashmap_entry *eptr,
-		    const struct hashmap_entry *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);
-
-	return strcmp(a->path, b->path);
-}
-
-static void add_left_or_right(struct hashmap *map, const char *path,
-			      const char *content, int is_right)
-{
-	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);
-	if (existing) {
-		free(e);
-		e = existing;
-	} else {
-		e->left[0] = e->right[0] = '\0';
-		hashmap_add(map, &e->entry);
-	}
-	strlcpy(is_right ? e->right : e->left, content, PATH_MAX);
-}
-
-struct path_entry {
-	struct hashmap_entry entry;
-	char path[FLEX_ARRAY];
-};
-
-static int path_entry_cmp(const void *unused_cmp_data,
-			  const struct hashmap_entry *eptr,
-			  const struct hashmap_entry *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);
-
-	return strcmp(a->path, key ? key : b->path);
-}
-
-static void changed_files(struct hashmap *result, const char *index_path,
-			  const char *workdir)
-{
-	struct child_process update_index = CHILD_PROCESS_INIT;
-	struct child_process diff_files = CHILD_PROCESS_INIT;
-	struct strbuf index_env = STRBUF_INIT, buf = STRBUF_INIT;
-	const char *git_dir = absolute_path(get_git_dir()), *env[] = {
-		NULL, NULL
-	};
-	FILE *fp;
-
-	strbuf_addf(&index_env, "GIT_INDEX_FILE=%s", index_path);
-	env[0] = index_env.buf;
-
-	strvec_pushl(&update_index.args,
-		     "--git-dir", git_dir, "--work-tree", workdir,
-		     "update-index", "--really-refresh", "-q",
-		     "--unmerged", NULL);
-	update_index.no_stdin = 1;
-	update_index.no_stdout = 1;
-	update_index.no_stderr = 1;
-	update_index.git_cmd = 1;
-	update_index.use_shell = 0;
-	update_index.clean_on_exit = 1;
-	update_index.dir = workdir;
-	update_index.env = env;
-	/* Ignore any errors of update-index */
-	run_command(&update_index);
-
-	strvec_pushl(&diff_files.args,
-		     "--git-dir", git_dir, "--work-tree", workdir,
-		     "diff-files", "--name-only", "-z", NULL);
-	diff_files.no_stdin = 1;
-	diff_files.git_cmd = 1;
-	diff_files.use_shell = 0;
-	diff_files.clean_on_exit = 1;
-	diff_files.out = -1;
-	diff_files.dir = workdir;
-	diff_files.env = env;
-	if (start_command(&diff_files))
-		die("could not obtain raw diff");
-	fp = xfdopen(diff_files.out, "r");
-	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);
-	}
-	fclose(fp);
-	if (finish_command(&diff_files))
-		die("diff-files did not exit properly");
-	strbuf_release(&index_env);
-	strbuf_release(&buf);
-}
-
-static NORETURN void exit_cleanup(const char *tmpdir, int exit_code)
-{
-	struct strbuf buf = STRBUF_INIT;
-	strbuf_addstr(&buf, tmpdir);
-	remove_dir_recursively(&buf, 0);
-	if (exit_code)
-		warning(_("failed: %d"), exit_code);
-	exit(exit_code);
-}
-
-static int ensure_leading_directories(char *path)
-{
-	switch (safe_create_leading_directories(path)) {
-		case SCLD_OK:
-		case SCLD_EXISTS:
-			return 0;
-		default:
-			return error(_("could not create leading directories "
-				       "of '%s'"), path);
-	}
-}
-
-/*
- * Unconditional writing of a plain regular file is what
- * "git difftool --dir-diff" wants to do for symlinks.  We are preparing two
- * temporary directories to be fed to a Git-unaware tool that knows how to
- * show a diff of two directories (e.g. "diff -r A B").
- *
- * Because the tool is Git-unaware, if a symbolic link appears in either of
- * these temporary directories, it will try to dereference and show the
- * difference of the target of the symbolic link, which is not what we want,
- * as the goal of the dir-diff mode is to produce an output that is logically
- * equivalent to what "git diff" produces.
- *
- * Most importantly, we want to get textual comparison of the result of the
- * readlink(2).  get_symlink() provides that---it returns the contents of
- * the symlink that gets written to a regular file to force the external tool
- * to compare the readlink(2) result as text, even on a filesystem that is
- * capable of doing a symbolic link.
- */
-static char *get_symlink(const struct object_id *oid, const char *path)
-{
-	char *data;
-	if (is_null_oid(oid)) {
-		/* The symlink is unknown to Git so read from the filesystem */
-		struct strbuf link = STRBUF_INIT;
-		if (has_symlinks) {
-			if (strbuf_readlink(&link, path, strlen(path)))
-				die(_("could not read symlink %s"), path);
-		} else if (strbuf_read_file(&link, path, 128))
-			die(_("could not read symlink file %s"), path);
-
-		data = strbuf_detach(&link, NULL);
-	} else {
-		enum object_type type;
-		unsigned long size;
-		data = read_object_file(oid, &type, &size);
-		if (!data)
-			die(_("could not read object %s for symlink %s"),
-				oid_to_hex(oid), path);
-	}
-
-	return data;
-}
-
-static int checkout_path(unsigned mode, struct object_id *oid,
-			 const char *path, const struct checkout *state)
-{
-	struct cache_entry *ce;
-	int ret;
-
-	ce = make_transient_cache_entry(mode, oid, path, 0);
-	ret = checkout_entry(ce, state, NULL, NULL);
-
-	discard_cache_entry(ce);
-	return ret;
-}
-
-static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
-			int argc, const char **argv)
-{
-	char tmpdir[PATH_MAX];
-	struct strbuf info = STRBUF_INIT, lpath = STRBUF_INIT;
-	struct strbuf rpath = STRBUF_INIT, buf = STRBUF_INIT;
-	struct strbuf ldir = STRBUF_INIT, rdir = STRBUF_INIT;
-	struct strbuf wtdir = STRBUF_INIT;
-	char *lbase_dir, *rbase_dir;
-	size_t ldir_len, rdir_len, wtdir_len;
-	const char *workdir, *tmp;
-	int ret = 0, i;
-	FILE *fp;
-	struct hashmap working_tree_dups, submodules, symlinks2;
-	struct hashmap_iter iter;
-	struct pair_entry *entry;
-	struct index_state wtindex;
-	struct checkout lstate, rstate;
-	int rc, flags = RUN_GIT_CMD, err = 0;
-	struct child_process child = CHILD_PROCESS_INIT;
-	const char *helper_argv[] = { "difftool--helper", NULL, NULL, NULL };
-	struct hashmap wt_modified, tmp_modified;
-	int indices_loaded = 0;
-
-	workdir = get_git_work_tree();
-
-	/* Setup temp directories */
-	tmp = getenv("TMPDIR");
-	xsnprintf(tmpdir, sizeof(tmpdir), "%s/git-difftool.XXXXXX", tmp ? tmp : "/tmp");
-	if (!mkdtemp(tmpdir))
-		return error("could not create '%s'", tmpdir);
-	strbuf_addf(&ldir, "%s/left/", tmpdir);
-	strbuf_addf(&rdir, "%s/right/", tmpdir);
-	strbuf_addstr(&wtdir, workdir);
-	if (!wtdir.len || !is_dir_sep(wtdir.buf[wtdir.len - 1]))
-		strbuf_addch(&wtdir, '/');
-	mkdir(ldir.buf, 0700);
-	mkdir(rdir.buf, 0700);
-
-	memset(&wtindex, 0, sizeof(wtindex));
-
-	memset(&lstate, 0, sizeof(lstate));
-	lstate.base_dir = lbase_dir = xstrdup(ldir.buf);
-	lstate.base_dir_len = ldir.len;
-	lstate.force = 1;
-	memset(&rstate, 0, sizeof(rstate));
-	rstate.base_dir = rbase_dir = xstrdup(rdir.buf);
-	rstate.base_dir_len = rdir.len;
-	rstate.force = 1;
-
-	ldir_len = ldir.len;
-	rdir_len = rdir.len;
-	wtdir_len = wtdir.len;
-
-	hashmap_init(&working_tree_dups, working_tree_entry_cmp, NULL, 0);
-	hashmap_init(&submodules, pair_cmp, NULL, 0);
-	hashmap_init(&symlinks2, pair_cmp, NULL, 0);
-
-	child.no_stdin = 1;
-	child.git_cmd = 1;
-	child.use_shell = 0;
-	child.clean_on_exit = 1;
-	child.dir = prefix;
-	child.out = -1;
-	strvec_pushl(&child.args, "diff", "--raw", "--no-abbrev", "-z",
-		     NULL);
-	for (i = 0; i < argc; i++)
-		strvec_push(&child.args, argv[i]);
-	if (start_command(&child))
-		die("could not obtain raw diff");
-	fp = xfdopen(child.out, "r");
-
-	/* Build index info for left and right sides of the diff */
-	i = 0;
-	while (!strbuf_getline_nul(&info, fp)) {
-		int lmode, rmode;
-		struct object_id loid, roid;
-		char status;
-		const char *src_path, *dst_path;
-
-		if (starts_with(info.buf, "::"))
-			die(N_("combined diff formats('-c' and '--cc') are "
-			       "not supported in\n"
-			       "directory diff mode('-d' and '--dir-diff')."));
-
-		if (parse_index_info(info.buf, &lmode, &rmode, &loid, &roid,
-				     &status))
-			break;
-		if (strbuf_getline_nul(&lpath, fp))
-			break;
-		src_path = lpath.buf;
-
-		i++;
-		if (status != 'C' && status != 'R') {
-			dst_path = src_path;
-		} else {
-			if (strbuf_getline_nul(&rpath, fp))
-				break;
-			dst_path = rpath.buf;
-		}
-
-		if (S_ISGITLINK(lmode) || S_ISGITLINK(rmode)) {
-			strbuf_reset(&buf);
-			strbuf_addf(&buf, "Subproject commit %s",
-				    oid_to_hex(&loid));
-			add_left_or_right(&submodules, src_path, buf.buf, 0);
-			strbuf_reset(&buf);
-			strbuf_addf(&buf, "Subproject commit %s",
-				    oid_to_hex(&roid));
-			if (oideq(&loid, &roid))
-				strbuf_addstr(&buf, "-dirty");
-			add_left_or_right(&submodules, dst_path, buf.buf, 1);
-			continue;
-		}
-
-		if (S_ISLNK(lmode)) {
-			char *content = get_symlink(&loid, src_path);
-			add_left_or_right(&symlinks2, src_path, content, 0);
-			free(content);
-		}
-
-		if (S_ISLNK(rmode)) {
-			char *content = get_symlink(&roid, dst_path);
-			add_left_or_right(&symlinks2, dst_path, content, 1);
-			free(content);
-		}
-
-		if (lmode && status != 'C') {
-			if (checkout_path(lmode, &loid, src_path, &lstate)) {
-				ret = error("could not write '%s'", src_path);
-				goto finish;
-			}
-		}
-
-		if (rmode && !S_ISLNK(rmode)) {
-			struct working_tree_entry *entry;
-
-			/* 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)) {
-				free(entry);
-				continue;
-			}
-			hashmap_add(&working_tree_dups, &entry->entry);
-
-			if (!use_wt_file(workdir, dst_path, &roid)) {
-				if (checkout_path(rmode, &roid, dst_path,
-						  &rstate)) {
-					ret = error("could not write '%s'",
-						    dst_path);
-					goto finish;
-				}
-			} else if (!is_null_oid(&roid)) {
-				/*
-				 * Changes in the working tree need special
-				 * treatment since they are not part of the
-				 * index.
-				 */
-				struct cache_entry *ce2 =
-					make_cache_entry(&wtindex, rmode, &roid,
-							 dst_path, 0, 0);
-
-				add_index_entry(&wtindex, ce2,
-						ADD_CACHE_JUST_APPEND);
-
-				add_path(&rdir, rdir_len, dst_path);
-				if (ensure_leading_directories(rdir.buf)) {
-					ret = error("could not create "
-						    "directory for '%s'",
-						    dst_path);
-					goto finish;
-				}
-				add_path(&wtdir, wtdir_len, dst_path);
-				if (symlinks) {
-					if (symlink(wtdir.buf, rdir.buf)) {
-						ret = error_errno("could not symlink '%s' to '%s'", wtdir.buf, rdir.buf);
-						goto finish;
-					}
-				} else {
-					struct stat st;
-					if (stat(wtdir.buf, &st))
-						st.st_mode = 0644;
-					if (copy_file(rdir.buf, wtdir.buf,
-						      st.st_mode)) {
-						ret = error("could not copy '%s' to '%s'", wtdir.buf, rdir.buf);
-						goto finish;
-					}
-				}
-			}
-		}
-	}
-
-	fclose(fp);
-	fp = NULL;
-	if (finish_command(&child)) {
-		ret = error("error occurred running diff --raw");
-		goto finish;
-	}
-
-	if (!i)
-		goto finish;
-
-	/*
-	 * Changes to submodules require special treatment.This loop writes a
-	 * 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 */) {
-		if (*entry->left) {
-			add_path(&ldir, ldir_len, entry->path);
-			ensure_leading_directories(ldir.buf);
-			write_file(ldir.buf, "%s", entry->left);
-		}
-		if (*entry->right) {
-			add_path(&rdir, rdir_len, entry->path);
-			ensure_leading_directories(rdir.buf);
-			write_file(rdir.buf, "%s", entry->right);
-		}
-	}
-
-	/*
-	 * Symbolic links require special treatment.The standard "git diff"
-	 * 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 */) {
-		if (*entry->left) {
-			add_path(&ldir, ldir_len, entry->path);
-			ensure_leading_directories(ldir.buf);
-			write_file(ldir.buf, "%s", entry->left);
-		}
-		if (*entry->right) {
-			add_path(&rdir, rdir_len, entry->path);
-			ensure_leading_directories(rdir.buf);
-			write_file(rdir.buf, "%s", entry->right);
-		}
-	}
-
-	strbuf_release(&buf);
-
-	strbuf_setlen(&ldir, ldir_len);
-	helper_argv[1] = ldir.buf;
-	strbuf_setlen(&rdir, rdir_len);
-	helper_argv[2] = rdir.buf;
-
-	if (extcmd) {
-		helper_argv[0] = extcmd;
-		flags = 0;
-	} else
-		setenv("GIT_DIFFTOOL_DIRDIFF", "true", 1);
-	rc = run_command_v_opt(helper_argv, flags);
-
-	/*
-	 * If the diff includes working copy files and those
-	 * files were modified during the diff, then the changes
-	 * should be copied back to the working tree.
-	 * Do not copy back files when symlinks are used and the
-	 * external tool did not replace the original link with a file.
-	 *
-	 * These hashes are loaded lazily since they aren't needed
-	 * in the common case of --symlinks and the difftool updating
-	 * files through the symlink.
-	 */
-	hashmap_init(&wt_modified, path_entry_cmp, NULL, wtindex.cache_nr);
-	hashmap_init(&tmp_modified, path_entry_cmp, NULL, wtindex.cache_nr);
-
-	for (i = 0; i < wtindex.cache_nr; i++) {
-		struct hashmap_entry dummy;
-		const char *name = wtindex.cache[i]->name;
-		struct stat st;
-
-		add_path(&rdir, rdir_len, name);
-		if (lstat(rdir.buf, &st))
-			continue;
-
-		if ((symlinks && S_ISLNK(st.st_mode)) || !S_ISREG(st.st_mode))
-			continue;
-
-		if (!indices_loaded) {
-			struct lock_file lock = LOCK_INIT;
-			strbuf_reset(&buf);
-			strbuf_addf(&buf, "%s/wtindex", tmpdir);
-			if (hold_lock_file_for_update(&lock, buf.buf, 0) < 0 ||
-			    write_locked_index(&wtindex, &lock, COMMIT_LOCK)) {
-				ret = error("could not write %s", buf.buf);
-				goto finish;
-			}
-			changed_files(&wt_modified, buf.buf, workdir);
-			strbuf_setlen(&rdir, rdir_len);
-			changed_files(&tmp_modified, buf.buf, rdir.buf);
-			add_path(&rdir, rdir_len, name);
-			indices_loaded = 1;
-		}
-
-		hashmap_entry_init(&dummy, strhash(name));
-		if (hashmap_get(&tmp_modified, &dummy, name)) {
-			add_path(&wtdir, wtdir_len, name);
-			if (hashmap_get(&wt_modified, &dummy, name)) {
-				warning(_("both files modified: '%s' and '%s'."),
-					wtdir.buf, rdir.buf);
-				warning(_("working tree file has been left."));
-				warning("%s", "");
-				err = 1;
-			} else if (unlink(wtdir.buf) ||
-				   copy_file(wtdir.buf, rdir.buf, st.st_mode))
-				warning_errno(_("could not copy '%s' to '%s'"),
-					      rdir.buf, wtdir.buf);
-		}
-	}
-
-	if (err) {
-		warning(_("temporary files exist in '%s'."), tmpdir);
-		warning(_("you may want to cleanup or recover these."));
-		exit(1);
-	} else
-		exit_cleanup(tmpdir, rc);
-
-finish:
-	if (fp)
-		fclose(fp);
-
-	free(lbase_dir);
-	free(rbase_dir);
-	strbuf_release(&ldir);
-	strbuf_release(&rdir);
-	strbuf_release(&wtdir);
-	strbuf_release(&buf);
-
-	return ret;
-}
-
-static int run_file_diff(int prompt, const char *prefix,
-			 int argc, const char **argv)
-{
-	struct strvec args = STRVEC_INIT;
-	const char *env[] = {
-		"GIT_PAGER=", "GIT_EXTERNAL_DIFF=git-difftool--helper", NULL,
-		NULL
-	};
-	int ret = 0, i;
-
-	if (prompt > 0)
-		env[2] = "GIT_DIFFTOOL_PROMPT=true";
-	else if (!prompt)
-		env[2] = "GIT_DIFFTOOL_NO_PROMPT=true";
-
-
-	strvec_push(&args, "diff");
-	for (i = 0; i < argc; i++)
-		strvec_push(&args, argv[i]);
-	ret = run_command_v_opt_cd_env(args.v, RUN_GIT_CMD, prefix, env);
-	exit(ret);
-}
-
-int cmd_difftool(int argc, const char **argv, const char *prefix)
-{
-	int use_gui_tool = 0, dir_diff = 0, prompt = -1, symlinks = 0,
-	    tool_help = 0, no_index = 0;
-	static char *difftool_cmd = NULL, *extcmd = NULL;
-	struct option builtin_difftool_options[] = {
-		OPT_BOOL('g', "gui", &use_gui_tool,
-			 N_("use `diff.guitool` instead of `diff.tool`")),
-		OPT_BOOL('d', "dir-diff", &dir_diff,
-			 N_("perform a full-directory diff")),
-		OPT_SET_INT_F('y', "no-prompt", &prompt,
-			N_("do not prompt before launching a diff tool"),
-			0, PARSE_OPT_NONEG),
-		OPT_SET_INT_F(0, "prompt", &prompt, NULL,
-			1, PARSE_OPT_NONEG | PARSE_OPT_HIDDEN),
-		OPT_BOOL(0, "symlinks", &symlinks,
-			 N_("use symlinks in dir-diff mode")),
-		OPT_STRING('t', "tool", &difftool_cmd, N_("tool"),
-			   N_("use the specified diff tool")),
-		OPT_BOOL(0, "tool-help", &tool_help,
-			 N_("print a list of diff tools that may be used with "
-			    "`--tool`")),
-		OPT_BOOL(0, "trust-exit-code", &trust_exit_code,
-			 N_("make 'git-difftool' exit when an invoked diff "
-			    "tool returns a non - zero exit code")),
-		OPT_STRING('x', "extcmd", &extcmd, N_("command"),
-			   N_("specify a custom command for viewing diffs")),
-		OPT_ARGUMENT("no-index", &no_index, N_("passed to `diff`")),
-		OPT_END()
-	};
-
-	git_config(difftool_config, NULL);
-	symlinks = has_symlinks;
-
-	argc = parse_options(argc, argv, prefix, builtin_difftool_options,
-			     builtin_difftool_usage, PARSE_OPT_KEEP_UNKNOWN |
-			     PARSE_OPT_KEEP_DASHDASH);
-
-	if (tool_help)
-		return print_tool_help();
-
-	if (!no_index && !startup_info->have_repository)
-		die(_("difftool requires worktree or --no-index"));
-
-	if (!no_index){
-		setup_work_tree();
-		setenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);
-		setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);
-	} else if (dir_diff)
-		die(_("--dir-diff is incompatible with --no-index"));
-
-	if (use_gui_tool + !!difftool_cmd + !!extcmd > 1)
-		die(_("--gui, --tool and --extcmd are mutually exclusive"));
-
-	if (use_gui_tool)
-		setenv("GIT_MERGETOOL_GUI", "true", 1);
-	else if (difftool_cmd) {
-		if (*difftool_cmd)
-			setenv("GIT_DIFF_TOOL", difftool_cmd, 1);
-		else
-			die(_("no <tool> given for --tool=<tool>"));
-	}
-
-	if (extcmd) {
-		if (*extcmd)
-			setenv("GIT_DIFFTOOL_EXTCMD", extcmd, 1);
-		else
-			die(_("no <cmd> given for --extcmd=<cmd>"));
-	}
-
-	setenv("GIT_DIFFTOOL_TRUST_EXIT_CODE",
-	       trust_exit_code ? "true" : "false", 1);
-
-	/*
-	 * In directory diff mode, 'git-difftool--helper' is called once
-	 * to compare the a / b directories. In file diff mode, 'git diff'
-	 * will invoke a separate instance of 'git-difftool--helper' for
-	 * each file that changed.
-	 */
-	if (dir_diff)
-		return run_dir_diff(extcmd, symlinks, prefix, argc, argv);
-	return run_file_diff(prompt, prefix, argc, argv);
-}
diff --git a/third_party/git/builtin/env--helper.c b/third_party/git/builtin/env--helper.c
deleted file mode 100644
index 27349098b074..000000000000
--- a/third_party/git/builtin/env--helper.c
+++ /dev/null
@@ -1,100 +0,0 @@
-#include "builtin.h"
-#include "config.h"
-#include "parse-options.h"
-
-static char const * const env__helper_usage[] = {
-	N_("git env--helper --type=[bool|ulong] <options> <env-var>"),
-	NULL
-};
-
-enum cmdmode {
-	ENV_HELPER_TYPE_BOOL = 1,
-	ENV_HELPER_TYPE_ULONG
-};
-
-static int option_parse_type(const struct option *opt, const char *arg,
-			     int unset)
-{
-	enum cmdmode *cmdmode = opt->value;
-
-	BUG_ON_OPT_NEG(unset);
-
-	if (!strcmp(arg, "bool"))
-		*cmdmode = ENV_HELPER_TYPE_BOOL;
-	else if (!strcmp(arg, "ulong"))
-		*cmdmode = ENV_HELPER_TYPE_ULONG;
-	else
-		die(_("unrecognized --type argument, %s"), arg);
-
-	return 0;
-}
-
-int cmd_env__helper(int argc, const char **argv, const char *prefix)
-{
-	int exit_code = 0;
-	const char *env_variable = NULL;
-	const char *env_default = NULL;
-	int ret;
-	int ret_int, default_int;
-	unsigned long ret_ulong, default_ulong;
-	enum cmdmode cmdmode = 0;
-	struct option opts[] = {
-		OPT_CALLBACK_F(0, "type", &cmdmode, N_("type"),
-			       N_("value is given this type"), PARSE_OPT_NONEG,
-			       option_parse_type),
-		OPT_STRING(0, "default", &env_default, N_("value"),
-			   N_("default for git_env_*(...) to fall back on")),
-		OPT_BOOL(0, "exit-code", &exit_code,
-			 N_("be quiet only use git_env_*() value as exit code")),
-		OPT_END(),
-	};
-
-	argc = parse_options(argc, argv, prefix, opts, env__helper_usage,
-			     PARSE_OPT_KEEP_UNKNOWN);
-	if (env_default && !*env_default)
-		usage_with_options(env__helper_usage, opts);
-	if (!cmdmode)
-		usage_with_options(env__helper_usage, opts);
-	if (argc != 1)
-		usage_with_options(env__helper_usage, opts);
-	env_variable = argv[0];
-
-	switch (cmdmode) {
-	case ENV_HELPER_TYPE_BOOL:
-		if (env_default) {
-			default_int = git_parse_maybe_bool(env_default);
-			if (default_int == -1) {
-				error(_("option `--default' expects a boolean value with `--type=bool`, not `%s`"),
-				      env_default);
-				usage_with_options(env__helper_usage, opts);
-			}
-		} else {
-			default_int = 0;
-		}
-		ret_int = git_env_bool(env_variable, default_int);
-		if (!exit_code)
-			puts(ret_int ? "true" : "false");
-		ret = ret_int;
-		break;
-	case ENV_HELPER_TYPE_ULONG:
-		if (env_default) {
-			if (!git_parse_ulong(env_default, &default_ulong)) {
-				error(_("option `--default' expects an unsigned long value with `--type=ulong`, not `%s`"),
-				      env_default);
-				usage_with_options(env__helper_usage, opts);
-			}
-		} else {
-			default_ulong = 0;
-		}
-		ret_ulong = git_env_ulong(env_variable, default_ulong);
-		if (!exit_code)
-			printf("%lu\n", ret_ulong);
-		ret = ret_ulong;
-		break;
-	default:
-		BUG("unknown <type> value");
-		break;
-	}
-
-	return !ret;
-}
diff --git a/third_party/git/builtin/fast-export.c b/third_party/git/builtin/fast-export.c
deleted file mode 100644
index d2e33f500521..000000000000
--- a/third_party/git/builtin/fast-export.c
+++ /dev/null
@@ -1,1312 +0,0 @@
-/*
- * "git fast-export" builtin command
- *
- * Copyright (C) 2007 Johannes E. Schindelin
- */
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "refs.h"
-#include "refspec.h"
-#include "object-store.h"
-#include "commit.h"
-#include "object.h"
-#include "tag.h"
-#include "diff.h"
-#include "diffcore.h"
-#include "log-tree.h"
-#include "revision.h"
-#include "decorate.h"
-#include "string-list.h"
-#include "utf8.h"
-#include "parse-options.h"
-#include "quote.h"
-#include "remote.h"
-#include "blob.h"
-#include "commit-slab.h"
-
-static const char *fast_export_usage[] = {
-	N_("git fast-export [rev-list-opts]"),
-	NULL
-};
-
-static int progress;
-static enum { SIGNED_TAG_ABORT, VERBATIM, WARN, WARN_STRIP, STRIP } signed_tag_mode = SIGNED_TAG_ABORT;
-static enum { TAG_FILTERING_ABORT, DROP, REWRITE } tag_of_filtered_mode = TAG_FILTERING_ABORT;
-static enum { REENCODE_ABORT, REENCODE_YES, REENCODE_NO } reencode_mode = REENCODE_ABORT;
-static int fake_missing_tagger;
-static int use_done_feature;
-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;
-static int anonymize;
-static struct hashmap anonymized_seeds;
-static struct revision_sources revision_sources;
-
-static int parse_opt_signed_tag_mode(const struct option *opt,
-				     const char *arg, int unset)
-{
-	if (unset || !strcmp(arg, "abort"))
-		signed_tag_mode = SIGNED_TAG_ABORT;
-	else if (!strcmp(arg, "verbatim") || !strcmp(arg, "ignore"))
-		signed_tag_mode = VERBATIM;
-	else if (!strcmp(arg, "warn"))
-		signed_tag_mode = WARN;
-	else if (!strcmp(arg, "warn-strip"))
-		signed_tag_mode = WARN_STRIP;
-	else if (!strcmp(arg, "strip"))
-		signed_tag_mode = STRIP;
-	else
-		return error("Unknown signed-tags mode: %s", arg);
-	return 0;
-}
-
-static int parse_opt_tag_of_filtered_mode(const struct option *opt,
-					  const char *arg, int unset)
-{
-	if (unset || !strcmp(arg, "abort"))
-		tag_of_filtered_mode = TAG_FILTERING_ABORT;
-	else if (!strcmp(arg, "drop"))
-		tag_of_filtered_mode = DROP;
-	else if (!strcmp(arg, "rewrite"))
-		tag_of_filtered_mode = REWRITE;
-	else
-		return error("Unknown tag-of-filtered mode: %s", arg);
-	return 0;
-}
-
-static int parse_opt_reencode_mode(const struct option *opt,
-				   const char *arg, int unset)
-{
-	if (unset) {
-		reencode_mode = REENCODE_ABORT;
-		return 0;
-	}
-
-	switch (git_parse_maybe_bool(arg)) {
-	case 0:
-		reencode_mode = REENCODE_NO;
-		break;
-	case 1:
-		reencode_mode = REENCODE_YES;
-		break;
-	default:
-		if (!strcasecmp(arg, "abort"))
-			reencode_mode = REENCODE_ABORT;
-		else
-			return error("Unknown reencoding mode: %s", arg);
-	}
-
-	return 0;
-}
-
-static struct decoration idnums;
-static uint32_t last_idnum;
-
-static int has_unshown_parent(struct commit *commit)
-{
-	struct commit_list *parent;
-
-	for (parent = commit->parents; parent; parent = parent->next)
-		if (!(parent->item->object.flags & SHOWN) &&
-		    !(parent->item->object.flags & UNINTERESTING))
-			return 1;
-	return 0;
-}
-
-struct anonymized_entry {
-	struct hashmap_entry hash;
-	const char *anon;
-	const char orig[FLEX_ARRAY];
-};
-
-struct anonymized_entry_key {
-	struct hashmap_entry hash;
-	const char *orig;
-	size_t orig_len;
-};
-
-static int anonymized_entry_cmp(const void *unused_cmp_data,
-				const struct hashmap_entry *eptr,
-				const struct hashmap_entry *entry_or_key,
-				const void *keydata)
-{
-	const struct anonymized_entry *a, *b;
-
-	a = container_of(eptr, const struct anonymized_entry, hash);
-	if (keydata) {
-		const struct anonymized_entry_key *key = keydata;
-		int equal = !strncmp(a->orig, key->orig, key->orig_len) &&
-			    !a->orig[key->orig_len];
-		return !equal;
-	}
-
-	b = container_of(entry_or_key, const struct anonymized_entry, hash);
-	return strcmp(a->orig, b->orig);
-}
-
-/*
- * Basically keep a cache of X->Y so that we can repeatedly replace
- * the same anonymized string with another. The actual generation
- * is farmed out to the generate function.
- */
-static const char *anonymize_str(struct hashmap *map,
-				 char *(*generate)(void *),
-				 const char *orig, size_t len,
-				 void *data)
-{
-	struct anonymized_entry_key key;
-	struct anonymized_entry *ret;
-
-	if (!map->cmpfn)
-		hashmap_init(map, anonymized_entry_cmp, NULL, 0);
-
-	hashmap_entry_init(&key.hash, memhash(orig, len));
-	key.orig = orig;
-	key.orig_len = len;
-
-	/* First check if it's a token the user configured manually... */
-	if (anonymized_seeds.cmpfn)
-		ret = hashmap_get_entry(&anonymized_seeds, &key, hash, &key);
-	else
-		ret = NULL;
-
-	/* ...otherwise check if we've already seen it in this context... */
-	if (!ret)
-		ret = hashmap_get_entry(map, &key, hash, &key);
-
-	/* ...and finally generate a new mapping if necessary */
-	if (!ret) {
-		FLEX_ALLOC_MEM(ret, orig, orig, len);
-		hashmap_entry_init(&ret->hash, key.hash.hash);
-		ret->anon = generate(data);
-		hashmap_put(map, &ret->hash);
-	}
-
-	return ret->anon;
-}
-
-/*
- * We anonymize each component of a path individually,
- * so that paths a/b and a/c will share a common root.
- * The paths are cached via anonymize_mem so that repeated
- * lookups for "a" will yield the same value.
- */
-static void anonymize_path(struct strbuf *out, const char *path,
-			   struct hashmap *map,
-			   char *(*generate)(void *))
-{
-	while (*path) {
-		const char *end_of_component = strchrnul(path, '/');
-		size_t len = end_of_component - path;
-		const char *c = anonymize_str(map, generate, path, len, NULL);
-		strbuf_addstr(out, c);
-		path = end_of_component;
-		if (*path)
-			strbuf_addch(out, *path++);
-	}
-}
-
-static inline void *mark_to_ptr(uint32_t mark)
-{
-	return (void *)(uintptr_t)mark;
-}
-
-static inline uint32_t ptr_to_mark(void * mark)
-{
-	return (uint32_t)(uintptr_t)mark;
-}
-
-static inline void mark_object(struct object *object, uint32_t mark)
-{
-	add_decoration(&idnums, object, mark_to_ptr(mark));
-}
-
-static inline void mark_next_object(struct object *object)
-{
-	mark_object(object, ++last_idnum);
-}
-
-static int get_object_mark(struct object *object)
-{
-	void *decoration = lookup_decoration(&idnums, object);
-	if (!decoration)
-		return 0;
-	return ptr_to_mark(decoration);
-}
-
-static struct commit *rewrite_commit(struct commit *p)
-{
-	for (;;) {
-		if (p->parents && p->parents->next)
-			break;
-		if (p->object.flags & UNINTERESTING)
-			break;
-		if (!(p->object.flags & TREESAME))
-			break;
-		if (!p->parents)
-			return NULL;
-		p = p->parents->item;
-	}
-	return p;
-}
-
-static void show_progress(void)
-{
-	static int counter = 0;
-	if (!progress)
-		return;
-	if ((++counter % progress) == 0)
-		printf("progress %d objects\n", counter);
-}
-
-/*
- * Ideally we would want some transformation of the blob data here
- * that is unreversible, but would still be the same size and have
- * the same data relationship to other blobs (so that we get the same
- * delta and packing behavior as the original). But the first and last
- * requirements there are probably mutually exclusive, so let's take
- * the easy way out for now, and just generate arbitrary content.
- *
- * There's no need to cache this result with anonymize_mem, since
- * we already handle blob content caching with marks.
- */
-static char *anonymize_blob(unsigned long *size)
-{
-	static int counter;
-	struct strbuf out = STRBUF_INIT;
-	strbuf_addf(&out, "anonymous blob %d", counter++);
-	*size = out.len;
-	return strbuf_detach(&out, NULL);
-}
-
-static void export_blob(const struct object_id *oid)
-{
-	unsigned long size;
-	enum object_type type;
-	char *buf;
-	struct object *object;
-	int eaten;
-
-	if (no_data)
-		return;
-
-	if (is_null_oid(oid))
-		return;
-
-	object = lookup_object(the_repository, oid);
-	if (object && object->flags & SHOWN)
-		return;
-
-	if (anonymize) {
-		buf = anonymize_blob(&size);
-		object = (struct object *)lookup_blob(the_repository, oid);
-		eaten = 0;
-	} else {
-		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)
-			die("oid mismatch in blob %s", oid_to_hex(oid));
-		object = parse_object_buffer(the_repository, oid, type,
-					     size, buf, &eaten);
-	}
-
-	if (!object)
-		die("Could not read blob %s", oid_to_hex(oid));
-
-	mark_next_object(object);
-
-	printf("blob\nmark :%"PRIu32"\n", last_idnum);
-	if (show_original_ids)
-		printf("original-oid %s\n", oid_to_hex(oid));
-	printf("data %"PRIuMAX"\n", (uintmax_t)size);
-	if (size && fwrite(buf, size, 1, stdout) != 1)
-		die_errno("could not write blob '%s'", oid_to_hex(oid));
-	printf("\n");
-
-	show_progress();
-
-	object->flags |= SHOWN;
-	if (!eaten)
-		free(buf);
-}
-
-static int depth_first(const void *a_, const void *b_)
-{
-	const struct diff_filepair *a = *((const struct diff_filepair **)a_);
-	const struct diff_filepair *b = *((const struct diff_filepair **)b_);
-	const char *name_a, *name_b;
-	int len_a, len_b, len;
-	int cmp;
-
-	name_a = a->one ? a->one->path : a->two->path;
-	name_b = b->one ? b->one->path : b->two->path;
-
-	len_a = strlen(name_a);
-	len_b = strlen(name_b);
-	len = (len_a < len_b) ? len_a : len_b;
-
-	/* strcmp will sort 'd' before 'd/e', we want 'd/e' before 'd' */
-	cmp = memcmp(name_a, name_b, len);
-	if (cmp)
-		return cmp;
-	cmp = len_b - len_a;
-	if (cmp)
-		return cmp;
-	/*
-	 * Move 'R'ename entries last so that all references of the file
-	 * appear in the output before it is renamed (e.g., when a file
-	 * was copied and renamed in the same commit).
-	 */
-	return (a->status == 'R') - (b->status == 'R');
-}
-
-static void print_path_1(const char *path)
-{
-	int need_quote = quote_c_style(path, NULL, NULL, 0);
-	if (need_quote)
-		quote_c_style(path, NULL, stdout, 0);
-	else if (strchr(path, ' '))
-		printf("\"%s\"", path);
-	else
-		printf("%s", path);
-}
-
-static char *anonymize_path_component(void *data)
-{
-	static int counter;
-	struct strbuf out = STRBUF_INIT;
-	strbuf_addf(&out, "path%d", counter++);
-	return strbuf_detach(&out, NULL);
-}
-
-static void print_path(const char *path)
-{
-	if (!anonymize)
-		print_path_1(path);
-	else {
-		static struct hashmap paths;
-		static struct strbuf anon = STRBUF_INIT;
-
-		anonymize_path(&anon, path, &paths, anonymize_path_component);
-		print_path_1(anon.buf);
-		strbuf_reset(&anon);
-	}
-}
-
-static char *generate_fake_oid(void *data)
-{
-	static uint32_t counter = 1; /* avoid null oid */
-	const unsigned hashsz = the_hash_algo->rawsz;
-	struct object_id oid;
-	char *hex = xmallocz(GIT_MAX_HEXSZ);
-
-	oidclr(&oid);
-	put_be32(oid.hash + hashsz - 4, counter++);
-	return oid_to_hex_r(hex, &oid);
-}
-
-static const char *anonymize_oid(const char *oid_hex)
-{
-	static struct hashmap objs;
-	size_t len = strlen(oid_hex);
-	return anonymize_str(&objs, generate_fake_oid, oid_hex, len, NULL);
-}
-
-static void show_filemodify(struct diff_queue_struct *q,
-			    struct diff_options *options, void *data)
-{
-	int i;
-	struct string_list *changed = data;
-
-	/*
-	 * Handle files below a directory first, in case they are all deleted
-	 * and the directory changes to a file or symlink.
-	 */
-	QSORT(q->queue, q->nr, depth_first);
-
-	for (i = 0; i < q->nr; i++) {
-		struct diff_filespec *ospec = q->queue[i]->one;
-		struct diff_filespec *spec = q->queue[i]->two;
-
-		switch (q->queue[i]->status) {
-		case DIFF_STATUS_DELETED:
-			printf("D ");
-			print_path(spec->path);
-			string_list_insert(changed, spec->path);
-			putchar('\n');
-			break;
-
-		case DIFF_STATUS_COPIED:
-		case DIFF_STATUS_RENAMED:
-			/*
-			 * If a change in the file corresponding to ospec->path
-			 * has been observed, we cannot trust its contents
-			 * because the diff is calculated based on the prior
-			 * contents, not the current contents.  So, declare a
-			 * copy or rename only if there was no change observed.
-			 */
-			if (!string_list_has_string(changed, ospec->path)) {
-				printf("%c ", q->queue[i]->status);
-				print_path(ospec->path);
-				putchar(' ');
-				print_path(spec->path);
-				string_list_insert(changed, spec->path);
-				putchar('\n');
-
-				if (oideq(&ospec->oid, &spec->oid) &&
-				    ospec->mode == spec->mode)
-					break;
-			}
-			/* fallthrough */
-
-		case DIFF_STATUS_TYPE_CHANGED:
-		case DIFF_STATUS_MODIFIED:
-		case DIFF_STATUS_ADDED:
-			/*
-			 * Links refer to objects in another repositories;
-			 * output the SHA-1 verbatim.
-			 */
-			if (no_data || S_ISGITLINK(spec->mode))
-				printf("M %06o %s ", spec->mode,
-				       anonymize ?
-				       anonymize_oid(oid_to_hex(&spec->oid)) :
-				       oid_to_hex(&spec->oid));
-			else {
-				struct object *object = lookup_object(the_repository,
-								      &spec->oid);
-				printf("M %06o :%d ", spec->mode,
-				       get_object_mark(object));
-			}
-			print_path(spec->path);
-			string_list_insert(changed, spec->path);
-			putchar('\n');
-			break;
-
-		default:
-			die("Unexpected comparison status '%c' for %s, %s",
-				q->queue[i]->status,
-				ospec->path ? ospec->path : "none",
-				spec->path ? spec->path : "none");
-		}
-	}
-}
-
-static const char *find_encoding(const char *begin, const char *end)
-{
-	const char *needle = "\nencoding ";
-	char *bol, *eol;
-
-	bol = memmem(begin, end ? end - begin : strlen(begin),
-		     needle, strlen(needle));
-	if (!bol)
-		return NULL;
-	bol += strlen(needle);
-	eol = strchrnul(bol, '\n');
-	*eol = '\0';
-	return bol;
-}
-
-static char *anonymize_ref_component(void *data)
-{
-	static int counter;
-	struct strbuf out = STRBUF_INIT;
-	strbuf_addf(&out, "ref%d", counter++);
-	return strbuf_detach(&out, NULL);
-}
-
-static const char *anonymize_refname(const char *refname)
-{
-	/*
-	 * If any of these prefixes is found, we will leave it intact
-	 * so that tags remain tags and so forth.
-	 */
-	static const char *prefixes[] = {
-		"refs/heads/",
-		"refs/tags/",
-		"refs/remotes/",
-		"refs/"
-	};
-	static struct hashmap refs;
-	static struct strbuf anon = STRBUF_INIT;
-	int i;
-
-	strbuf_reset(&anon);
-	for (i = 0; i < ARRAY_SIZE(prefixes); i++) {
-		if (skip_prefix(refname, prefixes[i], &refname)) {
-			strbuf_addstr(&anon, prefixes[i]);
-			break;
-		}
-	}
-
-	anonymize_path(&anon, refname, &refs, anonymize_ref_component);
-	return anon.buf;
-}
-
-/*
- * We do not even bother to cache commit messages, as they are unlikely
- * to be repeated verbatim, and it is not that interesting when they are.
- */
-static char *anonymize_commit_message(const char *old)
-{
-	static int counter;
-	return xstrfmt("subject %d\n\nbody\n", counter++);
-}
-
-static char *anonymize_ident(void *data)
-{
-	static int counter;
-	struct strbuf out = STRBUF_INIT;
-	strbuf_addf(&out, "User %d <user%d@example.com>", counter, counter);
-	counter++;
-	return strbuf_detach(&out, NULL);
-}
-
-/*
- * Our strategy here is to anonymize the names and email addresses,
- * but keep timestamps intact, as they influence things like traversal
- * order (and by themselves should not be too revealing).
- */
-static void anonymize_ident_line(const char **beg, const char **end)
-{
-	static struct hashmap idents;
-	static struct strbuf buffers[] = { STRBUF_INIT, STRBUF_INIT };
-	static unsigned which_buffer;
-
-	struct strbuf *out;
-	struct ident_split split;
-	const char *end_of_header;
-
-	out = &buffers[which_buffer++];
-	which_buffer %= ARRAY_SIZE(buffers);
-	strbuf_reset(out);
-
-	/* skip "committer", "author", "tagger", etc */
-	end_of_header = strchr(*beg, ' ');
-	if (!end_of_header)
-		BUG("malformed line fed to anonymize_ident_line: %.*s",
-		    (int)(*end - *beg), *beg);
-	end_of_header++;
-	strbuf_add(out, *beg, end_of_header - *beg);
-
-	if (!split_ident_line(&split, end_of_header, *end - end_of_header) &&
-	    split.date_begin) {
-		const char *ident;
-		size_t len;
-
-		len = split.mail_end - split.name_begin;
-		ident = anonymize_str(&idents, anonymize_ident,
-				      split.name_begin, len, NULL);
-		strbuf_addstr(out, ident);
-		strbuf_addch(out, ' ');
-		strbuf_add(out, split.date_begin, split.tz_end - split.date_begin);
-	} else {
-		strbuf_addstr(out, "Malformed Ident <malformed@example.com> 0 -0000");
-	}
-
-	*beg = out->buf;
-	*end = out->buf + out->len;
-}
-
-static void handle_commit(struct commit *commit, struct rev_info *rev,
-			  struct string_list *paths_of_changed_objects)
-{
-	int saved_output_format = rev->diffopt.output_format;
-	const char *commit_buffer;
-	const char *author, *author_end, *committer, *committer_end;
-	const char *encoding, *message;
-	char *reencoded = NULL;
-	struct commit_list *p;
-	const char *refname;
-	int i;
-
-	rev->diffopt.output_format = DIFF_FORMAT_CALLBACK;
-
-	parse_commit_or_die(commit);
-	commit_buffer = get_commit_buffer(commit, NULL);
-	author = strstr(commit_buffer, "\nauthor ");
-	if (!author)
-		die("could not find author in commit %s",
-		    oid_to_hex(&commit->object.oid));
-	author++;
-	author_end = strchrnul(author, '\n');
-	committer = strstr(author_end, "\ncommitter ");
-	if (!committer)
-		die("could not find committer in commit %s",
-		    oid_to_hex(&commit->object.oid));
-	committer++;
-	committer_end = strchrnul(committer, '\n');
-	message = strstr(committer_end, "\n\n");
-	encoding = find_encoding(committer_end, message);
-	if (message)
-		message += 2;
-
-	if (commit->parents &&
-	    (get_object_mark(&commit->parents->item->object) != 0 ||
-	     reference_excluded_commits) &&
-	    !full_tree) {
-		parse_commit_or_die(commit->parents->item);
-		diff_tree_oid(get_commit_tree_oid(commit->parents->item),
-			      get_commit_tree_oid(commit), "", &rev->diffopt);
-	}
-	else
-		diff_root_tree_oid(get_commit_tree_oid(commit),
-				   "", &rev->diffopt);
-
-	/* Export the referenced blobs, and remember the marks. */
-	for (i = 0; i < diff_queued_diff.nr; i++)
-		if (!S_ISGITLINK(diff_queued_diff.queue[i]->two->mode))
-			export_blob(&diff_queued_diff.queue[i]->two->oid);
-
-	refname = *revision_sources_at(&revision_sources, commit);
-	/*
-	 * FIXME: string_list_remove() below for each ref is overall
-	 * O(N^2).  Compared to a history walk and diffing trees, this is
-	 * just lost in the noise in practice.  However, theoretically a
-	 * repo may have enough refs for this to become slow.
-	 */
-	string_list_remove(&extra_refs, refname, 0);
-	if (anonymize) {
-		refname = anonymize_refname(refname);
-		anonymize_ident_line(&committer, &committer_end);
-		anonymize_ident_line(&author, &author_end);
-	}
-
-	mark_next_object(&commit->object);
-	if (anonymize) {
-		reencoded = anonymize_commit_message(message);
-	} else if (encoding) {
-		switch(reencode_mode) {
-		case REENCODE_YES:
-			reencoded = reencode_string(message, "UTF-8", encoding);
-			break;
-		case REENCODE_NO:
-			break;
-		case REENCODE_ABORT:
-			die("Encountered commit-specific encoding %s in commit "
-			    "%s; use --reencode=[yes|no] to handle it",
-			    encoding, oid_to_hex(&commit->object.oid));
-		}
-	}
-	if (!commit->parents)
-		printf("reset %s\n", refname);
-	printf("commit %s\nmark :%"PRIu32"\n", refname, last_idnum);
-	if (show_original_ids)
-		printf("original-oid %s\n", oid_to_hex(&commit->object.oid));
-	printf("%.*s\n%.*s\n",
-	       (int)(author_end - author), author,
-	       (int)(committer_end - committer), committer);
-	if (!reencoded && encoding)
-		printf("encoding %s\n", encoding);
-	printf("data %u\n%s",
-	       (unsigned)(reencoded
-			  ? strlen(reencoded) : message
-			  ? strlen(message) : 0),
-	       reencoded ? reencoded : message ? message : "");
-	free(reencoded);
-	unuse_commit_buffer(commit, commit_buffer);
-
-	for (i = 0, p = commit->parents; p; p = p->next) {
-		struct object *obj = &p->item->object;
-		int mark = get_object_mark(obj);
-
-		if (!mark && !reference_excluded_commits)
-			continue;
-		if (i == 0)
-			printf("from ");
-		else
-			printf("merge ");
-		if (mark)
-			printf(":%d\n", mark);
-		else
-			printf("%s\n",
-			       anonymize ?
-			       anonymize_oid(oid_to_hex(&obj->oid)) :
-			       oid_to_hex(&obj->oid));
-		i++;
-	}
-
-	if (full_tree)
-		printf("deleteall\n");
-	log_tree_diff_flush(rev);
-	string_list_clear(paths_of_changed_objects, 0);
-	rev->diffopt.output_format = saved_output_format;
-
-	printf("\n");
-
-	show_progress();
-}
-
-static char *anonymize_tag(void *data)
-{
-	static int counter;
-	struct strbuf out = STRBUF_INIT;
-	strbuf_addf(&out, "tag message %d", counter++);
-	return strbuf_detach(&out, NULL);
-}
-
-static void handle_tail(struct object_array *commits, struct rev_info *revs,
-			struct string_list *paths_of_changed_objects)
-{
-	struct commit *commit;
-	while (commits->nr) {
-		commit = (struct commit *)object_array_pop(commits);
-		if (has_unshown_parent(commit)) {
-			/* Queue again, to be handled later */
-			add_object_array(&commit->object, NULL, commits);
-			return;
-		}
-		handle_commit(commit, revs, paths_of_changed_objects);
-	}
-}
-
-static void handle_tag(const char *name, struct tag *tag)
-{
-	unsigned long size;
-	enum object_type type;
-	char *buf;
-	const char *tagger, *tagger_end, *message;
-	size_t message_size = 0;
-	struct object *tagged;
-	int tagged_mark;
-	struct commit *p;
-
-	/* Trees have no identifier in fast-export output, thus we have no way
-	 * to output tags of trees, tags of tags of trees, etc.  Simply omit
-	 * such tags.
-	 */
-	tagged = tag->tagged;
-	while (tagged->type == OBJ_TAG) {
-		tagged = ((struct tag *)tagged)->tagged;
-	}
-	if (tagged->type == OBJ_TREE) {
-		warning("Omitting tag %s,\nsince tags of trees (or tags of tags of trees, etc.) are not supported.",
-			oid_to_hex(&tag->object.oid));
-		return;
-	}
-
-	buf = read_object_file(&tag->object.oid, &type, &size);
-	if (!buf)
-		die("could not read tag %s", oid_to_hex(&tag->object.oid));
-	message = memmem(buf, size, "\n\n", 2);
-	if (message) {
-		message += 2;
-		message_size = strlen(message);
-	}
-	tagger = memmem(buf, message ? message - buf : size, "\ntagger ", 8);
-	if (!tagger) {
-		if (fake_missing_tagger)
-			tagger = "tagger Unspecified Tagger "
-				"<unspecified-tagger> 0 +0000";
-		else
-			tagger = "";
-		tagger_end = tagger + strlen(tagger);
-	} else {
-		tagger++;
-		tagger_end = strchrnul(tagger, '\n');
-		if (anonymize)
-			anonymize_ident_line(&tagger, &tagger_end);
-	}
-
-	if (anonymize) {
-		name = anonymize_refname(name);
-		if (message) {
-			static struct hashmap tags;
-			message = anonymize_str(&tags, anonymize_tag,
-						message, message_size, NULL);
-		}
-	}
-
-	/* handle signed tags */
-	if (message) {
-		const char *signature = strstr(message,
-					       "\n-----BEGIN PGP SIGNATURE-----\n");
-		if (signature)
-			switch(signed_tag_mode) {
-			case SIGNED_TAG_ABORT:
-				die("encountered signed tag %s; use "
-				    "--signed-tags=<mode> to handle it",
-				    oid_to_hex(&tag->object.oid));
-			case WARN:
-				warning("exporting signed tag %s",
-					oid_to_hex(&tag->object.oid));
-				/* fallthru */
-			case VERBATIM:
-				break;
-			case WARN_STRIP:
-				warning("stripping signature from tag %s",
-					oid_to_hex(&tag->object.oid));
-				/* fallthru */
-			case STRIP:
-				message_size = signature + 1 - message;
-				break;
-			}
-	}
-
-	/* handle tag->tagged having been filtered out due to paths specified */
-	tagged = tag->tagged;
-	tagged_mark = get_object_mark(tagged);
-	if (!tagged_mark) {
-		switch(tag_of_filtered_mode) {
-		case TAG_FILTERING_ABORT:
-			die("tag %s tags unexported object; use "
-			    "--tag-of-filtered-object=<mode> to handle it",
-			    oid_to_hex(&tag->object.oid));
-		case DROP:
-			/* Ignore this tag altogether */
-			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_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 (show_original_ids)
-		printf("original-oid %s\n", oid_to_hex(&tag->object.oid));
-	printf("%.*s%sdata %d\n%.*s\n",
-	       (int)(tagger_end - tagger), tagger,
-	       tagger == tagger_end ? "" : "\n",
-	       (int)message_size, (int)message_size, message ? message : "");
-	free(buf);
-}
-
-static struct commit *get_commit(struct rev_cmdline_entry *e, char *full_name)
-{
-	switch (e->item->type) {
-	case OBJ_COMMIT:
-		return (struct commit *)e->item;
-	case OBJ_TAG: {
-		struct tag *tag = (struct tag *)e->item;
-
-		/* handle nested tags */
-		while (tag && tag->object.type == OBJ_TAG) {
-			parse_object(the_repository, &tag->object.oid);
-			string_list_append(&tag_refs, full_name)->util = tag;
-			tag = (struct tag *)tag->tagged;
-		}
-		if (!tag)
-			die("Tag %s points nowhere?", e->name);
-		return (struct commit *)tag;
-		break;
-	}
-	default:
-		return NULL;
-	}
-}
-
-static void get_tags_and_duplicates(struct rev_cmdline_info *info)
-{
-	int i;
-
-	for (i = 0; i < info->nr; i++) {
-		struct rev_cmdline_entry *e = info->rev + i;
-		struct object_id oid;
-		struct commit *commit;
-		char *full_name;
-
-		if (e->flags & UNINTERESTING)
-			continue;
-
-		if (dwim_ref(e->name, strlen(e->name), &oid, &full_name, 0) != 1)
-			continue;
-
-		if (refspecs.nr) {
-			char *private;
-			private = apply_refspecs(&refspecs, full_name);
-			if (private) {
-				free(full_name);
-				full_name = private;
-			}
-		}
-
-		commit = get_commit(e, full_name);
-		if (!commit) {
-			warning("%s: Unexpected object of type %s, skipping.",
-				e->name,
-				type_name(e->item->type));
-			continue;
-		}
-
-		switch(commit->object.type) {
-		case OBJ_COMMIT:
-			break;
-		case OBJ_BLOB:
-			export_blob(&commit->object.oid);
-			continue;
-		default: /* OBJ_TAG (nested tags) is already handled */
-			warning("Tag points to object of unexpected type %s, skipping.",
-				type_name(commit->object.type));
-			continue;
-		}
-
-		/*
-		 * Make sure this ref gets properly updated eventually, whether
-		 * through a commit or manually at the end.
-		 */
-		if (e->item->type != OBJ_TAG)
-			string_list_append(&extra_refs, full_name)->util = commit;
-
-		if (!*revision_sources_at(&revision_sources, commit))
-			*revision_sources_at(&revision_sources, commit) = full_name;
-	}
-
-	string_list_sort(&extra_refs);
-	string_list_remove_duplicates(&extra_refs, 0);
-}
-
-static void handle_tags_and_duplicates(struct string_list *extras)
-{
-	struct commit *commit;
-	int i;
-
-	for (i = extras->nr - 1; i >= 0; i--) {
-		const char *name = extras->items[i].string;
-		struct object *object = extras->items[i].util;
-		int mark;
-
-		switch (object->type) {
-		case OBJ_TAG:
-			handle_tag(name, (struct tag *)object);
-			break;
-		case OBJ_COMMIT:
-			if (anonymize)
-				name = anonymize_refname(name);
-			/* create refs pointing to already seen commits */
-			commit = rewrite_commit((struct commit *)object);
-			if (!commit) {
-				/*
-				 * Neither this object nor any of its
-				 * ancestors touch any relevant paths, so
-				 * it has been filtered to nothing.  Delete
-				 * it.
-				 */
-				printf("reset %s\nfrom %s\n\n",
-				       name, oid_to_hex(&null_oid));
-				continue;
-			}
-
-			mark = get_object_mark(&commit->object);
-			if (!mark) {
-				/*
-				 * Getting here means we have a commit which
-				 * was excluded by a negative refspec (e.g.
-				 * fast-export ^HEAD HEAD).  If we are
-				 * referencing excluded commits, set the ref
-				 * to the exact commit.  Otherwise, the user
-				 * wants the branch exported but every commit
-				 * in its history to be deleted, which basically
-				 * just means deletion of the ref.
-				 */
-				if (!reference_excluded_commits) {
-					/* delete the ref */
-					printf("reset %s\nfrom %s\n\n",
-					       name, oid_to_hex(&null_oid));
-					continue;
-				}
-				/* set ref to commit using oid, not mark */
-				printf("reset %s\nfrom %s\n\n", name,
-				       oid_to_hex(&commit->object.oid));
-				continue;
-			}
-
-			printf("reset %s\nfrom :%d\n\n", name, mark
-			       );
-			show_progress();
-			break;
-		}
-	}
-}
-
-static void export_marks(char *file)
-{
-	unsigned int i;
-	uint32_t mark;
-	struct decoration_entry *deco = idnums.entries;
-	FILE *f;
-	int e = 0;
-
-	f = fopen_for_writing(file);
-	if (!f)
-		die_errno("Unable to open marks file %s for writing.", file);
-
-	for (i = 0; i < idnums.size; i++) {
-		if (deco->base && deco->base->type == 1) {
-			mark = ptr_to_mark(deco->decoration);
-			if (fprintf(f, ":%"PRIu32" %s\n", mark,
-				oid_to_hex(&deco->base->oid)) < 0) {
-			    e = 1;
-			    break;
-			}
-		}
-		deco++;
-	}
-
-	e |= ferror(f);
-	e |= fclose(f);
-	if (e)
-		error("Unable to write marks file %s.", file);
-}
-
-static void import_marks(char *input_file, int check_exists)
-{
-	char line[512];
-	FILE *f;
-	struct stat sb;
-
-	if (check_exists && stat(input_file, &sb))
-		return;
-
-	f = xfopen(input_file, "r");
-	while (fgets(line, sizeof(line), f)) {
-		uint32_t mark;
-		char *line_end, *mark_end;
-		struct object_id oid;
-		struct object *object;
-		struct commit *commit;
-		enum object_type type;
-
-		line_end = strchr(line, '\n');
-		if (line[0] != ':' || !line_end)
-			die("corrupt mark line: %s", line);
-		*line_end = '\0';
-
-		mark = strtoumax(line + 1, &mark_end, 10);
-		if (!mark || mark_end == line + 1
-			|| *mark_end != ' ' || get_oid_hex(mark_end + 1, &oid))
-			die("corrupt mark line: %s", line);
-
-		if (last_idnum < mark)
-			last_idnum = mark;
-
-		type = oid_object_info(the_repository, &oid, NULL);
-		if (type < 0)
-			die("object not found: %s", oid_to_hex(&oid));
-
-		if (type != OBJ_COMMIT)
-			/* only commits */
-			continue;
-
-		commit = lookup_commit(the_repository, &oid);
-		if (!commit)
-			die("not a commit? can't happen: %s", oid_to_hex(&oid));
-
-		object = &commit->object;
-
-		if (object->flags & SHOWN)
-			error("Object %s already has a mark", oid_to_hex(&oid));
-
-		mark_object(object, mark);
-
-		object->flags |= SHOWN;
-	}
-	fclose(f);
-}
-
-static void handle_deletes(void)
-{
-	int i;
-	for (i = 0; i < refspecs.nr; i++) {
-		struct refspec_item *refspec = &refspecs.items[i];
-		if (*refspec->src)
-			continue;
-
-		printf("reset %s\nfrom %s\n\n",
-				refspec->dst, oid_to_hex(&null_oid));
-	}
-}
-
-static char *anonymize_seed(void *data)
-{
-	return xstrdup(data);
-}
-
-static int parse_opt_anonymize_map(const struct option *opt,
-				   const char *arg, int unset)
-{
-	struct hashmap *map = opt->value;
-	const char *delim, *value;
-	size_t keylen;
-
-	BUG_ON_OPT_NEG(unset);
-
-	delim = strchr(arg, ':');
-	if (delim) {
-		keylen = delim - arg;
-		value = delim + 1;
-	} else {
-		keylen = strlen(arg);
-		value = arg;
-	}
-
-	if (!keylen || !*value)
-		return error(_("--anonymize-map token cannot be empty"));
-
-	anonymize_str(map, anonymize_seed, arg, keylen, (void *)value);
-
-	return 0;
-}
-
-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;
-	uint32_t lastimportid;
-	struct string_list refspecs_list = STRING_LIST_INIT_NODUP;
-	struct string_list paths_of_changed_objects = STRING_LIST_INIT_DUP;
-	struct option options[] = {
-		OPT_INTEGER(0, "progress", &progress,
-			    N_("show progress after <n> objects")),
-		OPT_CALLBACK(0, "signed-tags", &signed_tag_mode, N_("mode"),
-			     N_("select handling of signed tags"),
-			     parse_opt_signed_tag_mode),
-		OPT_CALLBACK(0, "tag-of-filtered-object", &tag_of_filtered_mode, N_("mode"),
-			     N_("select handling of tags that tag filtered objects"),
-			     parse_opt_tag_of_filtered_mode),
-		OPT_CALLBACK(0, "reencode", &reencode_mode, N_("mode"),
-			     N_("select handling of commit messages in an alternate encoding"),
-			     parse_opt_reencode_mode),
-		OPT_STRING(0, "export-marks", &export_filename, N_("file"),
-			     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,
-			 N_("Output full tree for each commit")),
-		OPT_BOOL(0, "use-done-feature", &use_done_feature,
-			     N_("Use the done feature to terminate the stream")),
-		OPT_BOOL(0, "no-data", &no_data, N_("Skip output of blob data")),
-		OPT_STRING_LIST(0, "refspec", &refspecs_list, N_("refspec"),
-			     N_("Apply refspec to exported refs")),
-		OPT_BOOL(0, "anonymize", &anonymize, N_("anonymize output")),
-		OPT_CALLBACK_F(0, "anonymize-map", &anonymized_seeds, N_("from:to"),
-			       N_("convert <from> to <to> in anonymized output"),
-			       PARSE_OPT_NONEG, parse_opt_anonymize_map),
-		OPT_BOOL(0, "reference-excluded-parents",
-			 &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()
-	};
-
-	if (argc == 1)
-		usage_with_options (fast_export_usage, options);
-
-	/* we handle encodings */
-	git_config(git_default_config, NULL);
-
-	repo_init_revisions(the_repository, &revs, prefix);
-	init_revision_sources(&revision_sources);
-	revs.topo_order = 1;
-	revs.sources = &revision_sources;
-	revs.rewrite_parents = 1;
-	argc = parse_options(argc, argv, prefix, options, fast_export_usage,
-			PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN);
-	argc = setup_revisions(argc, argv, &revs, NULL);
-	if (argc > 1)
-		usage_with_options (fast_export_usage, options);
-
-	if (anonymized_seeds.cmpfn && !anonymize)
-		die(_("--anonymize-map without --anonymize does not make sense"));
-
-	if (refspecs_list.nr) {
-		int i;
-
-		for (i = 0; i < refspecs_list.nr; i++)
-			refspec_append(&refspecs, refspecs_list.items[i].string);
-
-		string_list_clear(&refspecs_list, 1);
-	}
-
-	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);
-	lastimportid = last_idnum;
-
-	if (import_filename && revs.prune_data.nr)
-		full_tree = 1;
-
-	get_tags_and_duplicates(&revs.cmdline);
-
-	if (prepare_revision_walk(&revs))
-		die("revision walk setup failed");
-	revs.diffopt.format_callback = show_filemodify;
-	revs.diffopt.format_callback_data = &paths_of_changed_objects;
-	revs.diffopt.flags.recursive = 1;
-	while ((commit = get_revision(&revs))) {
-		if (has_unshown_parent(commit)) {
-			add_object_array(&commit->object, NULL, &commits);
-		}
-		else {
-			handle_commit(commit, &revs, &paths_of_changed_objects);
-			handle_tail(&commits, &revs, &paths_of_changed_objects);
-		}
-	}
-
-	handle_tags_and_duplicates(&extra_refs);
-	handle_tags_and_duplicates(&tag_refs);
-	handle_deletes();
-
-	if (export_filename && lastimportid != last_idnum)
-		export_marks(export_filename);
-
-	if (use_done_feature)
-		printf("done\n");
-
-	refspec_clear(&refspecs);
-
-	return 0;
-}
diff --git a/third_party/git/builtin/fast-import.c b/third_party/git/builtin/fast-import.c
deleted file mode 100644
index 1bf50a73dc35..000000000000
--- a/third_party/git/builtin/fast-import.c
+++ /dev/null
@@ -1,3634 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "repository.h"
-#include "config.h"
-#include "lockfile.h"
-#include "object.h"
-#include "blob.h"
-#include "tree.h"
-#include "commit.h"
-#include "delta.h"
-#include "pack.h"
-#include "refs.h"
-#include "csum-file.h"
-#include "quote.h"
-#include "dir.h"
-#include "run-command.h"
-#include "packfile.h"
-#include "object-store.h"
-#include "mem-pool.h"
-#include "commit-reach.h"
-#include "khash.h"
-
-#define PACK_ID_BITS 16
-#define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)
-#define DEPTH_BITS 13
-#define MAX_DEPTH ((1<<DEPTH_BITS)-1)
-
-/*
- * We abuse the setuid bit on directories to mean "do not delta".
- */
-#define NO_DELTA S_ISUID
-
-/*
- * The amount of additional space required in order to write an object into the
- * current pack. This is the hash lengths at the end of the pack, plus the
- * length of one object ID.
- */
-#define PACK_SIZE_THRESHOLD (the_hash_algo->rawsz * 3)
-
-struct object_entry {
-	struct pack_idx_entry idx;
-	struct hashmap_entry ent;
-	uint32_t type : TYPE_BITS,
-		pack_id : PACK_ID_BITS,
-		depth : DEPTH_BITS;
-};
-
-static int object_entry_hashcmp(const void *map_data,
-				const struct hashmap_entry *eptr,
-				const struct hashmap_entry *entry_or_key,
-				const void *keydata)
-{
-	const struct object_id *oid = keydata;
-	const struct object_entry *e1, *e2;
-
-	e1 = container_of(eptr, const struct object_entry, ent);
-	if (oid)
-		return oidcmp(&e1->idx.oid, oid);
-
-	e2 = container_of(entry_or_key, const struct object_entry, ent);
-	return oidcmp(&e1->idx.oid, &e2->idx.oid);
-}
-
-struct object_entry_pool {
-	struct object_entry_pool *next_pool;
-	struct object_entry *next_free;
-	struct object_entry *end;
-	struct object_entry entries[FLEX_ARRAY]; /* more */
-};
-
-struct mark_set {
-	union {
-		struct object_id *oids[1024];
-		struct object_entry *marked[1024];
-		struct mark_set *sets[1024];
-	} data;
-	unsigned int shift;
-};
-
-struct last_object {
-	struct strbuf data;
-	off_t offset;
-	unsigned int depth;
-	unsigned no_swap : 1;
-};
-
-struct atom_str {
-	struct atom_str *next_atom;
-	unsigned short str_len;
-	char str_dat[FLEX_ARRAY]; /* more */
-};
-
-struct tree_content;
-struct tree_entry {
-	struct tree_content *tree;
-	struct atom_str *name;
-	struct tree_entry_ms {
-		uint16_t mode;
-		struct object_id oid;
-	} versions[2];
-};
-
-struct tree_content {
-	unsigned int entry_capacity; /* must match avail_tree_content */
-	unsigned int entry_count;
-	unsigned int delta_depth;
-	struct tree_entry *entries[FLEX_ARRAY]; /* more */
-};
-
-struct avail_tree_content {
-	unsigned int entry_capacity; /* must match tree_content */
-	struct avail_tree_content *next_avail;
-};
-
-struct branch {
-	struct branch *table_next_branch;
-	struct branch *active_next_branch;
-	const char *name;
-	struct tree_entry branch_tree;
-	uintmax_t last_commit;
-	uintmax_t num_notes;
-	unsigned active : 1;
-	unsigned delete : 1;
-	unsigned pack_id : PACK_ID_BITS;
-	struct object_id oid;
-};
-
-struct tag {
-	struct tag *next_tag;
-	const char *name;
-	unsigned int pack_id;
-	struct object_id oid;
-};
-
-struct hash_list {
-	struct hash_list *next;
-	struct object_id oid;
-};
-
-typedef enum {
-	WHENSPEC_RAW = 1,
-	WHENSPEC_RAW_PERMISSIVE,
-	WHENSPEC_RFC2822,
-	WHENSPEC_NOW
-} whenspec_type;
-
-struct recent_command {
-	struct recent_command *prev;
-	struct recent_command *next;
-	char *buf;
-};
-
-typedef void (*mark_set_inserter_t)(struct mark_set *s, struct object_id *oid, uintmax_t mark);
-typedef void (*each_mark_fn_t)(uintmax_t mark, void *obj, void *cbp);
-
-/* Configured limits on output */
-static unsigned long max_depth = 50;
-static off_t max_packsize;
-static int unpack_limit = 100;
-static int force_update;
-
-/* Stats and misc. counters */
-static uintmax_t alloc_count;
-static uintmax_t marks_set_count;
-static uintmax_t object_count_by_type[1 << TYPE_BITS];
-static uintmax_t duplicate_count_by_type[1 << TYPE_BITS];
-static uintmax_t delta_count_by_type[1 << TYPE_BITS];
-static uintmax_t delta_count_attempts_by_type[1 << TYPE_BITS];
-static unsigned long object_count;
-static unsigned long branch_count;
-static unsigned long branch_load_count;
-static int failure;
-static FILE *pack_edges;
-static unsigned int show_stats = 1;
-static int global_argc;
-static const char **global_argv;
-
-/* Memory pools */
-static struct mem_pool fi_mem_pool =  {NULL, 2*1024*1024 -
-				       sizeof(struct mp_block), 0 };
-
-/* Atom management */
-static unsigned int atom_table_sz = 4451;
-static unsigned int atom_cnt;
-static struct atom_str **atom_table;
-
-/* The .pack file being generated */
-static struct pack_idx_option pack_idx_opts;
-static unsigned int pack_id;
-static struct hashfile *pack_file;
-static struct packed_git *pack_data;
-static struct packed_git **all_packs;
-static off_t pack_size;
-
-/* Table of objects we've written. */
-static unsigned int object_entry_alloc = 5000;
-static struct object_entry_pool *blocks;
-static struct hashmap object_table;
-static struct mark_set *marks;
-static const char *export_marks_file;
-static const char *import_marks_file;
-static int import_marks_file_from_stream;
-static int import_marks_file_ignore_missing;
-static int import_marks_file_done;
-static int relative_marks_paths;
-
-/* Our last blob */
-static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };
-
-/* Tree management */
-static unsigned int tree_entry_alloc = 1000;
-static void *avail_tree_entry;
-static unsigned int avail_tree_table_sz = 100;
-static struct avail_tree_content **avail_tree_table;
-static size_t tree_entry_allocd;
-static struct strbuf old_tree = STRBUF_INIT;
-static struct strbuf new_tree = STRBUF_INIT;
-
-/* Branch data */
-static unsigned long max_active_branches = 5;
-static unsigned long cur_active_branches;
-static unsigned long branch_table_sz = 1039;
-static struct branch **branch_table;
-static struct branch *active_branches;
-
-/* Tag data */
-static struct tag *first_tag;
-static struct tag *last_tag;
-
-/* Input stream parsing */
-static whenspec_type whenspec = WHENSPEC_RAW;
-static struct strbuf command_buf = STRBUF_INIT;
-static int unread_command_buf;
-static struct recent_command cmd_hist = {&cmd_hist, &cmd_hist, NULL};
-static struct recent_command *cmd_tail = &cmd_hist;
-static struct recent_command *rc_free;
-static unsigned int cmd_save = 100;
-static uintmax_t next_mark;
-static struct strbuf new_data = STRBUF_INIT;
-static int seen_data_command;
-static int require_explicit_termination;
-static int allow_unsafe_features;
-
-/* Signal handling */
-static volatile sig_atomic_t checkpoint_requested;
-
-/* Submodule marks */
-static struct string_list sub_marks_from = STRING_LIST_INIT_DUP;
-static struct string_list sub_marks_to = STRING_LIST_INIT_DUP;
-static kh_oid_map_t *sub_oid_map;
-
-/* Where to write output of cat-blob commands */
-static int cat_blob_fd = STDOUT_FILENO;
-
-static void parse_argv(void);
-static void parse_get_mark(const char *p);
-static void parse_cat_blob(const char *p);
-static void parse_ls(const char *p, struct branch *b);
-
-static void for_each_mark(struct mark_set *m, uintmax_t base, each_mark_fn_t callback, void *p)
-{
-	uintmax_t k;
-	if (m->shift) {
-		for (k = 0; k < 1024; k++) {
-			if (m->data.sets[k])
-				for_each_mark(m->data.sets[k], base + (k << m->shift), callback, p);
-		}
-	} else {
-		for (k = 0; k < 1024; k++) {
-			if (m->data.marked[k])
-				callback(base + k, m->data.marked[k], p);
-		}
-	}
-}
-
-static void dump_marks_fn(uintmax_t mark, void *object, void *cbp) {
-	struct object_entry *e = object;
-	FILE *f = cbp;
-
-	fprintf(f, ":%" PRIuMAX " %s\n", mark, oid_to_hex(&e->idx.oid));
-}
-
-static void write_branch_report(FILE *rpt, struct branch *b)
-{
-	fprintf(rpt, "%s:\n", b->name);
-
-	fprintf(rpt, "  status      :");
-	if (b->active)
-		fputs(" active", rpt);
-	if (b->branch_tree.tree)
-		fputs(" loaded", rpt);
-	if (is_null_oid(&b->branch_tree.versions[1].oid))
-		fputs(" dirty", rpt);
-	fputc('\n', rpt);
-
-	fprintf(rpt, "  tip commit  : %s\n", oid_to_hex(&b->oid));
-	fprintf(rpt, "  old tree    : %s\n",
-		oid_to_hex(&b->branch_tree.versions[0].oid));
-	fprintf(rpt, "  cur tree    : %s\n",
-		oid_to_hex(&b->branch_tree.versions[1].oid));
-	fprintf(rpt, "  commit clock: %" PRIuMAX "\n", b->last_commit);
-
-	fputs("  last pack   : ", rpt);
-	if (b->pack_id < MAX_PACK_ID)
-		fprintf(rpt, "%u", b->pack_id);
-	fputc('\n', rpt);
-
-	fputc('\n', rpt);
-}
-
-static void write_crash_report(const char *err)
-{
-	char *loc = git_pathdup("fast_import_crash_%"PRIuMAX, (uintmax_t) getpid());
-	FILE *rpt = fopen(loc, "w");
-	struct branch *b;
-	unsigned long lu;
-	struct recent_command *rc;
-
-	if (!rpt) {
-		error_errno("can't write crash report %s", loc);
-		free(loc);
-		return;
-	}
-
-	fprintf(stderr, "fast-import: dumping crash report to %s\n", loc);
-
-	fprintf(rpt, "fast-import crash report:\n");
-	fprintf(rpt, "    fast-import process: %"PRIuMAX"\n", (uintmax_t) getpid());
-	fprintf(rpt, "    parent process     : %"PRIuMAX"\n", (uintmax_t) getppid());
-	fprintf(rpt, "    at %s\n", show_date(time(NULL), 0, DATE_MODE(ISO8601)));
-	fputc('\n', rpt);
-
-	fputs("fatal: ", rpt);
-	fputs(err, rpt);
-	fputc('\n', rpt);
-
-	fputc('\n', rpt);
-	fputs("Most Recent Commands Before Crash\n", rpt);
-	fputs("---------------------------------\n", rpt);
-	for (rc = cmd_hist.next; rc != &cmd_hist; rc = rc->next) {
-		if (rc->next == &cmd_hist)
-			fputs("* ", rpt);
-		else
-			fputs("  ", rpt);
-		fputs(rc->buf, rpt);
-		fputc('\n', rpt);
-	}
-
-	fputc('\n', rpt);
-	fputs("Active Branch LRU\n", rpt);
-	fputs("-----------------\n", rpt);
-	fprintf(rpt, "    active_branches = %lu cur, %lu max\n",
-		cur_active_branches,
-		max_active_branches);
-	fputc('\n', rpt);
-	fputs("  pos  clock name\n", rpt);
-	fputs("  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", rpt);
-	for (b = active_branches, lu = 0; b; b = b->active_next_branch)
-		fprintf(rpt, "  %2lu) %6" PRIuMAX" %s\n",
-			++lu, b->last_commit, b->name);
-
-	fputc('\n', rpt);
-	fputs("Inactive Branches\n", rpt);
-	fputs("-----------------\n", rpt);
-	for (lu = 0; lu < branch_table_sz; lu++) {
-		for (b = branch_table[lu]; b; b = b->table_next_branch)
-			write_branch_report(rpt, b);
-	}
-
-	if (first_tag) {
-		struct tag *tg;
-		fputc('\n', rpt);
-		fputs("Annotated Tags\n", rpt);
-		fputs("--------------\n", rpt);
-		for (tg = first_tag; tg; tg = tg->next_tag) {
-			fputs(oid_to_hex(&tg->oid), rpt);
-			fputc(' ', rpt);
-			fputs(tg->name, rpt);
-			fputc('\n', rpt);
-		}
-	}
-
-	fputc('\n', rpt);
-	fputs("Marks\n", rpt);
-	fputs("-----\n", rpt);
-	if (export_marks_file)
-		fprintf(rpt, "  exported to %s\n", export_marks_file);
-	else
-		for_each_mark(marks, 0, dump_marks_fn, rpt);
-
-	fputc('\n', rpt);
-	fputs("-------------------\n", rpt);
-	fputs("END OF CRASH REPORT\n", rpt);
-	fclose(rpt);
-	free(loc);
-}
-
-static void end_packfile(void);
-static void unkeep_all_packs(void);
-static void dump_marks(void);
-
-static NORETURN void die_nicely(const char *err, va_list params)
-{
-	static int zombie;
-	char message[2 * PATH_MAX];
-
-	vsnprintf(message, sizeof(message), err, params);
-	fputs("fatal: ", stderr);
-	fputs(message, stderr);
-	fputc('\n', stderr);
-
-	if (!zombie) {
-		zombie = 1;
-		write_crash_report(message);
-		end_packfile();
-		unkeep_all_packs();
-		dump_marks();
-	}
-	exit(128);
-}
-
-#ifndef SIGUSR1	/* Windows, for example */
-
-static void set_checkpoint_signal(void)
-{
-}
-
-#else
-
-static void checkpoint_signal(int signo)
-{
-	checkpoint_requested = 1;
-}
-
-static void set_checkpoint_signal(void)
-{
-	struct sigaction sa;
-
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = checkpoint_signal;
-	sigemptyset(&sa.sa_mask);
-	sa.sa_flags = SA_RESTART;
-	sigaction(SIGUSR1, &sa, NULL);
-}
-
-#endif
-
-static void alloc_objects(unsigned int cnt)
-{
-	struct object_entry_pool *b;
-
-	b = xmalloc(sizeof(struct object_entry_pool)
-		+ cnt * sizeof(struct object_entry));
-	b->next_pool = blocks;
-	b->next_free = b->entries;
-	b->end = b->entries + cnt;
-	blocks = b;
-	alloc_count += cnt;
-}
-
-static struct object_entry *new_object(struct object_id *oid)
-{
-	struct object_entry *e;
-
-	if (blocks->next_free == blocks->end)
-		alloc_objects(object_entry_alloc);
-
-	e = blocks->next_free++;
-	oidcpy(&e->idx.oid, oid);
-	return e;
-}
-
-static struct object_entry *find_object(struct object_id *oid)
-{
-	return hashmap_get_entry_from_hash(&object_table, oidhash(oid), oid,
-					   struct object_entry, ent);
-}
-
-static struct object_entry *insert_object(struct object_id *oid)
-{
-	struct object_entry *e;
-	unsigned int hash = oidhash(oid);
-
-	e = hashmap_get_entry_from_hash(&object_table, hash, oid,
-					struct object_entry, ent);
-	if (!e) {
-		e = new_object(oid);
-		e->idx.offset = 0;
-		hashmap_entry_init(&e->ent, hash);
-		hashmap_add(&object_table, &e->ent);
-	}
-
-	return e;
-}
-
-static void invalidate_pack_id(unsigned int id)
-{
-	unsigned long lu;
-	struct tag *t;
-	struct hashmap_iter iter;
-	struct object_entry *e;
-
-	hashmap_for_each_entry(&object_table, &iter, e, ent) {
-		if (e->pack_id == id)
-			e->pack_id = MAX_PACK_ID;
-	}
-
-	for (lu = 0; lu < branch_table_sz; lu++) {
-		struct branch *b;
-
-		for (b = branch_table[lu]; b; b = b->table_next_branch)
-			if (b->pack_id == id)
-				b->pack_id = MAX_PACK_ID;
-	}
-
-	for (t = first_tag; t; t = t->next_tag)
-		if (t->pack_id == id)
-			t->pack_id = MAX_PACK_ID;
-}
-
-static unsigned int hc_str(const char *s, size_t len)
-{
-	unsigned int r = 0;
-	while (len-- > 0)
-		r = r * 31 + *s++;
-	return r;
-}
-
-static void insert_mark(struct mark_set *s, uintmax_t idnum, struct object_entry *oe)
-{
-	while ((idnum >> s->shift) >= 1024) {
-		s = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct mark_set));
-		s->shift = marks->shift + 10;
-		s->data.sets[0] = marks;
-		marks = s;
-	}
-	while (s->shift) {
-		uintmax_t i = idnum >> s->shift;
-		idnum -= i << s->shift;
-		if (!s->data.sets[i]) {
-			s->data.sets[i] = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct mark_set));
-			s->data.sets[i]->shift = s->shift - 10;
-		}
-		s = s->data.sets[i];
-	}
-	if (!s->data.marked[idnum])
-		marks_set_count++;
-	s->data.marked[idnum] = oe;
-}
-
-static void *find_mark(struct mark_set *s, uintmax_t idnum)
-{
-	uintmax_t orig_idnum = idnum;
-	struct object_entry *oe = NULL;
-	if ((idnum >> s->shift) < 1024) {
-		while (s && s->shift) {
-			uintmax_t i = idnum >> s->shift;
-			idnum -= i << s->shift;
-			s = s->data.sets[i];
-		}
-		if (s)
-			oe = s->data.marked[idnum];
-	}
-	if (!oe)
-		die("mark :%" PRIuMAX " not declared", orig_idnum);
-	return oe;
-}
-
-static struct atom_str *to_atom(const char *s, unsigned short len)
-{
-	unsigned int hc = hc_str(s, len) % atom_table_sz;
-	struct atom_str *c;
-
-	for (c = atom_table[hc]; c; c = c->next_atom)
-		if (c->str_len == len && !strncmp(s, c->str_dat, len))
-			return c;
-
-	c = mem_pool_alloc(&fi_mem_pool, sizeof(struct atom_str) + len + 1);
-	c->str_len = len;
-	memcpy(c->str_dat, s, len);
-	c->str_dat[len] = 0;
-	c->next_atom = atom_table[hc];
-	atom_table[hc] = c;
-	atom_cnt++;
-	return c;
-}
-
-static struct branch *lookup_branch(const char *name)
-{
-	unsigned int hc = hc_str(name, strlen(name)) % branch_table_sz;
-	struct branch *b;
-
-	for (b = branch_table[hc]; b; b = b->table_next_branch)
-		if (!strcmp(name, b->name))
-			return b;
-	return NULL;
-}
-
-static struct branch *new_branch(const char *name)
-{
-	unsigned int hc = hc_str(name, strlen(name)) % branch_table_sz;
-	struct branch *b = lookup_branch(name);
-
-	if (b)
-		die("Invalid attempt to create duplicate branch: %s", name);
-	if (check_refname_format(name, REFNAME_ALLOW_ONELEVEL))
-		die("Branch name doesn't conform to GIT standards: %s", name);
-
-	b = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct branch));
-	b->name = mem_pool_strdup(&fi_mem_pool, name);
-	b->table_next_branch = branch_table[hc];
-	b->branch_tree.versions[0].mode = S_IFDIR;
-	b->branch_tree.versions[1].mode = S_IFDIR;
-	b->num_notes = 0;
-	b->active = 0;
-	b->pack_id = MAX_PACK_ID;
-	branch_table[hc] = b;
-	branch_count++;
-	return b;
-}
-
-static unsigned int hc_entries(unsigned int cnt)
-{
-	cnt = cnt & 7 ? (cnt / 8) + 1 : cnt / 8;
-	return cnt < avail_tree_table_sz ? cnt : avail_tree_table_sz - 1;
-}
-
-static struct tree_content *new_tree_content(unsigned int cnt)
-{
-	struct avail_tree_content *f, *l = NULL;
-	struct tree_content *t;
-	unsigned int hc = hc_entries(cnt);
-
-	for (f = avail_tree_table[hc]; f; l = f, f = f->next_avail)
-		if (f->entry_capacity >= cnt)
-			break;
-
-	if (f) {
-		if (l)
-			l->next_avail = f->next_avail;
-		else
-			avail_tree_table[hc] = f->next_avail;
-	} else {
-		cnt = cnt & 7 ? ((cnt / 8) + 1) * 8 : cnt;
-		f = mem_pool_alloc(&fi_mem_pool, sizeof(*t) + sizeof(t->entries[0]) * cnt);
-		f->entry_capacity = cnt;
-	}
-
-	t = (struct tree_content*)f;
-	t->entry_count = 0;
-	t->delta_depth = 0;
-	return t;
-}
-
-static void release_tree_entry(struct tree_entry *e);
-static void release_tree_content(struct tree_content *t)
-{
-	struct avail_tree_content *f = (struct avail_tree_content*)t;
-	unsigned int hc = hc_entries(f->entry_capacity);
-	f->next_avail = avail_tree_table[hc];
-	avail_tree_table[hc] = f;
-}
-
-static void release_tree_content_recursive(struct tree_content *t)
-{
-	unsigned int i;
-	for (i = 0; i < t->entry_count; i++)
-		release_tree_entry(t->entries[i]);
-	release_tree_content(t);
-}
-
-static struct tree_content *grow_tree_content(
-	struct tree_content *t,
-	int amt)
-{
-	struct tree_content *r = new_tree_content(t->entry_count + amt);
-	r->entry_count = t->entry_count;
-	r->delta_depth = t->delta_depth;
-	COPY_ARRAY(r->entries, t->entries, t->entry_count);
-	release_tree_content(t);
-	return r;
-}
-
-static struct tree_entry *new_tree_entry(void)
-{
-	struct tree_entry *e;
-
-	if (!avail_tree_entry) {
-		unsigned int n = tree_entry_alloc;
-		tree_entry_allocd += n * sizeof(struct tree_entry);
-		ALLOC_ARRAY(e, n);
-		avail_tree_entry = e;
-		while (n-- > 1) {
-			*((void**)e) = e + 1;
-			e++;
-		}
-		*((void**)e) = NULL;
-	}
-
-	e = avail_tree_entry;
-	avail_tree_entry = *((void**)e);
-	return e;
-}
-
-static void release_tree_entry(struct tree_entry *e)
-{
-	if (e->tree)
-		release_tree_content_recursive(e->tree);
-	*((void**)e) = avail_tree_entry;
-	avail_tree_entry = e;
-}
-
-static struct tree_content *dup_tree_content(struct tree_content *s)
-{
-	struct tree_content *d;
-	struct tree_entry *a, *b;
-	unsigned int i;
-
-	if (!s)
-		return NULL;
-	d = new_tree_content(s->entry_count);
-	for (i = 0; i < s->entry_count; i++) {
-		a = s->entries[i];
-		b = new_tree_entry();
-		memcpy(b, a, sizeof(*a));
-		if (a->tree && is_null_oid(&b->versions[1].oid))
-			b->tree = dup_tree_content(a->tree);
-		else
-			b->tree = NULL;
-		d->entries[i] = b;
-	}
-	d->entry_count = s->entry_count;
-	d->delta_depth = s->delta_depth;
-
-	return d;
-}
-
-static void start_packfile(void)
-{
-	struct strbuf tmp_file = STRBUF_INIT;
-	struct packed_git *p;
-	int pack_fd;
-
-	pack_fd = odb_mkstemp(&tmp_file, "pack/tmp_pack_XXXXXX");
-	FLEX_ALLOC_STR(p, pack_name, tmp_file.buf);
-	strbuf_release(&tmp_file);
-
-	p->pack_fd = pack_fd;
-	p->do_not_close = 1;
-	pack_file = hashfd(pack_fd, p->pack_name);
-
-	pack_data = p;
-	pack_size = write_pack_header(pack_file, 0);
-	object_count = 0;
-
-	REALLOC_ARRAY(all_packs, pack_id + 1);
-	all_packs[pack_id] = p;
-}
-
-static const char *create_index(void)
-{
-	const char *tmpfile;
-	struct pack_idx_entry **idx, **c, **last;
-	struct object_entry *e;
-	struct object_entry_pool *o;
-
-	/* Build the table of object IDs. */
-	ALLOC_ARRAY(idx, object_count);
-	c = idx;
-	for (o = blocks; o; o = o->next_pool)
-		for (e = o->next_free; e-- != o->entries;)
-			if (pack_id == e->pack_id)
-				*c++ = &e->idx;
-	last = idx + object_count;
-	if (c != last)
-		die("internal consistency error creating the index");
-
-	tmpfile = write_idx_file(NULL, idx, object_count, &pack_idx_opts,
-				 pack_data->hash);
-	free(idx);
-	return tmpfile;
-}
-
-static char *keep_pack(const char *curr_index_name)
-{
-	static const char *keep_msg = "fast-import";
-	struct strbuf name = STRBUF_INIT;
-	int keep_fd;
-
-	odb_pack_name(&name, pack_data->hash, "keep");
-	keep_fd = odb_pack_keep(name.buf);
-	if (keep_fd < 0)
-		die_errno("cannot create keep file");
-	write_or_die(keep_fd, keep_msg, strlen(keep_msg));
-	if (close(keep_fd))
-		die_errno("failed to write keep file");
-
-	odb_pack_name(&name, pack_data->hash, "pack");
-	if (finalize_object_file(pack_data->pack_name, name.buf))
-		die("cannot store pack file");
-
-	odb_pack_name(&name, pack_data->hash, "idx");
-	if (finalize_object_file(curr_index_name, name.buf))
-		die("cannot store index file");
-	free((void *)curr_index_name);
-	return strbuf_detach(&name, NULL);
-}
-
-static void unkeep_all_packs(void)
-{
-	struct strbuf name = STRBUF_INIT;
-	int k;
-
-	for (k = 0; k < pack_id; k++) {
-		struct packed_git *p = all_packs[k];
-		odb_pack_name(&name, p->hash, "keep");
-		unlink_or_warn(name.buf);
-	}
-	strbuf_release(&name);
-}
-
-static int loosen_small_pack(const struct packed_git *p)
-{
-	struct child_process unpack = CHILD_PROCESS_INIT;
-
-	if (lseek(p->pack_fd, 0, SEEK_SET) < 0)
-		die_errno("Failed seeking to start of '%s'", p->pack_name);
-
-	unpack.in = p->pack_fd;
-	unpack.git_cmd = 1;
-	unpack.stdout_to_stderr = 1;
-	strvec_push(&unpack.args, "unpack-objects");
-	if (!show_stats)
-		strvec_push(&unpack.args, "-q");
-
-	return run_command(&unpack);
-}
-
-static void end_packfile(void)
-{
-	static int running;
-
-	if (running || !pack_data)
-		return;
-
-	running = 1;
-	clear_delta_base_cache();
-	if (object_count) {
-		struct packed_git *new_p;
-		struct object_id cur_pack_oid;
-		char *idx_name;
-		int i;
-		struct branch *b;
-		struct tag *t;
-
-		close_pack_windows(pack_data);
-		finalize_hashfile(pack_file, cur_pack_oid.hash, 0);
-		fixup_pack_header_footer(pack_data->pack_fd, pack_data->hash,
-					 pack_data->pack_name, object_count,
-					 cur_pack_oid.hash, pack_size);
-
-		if (object_count <= unpack_limit) {
-			if (!loosen_small_pack(pack_data)) {
-				invalidate_pack_id(pack_id);
-				goto discard_pack;
-			}
-		}
-
-		close(pack_data->pack_fd);
-		idx_name = keep_pack(create_index());
-
-		/* Register the packfile with core git's machinery. */
-		new_p = add_packed_git(idx_name, strlen(idx_name), 1);
-		if (!new_p)
-			die("core git rejected index %s", idx_name);
-		all_packs[pack_id] = new_p;
-		install_packed_git(the_repository, new_p);
-		free(idx_name);
-
-		/* Print the boundary */
-		if (pack_edges) {
-			fprintf(pack_edges, "%s:", new_p->pack_name);
-			for (i = 0; i < branch_table_sz; i++) {
-				for (b = branch_table[i]; b; b = b->table_next_branch) {
-					if (b->pack_id == pack_id)
-						fprintf(pack_edges, " %s",
-							oid_to_hex(&b->oid));
-				}
-			}
-			for (t = first_tag; t; t = t->next_tag) {
-				if (t->pack_id == pack_id)
-					fprintf(pack_edges, " %s",
-						oid_to_hex(&t->oid));
-			}
-			fputc('\n', pack_edges);
-			fflush(pack_edges);
-		}
-
-		pack_id++;
-	}
-	else {
-discard_pack:
-		close(pack_data->pack_fd);
-		unlink_or_warn(pack_data->pack_name);
-	}
-	FREE_AND_NULL(pack_data);
-	running = 0;
-
-	/* We can't carry a delta across packfiles. */
-	strbuf_release(&last_blob.data);
-	last_blob.offset = 0;
-	last_blob.depth = 0;
-}
-
-static void cycle_packfile(void)
-{
-	end_packfile();
-	start_packfile();
-}
-
-static int store_object(
-	enum object_type type,
-	struct strbuf *dat,
-	struct last_object *last,
-	struct object_id *oidout,
-	uintmax_t mark)
-{
-	void *out, *delta;
-	struct object_entry *e;
-	unsigned char hdr[96];
-	struct object_id oid;
-	unsigned long hdrlen, deltalen;
-	git_hash_ctx c;
-	git_zstream s;
-
-	hdrlen = xsnprintf((char *)hdr, sizeof(hdr), "%s %lu",
-			   type_name(type), (unsigned long)dat->len) + 1;
-	the_hash_algo->init_fn(&c);
-	the_hash_algo->update_fn(&c, hdr, hdrlen);
-	the_hash_algo->update_fn(&c, dat->buf, dat->len);
-	the_hash_algo->final_fn(oid.hash, &c);
-	if (oidout)
-		oidcpy(oidout, &oid);
-
-	e = insert_object(&oid);
-	if (mark)
-		insert_mark(marks, mark, e);
-	if (e->idx.offset) {
-		duplicate_count_by_type[type]++;
-		return 1;
-	} else if (find_sha1_pack(oid.hash,
-				  get_all_packs(the_repository))) {
-		e->type = type;
-		e->pack_id = MAX_PACK_ID;
-		e->idx.offset = 1; /* just not zero! */
-		duplicate_count_by_type[type]++;
-		return 1;
-	}
-
-	if (last && last->data.len && last->data.buf && last->depth < max_depth
-		&& dat->len > the_hash_algo->rawsz) {
-
-		delta_count_attempts_by_type[type]++;
-		delta = diff_delta(last->data.buf, last->data.len,
-			dat->buf, dat->len,
-			&deltalen, dat->len - the_hash_algo->rawsz);
-	} else
-		delta = NULL;
-
-	git_deflate_init(&s, pack_compression_level);
-	if (delta) {
-		s.next_in = delta;
-		s.avail_in = deltalen;
-	} else {
-		s.next_in = (void *)dat->buf;
-		s.avail_in = dat->len;
-	}
-	s.avail_out = git_deflate_bound(&s, s.avail_in);
-	s.next_out = out = xmalloc(s.avail_out);
-	while (git_deflate(&s, Z_FINISH) == Z_OK)
-		; /* nothing */
-	git_deflate_end(&s);
-
-	/* Determine if we should auto-checkpoint. */
-	if ((max_packsize
-		&& (pack_size + PACK_SIZE_THRESHOLD + s.total_out) > max_packsize)
-		|| (pack_size + PACK_SIZE_THRESHOLD + s.total_out) < pack_size) {
-
-		/* This new object needs to *not* have the current pack_id. */
-		e->pack_id = pack_id + 1;
-		cycle_packfile();
-
-		/* We cannot carry a delta into the new pack. */
-		if (delta) {
-			FREE_AND_NULL(delta);
-
-			git_deflate_init(&s, pack_compression_level);
-			s.next_in = (void *)dat->buf;
-			s.avail_in = dat->len;
-			s.avail_out = git_deflate_bound(&s, s.avail_in);
-			s.next_out = out = xrealloc(out, s.avail_out);
-			while (git_deflate(&s, Z_FINISH) == Z_OK)
-				; /* nothing */
-			git_deflate_end(&s);
-		}
-	}
-
-	e->type = type;
-	e->pack_id = pack_id;
-	e->idx.offset = pack_size;
-	object_count++;
-	object_count_by_type[type]++;
-
-	crc32_begin(pack_file);
-
-	if (delta) {
-		off_t ofs = e->idx.offset - last->offset;
-		unsigned pos = sizeof(hdr) - 1;
-
-		delta_count_by_type[type]++;
-		e->depth = last->depth + 1;
-
-		hdrlen = encode_in_pack_object_header(hdr, sizeof(hdr),
-						      OBJ_OFS_DELTA, deltalen);
-		hashwrite(pack_file, hdr, hdrlen);
-		pack_size += hdrlen;
-
-		hdr[pos] = ofs & 127;
-		while (ofs >>= 7)
-			hdr[--pos] = 128 | (--ofs & 127);
-		hashwrite(pack_file, hdr + pos, sizeof(hdr) - pos);
-		pack_size += sizeof(hdr) - pos;
-	} else {
-		e->depth = 0;
-		hdrlen = encode_in_pack_object_header(hdr, sizeof(hdr),
-						      type, dat->len);
-		hashwrite(pack_file, hdr, hdrlen);
-		pack_size += hdrlen;
-	}
-
-	hashwrite(pack_file, out, s.total_out);
-	pack_size += s.total_out;
-
-	e->idx.crc32 = crc32_end(pack_file);
-
-	free(out);
-	free(delta);
-	if (last) {
-		if (last->no_swap) {
-			last->data = *dat;
-		} else {
-			strbuf_swap(&last->data, dat);
-		}
-		last->offset = e->idx.offset;
-		last->depth = e->depth;
-	}
-	return 0;
-}
-
-static void truncate_pack(struct hashfile_checkpoint *checkpoint)
-{
-	if (hashfile_truncate(pack_file, checkpoint))
-		die_errno("cannot truncate pack to skip duplicate");
-	pack_size = checkpoint->offset;
-}
-
-static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
-{
-	size_t in_sz = 64 * 1024, out_sz = 64 * 1024;
-	unsigned char *in_buf = xmalloc(in_sz);
-	unsigned char *out_buf = xmalloc(out_sz);
-	struct object_entry *e;
-	struct object_id oid;
-	unsigned long hdrlen;
-	off_t offset;
-	git_hash_ctx c;
-	git_zstream s;
-	struct hashfile_checkpoint checkpoint;
-	int status = Z_OK;
-
-	/* Determine if we should auto-checkpoint. */
-	if ((max_packsize
-		&& (pack_size + PACK_SIZE_THRESHOLD + len) > max_packsize)
-		|| (pack_size + PACK_SIZE_THRESHOLD + len) < pack_size)
-		cycle_packfile();
-
-	hashfile_checkpoint(pack_file, &checkpoint);
-	offset = checkpoint.offset;
-
-	hdrlen = xsnprintf((char *)out_buf, out_sz, "blob %" PRIuMAX, len) + 1;
-
-	the_hash_algo->init_fn(&c);
-	the_hash_algo->update_fn(&c, out_buf, hdrlen);
-
-	crc32_begin(pack_file);
-
-	git_deflate_init(&s, pack_compression_level);
-
-	hdrlen = encode_in_pack_object_header(out_buf, out_sz, OBJ_BLOB, len);
-
-	s.next_out = out_buf + hdrlen;
-	s.avail_out = out_sz - hdrlen;
-
-	while (status != Z_STREAM_END) {
-		if (0 < len && !s.avail_in) {
-			size_t cnt = in_sz < len ? in_sz : (size_t)len;
-			size_t n = fread(in_buf, 1, cnt, stdin);
-			if (!n && feof(stdin))
-				die("EOF in data (%" PRIuMAX " bytes remaining)", len);
-
-			the_hash_algo->update_fn(&c, in_buf, n);
-			s.next_in = in_buf;
-			s.avail_in = n;
-			len -= n;
-		}
-
-		status = git_deflate(&s, len ? 0 : Z_FINISH);
-
-		if (!s.avail_out || status == Z_STREAM_END) {
-			size_t n = s.next_out - out_buf;
-			hashwrite(pack_file, out_buf, n);
-			pack_size += n;
-			s.next_out = out_buf;
-			s.avail_out = out_sz;
-		}
-
-		switch (status) {
-		case Z_OK:
-		case Z_BUF_ERROR:
-		case Z_STREAM_END:
-			continue;
-		default:
-			die("unexpected deflate failure: %d", status);
-		}
-	}
-	git_deflate_end(&s);
-	the_hash_algo->final_fn(oid.hash, &c);
-
-	if (oidout)
-		oidcpy(oidout, &oid);
-
-	e = insert_object(&oid);
-
-	if (mark)
-		insert_mark(marks, mark, e);
-
-	if (e->idx.offset) {
-		duplicate_count_by_type[OBJ_BLOB]++;
-		truncate_pack(&checkpoint);
-
-	} else if (find_sha1_pack(oid.hash,
-				  get_all_packs(the_repository))) {
-		e->type = OBJ_BLOB;
-		e->pack_id = MAX_PACK_ID;
-		e->idx.offset = 1; /* just not zero! */
-		duplicate_count_by_type[OBJ_BLOB]++;
-		truncate_pack(&checkpoint);
-
-	} else {
-		e->depth = 0;
-		e->type = OBJ_BLOB;
-		e->pack_id = pack_id;
-		e->idx.offset = offset;
-		e->idx.crc32 = crc32_end(pack_file);
-		object_count++;
-		object_count_by_type[OBJ_BLOB]++;
-	}
-
-	free(in_buf);
-	free(out_buf);
-}
-
-/* All calls must be guarded by find_object() or find_mark() to
- * ensure the 'struct object_entry' passed was written by this
- * process instance.  We unpack the entry by the offset, avoiding
- * the need for the corresponding .idx file.  This unpacking rule
- * works because we only use OBJ_REF_DELTA within the packfiles
- * created by fast-import.
- *
- * oe must not be NULL.  Such an oe usually comes from giving
- * an unknown SHA-1 to find_object() or an undefined mark to
- * find_mark().  Callers must test for this condition and use
- * the standard read_sha1_file() when it happens.
- *
- * oe->pack_id must not be MAX_PACK_ID.  Such an oe is usually from
- * find_mark(), where the mark was reloaded from an existing marks
- * file and is referencing an object that this fast-import process
- * instance did not write out to a packfile.  Callers must test for
- * this condition and use read_sha1_file() instead.
- */
-static void *gfi_unpack_entry(
-	struct object_entry *oe,
-	unsigned long *sizep)
-{
-	enum object_type type;
-	struct packed_git *p = all_packs[oe->pack_id];
-	if (p == pack_data && p->pack_size < (pack_size + the_hash_algo->rawsz)) {
-		/* The object is stored in the packfile we are writing to
-		 * and we have modified it since the last time we scanned
-		 * back to read a previously written object.  If an old
-		 * window covered [p->pack_size, p->pack_size + rawsz) its
-		 * data is stale and is not valid.  Closing all windows
-		 * and updating the packfile length ensures we can read
-		 * the newly written data.
-		 */
-		close_pack_windows(p);
-		hashflush(pack_file);
-
-		/* We have to offer rawsz bytes additional on the end of
-		 * the packfile as the core unpacker code assumes the
-		 * footer is present at the file end and must promise
-		 * at least rawsz bytes within any window it maps.  But
-		 * we don't actually create the footer here.
-		 */
-		p->pack_size = pack_size + the_hash_algo->rawsz;
-	}
-	return unpack_entry(the_repository, p, oe->idx.offset, &type, sizep);
-}
-
-static const char *get_mode(const char *str, uint16_t *modep)
-{
-	unsigned char c;
-	uint16_t mode = 0;
-
-	while ((c = *str++) != ' ') {
-		if (c < '0' || c > '7')
-			return NULL;
-		mode = (mode << 3) + (c - '0');
-	}
-	*modep = mode;
-	return str;
-}
-
-static void load_tree(struct tree_entry *root)
-{
-	struct object_id *oid = &root->versions[1].oid;
-	struct object_entry *myoe;
-	struct tree_content *t;
-	unsigned long size;
-	char *buf;
-	const char *c;
-
-	root->tree = t = new_tree_content(8);
-	if (is_null_oid(oid))
-		return;
-
-	myoe = find_object(oid);
-	if (myoe && myoe->pack_id != MAX_PACK_ID) {
-		if (myoe->type != OBJ_TREE)
-			die("Not a tree: %s", oid_to_hex(oid));
-		t->delta_depth = myoe->depth;
-		buf = gfi_unpack_entry(myoe, &size);
-		if (!buf)
-			die("Can't load tree %s", oid_to_hex(oid));
-	} else {
-		enum object_type type;
-		buf = read_object_file(oid, &type, &size);
-		if (!buf || type != OBJ_TREE)
-			die("Can't load tree %s", oid_to_hex(oid));
-	}
-
-	c = buf;
-	while (c != (buf + size)) {
-		struct tree_entry *e = new_tree_entry();
-
-		if (t->entry_count == t->entry_capacity)
-			root->tree = t = grow_tree_content(t, t->entry_count);
-		t->entries[t->entry_count++] = e;
-
-		e->tree = NULL;
-		c = get_mode(c, &e->versions[1].mode);
-		if (!c)
-			die("Corrupt mode in %s", oid_to_hex(oid));
-		e->versions[0].mode = e->versions[1].mode;
-		e->name = to_atom(c, strlen(c));
-		c += e->name->str_len + 1;
-		hashcpy(e->versions[0].oid.hash, (unsigned char *)c);
-		hashcpy(e->versions[1].oid.hash, (unsigned char *)c);
-		c += the_hash_algo->rawsz;
-	}
-	free(buf);
-}
-
-static int tecmp0 (const void *_a, const void *_b)
-{
-	struct tree_entry *a = *((struct tree_entry**)_a);
-	struct tree_entry *b = *((struct tree_entry**)_b);
-	return base_name_compare(
-		a->name->str_dat, a->name->str_len, a->versions[0].mode,
-		b->name->str_dat, b->name->str_len, b->versions[0].mode);
-}
-
-static int tecmp1 (const void *_a, const void *_b)
-{
-	struct tree_entry *a = *((struct tree_entry**)_a);
-	struct tree_entry *b = *((struct tree_entry**)_b);
-	return base_name_compare(
-		a->name->str_dat, a->name->str_len, a->versions[1].mode,
-		b->name->str_dat, b->name->str_len, b->versions[1].mode);
-}
-
-static void mktree(struct tree_content *t, int v, struct strbuf *b)
-{
-	size_t maxlen = 0;
-	unsigned int i;
-
-	if (!v)
-		QSORT(t->entries, t->entry_count, tecmp0);
-	else
-		QSORT(t->entries, t->entry_count, tecmp1);
-
-	for (i = 0; i < t->entry_count; i++) {
-		if (t->entries[i]->versions[v].mode)
-			maxlen += t->entries[i]->name->str_len + 34;
-	}
-
-	strbuf_reset(b);
-	strbuf_grow(b, maxlen);
-	for (i = 0; i < t->entry_count; i++) {
-		struct tree_entry *e = t->entries[i];
-		if (!e->versions[v].mode)
-			continue;
-		strbuf_addf(b, "%o %s%c",
-			(unsigned int)(e->versions[v].mode & ~NO_DELTA),
-			e->name->str_dat, '\0');
-		strbuf_add(b, e->versions[v].oid.hash, the_hash_algo->rawsz);
-	}
-}
-
-static void store_tree(struct tree_entry *root)
-{
-	struct tree_content *t;
-	unsigned int i, j, del;
-	struct last_object lo = { STRBUF_INIT, 0, 0, /* no_swap */ 1 };
-	struct object_entry *le = NULL;
-
-	if (!is_null_oid(&root->versions[1].oid))
-		return;
-
-	if (!root->tree)
-		load_tree(root);
-	t = root->tree;
-
-	for (i = 0; i < t->entry_count; i++) {
-		if (t->entries[i]->tree)
-			store_tree(t->entries[i]);
-	}
-
-	if (!(root->versions[0].mode & NO_DELTA))
-		le = find_object(&root->versions[0].oid);
-	if (S_ISDIR(root->versions[0].mode) && le && le->pack_id == pack_id) {
-		mktree(t, 0, &old_tree);
-		lo.data = old_tree;
-		lo.offset = le->idx.offset;
-		lo.depth = t->delta_depth;
-	}
-
-	mktree(t, 1, &new_tree);
-	store_object(OBJ_TREE, &new_tree, &lo, &root->versions[1].oid, 0);
-
-	t->delta_depth = lo.depth;
-	for (i = 0, j = 0, del = 0; i < t->entry_count; i++) {
-		struct tree_entry *e = t->entries[i];
-		if (e->versions[1].mode) {
-			e->versions[0].mode = e->versions[1].mode;
-			oidcpy(&e->versions[0].oid, &e->versions[1].oid);
-			t->entries[j++] = e;
-		} else {
-			release_tree_entry(e);
-			del++;
-		}
-	}
-	t->entry_count -= del;
-}
-
-static void tree_content_replace(
-	struct tree_entry *root,
-	const struct object_id *oid,
-	const uint16_t mode,
-	struct tree_content *newtree)
-{
-	if (!S_ISDIR(mode))
-		die("Root cannot be a non-directory");
-	oidclr(&root->versions[0].oid);
-	oidcpy(&root->versions[1].oid, oid);
-	if (root->tree)
-		release_tree_content_recursive(root->tree);
-	root->tree = newtree;
-}
-
-static int tree_content_set(
-	struct tree_entry *root,
-	const char *p,
-	const struct object_id *oid,
-	const uint16_t mode,
-	struct tree_content *subtree)
-{
-	struct tree_content *t;
-	const char *slash1;
-	unsigned int i, n;
-	struct tree_entry *e;
-
-	slash1 = strchrnul(p, '/');
-	n = slash1 - p;
-	if (!n)
-		die("Empty path component found in input");
-	if (!*slash1 && !S_ISDIR(mode) && subtree)
-		die("Non-directories cannot have subtrees");
-
-	if (!root->tree)
-		load_tree(root);
-	t = root->tree;
-	for (i = 0; i < t->entry_count; i++) {
-		e = t->entries[i];
-		if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) {
-			if (!*slash1) {
-				if (!S_ISDIR(mode)
-						&& e->versions[1].mode == mode
-						&& oideq(&e->versions[1].oid, oid))
-					return 0;
-				e->versions[1].mode = mode;
-				oidcpy(&e->versions[1].oid, oid);
-				if (e->tree)
-					release_tree_content_recursive(e->tree);
-				e->tree = subtree;
-
-				/*
-				 * We need to leave e->versions[0].sha1 alone
-				 * to avoid modifying the preimage tree used
-				 * when writing out the parent directory.
-				 * But after replacing the subdir with a
-				 * completely different one, it's not a good
-				 * delta base any more, and besides, we've
-				 * thrown away the tree entries needed to
-				 * make a delta against it.
-				 *
-				 * So let's just explicitly disable deltas
-				 * for the subtree.
-				 */
-				if (S_ISDIR(e->versions[0].mode))
-					e->versions[0].mode |= NO_DELTA;
-
-				oidclr(&root->versions[1].oid);
-				return 1;
-			}
-			if (!S_ISDIR(e->versions[1].mode)) {
-				e->tree = new_tree_content(8);
-				e->versions[1].mode = S_IFDIR;
-			}
-			if (!e->tree)
-				load_tree(e);
-			if (tree_content_set(e, slash1 + 1, oid, mode, subtree)) {
-				oidclr(&root->versions[1].oid);
-				return 1;
-			}
-			return 0;
-		}
-	}
-
-	if (t->entry_count == t->entry_capacity)
-		root->tree = t = grow_tree_content(t, t->entry_count);
-	e = new_tree_entry();
-	e->name = to_atom(p, n);
-	e->versions[0].mode = 0;
-	oidclr(&e->versions[0].oid);
-	t->entries[t->entry_count++] = e;
-	if (*slash1) {
-		e->tree = new_tree_content(8);
-		e->versions[1].mode = S_IFDIR;
-		tree_content_set(e, slash1 + 1, oid, mode, subtree);
-	} else {
-		e->tree = subtree;
-		e->versions[1].mode = mode;
-		oidcpy(&e->versions[1].oid, oid);
-	}
-	oidclr(&root->versions[1].oid);
-	return 1;
-}
-
-static int tree_content_remove(
-	struct tree_entry *root,
-	const char *p,
-	struct tree_entry *backup_leaf,
-	int allow_root)
-{
-	struct tree_content *t;
-	const char *slash1;
-	unsigned int i, n;
-	struct tree_entry *e;
-
-	slash1 = strchrnul(p, '/');
-	n = slash1 - p;
-
-	if (!root->tree)
-		load_tree(root);
-
-	if (!*p && allow_root) {
-		e = root;
-		goto del_entry;
-	}
-
-	t = root->tree;
-	for (i = 0; i < t->entry_count; i++) {
-		e = t->entries[i];
-		if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) {
-			if (*slash1 && !S_ISDIR(e->versions[1].mode))
-				/*
-				 * If p names a file in some subdirectory, and a
-				 * file or symlink matching the name of the
-				 * parent directory of p exists, then p cannot
-				 * exist and need not be deleted.
-				 */
-				return 1;
-			if (!*slash1 || !S_ISDIR(e->versions[1].mode))
-				goto del_entry;
-			if (!e->tree)
-				load_tree(e);
-			if (tree_content_remove(e, slash1 + 1, backup_leaf, 0)) {
-				for (n = 0; n < e->tree->entry_count; n++) {
-					if (e->tree->entries[n]->versions[1].mode) {
-						oidclr(&root->versions[1].oid);
-						return 1;
-					}
-				}
-				backup_leaf = NULL;
-				goto del_entry;
-			}
-			return 0;
-		}
-	}
-	return 0;
-
-del_entry:
-	if (backup_leaf)
-		memcpy(backup_leaf, e, sizeof(*backup_leaf));
-	else if (e->tree)
-		release_tree_content_recursive(e->tree);
-	e->tree = NULL;
-	e->versions[1].mode = 0;
-	oidclr(&e->versions[1].oid);
-	oidclr(&root->versions[1].oid);
-	return 1;
-}
-
-static int tree_content_get(
-	struct tree_entry *root,
-	const char *p,
-	struct tree_entry *leaf,
-	int allow_root)
-{
-	struct tree_content *t;
-	const char *slash1;
-	unsigned int i, n;
-	struct tree_entry *e;
-
-	slash1 = strchrnul(p, '/');
-	n = slash1 - p;
-	if (!n && !allow_root)
-		die("Empty path component found in input");
-
-	if (!root->tree)
-		load_tree(root);
-
-	if (!n) {
-		e = root;
-		goto found_entry;
-	}
-
-	t = root->tree;
-	for (i = 0; i < t->entry_count; i++) {
-		e = t->entries[i];
-		if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) {
-			if (!*slash1)
-				goto found_entry;
-			if (!S_ISDIR(e->versions[1].mode))
-				return 0;
-			if (!e->tree)
-				load_tree(e);
-			return tree_content_get(e, slash1 + 1, leaf, 0);
-		}
-	}
-	return 0;
-
-found_entry:
-	memcpy(leaf, e, sizeof(*leaf));
-	if (e->tree && is_null_oid(&e->versions[1].oid))
-		leaf->tree = dup_tree_content(e->tree);
-	else
-		leaf->tree = NULL;
-	return 1;
-}
-
-static int update_branch(struct branch *b)
-{
-	static const char *msg = "fast-import";
-	struct ref_transaction *transaction;
-	struct object_id old_oid;
-	struct strbuf err = STRBUF_INIT;
-
-	if (is_null_oid(&b->oid)) {
-		if (b->delete)
-			delete_ref(NULL, b->name, NULL, 0);
-		return 0;
-	}
-	if (read_ref(b->name, &old_oid))
-		oidclr(&old_oid);
-	if (!force_update && !is_null_oid(&old_oid)) {
-		struct commit *old_cmit, *new_cmit;
-
-		old_cmit = lookup_commit_reference_gently(the_repository,
-							  &old_oid, 0);
-		new_cmit = lookup_commit_reference_gently(the_repository,
-							  &b->oid, 0);
-		if (!old_cmit || !new_cmit)
-			return error("Branch %s is missing commits.", b->name);
-
-		if (!in_merge_bases(old_cmit, new_cmit)) {
-			warning("Not updating %s"
-				" (new tip %s does not contain %s)",
-				b->name, oid_to_hex(&b->oid),
-				oid_to_hex(&old_oid));
-			return -1;
-		}
-	}
-	transaction = ref_transaction_begin(&err);
-	if (!transaction ||
-	    ref_transaction_update(transaction, b->name, &b->oid, &old_oid,
-				   0, msg, &err) ||
-	    ref_transaction_commit(transaction, &err)) {
-		ref_transaction_free(transaction);
-		error("%s", err.buf);
-		strbuf_release(&err);
-		return -1;
-	}
-	ref_transaction_free(transaction);
-	strbuf_release(&err);
-	return 0;
-}
-
-static void dump_branches(void)
-{
-	unsigned int i;
-	struct branch *b;
-
-	for (i = 0; i < branch_table_sz; i++) {
-		for (b = branch_table[i]; b; b = b->table_next_branch)
-			failure |= update_branch(b);
-	}
-}
-
-static void dump_tags(void)
-{
-	static const char *msg = "fast-import";
-	struct tag *t;
-	struct strbuf ref_name = STRBUF_INIT;
-	struct strbuf err = STRBUF_INIT;
-	struct ref_transaction *transaction;
-
-	transaction = ref_transaction_begin(&err);
-	if (!transaction) {
-		failure |= error("%s", err.buf);
-		goto cleanup;
-	}
-	for (t = first_tag; t; t = t->next_tag) {
-		strbuf_reset(&ref_name);
-		strbuf_addf(&ref_name, "refs/tags/%s", t->name);
-
-		if (ref_transaction_update(transaction, ref_name.buf,
-					   &t->oid, NULL, 0, msg, &err)) {
-			failure |= error("%s", err.buf);
-			goto cleanup;
-		}
-	}
-	if (ref_transaction_commit(transaction, &err))
-		failure |= error("%s", err.buf);
-
- cleanup:
-	ref_transaction_free(transaction);
-	strbuf_release(&ref_name);
-	strbuf_release(&err);
-}
-
-static void dump_marks(void)
-{
-	struct lock_file mark_lock = LOCK_INIT;
-	FILE *f;
-
-	if (!export_marks_file || (import_marks_file && !import_marks_file_done))
-		return;
-
-	if (safe_create_leading_directories_const(export_marks_file)) {
-		failure |= error_errno("unable to create leading directories of %s",
-				       export_marks_file);
-		return;
-	}
-
-	if (hold_lock_file_for_update(&mark_lock, export_marks_file, 0) < 0) {
-		failure |= error_errno("Unable to write marks file %s",
-				       export_marks_file);
-		return;
-	}
-
-	f = fdopen_lock_file(&mark_lock, "w");
-	if (!f) {
-		int saved_errno = errno;
-		rollback_lock_file(&mark_lock);
-		failure |= error("Unable to write marks file %s: %s",
-			export_marks_file, strerror(saved_errno));
-		return;
-	}
-
-	for_each_mark(marks, 0, dump_marks_fn, f);
-	if (commit_lock_file(&mark_lock)) {
-		failure |= error_errno("Unable to write file %s",
-				       export_marks_file);
-		return;
-	}
-}
-
-static void insert_object_entry(struct mark_set *s, struct object_id *oid, uintmax_t mark)
-{
-	struct object_entry *e;
-	e = find_object(oid);
-	if (!e) {
-		enum object_type type = oid_object_info(the_repository,
-							oid, NULL);
-		if (type < 0)
-			die("object not found: %s", oid_to_hex(oid));
-		e = insert_object(oid);
-		e->type = type;
-		e->pack_id = MAX_PACK_ID;
-		e->idx.offset = 1; /* just not zero! */
-	}
-	insert_mark(s, mark, e);
-}
-
-static void insert_oid_entry(struct mark_set *s, struct object_id *oid, uintmax_t mark)
-{
-	insert_mark(s, mark, xmemdupz(oid, sizeof(*oid)));
-}
-
-static void read_mark_file(struct mark_set *s, FILE *f, mark_set_inserter_t inserter)
-{
-	char line[512];
-	while (fgets(line, sizeof(line), f)) {
-		uintmax_t mark;
-		char *end;
-		struct object_id oid;
-
-		/* Ensure SHA-1 objects are padded with zeros. */
-		memset(oid.hash, 0, sizeof(oid.hash));
-
-		end = strchr(line, '\n');
-		if (line[0] != ':' || !end)
-			die("corrupt mark line: %s", line);
-		*end = 0;
-		mark = strtoumax(line + 1, &end, 10);
-		if (!mark || end == line + 1
-			|| *end != ' '
-			|| get_oid_hex_any(end + 1, &oid) == GIT_HASH_UNKNOWN)
-			die("corrupt mark line: %s", line);
-		inserter(s, &oid, mark);
-	}
-}
-
-static void read_marks(void)
-{
-	FILE *f = fopen(import_marks_file, "r");
-	if (f)
-		;
-	else if (import_marks_file_ignore_missing && errno == ENOENT)
-		goto done; /* Marks file does not exist */
-	else
-		die_errno("cannot read '%s'", import_marks_file);
-	read_mark_file(marks, f, insert_object_entry);
-	fclose(f);
-done:
-	import_marks_file_done = 1;
-}
-
-
-static int read_next_command(void)
-{
-	static int stdin_eof = 0;
-
-	if (stdin_eof) {
-		unread_command_buf = 0;
-		return EOF;
-	}
-
-	for (;;) {
-		if (unread_command_buf) {
-			unread_command_buf = 0;
-		} else {
-			struct recent_command *rc;
-
-			stdin_eof = strbuf_getline_lf(&command_buf, stdin);
-			if (stdin_eof)
-				return EOF;
-
-			if (!seen_data_command
-				&& !starts_with(command_buf.buf, "feature ")
-				&& !starts_with(command_buf.buf, "option ")) {
-				parse_argv();
-			}
-
-			rc = rc_free;
-			if (rc)
-				rc_free = rc->next;
-			else {
-				rc = cmd_hist.next;
-				cmd_hist.next = rc->next;
-				cmd_hist.next->prev = &cmd_hist;
-				free(rc->buf);
-			}
-
-			rc->buf = xstrdup(command_buf.buf);
-			rc->prev = cmd_tail;
-			rc->next = cmd_hist.prev;
-			rc->prev->next = rc;
-			cmd_tail = rc;
-		}
-		if (command_buf.buf[0] == '#')
-			continue;
-		return 0;
-	}
-}
-
-static void skip_optional_lf(void)
-{
-	int term_char = fgetc(stdin);
-	if (term_char != '\n' && term_char != EOF)
-		ungetc(term_char, stdin);
-}
-
-static void parse_mark(void)
-{
-	const char *v;
-	if (skip_prefix(command_buf.buf, "mark :", &v)) {
-		next_mark = strtoumax(v, NULL, 10);
-		read_next_command();
-	}
-	else
-		next_mark = 0;
-}
-
-static void parse_original_identifier(void)
-{
-	const char *v;
-	if (skip_prefix(command_buf.buf, "original-oid ", &v))
-		read_next_command();
-}
-
-static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res)
-{
-	const char *data;
-	strbuf_reset(sb);
-
-	if (!skip_prefix(command_buf.buf, "data ", &data))
-		die("Expected 'data n' command, found: %s", command_buf.buf);
-
-	if (skip_prefix(data, "<<", &data)) {
-		char *term = xstrdup(data);
-		size_t term_len = command_buf.len - (data - command_buf.buf);
-
-		for (;;) {
-			if (strbuf_getline_lf(&command_buf, stdin) == EOF)
-				die("EOF in data (terminator '%s' not found)", term);
-			if (term_len == command_buf.len
-				&& !strcmp(term, command_buf.buf))
-				break;
-			strbuf_addbuf(sb, &command_buf);
-			strbuf_addch(sb, '\n');
-		}
-		free(term);
-	}
-	else {
-		uintmax_t len = strtoumax(data, NULL, 10);
-		size_t n = 0, length = (size_t)len;
-
-		if (limit && limit < len) {
-			*len_res = len;
-			return 0;
-		}
-		if (length < len)
-			die("data is too large to use in this context");
-
-		while (n < length) {
-			size_t s = strbuf_fread(sb, length - n, stdin);
-			if (!s && feof(stdin))
-				die("EOF in data (%lu bytes remaining)",
-					(unsigned long)(length - n));
-			n += s;
-		}
-	}
-
-	skip_optional_lf();
-	return 1;
-}
-
-static int validate_raw_date(const char *src, struct strbuf *result, int strict)
-{
-	const char *orig_src = src;
-	char *endp;
-	unsigned long num;
-
-	errno = 0;
-
-	num = strtoul(src, &endp, 10);
-	/*
-	 * NEEDSWORK: perhaps check for reasonable values? For example, we
-	 *            could error on values representing times more than a
-	 *            day in the future.
-	 */
-	if (errno || endp == src || *endp != ' ')
-		return -1;
-
-	src = endp + 1;
-	if (*src != '-' && *src != '+')
-		return -1;
-
-	num = strtoul(src + 1, &endp, 10);
-	/*
-	 * NEEDSWORK: check for brokenness other than num > 1400, such as
-	 *            (num % 100) >= 60, or ((num % 100) % 15) != 0 ?
-	 */
-	if (errno || endp == src + 1 || *endp || /* did not parse */
-	    (strict && (1400 < num))             /* parsed a broken timezone */
-	   )
-		return -1;
-
-	strbuf_addstr(result, orig_src);
-	return 0;
-}
-
-static char *parse_ident(const char *buf)
-{
-	const char *ltgt;
-	size_t name_len;
-	struct strbuf ident = STRBUF_INIT;
-
-	/* ensure there is a space delimiter even if there is no name */
-	if (*buf == '<')
-		--buf;
-
-	ltgt = buf + strcspn(buf, "<>");
-	if (*ltgt != '<')
-		die("Missing < in ident string: %s", buf);
-	if (ltgt != buf && ltgt[-1] != ' ')
-		die("Missing space before < in ident string: %s", buf);
-	ltgt = ltgt + 1 + strcspn(ltgt + 1, "<>");
-	if (*ltgt != '>')
-		die("Missing > in ident string: %s", buf);
-	ltgt++;
-	if (*ltgt != ' ')
-		die("Missing space after > in ident string: %s", buf);
-	ltgt++;
-	name_len = ltgt - buf;
-	strbuf_add(&ident, buf, name_len);
-
-	switch (whenspec) {
-	case WHENSPEC_RAW:
-		if (validate_raw_date(ltgt, &ident, 1) < 0)
-			die("Invalid raw date \"%s\" in ident: %s", ltgt, buf);
-		break;
-	case WHENSPEC_RAW_PERMISSIVE:
-		if (validate_raw_date(ltgt, &ident, 0) < 0)
-			die("Invalid raw date \"%s\" in ident: %s", ltgt, buf);
-		break;
-	case WHENSPEC_RFC2822:
-		if (parse_date(ltgt, &ident) < 0)
-			die("Invalid rfc2822 date \"%s\" in ident: %s", ltgt, buf);
-		break;
-	case WHENSPEC_NOW:
-		if (strcmp("now", ltgt))
-			die("Date in ident must be 'now': %s", buf);
-		datestamp(&ident);
-		break;
-	}
-
-	return strbuf_detach(&ident, NULL);
-}
-
-static void parse_and_store_blob(
-	struct last_object *last,
-	struct object_id *oidout,
-	uintmax_t mark)
-{
-	static struct strbuf buf = STRBUF_INIT;
-	uintmax_t len;
-
-	if (parse_data(&buf, big_file_threshold, &len))
-		store_object(OBJ_BLOB, &buf, last, oidout, mark);
-	else {
-		if (last) {
-			strbuf_release(&last->data);
-			last->offset = 0;
-			last->depth = 0;
-		}
-		stream_blob(len, oidout, mark);
-		skip_optional_lf();
-	}
-}
-
-static void parse_new_blob(void)
-{
-	read_next_command();
-	parse_mark();
-	parse_original_identifier();
-	parse_and_store_blob(&last_blob, NULL, next_mark);
-}
-
-static void unload_one_branch(void)
-{
-	while (cur_active_branches
-		&& cur_active_branches >= max_active_branches) {
-		uintmax_t min_commit = ULONG_MAX;
-		struct branch *e, *l = NULL, *p = NULL;
-
-		for (e = active_branches; e; e = e->active_next_branch) {
-			if (e->last_commit < min_commit) {
-				p = l;
-				min_commit = e->last_commit;
-			}
-			l = e;
-		}
-
-		if (p) {
-			e = p->active_next_branch;
-			p->active_next_branch = e->active_next_branch;
-		} else {
-			e = active_branches;
-			active_branches = e->active_next_branch;
-		}
-		e->active = 0;
-		e->active_next_branch = NULL;
-		if (e->branch_tree.tree) {
-			release_tree_content_recursive(e->branch_tree.tree);
-			e->branch_tree.tree = NULL;
-		}
-		cur_active_branches--;
-	}
-}
-
-static void load_branch(struct branch *b)
-{
-	load_tree(&b->branch_tree);
-	if (!b->active) {
-		b->active = 1;
-		b->active_next_branch = active_branches;
-		active_branches = b;
-		cur_active_branches++;
-		branch_load_count++;
-	}
-}
-
-static unsigned char convert_num_notes_to_fanout(uintmax_t num_notes)
-{
-	unsigned char fanout = 0;
-	while ((num_notes >>= 8))
-		fanout++;
-	return fanout;
-}
-
-static void construct_path_with_fanout(const char *hex_sha1,
-		unsigned char fanout, char *path)
-{
-	unsigned int i = 0, j = 0;
-	if (fanout >= the_hash_algo->rawsz)
-		die("Too large fanout (%u)", fanout);
-	while (fanout) {
-		path[i++] = hex_sha1[j++];
-		path[i++] = hex_sha1[j++];
-		path[i++] = '/';
-		fanout--;
-	}
-	memcpy(path + i, hex_sha1 + j, the_hash_algo->hexsz - j);
-	path[i + the_hash_algo->hexsz - j] = '\0';
-}
-
-static uintmax_t do_change_note_fanout(
-		struct tree_entry *orig_root, struct tree_entry *root,
-		char *hex_oid, unsigned int hex_oid_len,
-		char *fullpath, unsigned int fullpath_len,
-		unsigned char fanout)
-{
-	struct tree_content *t;
-	struct tree_entry *e, leaf;
-	unsigned int i, tmp_hex_oid_len, tmp_fullpath_len;
-	uintmax_t num_notes = 0;
-	struct object_id oid;
-	/* hex oid + '/' between each pair of hex digits + NUL */
-	char realpath[GIT_MAX_HEXSZ + ((GIT_MAX_HEXSZ / 2) - 1) + 1];
-	const unsigned hexsz = the_hash_algo->hexsz;
-
-	if (!root->tree)
-		load_tree(root);
-	t = root->tree;
-
-	for (i = 0; t && i < t->entry_count; i++) {
-		e = t->entries[i];
-		tmp_hex_oid_len = hex_oid_len + e->name->str_len;
-		tmp_fullpath_len = fullpath_len;
-
-		/*
-		 * We're interested in EITHER existing note entries (entries
-		 * with exactly 40 hex chars in path, not including directory
-		 * separators), OR directory entries that may contain note
-		 * entries (with < 40 hex chars in path).
-		 * Also, each path component in a note entry must be a multiple
-		 * of 2 chars.
-		 */
-		if (!e->versions[1].mode ||
-		    tmp_hex_oid_len > hexsz ||
-		    e->name->str_len % 2)
-			continue;
-
-		/* This _may_ be a note entry, or a subdir containing notes */
-		memcpy(hex_oid + hex_oid_len, e->name->str_dat,
-		       e->name->str_len);
-		if (tmp_fullpath_len)
-			fullpath[tmp_fullpath_len++] = '/';
-		memcpy(fullpath + tmp_fullpath_len, e->name->str_dat,
-		       e->name->str_len);
-		tmp_fullpath_len += e->name->str_len;
-		fullpath[tmp_fullpath_len] = '\0';
-
-		if (tmp_hex_oid_len == hexsz && !get_oid_hex(hex_oid, &oid)) {
-			/* This is a note entry */
-			if (fanout == 0xff) {
-				/* Counting mode, no rename */
-				num_notes++;
-				continue;
-			}
-			construct_path_with_fanout(hex_oid, fanout, realpath);
-			if (!strcmp(fullpath, realpath)) {
-				/* Note entry is in correct location */
-				num_notes++;
-				continue;
-			}
-
-			/* Rename fullpath to realpath */
-			if (!tree_content_remove(orig_root, fullpath, &leaf, 0))
-				die("Failed to remove path %s", fullpath);
-			tree_content_set(orig_root, realpath,
-				&leaf.versions[1].oid,
-				leaf.versions[1].mode,
-				leaf.tree);
-		} else if (S_ISDIR(e->versions[1].mode)) {
-			/* This is a subdir that may contain note entries */
-			num_notes += do_change_note_fanout(orig_root, e,
-				hex_oid, tmp_hex_oid_len,
-				fullpath, tmp_fullpath_len, fanout);
-		}
-
-		/* The above may have reallocated the current tree_content */
-		t = root->tree;
-	}
-	return num_notes;
-}
-
-static uintmax_t change_note_fanout(struct tree_entry *root,
-		unsigned char fanout)
-{
-	/*
-	 * The size of path is due to one slash between every two hex digits,
-	 * plus the terminating NUL.  Note that there is no slash at the end, so
-	 * the number of slashes is one less than half the number of hex
-	 * characters.
-	 */
-	char hex_oid[GIT_MAX_HEXSZ], path[GIT_MAX_HEXSZ + (GIT_MAX_HEXSZ / 2) - 1 + 1];
-	return do_change_note_fanout(root, root, hex_oid, 0, path, 0, fanout);
-}
-
-static int parse_mapped_oid_hex(const char *hex, struct object_id *oid, const char **end)
-{
-	int algo;
-	khiter_t it;
-
-	/* Make SHA-1 object IDs have all-zero padding. */
-	memset(oid->hash, 0, sizeof(oid->hash));
-
-	algo = parse_oid_hex_any(hex, oid, end);
-	if (algo == GIT_HASH_UNKNOWN)
-		return -1;
-
-	it = kh_get_oid_map(sub_oid_map, *oid);
-	/* No such object? */
-	if (it == kh_end(sub_oid_map)) {
-		/* If we're using the same algorithm, pass it through. */
-		if (hash_algos[algo].format_id == the_hash_algo->format_id)
-			return 0;
-		return -1;
-	}
-	oidcpy(oid, kh_value(sub_oid_map, it));
-	return 0;
-}
-
-/*
- * Given a pointer into a string, parse a mark reference:
- *
- *   idnum ::= ':' bigint;
- *
- * Return the first character after the value in *endptr.
- *
- * Complain if the following character is not what is expected,
- * either a space or end of the string.
- */
-static uintmax_t parse_mark_ref(const char *p, char **endptr)
-{
-	uintmax_t mark;
-
-	assert(*p == ':');
-	p++;
-	mark = strtoumax(p, endptr, 10);
-	if (*endptr == p)
-		die("No value after ':' in mark: %s", command_buf.buf);
-	return mark;
-}
-
-/*
- * Parse the mark reference, and complain if this is not the end of
- * the string.
- */
-static uintmax_t parse_mark_ref_eol(const char *p)
-{
-	char *end;
-	uintmax_t mark;
-
-	mark = parse_mark_ref(p, &end);
-	if (*end != '\0')
-		die("Garbage after mark: %s", command_buf.buf);
-	return mark;
-}
-
-/*
- * Parse the mark reference, demanding a trailing space.  Return a
- * pointer to the space.
- */
-static uintmax_t parse_mark_ref_space(const char **p)
-{
-	uintmax_t mark;
-	char *end;
-
-	mark = parse_mark_ref(*p, &end);
-	if (*end++ != ' ')
-		die("Missing space after mark: %s", command_buf.buf);
-	*p = end;
-	return mark;
-}
-
-static void file_change_m(const char *p, struct branch *b)
-{
-	static struct strbuf uq = STRBUF_INIT;
-	const char *endp;
-	struct object_entry *oe;
-	struct object_id oid;
-	uint16_t mode, inline_data = 0;
-
-	p = get_mode(p, &mode);
-	if (!p)
-		die("Corrupt mode: %s", command_buf.buf);
-	switch (mode) {
-	case 0644:
-	case 0755:
-		mode |= S_IFREG;
-	case S_IFREG | 0644:
-	case S_IFREG | 0755:
-	case S_IFLNK:
-	case S_IFDIR:
-	case S_IFGITLINK:
-		/* ok */
-		break;
-	default:
-		die("Corrupt mode: %s", command_buf.buf);
-	}
-
-	if (*p == ':') {
-		oe = find_mark(marks, parse_mark_ref_space(&p));
-		oidcpy(&oid, &oe->idx.oid);
-	} else if (skip_prefix(p, "inline ", &p)) {
-		inline_data = 1;
-		oe = NULL; /* not used with inline_data, but makes gcc happy */
-	} else {
-		if (parse_mapped_oid_hex(p, &oid, &p))
-			die("Invalid dataref: %s", command_buf.buf);
-		oe = find_object(&oid);
-		if (*p++ != ' ')
-			die("Missing space after SHA1: %s", command_buf.buf);
-	}
-
-	strbuf_reset(&uq);
-	if (!unquote_c_style(&uq, p, &endp)) {
-		if (*endp)
-			die("Garbage after path in: %s", command_buf.buf);
-		p = uq.buf;
-	}
-
-	/* Git does not track empty, non-toplevel directories. */
-	if (S_ISDIR(mode) && is_empty_tree_oid(&oid) && *p) {
-		tree_content_remove(&b->branch_tree, p, NULL, 0);
-		return;
-	}
-
-	if (S_ISGITLINK(mode)) {
-		if (inline_data)
-			die("Git links cannot be specified 'inline': %s",
-				command_buf.buf);
-		else if (oe) {
-			if (oe->type != OBJ_COMMIT)
-				die("Not a commit (actually a %s): %s",
-					type_name(oe->type), command_buf.buf);
-		}
-		/*
-		 * Accept the sha1 without checking; it expected to be in
-		 * another repository.
-		 */
-	} else if (inline_data) {
-		if (S_ISDIR(mode))
-			die("Directories cannot be specified 'inline': %s",
-				command_buf.buf);
-		if (p != uq.buf) {
-			strbuf_addstr(&uq, p);
-			p = uq.buf;
-		}
-		while (read_next_command() != EOF) {
-			const char *v;
-			if (skip_prefix(command_buf.buf, "cat-blob ", &v))
-				parse_cat_blob(v);
-			else {
-				parse_and_store_blob(&last_blob, &oid, 0);
-				break;
-			}
-		}
-	} else {
-		enum object_type expected = S_ISDIR(mode) ?
-						OBJ_TREE: OBJ_BLOB;
-		enum object_type type = oe ? oe->type :
-					oid_object_info(the_repository, &oid,
-							NULL);
-		if (type < 0)
-			die("%s not found: %s",
-					S_ISDIR(mode) ?  "Tree" : "Blob",
-					command_buf.buf);
-		if (type != expected)
-			die("Not a %s (actually a %s): %s",
-				type_name(expected), type_name(type),
-				command_buf.buf);
-	}
-
-	if (!*p) {
-		tree_content_replace(&b->branch_tree, &oid, mode, NULL);
-		return;
-	}
-	tree_content_set(&b->branch_tree, p, &oid, mode, NULL);
-}
-
-static void file_change_d(const char *p, struct branch *b)
-{
-	static struct strbuf uq = STRBUF_INIT;
-	const char *endp;
-
-	strbuf_reset(&uq);
-	if (!unquote_c_style(&uq, p, &endp)) {
-		if (*endp)
-			die("Garbage after path in: %s", command_buf.buf);
-		p = uq.buf;
-	}
-	tree_content_remove(&b->branch_tree, p, NULL, 1);
-}
-
-static void file_change_cr(const char *s, struct branch *b, int rename)
-{
-	const char *d;
-	static struct strbuf s_uq = STRBUF_INIT;
-	static struct strbuf d_uq = STRBUF_INIT;
-	const char *endp;
-	struct tree_entry leaf;
-
-	strbuf_reset(&s_uq);
-	if (!unquote_c_style(&s_uq, s, &endp)) {
-		if (*endp != ' ')
-			die("Missing space after source: %s", command_buf.buf);
-	} else {
-		endp = strchr(s, ' ');
-		if (!endp)
-			die("Missing space after source: %s", command_buf.buf);
-		strbuf_add(&s_uq, s, endp - s);
-	}
-	s = s_uq.buf;
-
-	endp++;
-	if (!*endp)
-		die("Missing dest: %s", command_buf.buf);
-
-	d = endp;
-	strbuf_reset(&d_uq);
-	if (!unquote_c_style(&d_uq, d, &endp)) {
-		if (*endp)
-			die("Garbage after dest in: %s", command_buf.buf);
-		d = d_uq.buf;
-	}
-
-	memset(&leaf, 0, sizeof(leaf));
-	if (rename)
-		tree_content_remove(&b->branch_tree, s, &leaf, 1);
-	else
-		tree_content_get(&b->branch_tree, s, &leaf, 1);
-	if (!leaf.versions[1].mode)
-		die("Path %s not in branch", s);
-	if (!*d) {	/* C "path/to/subdir" "" */
-		tree_content_replace(&b->branch_tree,
-			&leaf.versions[1].oid,
-			leaf.versions[1].mode,
-			leaf.tree);
-		return;
-	}
-	tree_content_set(&b->branch_tree, d,
-		&leaf.versions[1].oid,
-		leaf.versions[1].mode,
-		leaf.tree);
-}
-
-static void note_change_n(const char *p, struct branch *b, unsigned char *old_fanout)
-{
-	static struct strbuf uq = STRBUF_INIT;
-	struct object_entry *oe;
-	struct branch *s;
-	struct object_id oid, commit_oid;
-	char path[GIT_MAX_RAWSZ * 3];
-	uint16_t inline_data = 0;
-	unsigned char new_fanout;
-
-	/*
-	 * When loading a branch, we don't traverse its tree to count the real
-	 * number of notes (too expensive to do this for all non-note refs).
-	 * This means that recently loaded notes refs might incorrectly have
-	 * b->num_notes == 0, and consequently, old_fanout might be wrong.
-	 *
-	 * Fix this by traversing the tree and counting the number of notes
-	 * when b->num_notes == 0. If the notes tree is truly empty, the
-	 * calculation should not take long.
-	 */
-	if (b->num_notes == 0 && *old_fanout == 0) {
-		/* Invoke change_note_fanout() in "counting mode". */
-		b->num_notes = change_note_fanout(&b->branch_tree, 0xff);
-		*old_fanout = convert_num_notes_to_fanout(b->num_notes);
-	}
-
-	/* Now parse the notemodify command. */
-	/* <dataref> or 'inline' */
-	if (*p == ':') {
-		oe = find_mark(marks, parse_mark_ref_space(&p));
-		oidcpy(&oid, &oe->idx.oid);
-	} else if (skip_prefix(p, "inline ", &p)) {
-		inline_data = 1;
-		oe = NULL; /* not used with inline_data, but makes gcc happy */
-	} else {
-		if (parse_mapped_oid_hex(p, &oid, &p))
-			die("Invalid dataref: %s", command_buf.buf);
-		oe = find_object(&oid);
-		if (*p++ != ' ')
-			die("Missing space after SHA1: %s", command_buf.buf);
-	}
-
-	/* <commit-ish> */
-	s = lookup_branch(p);
-	if (s) {
-		if (is_null_oid(&s->oid))
-			die("Can't add a note on empty branch.");
-		oidcpy(&commit_oid, &s->oid);
-	} else if (*p == ':') {
-		uintmax_t commit_mark = parse_mark_ref_eol(p);
-		struct object_entry *commit_oe = find_mark(marks, commit_mark);
-		if (commit_oe->type != OBJ_COMMIT)
-			die("Mark :%" PRIuMAX " not a commit", commit_mark);
-		oidcpy(&commit_oid, &commit_oe->idx.oid);
-	} else if (!get_oid(p, &commit_oid)) {
-		unsigned long size;
-		char *buf = read_object_with_reference(the_repository,
-						       &commit_oid,
-						       commit_type, &size,
-						       &commit_oid);
-		if (!buf || size < the_hash_algo->hexsz + 6)
-			die("Not a valid commit: %s", p);
-		free(buf);
-	} else
-		die("Invalid ref name or SHA1 expression: %s", p);
-
-	if (inline_data) {
-		if (p != uq.buf) {
-			strbuf_addstr(&uq, p);
-			p = uq.buf;
-		}
-		read_next_command();
-		parse_and_store_blob(&last_blob, &oid, 0);
-	} else if (oe) {
-		if (oe->type != OBJ_BLOB)
-			die("Not a blob (actually a %s): %s",
-				type_name(oe->type), command_buf.buf);
-	} else if (!is_null_oid(&oid)) {
-		enum object_type type = oid_object_info(the_repository, &oid,
-							NULL);
-		if (type < 0)
-			die("Blob not found: %s", command_buf.buf);
-		if (type != OBJ_BLOB)
-			die("Not a blob (actually a %s): %s",
-			    type_name(type), command_buf.buf);
-	}
-
-	construct_path_with_fanout(oid_to_hex(&commit_oid), *old_fanout, path);
-	if (tree_content_remove(&b->branch_tree, path, NULL, 0))
-		b->num_notes--;
-
-	if (is_null_oid(&oid))
-		return; /* nothing to insert */
-
-	b->num_notes++;
-	new_fanout = convert_num_notes_to_fanout(b->num_notes);
-	construct_path_with_fanout(oid_to_hex(&commit_oid), new_fanout, path);
-	tree_content_set(&b->branch_tree, path, &oid, S_IFREG | 0644, NULL);
-}
-
-static void file_change_deleteall(struct branch *b)
-{
-	release_tree_content_recursive(b->branch_tree.tree);
-	oidclr(&b->branch_tree.versions[0].oid);
-	oidclr(&b->branch_tree.versions[1].oid);
-	load_tree(&b->branch_tree);
-	b->num_notes = 0;
-}
-
-static void parse_from_commit(struct branch *b, char *buf, unsigned long size)
-{
-	if (!buf || size < the_hash_algo->hexsz + 6)
-		die("Not a valid commit: %s", oid_to_hex(&b->oid));
-	if (memcmp("tree ", buf, 5)
-		|| get_oid_hex(buf + 5, &b->branch_tree.versions[1].oid))
-		die("The commit %s is corrupt", oid_to_hex(&b->oid));
-	oidcpy(&b->branch_tree.versions[0].oid,
-	       &b->branch_tree.versions[1].oid);
-}
-
-static void parse_from_existing(struct branch *b)
-{
-	if (is_null_oid(&b->oid)) {
-		oidclr(&b->branch_tree.versions[0].oid);
-		oidclr(&b->branch_tree.versions[1].oid);
-	} else {
-		unsigned long size;
-		char *buf;
-
-		buf = read_object_with_reference(the_repository,
-						 &b->oid, commit_type, &size,
-						 &b->oid);
-		parse_from_commit(b, buf, size);
-		free(buf);
-	}
-}
-
-static int parse_objectish(struct branch *b, const char *objectish)
-{
-	struct branch *s;
-	struct object_id oid;
-
-	oidcpy(&oid, &b->branch_tree.versions[1].oid);
-
-	s = lookup_branch(objectish);
-	if (b == s)
-		die("Can't create a branch from itself: %s", b->name);
-	else if (s) {
-		struct object_id *t = &s->branch_tree.versions[1].oid;
-		oidcpy(&b->oid, &s->oid);
-		oidcpy(&b->branch_tree.versions[0].oid, t);
-		oidcpy(&b->branch_tree.versions[1].oid, t);
-	} else if (*objectish == ':') {
-		uintmax_t idnum = parse_mark_ref_eol(objectish);
-		struct object_entry *oe = find_mark(marks, idnum);
-		if (oe->type != OBJ_COMMIT)
-			die("Mark :%" PRIuMAX " not a commit", idnum);
-		if (!oideq(&b->oid, &oe->idx.oid)) {
-			oidcpy(&b->oid, &oe->idx.oid);
-			if (oe->pack_id != MAX_PACK_ID) {
-				unsigned long size;
-				char *buf = gfi_unpack_entry(oe, &size);
-				parse_from_commit(b, buf, size);
-				free(buf);
-			} else
-				parse_from_existing(b);
-		}
-	} else if (!get_oid(objectish, &b->oid)) {
-		parse_from_existing(b);
-		if (is_null_oid(&b->oid))
-			b->delete = 1;
-	}
-	else
-		die("Invalid ref name or SHA1 expression: %s", objectish);
-
-	if (b->branch_tree.tree && !oideq(&oid, &b->branch_tree.versions[1].oid)) {
-		release_tree_content_recursive(b->branch_tree.tree);
-		b->branch_tree.tree = NULL;
-	}
-
-	read_next_command();
-	return 1;
-}
-
-static int parse_from(struct branch *b)
-{
-	const char *from;
-
-	if (!skip_prefix(command_buf.buf, "from ", &from))
-		return 0;
-
-	return parse_objectish(b, from);
-}
-
-static int parse_objectish_with_prefix(struct branch *b, const char *prefix)
-{
-	const char *base;
-
-	if (!skip_prefix(command_buf.buf, prefix, &base))
-		return 0;
-
-	return parse_objectish(b, base);
-}
-
-static struct hash_list *parse_merge(unsigned int *count)
-{
-	struct hash_list *list = NULL, **tail = &list, *n;
-	const char *from;
-	struct branch *s;
-
-	*count = 0;
-	while (skip_prefix(command_buf.buf, "merge ", &from)) {
-		n = xmalloc(sizeof(*n));
-		s = lookup_branch(from);
-		if (s)
-			oidcpy(&n->oid, &s->oid);
-		else if (*from == ':') {
-			uintmax_t idnum = parse_mark_ref_eol(from);
-			struct object_entry *oe = find_mark(marks, idnum);
-			if (oe->type != OBJ_COMMIT)
-				die("Mark :%" PRIuMAX " not a commit", idnum);
-			oidcpy(&n->oid, &oe->idx.oid);
-		} else if (!get_oid(from, &n->oid)) {
-			unsigned long size;
-			char *buf = read_object_with_reference(the_repository,
-							       &n->oid,
-							       commit_type,
-							       &size, &n->oid);
-			if (!buf || size < the_hash_algo->hexsz + 6)
-				die("Not a valid commit: %s", from);
-			free(buf);
-		} else
-			die("Invalid ref name or SHA1 expression: %s", from);
-
-		n->next = NULL;
-		*tail = n;
-		tail = &n->next;
-
-		(*count)++;
-		read_next_command();
-	}
-	return list;
-}
-
-static void parse_new_commit(const char *arg)
-{
-	static struct strbuf msg = STRBUF_INIT;
-	struct branch *b;
-	char *author = NULL;
-	char *committer = NULL;
-	char *encoding = NULL;
-	struct hash_list *merge_list = NULL;
-	unsigned int merge_count;
-	unsigned char prev_fanout, new_fanout;
-	const char *v;
-
-	b = lookup_branch(arg);
-	if (!b)
-		b = new_branch(arg);
-
-	read_next_command();
-	parse_mark();
-	parse_original_identifier();
-	if (skip_prefix(command_buf.buf, "author ", &v)) {
-		author = parse_ident(v);
-		read_next_command();
-	}
-	if (skip_prefix(command_buf.buf, "committer ", &v)) {
-		committer = parse_ident(v);
-		read_next_command();
-	}
-	if (!committer)
-		die("Expected committer but didn't get one");
-	if (skip_prefix(command_buf.buf, "encoding ", &v)) {
-		encoding = xstrdup(v);
-		read_next_command();
-	}
-	parse_data(&msg, 0, NULL);
-	read_next_command();
-	parse_from(b);
-	merge_list = parse_merge(&merge_count);
-
-	/* ensure the branch is active/loaded */
-	if (!b->branch_tree.tree || !max_active_branches) {
-		unload_one_branch();
-		load_branch(b);
-	}
-
-	prev_fanout = convert_num_notes_to_fanout(b->num_notes);
-
-	/* file_change* */
-	while (command_buf.len > 0) {
-		if (skip_prefix(command_buf.buf, "M ", &v))
-			file_change_m(v, b);
-		else if (skip_prefix(command_buf.buf, "D ", &v))
-			file_change_d(v, b);
-		else if (skip_prefix(command_buf.buf, "R ", &v))
-			file_change_cr(v, b, 1);
-		else if (skip_prefix(command_buf.buf, "C ", &v))
-			file_change_cr(v, b, 0);
-		else if (skip_prefix(command_buf.buf, "N ", &v))
-			note_change_n(v, b, &prev_fanout);
-		else if (!strcmp("deleteall", command_buf.buf))
-			file_change_deleteall(b);
-		else if (skip_prefix(command_buf.buf, "ls ", &v))
-			parse_ls(v, b);
-		else if (skip_prefix(command_buf.buf, "cat-blob ", &v))
-			parse_cat_blob(v);
-		else {
-			unread_command_buf = 1;
-			break;
-		}
-		if (read_next_command() == EOF)
-			break;
-	}
-
-	new_fanout = convert_num_notes_to_fanout(b->num_notes);
-	if (new_fanout != prev_fanout)
-		b->num_notes = change_note_fanout(&b->branch_tree, new_fanout);
-
-	/* build the tree and the commit */
-	store_tree(&b->branch_tree);
-	oidcpy(&b->branch_tree.versions[0].oid,
-	       &b->branch_tree.versions[1].oid);
-
-	strbuf_reset(&new_data);
-	strbuf_addf(&new_data, "tree %s\n",
-		oid_to_hex(&b->branch_tree.versions[1].oid));
-	if (!is_null_oid(&b->oid))
-		strbuf_addf(&new_data, "parent %s\n",
-			    oid_to_hex(&b->oid));
-	while (merge_list) {
-		struct hash_list *next = merge_list->next;
-		strbuf_addf(&new_data, "parent %s\n",
-			    oid_to_hex(&merge_list->oid));
-		free(merge_list);
-		merge_list = next;
-	}
-	strbuf_addf(&new_data,
-		"author %s\n"
-		"committer %s\n",
-		author ? author : committer, committer);
-	if (encoding)
-		strbuf_addf(&new_data,
-			"encoding %s\n",
-			encoding);
-	strbuf_addch(&new_data, '\n');
-	strbuf_addbuf(&new_data, &msg);
-	free(author);
-	free(committer);
-	free(encoding);
-
-	if (!store_object(OBJ_COMMIT, &new_data, NULL, &b->oid, next_mark))
-		b->pack_id = pack_id;
-	b->last_commit = object_count_by_type[OBJ_COMMIT];
-}
-
-static void parse_new_tag(const char *arg)
-{
-	static struct strbuf msg = STRBUF_INIT;
-	const char *from;
-	char *tagger;
-	struct branch *s;
-	struct tag *t;
-	uintmax_t from_mark = 0;
-	struct object_id oid;
-	enum object_type type;
-	const char *v;
-
-	t = mem_pool_alloc(&fi_mem_pool, sizeof(struct tag));
-	memset(t, 0, sizeof(struct tag));
-	t->name = mem_pool_strdup(&fi_mem_pool, arg);
-	if (last_tag)
-		last_tag->next_tag = t;
-	else
-		first_tag = t;
-	last_tag = t;
-	read_next_command();
-	parse_mark();
-
-	/* from ... */
-	if (!skip_prefix(command_buf.buf, "from ", &from))
-		die("Expected from command, got %s", command_buf.buf);
-	s = lookup_branch(from);
-	if (s) {
-		if (is_null_oid(&s->oid))
-			die("Can't tag an empty branch.");
-		oidcpy(&oid, &s->oid);
-		type = OBJ_COMMIT;
-	} else if (*from == ':') {
-		struct object_entry *oe;
-		from_mark = parse_mark_ref_eol(from);
-		oe = find_mark(marks, from_mark);
-		type = oe->type;
-		oidcpy(&oid, &oe->idx.oid);
-	} else if (!get_oid(from, &oid)) {
-		struct object_entry *oe = find_object(&oid);
-		if (!oe) {
-			type = oid_object_info(the_repository, &oid, NULL);
-			if (type < 0)
-				die("Not a valid object: %s", from);
-		} else
-			type = oe->type;
-	} else
-		die("Invalid ref name or SHA1 expression: %s", from);
-	read_next_command();
-
-	/* original-oid ... */
-	parse_original_identifier();
-
-	/* tagger ... */
-	if (skip_prefix(command_buf.buf, "tagger ", &v)) {
-		tagger = parse_ident(v);
-		read_next_command();
-	} else
-		tagger = NULL;
-
-	/* tag payload/message */
-	parse_data(&msg, 0, NULL);
-
-	/* build the tag object */
-	strbuf_reset(&new_data);
-
-	strbuf_addf(&new_data,
-		    "object %s\n"
-		    "type %s\n"
-		    "tag %s\n",
-		    oid_to_hex(&oid), type_name(type), t->name);
-	if (tagger)
-		strbuf_addf(&new_data,
-			    "tagger %s\n", tagger);
-	strbuf_addch(&new_data, '\n');
-	strbuf_addbuf(&new_data, &msg);
-	free(tagger);
-
-	if (store_object(OBJ_TAG, &new_data, NULL, &t->oid, next_mark))
-		t->pack_id = MAX_PACK_ID;
-	else
-		t->pack_id = pack_id;
-}
-
-static void parse_reset_branch(const char *arg)
-{
-	struct branch *b;
-	const char *tag_name;
-
-	b = lookup_branch(arg);
-	if (b) {
-		oidclr(&b->oid);
-		oidclr(&b->branch_tree.versions[0].oid);
-		oidclr(&b->branch_tree.versions[1].oid);
-		if (b->branch_tree.tree) {
-			release_tree_content_recursive(b->branch_tree.tree);
-			b->branch_tree.tree = NULL;
-		}
-	}
-	else
-		b = new_branch(arg);
-	read_next_command();
-	parse_from(b);
-	if (b->delete && skip_prefix(b->name, "refs/tags/", &tag_name)) {
-		/*
-		 * Elsewhere, we call dump_branches() before dump_tags(),
-		 * and dump_branches() will handle ref deletions first, so
-		 * in order to make sure the deletion actually takes effect,
-		 * we need to remove the tag from our list of tags to update.
-		 *
-		 * NEEDSWORK: replace list of tags with hashmap for faster
-		 * deletion?
-		 */
-		struct tag *t, *prev = NULL;
-		for (t = first_tag; t; t = t->next_tag) {
-			if (!strcmp(t->name, tag_name))
-				break;
-			prev = t;
-		}
-		if (t) {
-			if (prev)
-				prev->next_tag = t->next_tag;
-			else
-				first_tag = t->next_tag;
-			if (!t->next_tag)
-				last_tag = prev;
-			/* There is no mem_pool_free(t) function to call. */
-		}
-	}
-	if (command_buf.len > 0)
-		unread_command_buf = 1;
-}
-
-static void cat_blob_write(const char *buf, unsigned long size)
-{
-	if (write_in_full(cat_blob_fd, buf, size) < 0)
-		die_errno("Write to frontend failed");
-}
-
-static void cat_blob(struct object_entry *oe, struct object_id *oid)
-{
-	struct strbuf line = STRBUF_INIT;
-	unsigned long size;
-	enum object_type type = 0;
-	char *buf;
-
-	if (!oe || oe->pack_id == MAX_PACK_ID) {
-		buf = read_object_file(oid, &type, &size);
-	} else {
-		type = oe->type;
-		buf = gfi_unpack_entry(oe, &size);
-	}
-
-	/*
-	 * Output based on batch_one_object() from cat-file.c.
-	 */
-	if (type <= 0) {
-		strbuf_reset(&line);
-		strbuf_addf(&line, "%s missing\n", oid_to_hex(oid));
-		cat_blob_write(line.buf, line.len);
-		strbuf_release(&line);
-		free(buf);
-		return;
-	}
-	if (!buf)
-		die("Can't read object %s", oid_to_hex(oid));
-	if (type != OBJ_BLOB)
-		die("Object %s is a %s but a blob was expected.",
-		    oid_to_hex(oid), type_name(type));
-	strbuf_reset(&line);
-	strbuf_addf(&line, "%s %s %"PRIuMAX"\n", oid_to_hex(oid),
-		    type_name(type), (uintmax_t)size);
-	cat_blob_write(line.buf, line.len);
-	strbuf_release(&line);
-	cat_blob_write(buf, size);
-	cat_blob_write("\n", 1);
-	if (oe && oe->pack_id == pack_id) {
-		last_blob.offset = oe->idx.offset;
-		strbuf_attach(&last_blob.data, buf, size, size);
-		last_blob.depth = oe->depth;
-	} else
-		free(buf);
-}
-
-static void parse_get_mark(const char *p)
-{
-	struct object_entry *oe;
-	char output[GIT_MAX_HEXSZ + 2];
-
-	/* get-mark SP <object> LF */
-	if (*p != ':')
-		die("Not a mark: %s", p);
-
-	oe = find_mark(marks, parse_mark_ref_eol(p));
-	if (!oe)
-		die("Unknown mark: %s", command_buf.buf);
-
-	xsnprintf(output, sizeof(output), "%s\n", oid_to_hex(&oe->idx.oid));
-	cat_blob_write(output, the_hash_algo->hexsz + 1);
-}
-
-static void parse_cat_blob(const char *p)
-{
-	struct object_entry *oe;
-	struct object_id oid;
-
-	/* cat-blob SP <object> LF */
-	if (*p == ':') {
-		oe = find_mark(marks, parse_mark_ref_eol(p));
-		if (!oe)
-			die("Unknown mark: %s", command_buf.buf);
-		oidcpy(&oid, &oe->idx.oid);
-	} else {
-		if (parse_mapped_oid_hex(p, &oid, &p))
-			die("Invalid dataref: %s", command_buf.buf);
-		if (*p)
-			die("Garbage after SHA1: %s", command_buf.buf);
-		oe = find_object(&oid);
-	}
-
-	cat_blob(oe, &oid);
-}
-
-static struct object_entry *dereference(struct object_entry *oe,
-					struct object_id *oid)
-{
-	unsigned long size;
-	char *buf = NULL;
-	const unsigned hexsz = the_hash_algo->hexsz;
-
-	if (!oe) {
-		enum object_type type = oid_object_info(the_repository, oid,
-							NULL);
-		if (type < 0)
-			die("object not found: %s", oid_to_hex(oid));
-		/* cache it! */
-		oe = insert_object(oid);
-		oe->type = type;
-		oe->pack_id = MAX_PACK_ID;
-		oe->idx.offset = 1;
-	}
-	switch (oe->type) {
-	case OBJ_TREE:	/* easy case. */
-		return oe;
-	case OBJ_COMMIT:
-	case OBJ_TAG:
-		break;
-	default:
-		die("Not a tree-ish: %s", command_buf.buf);
-	}
-
-	if (oe->pack_id != MAX_PACK_ID) {	/* in a pack being written */
-		buf = gfi_unpack_entry(oe, &size);
-	} else {
-		enum object_type unused;
-		buf = read_object_file(oid, &unused, &size);
-	}
-	if (!buf)
-		die("Can't load object %s", oid_to_hex(oid));
-
-	/* Peel one layer. */
-	switch (oe->type) {
-	case OBJ_TAG:
-		if (size < hexsz + strlen("object ") ||
-		    get_oid_hex(buf + strlen("object "), oid))
-			die("Invalid SHA1 in tag: %s", command_buf.buf);
-		break;
-	case OBJ_COMMIT:
-		if (size < hexsz + strlen("tree ") ||
-		    get_oid_hex(buf + strlen("tree "), oid))
-			die("Invalid SHA1 in commit: %s", command_buf.buf);
-	}
-
-	free(buf);
-	return find_object(oid);
-}
-
-static void insert_mapped_mark(uintmax_t mark, void *object, void *cbp)
-{
-	struct object_id *fromoid = object;
-	struct object_id *tooid = find_mark(cbp, mark);
-	int ret;
-	khiter_t it;
-
-	it = kh_put_oid_map(sub_oid_map, *fromoid, &ret);
-	/* We've already seen this object. */
-	if (ret == 0)
-		return;
-	kh_value(sub_oid_map, it) = tooid;
-}
-
-static void build_mark_map_one(struct mark_set *from, struct mark_set *to)
-{
-	for_each_mark(from, 0, insert_mapped_mark, to);
-}
-
-static void build_mark_map(struct string_list *from, struct string_list *to)
-{
-	struct string_list_item *fromp, *top;
-
-	sub_oid_map = kh_init_oid_map();
-
-	for_each_string_list_item(fromp, from) {
-		top = string_list_lookup(to, fromp->string);
-		if (!fromp->util) {
-			die(_("Missing from marks for submodule '%s'"), fromp->string);
-		} else if (!top || !top->util) {
-			die(_("Missing to marks for submodule '%s'"), fromp->string);
-		}
-		build_mark_map_one(fromp->util, top->util);
-	}
-}
-
-static struct object_entry *parse_treeish_dataref(const char **p)
-{
-	struct object_id oid;
-	struct object_entry *e;
-
-	if (**p == ':') {	/* <mark> */
-		e = find_mark(marks, parse_mark_ref_space(p));
-		if (!e)
-			die("Unknown mark: %s", command_buf.buf);
-		oidcpy(&oid, &e->idx.oid);
-	} else {	/* <sha1> */
-		if (parse_mapped_oid_hex(*p, &oid, p))
-			die("Invalid dataref: %s", command_buf.buf);
-		e = find_object(&oid);
-		if (*(*p)++ != ' ')
-			die("Missing space after tree-ish: %s", command_buf.buf);
-	}
-
-	while (!e || e->type != OBJ_TREE)
-		e = dereference(e, &oid);
-	return e;
-}
-
-static void print_ls(int mode, const unsigned char *hash, const char *path)
-{
-	static struct strbuf line = STRBUF_INIT;
-
-	/* See show_tree(). */
-	const char *type =
-		S_ISGITLINK(mode) ? commit_type :
-		S_ISDIR(mode) ? tree_type :
-		blob_type;
-
-	if (!mode) {
-		/* missing SP path LF */
-		strbuf_reset(&line);
-		strbuf_addstr(&line, "missing ");
-		quote_c_style(path, &line, NULL, 0);
-		strbuf_addch(&line, '\n');
-	} else {
-		/* mode SP type SP object_name TAB path LF */
-		strbuf_reset(&line);
-		strbuf_addf(&line, "%06o %s %s\t",
-				mode & ~NO_DELTA, type, hash_to_hex(hash));
-		quote_c_style(path, &line, NULL, 0);
-		strbuf_addch(&line, '\n');
-	}
-	cat_blob_write(line.buf, line.len);
-}
-
-static void parse_ls(const char *p, struct branch *b)
-{
-	struct tree_entry *root = NULL;
-	struct tree_entry leaf = {NULL};
-
-	/* ls SP (<tree-ish> SP)? <path> */
-	if (*p == '"') {
-		if (!b)
-			die("Not in a commit: %s", command_buf.buf);
-		root = &b->branch_tree;
-	} else {
-		struct object_entry *e = parse_treeish_dataref(&p);
-		root = new_tree_entry();
-		oidcpy(&root->versions[1].oid, &e->idx.oid);
-		if (!is_null_oid(&root->versions[1].oid))
-			root->versions[1].mode = S_IFDIR;
-		load_tree(root);
-	}
-	if (*p == '"') {
-		static struct strbuf uq = STRBUF_INIT;
-		const char *endp;
-		strbuf_reset(&uq);
-		if (unquote_c_style(&uq, p, &endp))
-			die("Invalid path: %s", command_buf.buf);
-		if (*endp)
-			die("Garbage after path in: %s", command_buf.buf);
-		p = uq.buf;
-	}
-	tree_content_get(root, p, &leaf, 1);
-	/*
-	 * A directory in preparation would have a sha1 of zero
-	 * until it is saved.  Save, for simplicity.
-	 */
-	if (S_ISDIR(leaf.versions[1].mode))
-		store_tree(&leaf);
-
-	print_ls(leaf.versions[1].mode, leaf.versions[1].oid.hash, p);
-	if (leaf.tree)
-		release_tree_content_recursive(leaf.tree);
-	if (!b || root != &b->branch_tree)
-		release_tree_entry(root);
-}
-
-static void checkpoint(void)
-{
-	checkpoint_requested = 0;
-	if (object_count) {
-		cycle_packfile();
-	}
-	dump_branches();
-	dump_tags();
-	dump_marks();
-}
-
-static void parse_checkpoint(void)
-{
-	checkpoint_requested = 1;
-	skip_optional_lf();
-}
-
-static void parse_progress(void)
-{
-	fwrite(command_buf.buf, 1, command_buf.len, stdout);
-	fputc('\n', stdout);
-	fflush(stdout);
-	skip_optional_lf();
-}
-
-static void parse_alias(void)
-{
-	struct object_entry *e;
-	struct branch b;
-
-	skip_optional_lf();
-	read_next_command();
-
-	/* mark ... */
-	parse_mark();
-	if (!next_mark)
-		die(_("Expected 'mark' command, got %s"), command_buf.buf);
-
-	/* to ... */
-	memset(&b, 0, sizeof(b));
-	if (!parse_objectish_with_prefix(&b, "to "))
-		die(_("Expected 'to' command, got %s"), command_buf.buf);
-	e = find_object(&b.oid);
-	assert(e);
-	insert_mark(marks, next_mark, e);
-}
-
-static char* make_fast_import_path(const char *path)
-{
-	if (!relative_marks_paths || is_absolute_path(path))
-		return xstrdup(path);
-	return git_pathdup("info/fast-import/%s", path);
-}
-
-static void option_import_marks(const char *marks,
-					int from_stream, int ignore_missing)
-{
-	if (import_marks_file) {
-		if (from_stream)
-			die("Only one import-marks command allowed per stream");
-
-		/* read previous mark file */
-		if(!import_marks_file_from_stream)
-			read_marks();
-	}
-
-	import_marks_file = make_fast_import_path(marks);
-	import_marks_file_from_stream = from_stream;
-	import_marks_file_ignore_missing = ignore_missing;
-}
-
-static void option_date_format(const char *fmt)
-{
-	if (!strcmp(fmt, "raw"))
-		whenspec = WHENSPEC_RAW;
-	else if (!strcmp(fmt, "raw-permissive"))
-		whenspec = WHENSPEC_RAW_PERMISSIVE;
-	else if (!strcmp(fmt, "rfc2822"))
-		whenspec = WHENSPEC_RFC2822;
-	else if (!strcmp(fmt, "now"))
-		whenspec = WHENSPEC_NOW;
-	else
-		die("unknown --date-format argument %s", fmt);
-}
-
-static unsigned long ulong_arg(const char *option, const char *arg)
-{
-	char *endptr;
-	unsigned long rv = strtoul(arg, &endptr, 0);
-	if (strchr(arg, '-') || endptr == arg || *endptr)
-		die("%s: argument must be a non-negative integer", option);
-	return rv;
-}
-
-static void option_depth(const char *depth)
-{
-	max_depth = ulong_arg("--depth", depth);
-	if (max_depth > MAX_DEPTH)
-		die("--depth cannot exceed %u", MAX_DEPTH);
-}
-
-static void option_active_branches(const char *branches)
-{
-	max_active_branches = ulong_arg("--active-branches", branches);
-}
-
-static void option_export_marks(const char *marks)
-{
-	export_marks_file = make_fast_import_path(marks);
-}
-
-static void option_cat_blob_fd(const char *fd)
-{
-	unsigned long n = ulong_arg("--cat-blob-fd", fd);
-	if (n > (unsigned long) INT_MAX)
-		die("--cat-blob-fd cannot exceed %d", INT_MAX);
-	cat_blob_fd = (int) n;
-}
-
-static void option_export_pack_edges(const char *edges)
-{
-	if (pack_edges)
-		fclose(pack_edges);
-	pack_edges = xfopen(edges, "a");
-}
-
-static void option_rewrite_submodules(const char *arg, struct string_list *list)
-{
-	struct mark_set *ms;
-	FILE *fp;
-	char *s = xstrdup(arg);
-	char *f = strchr(s, ':');
-	if (!f)
-		die(_("Expected format name:filename for submodule rewrite option"));
-	*f = '\0';
-	f++;
-	ms = xcalloc(1, sizeof(*ms));
-	string_list_insert(list, s)->util = ms;
-
-	fp = fopen(f, "r");
-	if (!fp)
-		die_errno("cannot read '%s'", f);
-	read_mark_file(ms, fp, insert_oid_entry);
-	fclose(fp);
-}
-
-static int parse_one_option(const char *option)
-{
-	if (skip_prefix(option, "max-pack-size=", &option)) {
-		unsigned long v;
-		if (!git_parse_ulong(option, &v))
-			return 0;
-		if (v < 8192) {
-			warning("max-pack-size is now in bytes, assuming --max-pack-size=%lum", v);
-			v *= 1024 * 1024;
-		} else if (v < 1024 * 1024) {
-			warning("minimum max-pack-size is 1 MiB");
-			v = 1024 * 1024;
-		}
-		max_packsize = v;
-	} else if (skip_prefix(option, "big-file-threshold=", &option)) {
-		unsigned long v;
-		if (!git_parse_ulong(option, &v))
-			return 0;
-		big_file_threshold = v;
-	} else if (skip_prefix(option, "depth=", &option)) {
-		option_depth(option);
-	} else if (skip_prefix(option, "active-branches=", &option)) {
-		option_active_branches(option);
-	} else if (skip_prefix(option, "export-pack-edges=", &option)) {
-		option_export_pack_edges(option);
-	} else if (!strcmp(option, "quiet")) {
-		show_stats = 0;
-	} else if (!strcmp(option, "stats")) {
-		show_stats = 1;
-	} else if (!strcmp(option, "allow-unsafe-features")) {
-		; /* already handled during early option parsing */
-	} else {
-		return 0;
-	}
-
-	return 1;
-}
-
-static void check_unsafe_feature(const char *feature, int from_stream)
-{
-	if (from_stream && !allow_unsafe_features)
-		die(_("feature '%s' forbidden in input without --allow-unsafe-features"),
-		    feature);
-}
-
-static int parse_one_feature(const char *feature, int from_stream)
-{
-	const char *arg;
-
-	if (skip_prefix(feature, "date-format=", &arg)) {
-		option_date_format(arg);
-	} else if (skip_prefix(feature, "import-marks=", &arg)) {
-		check_unsafe_feature("import-marks", from_stream);
-		option_import_marks(arg, from_stream, 0);
-	} else if (skip_prefix(feature, "import-marks-if-exists=", &arg)) {
-		check_unsafe_feature("import-marks-if-exists", from_stream);
-		option_import_marks(arg, from_stream, 1);
-	} else if (skip_prefix(feature, "export-marks=", &arg)) {
-		check_unsafe_feature(feature, from_stream);
-		option_export_marks(arg);
-	} else if (!strcmp(feature, "alias")) {
-		; /* Don't die - this feature is supported */
-	} else if (skip_prefix(feature, "rewrite-submodules-to=", &arg)) {
-		option_rewrite_submodules(arg, &sub_marks_to);
-	} else if (skip_prefix(feature, "rewrite-submodules-from=", &arg)) {
-		option_rewrite_submodules(arg, &sub_marks_from);
-	} else if (skip_prefix(feature, "rewrite-submodules-from=", &arg)) {
-	} else if (!strcmp(feature, "get-mark")) {
-		; /* Don't die - this feature is supported */
-	} else if (!strcmp(feature, "cat-blob")) {
-		; /* Don't die - this feature is supported */
-	} else if (!strcmp(feature, "relative-marks")) {
-		relative_marks_paths = 1;
-	} else if (!strcmp(feature, "no-relative-marks")) {
-		relative_marks_paths = 0;
-	} else if (!strcmp(feature, "done")) {
-		require_explicit_termination = 1;
-	} else if (!strcmp(feature, "force")) {
-		force_update = 1;
-	} else if (!strcmp(feature, "notes") || !strcmp(feature, "ls")) {
-		; /* do nothing; we have the feature */
-	} else {
-		return 0;
-	}
-
-	return 1;
-}
-
-static void parse_feature(const char *feature)
-{
-	if (seen_data_command)
-		die("Got feature command '%s' after data command", feature);
-
-	if (parse_one_feature(feature, 1))
-		return;
-
-	die("This version of fast-import does not support feature %s.", feature);
-}
-
-static void parse_option(const char *option)
-{
-	if (seen_data_command)
-		die("Got option command '%s' after data command", option);
-
-	if (parse_one_option(option))
-		return;
-
-	die("This version of fast-import does not support option: %s", option);
-}
-
-static void git_pack_config(void)
-{
-	int indexversion_value;
-	int limit;
-	unsigned long packsizelimit_value;
-
-	if (!git_config_get_ulong("pack.depth", &max_depth)) {
-		if (max_depth > MAX_DEPTH)
-			max_depth = MAX_DEPTH;
-	}
-	if (!git_config_get_int("pack.indexversion", &indexversion_value)) {
-		pack_idx_opts.version = indexversion_value;
-		if (pack_idx_opts.version > 2)
-			git_die_config("pack.indexversion",
-					"bad pack.indexversion=%"PRIu32, pack_idx_opts.version);
-	}
-	if (!git_config_get_ulong("pack.packsizelimit", &packsizelimit_value))
-		max_packsize = packsizelimit_value;
-
-	if (!git_config_get_int("fastimport.unpacklimit", &limit))
-		unpack_limit = limit;
-	else if (!git_config_get_int("transfer.unpacklimit", &limit))
-		unpack_limit = limit;
-
-	git_config(git_default_config, NULL);
-}
-
-static const char fast_import_usage[] =
-"git fast-import [--date-format=<f>] [--max-pack-size=<n>] [--big-file-threshold=<n>] [--depth=<n>] [--active-branches=<n>] [--export-marks=<marks.file>]";
-
-static void parse_argv(void)
-{
-	unsigned int i;
-
-	for (i = 1; i < global_argc; i++) {
-		const char *a = global_argv[i];
-
-		if (*a != '-' || !strcmp(a, "--"))
-			break;
-
-		if (!skip_prefix(a, "--", &a))
-			die("unknown option %s", a);
-
-		if (parse_one_option(a))
-			continue;
-
-		if (parse_one_feature(a, 0))
-			continue;
-
-		if (skip_prefix(a, "cat-blob-fd=", &a)) {
-			option_cat_blob_fd(a);
-			continue;
-		}
-
-		die("unknown option --%s", a);
-	}
-	if (i != global_argc)
-		usage(fast_import_usage);
-
-	seen_data_command = 1;
-	if (import_marks_file)
-		read_marks();
-	build_mark_map(&sub_marks_from, &sub_marks_to);
-}
-
-int cmd_fast_import(int argc, const char **argv, const char *prefix)
-{
-	unsigned int i;
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage(fast_import_usage);
-
-	reset_pack_idx_option(&pack_idx_opts);
-	git_pack_config();
-
-	alloc_objects(object_entry_alloc);
-	strbuf_init(&command_buf, 0);
-	atom_table = xcalloc(atom_table_sz, sizeof(struct atom_str*));
-	branch_table = xcalloc(branch_table_sz, sizeof(struct branch*));
-	avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*));
-	marks = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct mark_set));
-
-	hashmap_init(&object_table, object_entry_hashcmp, NULL, 0);
-
-	/*
-	 * We don't parse most options until after we've seen the set of
-	 * "feature" lines at the start of the stream (which allows the command
-	 * line to override stream data). But we must do an early parse of any
-	 * command-line options that impact how we interpret the feature lines.
-	 */
-	for (i = 1; i < argc; i++) {
-		const char *arg = argv[i];
-		if (*arg != '-' || !strcmp(arg, "--"))
-			break;
-		if (!strcmp(arg, "--allow-unsafe-features"))
-			allow_unsafe_features = 1;
-	}
-
-	global_argc = argc;
-	global_argv = argv;
-
-	rc_free = mem_pool_alloc(&fi_mem_pool, cmd_save * sizeof(*rc_free));
-	for (i = 0; i < (cmd_save - 1); i++)
-		rc_free[i].next = &rc_free[i + 1];
-	rc_free[cmd_save - 1].next = NULL;
-
-	start_packfile();
-	set_die_routine(die_nicely);
-	set_checkpoint_signal();
-	while (read_next_command() != EOF) {
-		const char *v;
-		if (!strcmp("blob", command_buf.buf))
-			parse_new_blob();
-		else if (skip_prefix(command_buf.buf, "commit ", &v))
-			parse_new_commit(v);
-		else if (skip_prefix(command_buf.buf, "tag ", &v))
-			parse_new_tag(v);
-		else if (skip_prefix(command_buf.buf, "reset ", &v))
-			parse_reset_branch(v);
-		else if (skip_prefix(command_buf.buf, "ls ", &v))
-			parse_ls(v, NULL);
-		else if (skip_prefix(command_buf.buf, "cat-blob ", &v))
-			parse_cat_blob(v);
-		else if (skip_prefix(command_buf.buf, "get-mark ", &v))
-			parse_get_mark(v);
-		else if (!strcmp("checkpoint", command_buf.buf))
-			parse_checkpoint();
-		else if (!strcmp("done", command_buf.buf))
-			break;
-		else if (!strcmp("alias", command_buf.buf))
-			parse_alias();
-		else if (starts_with(command_buf.buf, "progress "))
-			parse_progress();
-		else if (skip_prefix(command_buf.buf, "feature ", &v))
-			parse_feature(v);
-		else if (skip_prefix(command_buf.buf, "option git ", &v))
-			parse_option(v);
-		else if (starts_with(command_buf.buf, "option "))
-			/* ignore non-git options*/;
-		else
-			die("Unsupported command: %s", command_buf.buf);
-
-		if (checkpoint_requested)
-			checkpoint();
-	}
-
-	/* argv hasn't been parsed yet, do so */
-	if (!seen_data_command)
-		parse_argv();
-
-	if (require_explicit_termination && feof(stdin))
-		die("stream ends early");
-
-	end_packfile();
-
-	dump_branches();
-	dump_tags();
-	unkeep_all_packs();
-	dump_marks();
-
-	if (pack_edges)
-		fclose(pack_edges);
-
-	if (show_stats) {
-		uintmax_t total_count = 0, duplicate_count = 0;
-		for (i = 0; i < ARRAY_SIZE(object_count_by_type); i++)
-			total_count += object_count_by_type[i];
-		for (i = 0; i < ARRAY_SIZE(duplicate_count_by_type); i++)
-			duplicate_count += duplicate_count_by_type[i];
-
-		fprintf(stderr, "%s statistics:\n", argv[0]);
-		fprintf(stderr, "---------------------------------------------------------------------\n");
-		fprintf(stderr, "Alloc'd objects: %10" PRIuMAX "\n", alloc_count);
-		fprintf(stderr, "Total objects:   %10" PRIuMAX " (%10" PRIuMAX " duplicates                  )\n", total_count, duplicate_count);
-		fprintf(stderr, "      blobs  :   %10" PRIuMAX " (%10" PRIuMAX " duplicates %10" PRIuMAX " deltas of %10" PRIuMAX" attempts)\n", object_count_by_type[OBJ_BLOB], duplicate_count_by_type[OBJ_BLOB], delta_count_by_type[OBJ_BLOB], delta_count_attempts_by_type[OBJ_BLOB]);
-		fprintf(stderr, "      trees  :   %10" PRIuMAX " (%10" PRIuMAX " duplicates %10" PRIuMAX " deltas of %10" PRIuMAX" attempts)\n", object_count_by_type[OBJ_TREE], duplicate_count_by_type[OBJ_TREE], delta_count_by_type[OBJ_TREE], delta_count_attempts_by_type[OBJ_TREE]);
-		fprintf(stderr, "      commits:   %10" PRIuMAX " (%10" PRIuMAX " duplicates %10" PRIuMAX " deltas of %10" PRIuMAX" attempts)\n", object_count_by_type[OBJ_COMMIT], duplicate_count_by_type[OBJ_COMMIT], delta_count_by_type[OBJ_COMMIT], delta_count_attempts_by_type[OBJ_COMMIT]);
-		fprintf(stderr, "      tags   :   %10" PRIuMAX " (%10" PRIuMAX " duplicates %10" PRIuMAX " deltas of %10" PRIuMAX" attempts)\n", object_count_by_type[OBJ_TAG], duplicate_count_by_type[OBJ_TAG], delta_count_by_type[OBJ_TAG], delta_count_attempts_by_type[OBJ_TAG]);
-		fprintf(stderr, "Total branches:  %10lu (%10lu loads     )\n", branch_count, branch_load_count);
-		fprintf(stderr, "      marks:     %10" PRIuMAX " (%10" PRIuMAX " unique    )\n", (((uintmax_t)1) << marks->shift) * 1024, marks_set_count);
-		fprintf(stderr, "      atoms:     %10u\n", atom_cnt);
-		fprintf(stderr, "Memory total:    %10" PRIuMAX " KiB\n", (tree_entry_allocd + fi_mem_pool.pool_alloc + alloc_count*sizeof(struct object_entry))/1024);
-		fprintf(stderr, "       pools:    %10lu KiB\n", (unsigned long)((tree_entry_allocd + fi_mem_pool.pool_alloc) /1024));
-		fprintf(stderr, "     objects:    %10" PRIuMAX " KiB\n", (alloc_count*sizeof(struct object_entry))/1024);
-		fprintf(stderr, "---------------------------------------------------------------------\n");
-		pack_report();
-		fprintf(stderr, "---------------------------------------------------------------------\n");
-		fprintf(stderr, "\n");
-	}
-
-	return failure ? 1 : 0;
-}
diff --git a/third_party/git/builtin/fetch-pack.c b/third_party/git/builtin/fetch-pack.c
deleted file mode 100644
index 58b7c1fbdc47..000000000000
--- a/third_party/git/builtin/fetch-pack.c
+++ /dev/null
@@ -1,271 +0,0 @@
-#include "builtin.h"
-#include "pkt-line.h"
-#include "fetch-pack.h"
-#include "remote.h"
-#include "connect.h"
-#include "oid-array.h"
-#include "protocol.h"
-
-static const char fetch_pack_usage[] =
-"git fetch-pack [--all] [--stdin] [--quiet | -q] [--keep | -k] [--thin] "
-"[--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] "
-"[--no-progress] [--diag-url] [-v] [<host>:]<directory> [<refs>...]";
-
-static void add_sought_entry(struct ref ***sought, int *nr, int *alloc,
-			     const char *name)
-{
-	struct ref *ref;
-	struct object_id oid;
-	const char *p;
-
-	if (!parse_oid_hex(name, &oid, &p)) {
-		if (*p == ' ') {
-			/* <oid> <ref>, find refname */
-			name = p + 1;
-		} else if (*p == '\0') {
-			; /* <oid>, leave oid as name */
-		} else {
-			/* <ref>, clear cruft from oid */
-			oidclr(&oid);
-		}
-	} else {
-		/* <ref>, clear cruft from get_oid_hex */
-		oidclr(&oid);
-	}
-
-	ref = alloc_ref(name);
-	oidcpy(&ref->old_oid, &oid);
-	(*nr)++;
-	ALLOC_GROW(*sought, *nr, *alloc);
-	(*sought)[*nr - 1] = ref;
-}
-
-int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
-{
-	int i, ret;
-	struct ref *ref = NULL;
-	const char *dest = NULL;
-	struct ref **sought = NULL;
-	int nr_sought = 0, alloc_sought = 0;
-	int fd[2];
-	struct string_list pack_lockfiles = STRING_LIST_INIT_DUP;
-	struct string_list *pack_lockfiles_ptr = NULL;
-	struct child_process *conn;
-	struct fetch_pack_args args;
-	struct oid_array shallow = OID_ARRAY_INIT;
-	struct string_list deepen_not = STRING_LIST_INIT_DUP;
-	struct packet_reader reader;
-	enum protocol_version version;
-
-	fetch_if_missing = 0;
-
-	packet_trace_identity("fetch-pack");
-
-	memset(&args, 0, sizeof(args));
-	args.uploadpack = "git-upload-pack";
-
-	for (i = 1; i < argc && *argv[i] == '-'; i++) {
-		const char *arg = argv[i];
-
-		if (skip_prefix(arg, "--upload-pack=", &arg)) {
-			args.uploadpack = arg;
-			continue;
-		}
-		if (skip_prefix(arg, "--exec=", &arg)) {
-			args.uploadpack = arg;
-			continue;
-		}
-		if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) {
-			args.quiet = 1;
-			continue;
-		}
-		if (!strcmp("--keep", arg) || !strcmp("-k", arg)) {
-			args.lock_pack = args.keep_pack;
-			args.keep_pack = 1;
-			continue;
-		}
-		if (!strcmp("--thin", arg)) {
-			args.use_thin_pack = 1;
-			continue;
-		}
-		if (!strcmp("--include-tag", arg)) {
-			args.include_tag = 1;
-			continue;
-		}
-		if (!strcmp("--all", arg)) {
-			args.fetch_all = 1;
-			continue;
-		}
-		if (!strcmp("--stdin", arg)) {
-			args.stdin_refs = 1;
-			continue;
-		}
-		if (!strcmp("--diag-url", arg)) {
-			args.diag_url = 1;
-			continue;
-		}
-		if (!strcmp("-v", arg)) {
-			args.verbose = 1;
-			continue;
-		}
-		if (skip_prefix(arg, "--depth=", &arg)) {
-			args.depth = strtol(arg, NULL, 0);
-			continue;
-		}
-		if (skip_prefix(arg, "--shallow-since=", &arg)) {
-			args.deepen_since = xstrdup(arg);
-			continue;
-		}
-		if (skip_prefix(arg, "--shallow-exclude=", &arg)) {
-			string_list_append(&deepen_not, arg);
-			continue;
-		}
-		if (!strcmp(arg, "--deepen-relative")) {
-			args.deepen_relative = 1;
-			continue;
-		}
-		if (!strcmp("--no-progress", arg)) {
-			args.no_progress = 1;
-			continue;
-		}
-		if (!strcmp("--stateless-rpc", arg)) {
-			args.stateless_rpc = 1;
-			continue;
-		}
-		if (!strcmp("--lock-pack", arg)) {
-			args.lock_pack = 1;
-			pack_lockfiles_ptr = &pack_lockfiles;
-			continue;
-		}
-		if (!strcmp("--check-self-contained-and-connected", arg)) {
-			args.check_self_contained_and_connected = 1;
-			continue;
-		}
-		if (!strcmp("--cloning", arg)) {
-			args.cloning = 1;
-			continue;
-		}
-		if (!strcmp("--update-shallow", arg)) {
-			args.update_shallow = 1;
-			continue;
-		}
-		if (!strcmp("--from-promisor", arg)) {
-			args.from_promisor = 1;
-			continue;
-		}
-		if (skip_prefix(arg, ("--" CL_ARG__FILTER "="), &arg)) {
-			parse_list_objects_filter(&args.filter_options, arg);
-			continue;
-		}
-		if (!strcmp(arg, ("--no-" CL_ARG__FILTER))) {
-			list_objects_filter_set_no_filter(&args.filter_options);
-			continue;
-		}
-		usage(fetch_pack_usage);
-	}
-	if (deepen_not.nr)
-		args.deepen_not = &deepen_not;
-
-	if (i < argc)
-		dest = argv[i++];
-	else
-		usage(fetch_pack_usage);
-
-	/*
-	 * Copy refs from cmdline to growable list, then append any
-	 * refs from the standard input:
-	 */
-	for (; i < argc; i++)
-		add_sought_entry(&sought, &nr_sought, &alloc_sought, argv[i]);
-	if (args.stdin_refs) {
-		if (args.stateless_rpc) {
-			/* in stateless RPC mode we use pkt-line to read
-			 * from stdin, until we get a flush packet
-			 */
-			for (;;) {
-				char *line = packet_read_line(0, NULL);
-				if (!line)
-					break;
-				add_sought_entry(&sought, &nr_sought,  &alloc_sought, line);
-			}
-		}
-		else {
-			/* read from stdin one ref per line, until EOF */
-			struct strbuf line = STRBUF_INIT;
-			while (strbuf_getline_lf(&line, stdin) != EOF)
-				add_sought_entry(&sought, &nr_sought, &alloc_sought, line.buf);
-			strbuf_release(&line);
-		}
-	}
-
-	if (args.stateless_rpc) {
-		conn = NULL;
-		fd[0] = 0;
-		fd[1] = 1;
-	} else {
-		int flags = args.verbose ? CONNECT_VERBOSE : 0;
-		if (args.diag_url)
-			flags |= CONNECT_DIAG_URL;
-		conn = git_connect(fd, dest, args.uploadpack,
-				   flags);
-		if (!conn)
-			return args.diag_url ? 0 : 1;
-	}
-
-	packet_reader_init(&reader, fd[0], NULL, 0,
-			   PACKET_READ_CHOMP_NEWLINE |
-			   PACKET_READ_GENTLE_ON_EOF |
-			   PACKET_READ_DIE_ON_ERR_PACKET);
-
-	version = discover_version(&reader);
-	switch (version) {
-	case protocol_v2:
-		get_remote_refs(fd[1], &reader, &ref, 0, NULL, NULL, args.stateless_rpc);
-		break;
-	case protocol_v1:
-	case protocol_v0:
-		get_remote_heads(&reader, &ref, 0, NULL, &shallow);
-		break;
-	case protocol_unknown_version:
-		BUG("unknown protocol version");
-	}
-
-	ref = fetch_pack(&args, fd, ref, sought, nr_sought,
-			 &shallow, pack_lockfiles_ptr, version);
-	if (pack_lockfiles.nr) {
-		int i;
-
-		printf("lock %s\n", pack_lockfiles.items[0].string);
-		fflush(stdout);
-		for (i = 1; i < pack_lockfiles.nr; i++)
-			warning(_("Lockfile created but not reported: %s"),
-				pack_lockfiles.items[i].string);
-	}
-	if (args.check_self_contained_and_connected &&
-	    args.self_contained_and_connected) {
-		printf("connectivity-ok\n");
-		fflush(stdout);
-	}
-	close(fd[0]);
-	close(fd[1]);
-	if (finish_connect(conn))
-		return 1;
-
-	ret = !ref;
-
-	/*
-	 * If the heads to pull were given, we should have consumed
-	 * all of them by matching the remote.  Otherwise, 'git fetch
-	 * remote no-such-ref' would silently succeed without issuing
-	 * an error.
-	 */
-	ret |= report_unmatched_refs(sought, nr_sought);
-
-	while (ref) {
-		printf("%s %s\n",
-		       oid_to_hex(&ref->old_oid), ref->name);
-		ref = ref->next;
-	}
-
-	return ret;
-}
diff --git a/third_party/git/builtin/fetch.c b/third_party/git/builtin/fetch.c
deleted file mode 100644
index f9c3c49f14d9..000000000000
--- a/third_party/git/builtin/fetch.c
+++ /dev/null
@@ -1,1943 +0,0 @@
-/*
- * "git fetch"
- */
-#include "cache.h"
-#include "config.h"
-#include "repository.h"
-#include "refs.h"
-#include "refspec.h"
-#include "object-store.h"
-#include "oidset.h"
-#include "commit.h"
-#include "builtin.h"
-#include "string-list.h"
-#include "remote.h"
-#include "transport.h"
-#include "run-command.h"
-#include "parse-options.h"
-#include "sigchain.h"
-#include "submodule-config.h"
-#include "submodule.h"
-#include "connected.h"
-#include "strvec.h"
-#include "utf8.h"
-#include "packfile.h"
-#include "list-objects-filter-options.h"
-#include "commit-reach.h"
-#include "branch.h"
-#include "promisor-remote.h"
-#include "commit-graph.h"
-#include "shallow.h"
-
-#define FORCED_UPDATES_DELAY_WARNING_IN_MS (10 * 1000)
-
-static const char * const builtin_fetch_usage[] = {
-	N_("git fetch [<options>] [<repository> [<refspec>...]]"),
-	N_("git fetch [<options>] <group>"),
-	N_("git fetch --multiple [<options>] [(<repository> | <group>)...]"),
-	N_("git fetch --all [<options>]"),
-	NULL
-};
-
-enum {
-	TAGS_UNSET = 0,
-	TAGS_DEFAULT = 1,
-	TAGS_SET = 2
-};
-
-static int fetch_prune_config = -1; /* unspecified */
-static int fetch_show_forced_updates = 1;
-static uint64_t forced_updates_ms = 0;
-static int prune = -1; /* unspecified */
-#define PRUNE_BY_DEFAULT 0 /* do we prune by default? */
-
-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 write_fetch_head = 1;
-static int verbosity, deepen_relative, set_upstream;
-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 enum transport_family family;
-static const char *depth;
-static const char *deepen_since;
-static const char *upload_pack;
-static struct string_list deepen_not = STRING_LIST_INIT_NODUP;
-static struct strbuf default_rla = STRBUF_INIT;
-static struct transport *gtransport;
-static struct transport *gsecondary;
-static const char *submodule_prefix = "";
-static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
-static int recurse_submodules_default = RECURSE_SUBMODULES_ON_DEMAND;
-static int shown_url = 0;
-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 stdin_refspecs = 0;
-
-static int git_fetch_config(const char *k, const char *v, void *cb)
-{
-	if (!strcmp(k, "fetch.prune")) {
-		fetch_prune_config = git_config_bool(k, v);
-		return 0;
-	}
-
-	if (!strcmp(k, "fetch.prunetags")) {
-		fetch_prune_tags_config = git_config_bool(k, v);
-		return 0;
-	}
-
-	if (!strcmp(k, "fetch.showforcedupdates")) {
-		fetch_show_forced_updates = git_config_bool(k, v);
-		return 0;
-	}
-
-	if (!strcmp(k, "submodule.recurse")) {
-		int r = git_config_bool(k, v) ?
-			RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF;
-		recurse_submodules = r;
-	}
-
-	if (!strcmp(k, "submodule.fetchjobs")) {
-		submodule_fetch_jobs_config = 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);
-}
-
-static int parse_refmap_arg(const struct option *opt, const char *arg, int unset)
-{
-	BUG_ON_OPT_NEG(unset);
-
-	/*
-	 * "git fetch --refmap='' origin foo"
-	 * can be used to tell the command not to store anywhere
-	 */
-	refspec_append(&refmap, arg);
-
-	return 0;
-}
-
-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"),
-		   N_("path to upload pack on remote end")),
-	OPT__FORCE(&force, N_("force overwrite of local reference"), 0),
-	OPT_BOOL('m', "multiple", &multiple,
-		 N_("fetch from multiple remotes")),
-	OPT_SET_INT('t', "tags", &tags,
-		    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,
-		    N_("number of submodules fetched in parallel")),
-	OPT_BOOL('p', "prune", &prune,
-		 N_("prune remote-tracking branches no longer on remote")),
-	OPT_BOOL('P', "prune-tags", &prune_tags,
-		 N_("prune local tags no longer on remote and clobber changed tags")),
-	OPT_CALLBACK_F(0, "recurse-submodules", &recurse_submodules, N_("on-demand"),
-		    N_("control recursive fetching of submodules"),
-		    PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules),
-	OPT_BOOL(0, "dry-run", &dry_run,
-		 N_("dry run")),
-	OPT_BOOL(0, "write-fetch-head", &write_fetch_head,
-		 N_("write fetched references to the FETCH_HEAD file")),
-	OPT_BOOL('k', "keep", &keep, N_("keep downloaded pack")),
-	OPT_BOOL('u', "update-head-ok", &update_head_ok,
-		    N_("allow updating of HEAD ref")),
-	OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
-	OPT_STRING(0, "depth", &depth, N_("depth"),
-		   N_("deepen history of shallow clone")),
-	OPT_STRING(0, "shallow-since", &deepen_since, N_("time"),
-		   N_("deepen history of shallow repository based on time")),
-	OPT_STRING_LIST(0, "shallow-exclude", &deepen_not, N_("revision"),
-			N_("deepen history of shallow clone, excluding rev")),
-	OPT_INTEGER(0, "deepen", &deepen_relative,
-		    N_("deepen history of shallow clone")),
-	OPT_SET_INT_F(0, "unshallow", &unshallow,
-		      N_("convert to a complete repository"),
-		      1, PARSE_OPT_NONEG),
-	{ OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"),
-		   N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN },
-	OPT_CALLBACK_F(0, "recurse-submodules-default",
-		   &recurse_submodules_default, N_("on-demand"),
-		   N_("default for recursive fetching of submodules "
-		      "(lower priority than config files)"),
-		   PARSE_OPT_HIDDEN, option_fetch_parse_recurse_submodules),
-	OPT_BOOL(0, "update-shallow", &update_shallow,
-		 N_("accept refs that update .git/shallow")),
-	OPT_CALLBACK_F(0, "refmap", NULL, N_("refmap"),
-		       N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg),
-	OPT_STRING_LIST('o', "server-option", &server_options, N_("server-specific"), N_("option to transmit")),
-	OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
-			TRANSPORT_FAMILY_IPV4),
-	OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
-			TRANSPORT_FAMILY_IPV6),
-	OPT_STRING_LIST(0, "negotiation-tip", &negotiation_tip, N_("revision"),
-			N_("report that we have only objects reachable from this object")),
-	OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
-	OPT_BOOL(0, "auto-maintenance", &enable_auto_gc,
-		 N_("run 'maintenance --auto' after fetching")),
-	OPT_BOOL(0, "auto-gc", &enable_auto_gc,
-		 N_("run 'maintenance --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_BOOL(0, "stdin", &stdin_refspecs,
-		 N_("accept refspecs from stdin")),
-	OPT_END()
-};
-
-static void unlock_pack(void)
-{
-	if (gtransport)
-		transport_unlock_pack(gtransport);
-	if (gsecondary)
-		transport_unlock_pack(gsecondary);
-}
-
-static void unlock_pack_on_signal(int signo)
-{
-	unlock_pack();
-	sigchain_pop(signo);
-	raise(signo);
-}
-
-static void add_merge_config(struct ref **head,
-			   const struct ref *remote_refs,
-		           struct branch *branch,
-		           struct ref ***tail)
-{
-	int i;
-
-	for (i = 0; i < branch->merge_nr; i++) {
-		struct ref *rm, **old_tail = *tail;
-		struct refspec_item refspec;
-
-		for (rm = *head; rm; rm = rm->next) {
-			if (branch_merge_matches(branch, i, rm->name)) {
-				rm->fetch_head_status = FETCH_HEAD_MERGE;
-				break;
-			}
-		}
-		if (rm)
-			continue;
-
-		/*
-		 * Not fetched to a remote-tracking branch?  We need to fetch
-		 * it anyway to allow this branch's "branch.$name.merge"
-		 * to be honored by 'git pull', but we do not have to
-		 * fail if branch.$name.merge is misconfigured to point
-		 * at a nonexisting branch.  If we were indeed called by
-		 * 'git pull', it will notice the misconfiguration because
-		 * there is no entry in the resulting FETCH_HEAD marked
-		 * for merging.
-		 */
-		memset(&refspec, 0, sizeof(refspec));
-		refspec.src = branch->merge[i]->src;
-		get_fetch_map(remote_refs, &refspec, tail, 1);
-		for (rm = *old_tail; rm; rm = rm->next)
-			rm->fetch_head_status = FETCH_HEAD_MERGE;
-	}
-}
-
-static void create_fetch_oidset(struct ref **head, struct oidset *out)
-{
-	struct ref *rm = *head;
-	while (rm) {
-		oidset_insert(out, &rm->old_oid);
-		rm = rm->next;
-	}
-}
-
-struct refname_hash_entry {
-	struct hashmap_entry ent;
-	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 *keydata)
-{
-	const struct refname_hash_entry *e1, *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);
-}
-
-static struct refname_hash_entry *refname_hash_add(struct hashmap *map,
-						   const char *refname,
-						   const struct object_id *oid)
-{
-	struct refname_hash_entry *ent;
-	size_t len = strlen(refname);
-
-	FLEX_ALLOC_MEM(ent, refname, refname, len);
-	hashmap_entry_init(&ent->ent, strhash(refname));
-	oidcpy(&ent->oid, oid);
-	hashmap_add(map, &ent->ent);
-	return ent;
-}
-
-static int add_one_refname(const char *refname,
-			   const struct object_id *oid,
-			   int flag, void *cbdata)
-{
-	struct hashmap *refname_map = cbdata;
-
-	(void) refname_hash_add(refname_map, refname, oid);
-	return 0;
-}
-
-static void refname_hash_init(struct hashmap *map)
-{
-	hashmap_init(map, refname_hash_entry_cmp, NULL, 0);
-}
-
-static int refname_hash_exists(struct hashmap *map, const char *refname)
-{
-	return !!hashmap_get_from_hash(map, strhash(refname), refname);
-}
-
-static void clear_item(struct refname_hash_entry *item)
-{
-	item->ignore = 1;
-}
-
-static void find_non_local_tags(const struct ref *refs,
-				struct ref **head,
-				struct ref ***tail)
-{
-	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) {
-		if (!starts_with(ref->name, "refs/tags/"))
-			continue;
-
-		/*
-		 * The peeled ref always follows the matching base
-		 * ref, so if we see a peeled ref that we don't want
-		 * to fetch then we can mark the ref entry in the list
-		 * as one to ignore by setting util to NULL.
-		 */
-		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))
-				clear_item(item);
-			item = NULL;
-			continue;
-		}
-
-		/*
-		 * If item is non-NULL here, then we previously saw a
-		 * ref not followed by a peeled reference, so we need
-		 * to check if it is a lightweight tag that we want to
-		 * fetch.
-		 */
-		if (item &&
-		    !has_object_file_with_flags(&item->oid, quick_flags) &&
-		    !oidset_contains(&fetch_oids, &item->oid))
-			clear_item(item);
-
-		item = NULL;
-
-		/* skip duplicates and refs that we already have */
-		if (refname_hash_exists(&remote_refs, ref->name) ||
-		    refname_hash_exists(&existing_refs, ref->name))
-			continue;
-
-		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);
-
-	/*
-	 * 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))
-		clear_item(item);
-
-	/*
-	 * For all the tags in the remote_refs_list,
-	 * add them to the list of refs to be fetched
-	 */
-	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);
-		if (!item)
-			BUG("unseen remote ref?");
-
-		/* Unless we have already decided to ignore this item... */
-		if (item->ignore)
-			continue;
-
-		rm = alloc_ref(item->refname);
-		rm->peer_ref = alloc_ref(item->refname);
-		oidcpy(&rm->old_oid, &item->oid);
-		**tail = rm;
-		*tail = &rm->next;
-	}
-	hashmap_free_entries(&remote_refs, struct refname_hash_entry, ent);
-	string_list_clear(&remote_refs_list, 0);
-	oidset_clear(&fetch_oids);
-}
-
-static struct ref *get_ref_map(struct remote *remote,
-			       const struct ref *remote_refs,
-			       struct refspec *rs,
-			       int tags, int *autotags)
-{
-	int i;
-	struct ref *rm;
-	struct ref *ref_map = NULL;
-	struct ref **tail = &ref_map;
-
-	/* opportunistically-updated references: */
-	struct ref *orefs = NULL, **oref_tail = &orefs;
-
-	struct hashmap existing_refs;
-	int existing_refs_populated = 0;
-
-	if (rs->nr) {
-		struct refspec *fetch_refspec;
-
-		for (i = 0; i < rs->nr; i++) {
-			get_fetch_map(remote_refs, &rs->items[i], &tail, 0);
-			if (rs->items[i].dst && rs->items[i].dst[0])
-				*autotags = 1;
-		}
-		/* Merge everything on the command line (but not --tags) */
-		for (rm = ref_map; rm; rm = rm->next)
-			rm->fetch_head_status = FETCH_HEAD_MERGE;
-
-		/*
-		 * For any refs that we happen to be fetching via
-		 * command-line arguments, the destination ref might
-		 * have been missing or have been different than the
-		 * remote-tracking ref that would be derived from the
-		 * configured refspec.  In these cases, we want to
-		 * take the opportunity to update their configured
-		 * remote-tracking reference.  However, we do not want
-		 * to mention these entries in FETCH_HEAD at all, as
-		 * they would simply be duplicates of existing
-		 * entries, so we set them FETCH_HEAD_IGNORE below.
-		 *
-		 * We compute these entries now, based only on the
-		 * refspecs specified on the command line.  But we add
-		 * them to the list following the refspecs resulting
-		 * from the tags option so that one of the latter,
-		 * which has FETCH_HEAD_NOT_FOR_MERGE, is not removed
-		 * by ref_remove_duplicates() in favor of one of these
-		 * opportunistic entries with FETCH_HEAD_IGNORE.
-		 */
-		if (refmap.nr)
-			fetch_refspec = &refmap;
-		else
-			fetch_refspec = &remote->fetch;
-
-		for (i = 0; i < fetch_refspec->nr; i++)
-			get_fetch_map(ref_map, &fetch_refspec->items[i], &oref_tail, 1);
-	} else if (refmap.nr) {
-		die("--refmap option is only meaningful with command-line refspec(s).");
-	} else {
-		/* Use the defaults */
-		struct branch *branch = branch_get(NULL);
-		int has_merge = branch_has_merge_config(branch);
-		if (remote &&
-		    (remote->fetch.nr ||
-		     /* Note: has_merge implies non-NULL branch->remote_name */
-		     (has_merge && !strcmp(branch->remote_name, remote->name)))) {
-			for (i = 0; i < remote->fetch.nr; i++) {
-				get_fetch_map(remote_refs, &remote->fetch.items[i], &tail, 0);
-				if (remote->fetch.items[i].dst &&
-				    remote->fetch.items[i].dst[0])
-					*autotags = 1;
-				if (!i && !has_merge && ref_map &&
-				    !remote->fetch.items[0].pattern)
-					ref_map->fetch_head_status = FETCH_HEAD_MERGE;
-			}
-			/*
-			 * if the remote we're fetching from is the same
-			 * as given in branch.<name>.remote, we add the
-			 * ref given in branch.<name>.merge, too.
-			 *
-			 * Note: has_merge implies non-NULL branch->remote_name
-			 */
-			if (has_merge &&
-			    !strcmp(branch->remote_name, remote->name))
-				add_merge_config(&ref_map, remote_refs, branch, &tail);
-		} else {
-			ref_map = get_remote_ref(remote_refs, "HEAD");
-			if (!ref_map)
-				die(_("Couldn't find remote ref HEAD"));
-			ref_map->fetch_head_status = FETCH_HEAD_MERGE;
-			tail = &ref_map->next;
-		}
-	}
-
-	if (tags == TAGS_SET)
-		/* also fetch all tags */
-		get_fetch_map(remote_refs, tag_refspec, &tail, 0);
-	else if (tags == TAGS_DEFAULT && *autotags)
-		find_non_local_tags(remote_refs, &ref_map, &tail);
-
-	/* Now append any refs to be updated opportunistically: */
-	*tail = orefs;
-	for (rm = orefs; rm; rm = rm->next) {
-		rm->fetch_head_status = FETCH_HEAD_IGNORE;
-		tail = &rm->next;
-	}
-
-	/*
-	 * apply negative refspecs first, before we remove duplicates. This is
-	 * necessary as negative refspecs might remove an otherwise conflicting
-	 * duplicate.
-	 */
-	if (rs->nr)
-		ref_map = apply_negative_refspecs(ref_map, rs);
-	else
-		ref_map = apply_negative_refspecs(ref_map, &remote->fetch);
-
-	ref_map = ref_remove_duplicates(ref_map);
-
-	for (rm = ref_map; rm; rm = rm->next) {
-		if (rm->peer_ref) {
-			const char *refname = rm->peer_ref->name;
-			struct refname_hash_entry *peer_item;
-			unsigned int hash = strhash(refname);
-
-			if (!existing_refs_populated) {
-				refname_hash_init(&existing_refs);
-				for_each_ref(add_one_refname, &existing_refs);
-				existing_refs_populated = 1;
-			}
-
-			peer_item = hashmap_get_entry_from_hash(&existing_refs,
-						hash, refname,
-						struct refname_hash_entry, ent);
-			if (peer_item) {
-				struct object_id *old_oid = &peer_item->oid;
-				oidcpy(&rm->peer_ref->old_oid, old_oid);
-			}
-		}
-	}
-	if (existing_refs_populated)
-		hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent);
-
-	return ref_map;
-}
-
-#define STORE_REF_ERROR_OTHER 1
-#define STORE_REF_ERROR_DF_CONFLICT 2
-
-static int s_update_ref(const char *action,
-			struct ref *ref,
-			int check_old)
-{
-	char *msg;
-	char *rla = getenv("GIT_REFLOG_ACTION");
-	struct ref_transaction *transaction;
-	struct strbuf err = STRBUF_INIT;
-	int ret, df_conflict = 0;
-
-	if (dry_run)
-		return 0;
-	if (!rla)
-		rla = default_rla.buf;
-	msg = xstrfmt("%s: %s", rla, action);
-
-	transaction = ref_transaction_begin(&err);
-	if (!transaction ||
-	    ref_transaction_update(transaction, ref->name,
-				   &ref->new_oid,
-				   check_old ? &ref->old_oid : NULL,
-				   0, msg, &err))
-		goto fail;
-
-	ret = ref_transaction_commit(transaction, &err);
-	if (ret) {
-		df_conflict = (ret == TRANSACTION_NAME_CONFLICT);
-		goto fail;
-	}
-
-	ref_transaction_free(transaction);
-	strbuf_release(&err);
-	free(msg);
-	return 0;
-fail:
-	ref_transaction_free(transaction);
-	error("%s", err.buf);
-	strbuf_release(&err);
-	free(msg);
-	return df_conflict ? STORE_REF_ERROR_DF_CONFLICT
-			   : STORE_REF_ERROR_OTHER;
-}
-
-static int refcol_width = 10;
-static int compact_format;
-
-static void adjust_refcol_width(const struct ref *ref)
-{
-	int max, rlen, llen, len;
-
-	/* uptodate lines are only shown on high verbosity level */
-	if (!verbosity && oideq(&ref->peer_ref->old_oid, &ref->old_oid))
-		return;
-
-	max    = term_columns();
-	rlen   = utf8_strwidth(prettify_refname(ref->name));
-
-	llen   = utf8_strwidth(prettify_refname(ref->peer_ref->name));
-
-	/*
-	 * rough estimation to see if the output line is too long and
-	 * should not be counted (we can't do precise calculation
-	 * anyway because we don't know if the error explanation part
-	 * will be printed in update_local_ref)
-	 */
-	if (compact_format) {
-		llen = 0;
-		max = max * 2 / 3;
-	}
-	len = 21 /* flag and summary */ + rlen + 4 /* -> */ + llen;
-	if (len >= max)
-		return;
-
-	/*
-	 * Not precise calculation for compact mode because '*' can
-	 * appear on the left hand side of '->' and shrink the column
-	 * back.
-	 */
-	if (refcol_width < rlen)
-		refcol_width = rlen;
-}
-
-static void prepare_format_display(struct ref *ref_map)
-{
-	struct ref *rm;
-	const char *format = "full";
-
-	git_config_get_string_tmp("fetch.output", &format);
-	if (!strcasecmp(format, "full"))
-		compact_format = 0;
-	else if (!strcasecmp(format, "compact"))
-		compact_format = 1;
-	else
-		die(_("configuration fetch.output contains invalid value %s"),
-		    format);
-
-	for (rm = ref_map; rm; rm = rm->next) {
-		if (rm->status == REF_STATUS_REJECT_SHALLOW ||
-		    !rm->peer_ref ||
-		    !strcmp(rm->name, "HEAD"))
-			continue;
-
-		adjust_refcol_width(rm);
-	}
-}
-
-static void print_remote_to_local(struct strbuf *display,
-				  const char *remote, const char *local)
-{
-	strbuf_addf(display, "%-*s -> %s", refcol_width, remote, local);
-}
-
-static int find_and_replace(struct strbuf *haystack,
-			    const char *needle,
-			    const char *placeholder)
-{
-	const char *p = NULL;
-	int plen, nlen;
-
-	nlen = strlen(needle);
-	if (ends_with(haystack->buf, needle))
-		p = haystack->buf + haystack->len - nlen;
-	else
-		p = strstr(haystack->buf, needle);
-	if (!p)
-		return 0;
-
-	if (p > haystack->buf && p[-1] != '/')
-		return 0;
-
-	plen = strlen(p);
-	if (plen > nlen && p[nlen] != '/')
-		return 0;
-
-	strbuf_splice(haystack, p - haystack->buf, nlen,
-		      placeholder, strlen(placeholder));
-	return 1;
-}
-
-static void print_compact(struct strbuf *display,
-			  const char *remote, const char *local)
-{
-	struct strbuf r = STRBUF_INIT;
-	struct strbuf l = STRBUF_INIT;
-
-	if (!strcmp(remote, local)) {
-		strbuf_addf(display, "%-*s -> *", refcol_width, remote);
-		return;
-	}
-
-	strbuf_addstr(&r, remote);
-	strbuf_addstr(&l, local);
-
-	if (!find_and_replace(&r, local, "*"))
-		find_and_replace(&l, remote, "*");
-	print_remote_to_local(display, r.buf, l.buf);
-
-	strbuf_release(&r);
-	strbuf_release(&l);
-}
-
-static void format_display(struct strbuf *display, char code,
-			   const char *summary, const char *error,
-			   const char *remote, const char *local,
-			   int summary_width)
-{
-	int width = (summary_width + strlen(summary) - gettext_width(summary));
-
-	strbuf_addf(display, "%c %-*s ", code, width, summary);
-	if (!compact_format)
-		print_remote_to_local(display, remote, local);
-	else
-		print_compact(display, remote, local);
-	if (error)
-		strbuf_addf(display, "  (%s)", error);
-}
-
-static int update_local_ref(struct ref *ref,
-			    const char *remote,
-			    const struct ref *remote_ref,
-			    struct strbuf *display,
-			    int summary_width)
-{
-	struct commit *current = NULL, *updated;
-	enum object_type type;
-	struct branch *current_branch = branch_get(NULL);
-	const char *pretty_ref = prettify_refname(ref->name);
-	int fast_forward = 0;
-
-	type = oid_object_info(the_repository, &ref->new_oid, NULL);
-	if (type < 0)
-		die(_("object %s not found"), oid_to_hex(&ref->new_oid));
-
-	if (oideq(&ref->old_oid, &ref->new_oid)) {
-		if (verbosity > 0)
-			format_display(display, '=', _("[up to date]"), NULL,
-				       remote, pretty_ref, summary_width);
-		return 0;
-	}
-
-	if (current_branch &&
-	    !strcmp(ref->name, current_branch->name) &&
-	    !(update_head_ok || is_bare_repository()) &&
-	    !is_null_oid(&ref->old_oid)) {
-		/*
-		 * If this is the head, and it's not okay to update
-		 * the head, and the old value of the head isn't empty...
-		 */
-		format_display(display, '!', _("[rejected]"),
-			       _("can't fetch in current branch"),
-			       remote, pretty_ref, summary_width);
-		return 1;
-	}
-
-	if (!is_null_oid(&ref->old_oid) &&
-	    starts_with(ref->name, "refs/tags/")) {
-		if (force || ref->force) {
-			int r;
-			r = s_update_ref("updating tag", ref, 0);
-			format_display(display, r ? '!' : 't', _("[tag update]"),
-				       r ? _("unable to update local ref") : NULL,
-				       remote, pretty_ref, summary_width);
-			return r;
-		} else {
-			format_display(display, '!', _("[rejected]"), _("would clobber existing tag"),
-				       remote, pretty_ref, summary_width);
-			return 1;
-		}
-	}
-
-	current = lookup_commit_reference_gently(the_repository,
-						 &ref->old_oid, 1);
-	updated = lookup_commit_reference_gently(the_repository,
-						 &ref->new_oid, 1);
-	if (!current || !updated) {
-		const char *msg;
-		const char *what;
-		int r;
-		/*
-		 * Nicely describe the new ref we're fetching.
-		 * Base this on the remote's ref name, as it's
-		 * more likely to follow a standard layout.
-		 */
-		const char *name = remote_ref ? remote_ref->name : "";
-		if (starts_with(name, "refs/tags/")) {
-			msg = "storing tag";
-			what = _("[new tag]");
-		} else if (starts_with(name, "refs/heads/")) {
-			msg = "storing head";
-			what = _("[new branch]");
-		} else {
-			msg = "storing ref";
-			what = _("[new ref]");
-		}
-
-		r = s_update_ref(msg, ref, 0);
-		format_display(display, r ? '!' : '*', what,
-			       r ? _("unable to update local ref") : NULL,
-			       remote, pretty_ref, summary_width);
-		return r;
-	}
-
-	if (fetch_show_forced_updates) {
-		uint64_t t_before = getnanotime();
-		fast_forward = in_merge_bases(current, updated);
-		forced_updates_ms += (getnanotime() - t_before) / 1000000;
-	} else {
-		fast_forward = 1;
-	}
-
-	if (fast_forward) {
-		struct strbuf quickref = STRBUF_INIT;
-		int r;
-
-		strbuf_add_unique_abbrev(&quickref, &current->object.oid, DEFAULT_ABBREV);
-		strbuf_addstr(&quickref, "..");
-		strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV);
-		r = s_update_ref("fast-forward", ref, 1);
-		format_display(display, r ? '!' : ' ', quickref.buf,
-			       r ? _("unable to update local ref") : NULL,
-			       remote, pretty_ref, summary_width);
-		strbuf_release(&quickref);
-		return r;
-	} else if (force || ref->force) {
-		struct strbuf quickref = STRBUF_INIT;
-		int r;
-		strbuf_add_unique_abbrev(&quickref, &current->object.oid, DEFAULT_ABBREV);
-		strbuf_addstr(&quickref, "...");
-		strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV);
-		r = s_update_ref("forced-update", ref, 1);
-		format_display(display, r ? '!' : '+', quickref.buf,
-			       r ? _("unable to update local ref") : _("forced update"),
-			       remote, pretty_ref, summary_width);
-		strbuf_release(&quickref);
-		return r;
-	} else {
-		format_display(display, '!', _("[rejected]"), _("non-fast-forward"),
-			       remote, pretty_ref, summary_width);
-		return 1;
-	}
-}
-
-static int iterate_ref_map(void *cb_data, struct object_id *oid)
-{
-	struct ref **rm = cb_data;
-	struct ref *ref = *rm;
-
-	while (ref && ref->status == REF_STATUS_REJECT_SHALLOW)
-		ref = ref->next;
-	if (!ref)
-		return -1; /* end of the list */
-	*rm = ref->next;
-	oidcpy(oid, &ref->old_oid);
-	return 0;
-}
-
-static const char warn_show_forced_updates[] =
-N_("Fetch normally indicates which branches had a forced update,\n"
-   "but that check has been disabled. To re-enable, use '--show-forced-updates'\n"
-   "flag or run 'git config fetch.showForcedUpdates true'.");
-static const char warn_time_show_forced_updates[] =
-N_("It took %.2f seconds to check forced updates. You can use\n"
-   "'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates false'\n"
-   " to avoid this check.\n");
-
-static int store_updated_refs(const char *raw_url, const char *remote_name,
-			      int connectivity_checked, struct ref *ref_map)
-{
-	FILE *fp;
-	struct commit *commit;
-	int url_len, i, rc = 0;
-	struct strbuf note = STRBUF_INIT;
-	const char *what, *kind;
-	struct ref *rm;
-	char *url;
-	const char *filename = (!write_fetch_head
-				? "/dev/null"
-				: git_path_fetch_head(the_repository));
-	int want_status;
-	int summary_width = transport_summary_width(ref_map);
-
-	fp = fopen(filename, "a");
-	if (!fp)
-		return error_errno(_("cannot open %s"), filename);
-
-	if (raw_url)
-		url = transport_anonymize_url(raw_url);
-	else
-		url = xstrdup("foreign");
-
-	if (!connectivity_checked) {
-		struct check_connected_options opt = CHECK_CONNECTED_INIT;
-
-		rm = ref_map;
-		if (check_connected(iterate_ref_map, &rm, &opt)) {
-			rc = error(_("%s did not send all necessary objects\n"), url);
-			goto abort;
-		}
-	}
-
-	prepare_format_display(ref_map);
-
-	/*
-	 * We do a pass for each fetch_head_status type in their enum order, so
-	 * merged entries are written before not-for-merge. That lets readers
-	 * use FETCH_HEAD as a refname to refer to the ref to be merged.
-	 */
-	for (want_status = FETCH_HEAD_MERGE;
-	     want_status <= FETCH_HEAD_IGNORE;
-	     want_status++) {
-		for (rm = ref_map; rm; rm = rm->next) {
-			struct ref *ref = NULL;
-			const char *merge_status_marker = "";
-
-			if (rm->status == REF_STATUS_REJECT_SHALLOW) {
-				if (want_status == FETCH_HEAD_MERGE)
-					warning(_("reject %s because shallow roots are not allowed to be updated"),
-						rm->peer_ref ? rm->peer_ref->name : rm->name);
-				continue;
-			}
-
-			commit = lookup_commit_reference_gently(the_repository,
-								&rm->old_oid,
-								1);
-			if (!commit)
-				rm->fetch_head_status = FETCH_HEAD_NOT_FOR_MERGE;
-
-			if (rm->fetch_head_status != want_status)
-				continue;
-
-			if (rm->peer_ref) {
-				ref = alloc_ref(rm->peer_ref->name);
-				oidcpy(&ref->old_oid, &rm->peer_ref->old_oid);
-				oidcpy(&ref->new_oid, &rm->old_oid);
-				ref->force = rm->peer_ref->force;
-			}
-
-			if (recurse_submodules != RECURSE_SUBMODULES_OFF &&
-			    (!rm->peer_ref || !oideq(&ref->old_oid, &ref->new_oid))) {
-				check_for_new_submodule_commits(&rm->old_oid);
-			}
-
-			if (!strcmp(rm->name, "HEAD")) {
-				kind = "";
-				what = "";
-			}
-			else if (skip_prefix(rm->name, "refs/heads/", &what))
-				kind = "branch";
-			else if (skip_prefix(rm->name, "refs/tags/", &what))
-				kind = "tag";
-			else if (skip_prefix(rm->name, "refs/remotes/", &what))
-				kind = "remote-tracking branch";
-			else {
-				kind = "";
-				what = rm->name;
-			}
-
-			url_len = strlen(url);
-			for (i = url_len - 1; url[i] == '/' && 0 <= i; i--)
-				;
-			url_len = i + 1;
-			if (4 < i && !strncmp(".git", url + i - 3, 4))
-				url_len = i - 3;
-
-			strbuf_reset(&note);
-			if (*what) {
-				if (*kind)
-					strbuf_addf(&note, "%s ", kind);
-				strbuf_addf(&note, "'%s' of ", what);
-			}
-			switch (rm->fetch_head_status) {
-			case FETCH_HEAD_NOT_FOR_MERGE:
-				merge_status_marker = "not-for-merge";
-				/* fall-through */
-			case FETCH_HEAD_MERGE:
-				fprintf(fp, "%s\t%s\t%s",
-					oid_to_hex(&rm->old_oid),
-					merge_status_marker,
-					note.buf);
-				for (i = 0; i < url_len; ++i)
-					if ('\n' == url[i])
-						fputs("\\n", fp);
-					else
-						fputc(url[i], fp);
-				fputc('\n', fp);
-				break;
-			default:
-				/* do not write anything to FETCH_HEAD */
-				break;
-			}
-
-			strbuf_reset(&note);
-			if (ref) {
-				rc |= update_local_ref(ref, what, rm, &note,
-						       summary_width);
-				free(ref);
-			} else if (write_fetch_head || dry_run) {
-				/*
-				 * Display fetches written to FETCH_HEAD (or
-				 * would be written to FETCH_HEAD, if --dry-run
-				 * is set).
-				 */
-				format_display(&note, '*',
-					       *kind ? kind : "branch", NULL,
-					       *what ? what : "HEAD",
-					       "FETCH_HEAD", summary_width);
-			}
-			if (note.len) {
-				if (verbosity >= 0 && !shown_url) {
-					fprintf(stderr, _("From %.*s\n"),
-							url_len, url);
-					shown_url = 1;
-				}
-				if (verbosity >= 0)
-					fprintf(stderr, " %s\n", note.buf);
-			}
-		}
-	}
-
-	if (rc & STORE_REF_ERROR_DF_CONFLICT)
-		error(_("some local refs could not be updated; try running\n"
-		      " 'git remote prune %s' to remove any old, conflicting "
-		      "branches"), remote_name);
-
-	if (advice_fetch_show_forced_updates) {
-		if (!fetch_show_forced_updates) {
-			warning(_(warn_show_forced_updates));
-		} else if (forced_updates_ms > FORCED_UPDATES_DELAY_WARNING_IN_MS) {
-			warning(_(warn_time_show_forced_updates),
-				forced_updates_ms / 1000.0);
-		}
-	}
-
- abort:
-	strbuf_release(&note);
-	free(url);
-	fclose(fp);
-	return rc;
-}
-
-/*
- * We would want to bypass the object transfer altogether if
- * everything we are going to fetch already exists and is connected
- * locally.
- */
-static int check_exist_and_connected(struct ref *ref_map)
-{
-	struct ref *rm = ref_map;
-	struct check_connected_options opt = CHECK_CONNECTED_INIT;
-	struct ref *r;
-
-	/*
-	 * If we are deepening a shallow clone we already have these
-	 * objects reachable.  Running rev-list here will return with
-	 * a good (0) exit status and we'll bypass the fetch that we
-	 * really need to perform.  Claiming failure now will ensure
-	 * we perform the network exchange to deepen our history.
-	 */
-	if (deepen)
-		return -1;
-
-	/*
-	 * check_connected() allows objects to merely be promised, but
-	 * 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))
-			return -1;
-	}
-
-	opt.quiet = 1;
-	return check_connected(iterate_ref_map, &rm, &opt);
-}
-
-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);
-		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
-		 * time to update refs to reference the new objects.
-		 */
-		return 0;
-	transport_unlock_pack(transport);
-	return ret;
-}
-
-/* Update local refs based on the ref values fetched from a remote */
-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);
-	transport_unlock_pack(transport);
-	trace2_region_leave("fetch", "consume_refs", the_repository);
-	return ret;
-}
-
-static int prune_refs(struct refspec *rs, struct ref *ref_map,
-		      const char *raw_url)
-{
-	int url_len, i, result = 0;
-	struct ref *ref, *stale_refs = get_stale_heads(rs, ref_map);
-	char *url;
-	int summary_width = transport_summary_width(stale_refs);
-	const char *dangling_msg = dry_run
-		? _("   (%s will become dangling)")
-		: _("   (%s has become dangling)");
-
-	if (raw_url)
-		url = transport_anonymize_url(raw_url);
-	else
-		url = xstrdup("foreign");
-
-	url_len = strlen(url);
-	for (i = url_len - 1; url[i] == '/' && 0 <= i; i--)
-		;
-
-	url_len = i + 1;
-	if (4 < i && !strncmp(".git", url + i - 3, 4))
-		url_len = i - 3;
-
-	if (!dry_run) {
-		struct string_list refnames = STRING_LIST_INIT_NODUP;
-
-		for (ref = stale_refs; ref; ref = ref->next)
-			string_list_append(&refnames, ref->name);
-
-		result = delete_refs("fetch: prune", &refnames, 0);
-		string_list_clear(&refnames, 0);
-	}
-
-	if (verbosity >= 0) {
-		for (ref = stale_refs; ref; ref = ref->next) {
-			struct strbuf sb = STRBUF_INIT;
-			if (!shown_url) {
-				fprintf(stderr, _("From %.*s\n"), url_len, url);
-				shown_url = 1;
-			}
-			format_display(&sb, '-', _("[deleted]"), NULL,
-				       _("(none)"), prettify_refname(ref->name),
-				       summary_width);
-			fprintf(stderr, " %s\n",sb.buf);
-			strbuf_release(&sb);
-			warn_dangling_symref(stderr, dangling_msg, ref->name);
-		}
-	}
-
-	free(url);
-	free_refs(stale_refs);
-	return result;
-}
-
-static void check_not_current_branch(struct ref *ref_map)
-{
-	struct branch *current_branch = branch_get(NULL);
-
-	if (is_bare_repository() || !current_branch)
-		return;
-
-	for (; ref_map; ref_map = ref_map->next)
-		if (ref_map->peer_ref && !strcmp(current_branch->refname,
-					ref_map->peer_ref->name))
-			die(_("Refusing to fetch into current branch %s "
-			    "of non-bare repository"), current_branch->refname);
-}
-
-static int truncate_fetch_head(void)
-{
-	const char *filename = git_path_fetch_head(the_repository);
-	FILE *fp = fopen_for_writing(filename);
-
-	if (!fp)
-		return error_errno(_("cannot open %s"), filename);
-	fclose(fp);
-	return 0;
-}
-
-static void set_option(struct transport *transport, const char *name, const char *value)
-{
-	int r = transport_set_option(transport, name, value);
-	if (r < 0)
-		die(_("Option \"%s\" value \"%s\" is not valid for %s"),
-		    name, value, transport->url);
-	if (r > 0)
-		warning(_("Option \"%s\" is ignored for %s\n"),
-			name, transport->url);
-}
-
-
-static int add_oid(const char *refname, const struct object_id *oid, int flags,
-		   void *cb_data)
-{
-	struct oid_array *oids = cb_data;
-
-	oid_array_append(oids, oid);
-	return 0;
-}
-
-static void add_negotiation_tips(struct git_transport_options *smart_options)
-{
-	struct oid_array *oids = xcalloc(1, sizeof(*oids));
-	int i;
-
-	for (i = 0; i < negotiation_tip.nr; i++) {
-		const char *s = negotiation_tip.items[i].string;
-		int old_nr;
-		if (!has_glob_specials(s)) {
-			struct object_id oid;
-			if (get_oid(s, &oid))
-				die("%s is not a valid object", s);
-			oid_array_append(oids, &oid);
-			continue;
-		}
-		old_nr = oids->nr;
-		for_each_glob_ref(add_oid, s, oids);
-		if (old_nr == oids->nr)
-			warning("Ignoring --negotiation-tip=%s because it does not match any refs",
-				s);
-	}
-	smart_options->negotiation_tips = oids;
-}
-
-static struct transport *prepare_transport(struct remote *remote, int deepen)
-{
-	struct transport *transport;
-
-	transport = transport_get(remote, NULL);
-	transport_set_verbosity(transport, verbosity, progress);
-	transport->family = family;
-	if (upload_pack)
-		set_option(transport, TRANS_OPT_UPLOADPACK, upload_pack);
-	if (keep)
-		set_option(transport, TRANS_OPT_KEEP, "yes");
-	if (depth)
-		set_option(transport, TRANS_OPT_DEPTH, depth);
-	if (deepen && deepen_since)
-		set_option(transport, TRANS_OPT_DEEPEN_SINCE, deepen_since);
-	if (deepen && deepen_not.nr)
-		set_option(transport, TRANS_OPT_DEEPEN_NOT,
-			   (const char *)&deepen_not);
-	if (deepen_relative)
-		set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, "yes");
-	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);
-		set_option(transport, TRANS_OPT_FROM_PROMISOR, "1");
-	}
-	if (negotiation_tip.nr) {
-		if (transport->smart_options)
-			add_negotiation_tips(transport->smart_options);
-		else
-			warning("Ignoring --negotiation-tip because the protocol does not support it.");
-	}
-	return transport;
-}
-
-static void backfill_tags(struct transport *transport, struct ref *ref_map)
-{
-	int cannot_reuse;
-
-	/*
-	 * Once we have set TRANS_OPT_DEEPEN_SINCE, we can't unset it
-	 * when remote helper is used (setting it to an empty string
-	 * is not unsetting). We could extend the remote helper
-	 * protocol for that, but for now, just force a new connection
-	 * without deepen-since. Similar story for deepen-not.
-	 */
-	cannot_reuse = transport->cannot_reuse ||
-		deepen_since || deepen_not.nr;
-	if (cannot_reuse) {
-		gsecondary = prepare_transport(transport->remote, 0);
-		transport = gsecondary;
-	}
-
-	transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL);
-	transport_set_option(transport, TRANS_OPT_DEPTH, "0");
-	transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL);
-	if (!fetch_refs(transport, ref_map))
-		consume_refs(transport, ref_map);
-
-	if (gsecondary) {
-		transport_disconnect(gsecondary);
-		gsecondary = NULL;
-	}
-}
-
-static int do_fetch(struct transport *transport,
-		    struct refspec *rs)
-{
-	struct ref *ref_map;
-	int autotags = (transport->remote->fetch_tags == 1);
-	int retcode = 0;
-	const struct ref *remote_refs;
-	struct strvec ref_prefixes = STRVEC_INIT;
-	int must_list_refs = 1;
-
-	if (tags == TAGS_DEFAULT) {
-		if (transport->remote->fetch_tags == 2)
-			tags = TAGS_SET;
-		if (transport->remote->fetch_tags == -1)
-			tags = TAGS_UNSET;
-	}
-
-	/* if not appending, truncate FETCH_HEAD */
-	if (!append && write_fetch_head) {
-		retcode = truncate_fetch_head();
-		if (retcode)
-			goto cleanup;
-	}
-
-	if (rs->nr) {
-		int i;
-
-		refspec_ref_prefixes(rs, &ref_prefixes);
-
-		/*
-		 * We can avoid listing refs if all of them are exact
-		 * OIDs
-		 */
-		must_list_refs = 0;
-		for (i = 0; i < rs->nr; i++) {
-			if (!rs->items[i].exact_sha1) {
-				must_list_refs = 1;
-				break;
-			}
-		}
-	} else if (transport->remote && transport->remote->fetch.nr)
-		refspec_ref_prefixes(&transport->remote->fetch, &ref_prefixes);
-
-	if (tags == TAGS_SET || tags == TAGS_DEFAULT) {
-		must_list_refs = 1;
-		if (ref_prefixes.nr)
-			strvec_push(&ref_prefixes, "refs/tags/");
-	}
-
-	if (must_list_refs) {
-		trace2_region_enter("fetch", "remote_refs", the_repository);
-		remote_refs = transport_get_remote_refs(transport, &ref_prefixes);
-		trace2_region_leave("fetch", "remote_refs", the_repository);
-	} else
-		remote_refs = NULL;
-
-	strvec_clear(&ref_prefixes);
-
-	ref_map = get_ref_map(transport->remote, remote_refs, rs,
-			      tags, &autotags);
-	if (!update_head_ok)
-		check_not_current_branch(ref_map);
-
-	if (tags == TAGS_DEFAULT && autotags)
-		transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1");
-	if (prune) {
-		/*
-		 * We only prune based on refspecs specified
-		 * explicitly (via command line or configuration); we
-		 * don't care whether --tags was specified.
-		 */
-		if (rs->nr) {
-			prune_refs(rs, ref_map, transport->url);
-		} else {
-			prune_refs(&transport->remote->fetch,
-				   ref_map,
-				   transport->url);
-		}
-	}
-	if (fetch_refs(transport, ref_map) || consume_refs(transport, ref_map)) {
-		free_refs(ref_map);
-		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
-	 * following ... */
-	if (tags == TAGS_DEFAULT && autotags) {
-		struct ref **tail = &ref_map;
-		ref_map = NULL;
-		find_non_local_tags(remote_refs, &ref_map, &tail);
-		if (ref_map)
-			backfill_tags(transport, ref_map);
-		free_refs(ref_map);
-	}
-
- cleanup:
-	return retcode;
-}
-
-static int get_one_remote_for_fetch(struct remote *remote, void *priv)
-{
-	struct string_list *list = priv;
-	if (!remote->skip_default_update)
-		string_list_append(list, remote->name);
-	return 0;
-}
-
-struct remote_group_data {
-	const char *name;
-	struct string_list *list;
-};
-
-static int get_remote_group(const char *key, const char *value, void *priv)
-{
-	struct remote_group_data *g = priv;
-
-	if (skip_prefix(key, "remotes.", &key) && !strcmp(key, g->name)) {
-		/* split list by white space */
-		while (*value) {
-			size_t wordlen = strcspn(value, " \t\n");
-
-			if (wordlen >= 1)
-				string_list_append_nodup(g->list,
-						   xstrndup(value, wordlen));
-			value += wordlen + (value[wordlen] != '\0');
-		}
-	}
-
-	return 0;
-}
-
-static int add_remote_or_group(const char *name, struct string_list *list)
-{
-	int prev_nr = list->nr;
-	struct remote_group_data g;
-	g.name = name; g.list = list;
-
-	git_config(get_remote_group, &g);
-	if (list->nr == prev_nr) {
-		struct remote *remote = remote_get(name);
-		if (!remote_is_configured(remote, 0))
-			return 0;
-		string_list_append(list, remote->name);
-	}
-	return 1;
-}
-
-static void add_options_to_argv(struct strvec *argv)
-{
-	if (dry_run)
-		strvec_push(argv, "--dry-run");
-	if (prune != -1)
-		strvec_push(argv, prune ? "--prune" : "--no-prune");
-	if (prune_tags != -1)
-		strvec_push(argv, prune_tags ? "--prune-tags" : "--no-prune-tags");
-	if (update_head_ok)
-		strvec_push(argv, "--update-head-ok");
-	if (force)
-		strvec_push(argv, "--force");
-	if (keep)
-		strvec_push(argv, "--keep");
-	if (recurse_submodules == RECURSE_SUBMODULES_ON)
-		strvec_push(argv, "--recurse-submodules");
-	else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)
-		strvec_push(argv, "--recurse-submodules=on-demand");
-	if (tags == TAGS_SET)
-		strvec_push(argv, "--tags");
-	else if (tags == TAGS_UNSET)
-		strvec_push(argv, "--no-tags");
-	if (verbosity >= 2)
-		strvec_push(argv, "-v");
-	if (verbosity >= 1)
-		strvec_push(argv, "-v");
-	else if (verbosity < 0)
-		strvec_push(argv, "-q");
-	if (family == TRANSPORT_FAMILY_IPV4)
-		strvec_push(argv, "--ipv4");
-	else if (family == TRANSPORT_FAMILY_IPV6)
-		strvec_push(argv, "--ipv6");
-}
-
-/* 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;
-
-	strvec_pushv(&cp->args, state->argv);
-	strvec_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)
-{
-	int i, result = 0;
-	struct strvec argv = STRVEC_INIT;
-
-	if (!append && write_fetch_head) {
-		int errcode = truncate_fetch_head();
-		if (errcode)
-			return errcode;
-	}
-
-	strvec_pushl(&argv, "fetch", "--append", "--no-auto-gc",
-		     "--no-write-commit-graph", NULL);
-	add_options_to_argv(&argv);
-
-	if (max_children != 1 && list->nr != 1) {
-		struct parallel_fetch_state state = { argv.v, list, 0, 0 };
-
-		strvec_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;
-			strvec_push(&argv, name);
-			if (verbosity >= 0)
-				printf(_("Fetching %s\n"), name);
-			if (run_command_v_opt(argv.v, RUN_GIT_CMD)) {
-				error(_("Could not fetch %s"), name);
-				result = 1;
-			}
-			strvec_pop(&argv);
-		}
-
-	strvec_clear(&argv);
-	return !!result;
-}
-
-/*
- * Fetching from the promisor remote should use the given filter-spec
- * or inherit the default filter-spec from the config.
- */
-static inline void fetch_one_setup_partial(struct remote *remote)
-{
-	/*
-	 * Explicit --no-filter argument overrides everything, regardless
-	 * of any prior partial clones and fetches.
-	 */
-	if (filter_options.no_filter)
-		return;
-
-	/*
-	 * 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)
-		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 there is currently no default filter-spec.
-	 */
-	if (filter_options.choice) {
-		partial_clone_register(remote->name, &filter_options);
-		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);
-	return;
-}
-
-static int fetch_one(struct remote *remote, int argc, const char **argv,
-		     int prune_tags_ok, int use_stdin_refspecs)
-{
-	struct refspec rs = REFSPEC_INIT_FETCH;
-	int i;
-	int exit_code;
-	int maybe_prune_tags;
-	int remote_via_config = remote_is_configured(remote, 0);
-
-	if (!remote)
-		die(_("No remote repository specified.  Please, specify either a URL or a\n"
-		    "remote name from which new revisions should be fetched."));
-
-	gtransport = prepare_transport(remote, 1);
-
-	if (prune < 0) {
-		/* no command line request */
-		if (0 <= remote->prune)
-			prune = remote->prune;
-		else if (0 <= fetch_prune_config)
-			prune = fetch_prune_config;
-		else
-			prune = PRUNE_BY_DEFAULT;
-	}
-
-	if (prune_tags < 0) {
-		/* no command line request */
-		if (0 <= remote->prune_tags)
-			prune_tags = remote->prune_tags;
-		else if (0 <= fetch_prune_tags_config)
-			prune_tags = fetch_prune_tags_config;
-		else
-			prune_tags = PRUNE_TAGS_BY_DEFAULT;
-	}
-
-	maybe_prune_tags = prune_tags_ok && prune_tags;
-	if (maybe_prune_tags && remote_via_config)
-		refspec_append(&remote->fetch, TAG_REFSPEC);
-
-	if (maybe_prune_tags && (argc || !remote_via_config))
-		refspec_append(&rs, TAG_REFSPEC);
-
-	for (i = 0; i < argc; i++) {
-		if (!strcmp(argv[i], "tag")) {
-			i++;
-			if (i >= argc)
-				die(_("You need to specify a tag name."));
-
-			refspec_appendf(&rs, "refs/tags/%s:refs/tags/%s",
-					argv[i], argv[i]);
-		} else {
-			refspec_append(&rs, argv[i]);
-		}
-	}
-
-	if (use_stdin_refspecs) {
-		struct strbuf line = STRBUF_INIT;
-		while (strbuf_getline_lf(&line, stdin) != EOF)
-			refspec_append(&rs, line.buf);
-		strbuf_release(&line);
-	}
-
-	if (server_options.nr)
-		gtransport->server_options = &server_options;
-
-	sigchain_push_common(unlock_pack_on_signal);
-	atexit(unlock_pack);
-	sigchain_push(SIGPIPE, SIG_IGN);
-	exit_code = do_fetch(gtransport, &rs);
-	sigchain_pop(SIGPIPE);
-	refspec_clear(&rs);
-	transport_disconnect(gtransport);
-	gtransport = NULL;
-	return exit_code;
-}
-
-int cmd_fetch(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	struct string_list list = STRING_LIST_INIT_DUP;
-	struct remote *remote = NULL;
-	int result = 0;
-	int prune_tags_ok = 1;
-
-	packet_trace_identity("fetch");
-
-	/* Record the command line for the reflog */
-	strbuf_addstr(&default_rla, "fetch");
-	for (i = 1; i < argc; i++) {
-		/* This handles non-URLs gracefully */
-		char *anon = transport_anonymize_url(argv[i]);
-
-		strbuf_addf(&default_rla, " %s", anon);
-		free(anon);
-	}
-
-	git_config(git_fetch_config, NULL);
-
-	argc = parse_options(argc, argv, prefix,
-			     builtin_fetch_options, builtin_fetch_usage, 0);
-	if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
-		int *sfjc = submodule_fetch_jobs_config == -1
-			    ? &submodule_fetch_jobs_config : NULL;
-		int *rs = recurse_submodules == RECURSE_SUBMODULES_DEFAULT
-			  ? &recurse_submodules : NULL;
-
-		fetch_config_from_gitmodules(sfjc, rs);
-	}
-
-	if (deepen_relative) {
-		if (deepen_relative < 0)
-			die(_("Negative depth in --deepen is not supported"));
-		if (depth)
-			die(_("--deepen and --depth are mutually exclusive"));
-		depth = xstrfmt("%d", deepen_relative);
-	}
-	if (unshallow) {
-		if (depth)
-			die(_("--depth and --unshallow cannot be used together"));
-		else if (!is_repository_shallow(the_repository))
-			die(_("--unshallow on a complete repository does not make sense"));
-		else
-			depth = xstrfmt("%d", INFINITE_DEPTH);
-	}
-
-	/* no need to be strict, transport_set_option() will validate it again */
-	if (depth && atoi(depth) < 1)
-		die(_("depth %s is not a positive number"), depth);
-	if (depth || deepen_since || deepen_not.nr)
-		deepen = 1;
-
-	/* FETCH_HEAD never gets updated in --dry-run mode */
-	if (dry_run)
-		write_fetch_head = 0;
-
-	if (all) {
-		if (argc == 1)
-			die(_("fetch --all does not take a repository argument"));
-		else if (argc > 1)
-			die(_("fetch --all does not make sense with refspecs"));
-		(void) for_each_remote(get_one_remote_for_fetch, &list);
-	} else if (argc == 0) {
-		/* No arguments -- use default remote */
-		remote = remote_get(NULL);
-	} else if (multiple) {
-		/* All arguments are assumed to be remotes or groups */
-		for (i = 0; i < argc; i++)
-			if (!add_remote_or_group(argv[i], &list))
-				die(_("No such remote or remote group: %s"), argv[i]);
-	} else {
-		/* Single remote or group */
-		(void) add_remote_or_group(argv[0], &list);
-		if (list.nr > 1) {
-			/* More than one remote */
-			if (argc > 1)
-				die(_("Fetching a group and specifying refspecs does not make sense"));
-		} else {
-			/* Zero or one remotes */
-			remote = remote_get(argv[0]);
-			prune_tags_ok = (argc == 1);
-			argc--;
-			argv++;
-		}
-	}
-
-	if (remote) {
-		if (filter_options.choice || has_promisor_remote())
-			fetch_one_setup_partial(remote);
-		result = fetch_one(remote, argc, argv, prune_tags_ok, stdin_refspecs);
-	} else {
-		int max_children = max_jobs;
-
-		if (filter_options.choice)
-			die(_("--filter can only be used with the remote "
-			      "configured in extensions.partialclone"));
-
-		if (stdin_refspecs)
-			die(_("--stdin can only be used when fetching "
-			      "from one remote"));
-
-		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);
-	}
-
-	if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) {
-		struct strvec options = STRVEC_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,
-						    &options,
-						    submodule_prefix,
-						    recurse_submodules,
-						    recurse_submodules_default,
-						    verbosity < 0,
-						    max_children);
-		strvec_clear(&options);
-	}
-
-	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)
-		run_auto_maintenance(verbosity < 0);
-
-	return result;
-}
diff --git a/third_party/git/builtin/fmt-merge-msg.c b/third_party/git/builtin/fmt-merge-msg.c
deleted file mode 100644
index 48a8699de728..000000000000
--- a/third_party/git/builtin/fmt-merge-msg.c
+++ /dev/null
@@ -1,65 +0,0 @@
-#include "builtin.h"
-#include "config.h"
-#include "fmt-merge-msg.h"
-#include "parse-options.h"
-
-static const char * const fmt_merge_msg_usage[] = {
-	N_("git fmt-merge-msg [-m <message>] [--log[=<n>] | --no-log] [--file <file>]"),
-	NULL
-};
-
-int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
-{
-	const char *inpath = NULL;
-	const char *message = NULL;
-	int shortlog_len = -1;
-	struct option options[] = {
-		{ OPTION_INTEGER, 0, "log", &shortlog_len, N_("n"),
-		  N_("populate log with at most <n> entries from shortlog"),
-		  PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN },
-		{ OPTION_INTEGER, 0, "summary", &shortlog_len, N_("n"),
-		  N_("alias for --log (deprecated)"),
-		  PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN, NULL,
-		  DEFAULT_MERGE_LOG_LEN },
-		OPT_STRING('m', "message", &message, N_("text"),
-			N_("use <text> as start of message")),
-		OPT_FILENAME('F', "file", &inpath, N_("file to read from")),
-		OPT_END()
-	};
-
-	FILE *in = stdin;
-	struct strbuf input = STRBUF_INIT, output = STRBUF_INIT;
-	int ret;
-	struct fmt_merge_msg_opts opts;
-
-	git_config(fmt_merge_msg_config, NULL);
-	argc = parse_options(argc, argv, prefix, options, fmt_merge_msg_usage,
-			     0);
-	if (argc > 0)
-		usage_with_options(fmt_merge_msg_usage, options);
-	if (shortlog_len < 0)
-		shortlog_len = (merge_log_config > 0) ? merge_log_config : 0;
-
-	if (inpath && strcmp(inpath, "-")) {
-		in = fopen(inpath, "r");
-		if (!in)
-			die_errno("cannot open '%s'", inpath);
-	}
-
-	if (strbuf_read(&input, fileno(in), 0) < 0)
-		die_errno("could not read input file");
-
-	if (message)
-		strbuf_addstr(&output, message);
-
-	memset(&opts, 0, sizeof(opts));
-	opts.add_title = !message;
-	opts.credit_people = 1;
-	opts.shortlog_len = shortlog_len;
-
-	ret = fmt_merge_msg(&input, &output, &opts);
-	if (ret)
-		return ret;
-	write_in_full(STDOUT_FILENO, output.buf, output.len);
-	return 0;
-}
diff --git a/third_party/git/builtin/for-each-ref.c b/third_party/git/builtin/for-each-ref.c
deleted file mode 100644
index 9d1ecda2b8f3..000000000000
--- a/third_party/git/builtin/for-each-ref.c
+++ /dev/null
@@ -1,87 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "refs.h"
-#include "object.h"
-#include "parse-options.h"
-#include "ref-filter.h"
-
-static char const * const for_each_ref_usage[] = {
-	N_("git for-each-ref [<options>] [<pattern>]"),
-	N_("git for-each-ref [--points-at <object>]"),
-	N_("git for-each-ref [--merged [<commit>]] [--no-merged [<commit>]]"),
-	N_("git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"),
-	NULL
-};
-
-int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
-	int maxcount = 0, icase = 0;
-	struct ref_array array;
-	struct ref_filter filter;
-	struct ref_format format = REF_FORMAT_INIT;
-
-	struct option opts[] = {
-		OPT_BIT('s', "shell", &format.quote_style,
-			N_("quote placeholders suitably for shells"), QUOTE_SHELL),
-		OPT_BIT('p', "perl",  &format.quote_style,
-			N_("quote placeholders suitably for perl"), QUOTE_PERL),
-		OPT_BIT(0 , "python", &format.quote_style,
-			N_("quote placeholders suitably for python"), QUOTE_PYTHON),
-		OPT_BIT(0 , "tcl",  &format.quote_style,
-			N_("quote placeholders suitably for Tcl"), QUOTE_TCL),
-
-		OPT_GROUP(""),
-		OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")),
-		OPT_STRING(  0 , "format", &format.format, N_("format"), N_("format to use for the output")),
-		OPT__COLOR(&format.use_color, N_("respect format colors")),
-		OPT_REF_SORT(sorting_tail),
-		OPT_CALLBACK(0, "points-at", &filter.points_at,
-			     N_("object"), N_("print only refs which points at the given object"),
-			     parse_opt_object_name),
-		OPT_MERGED(&filter, N_("print only refs that are merged")),
-		OPT_NO_MERGED(&filter, N_("print only refs that are not merged")),
-		OPT_CONTAINS(&filter.with_commit, N_("print only refs which contain the commit")),
-		OPT_NO_CONTAINS(&filter.no_commit, N_("print only refs which don't contain the commit")),
-		OPT_BOOL(0, "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
-		OPT_END(),
-	};
-
-	memset(&array, 0, sizeof(array));
-	memset(&filter, 0, sizeof(filter));
-
-	format.format = "%(objectname) %(objecttype)\t%(refname)";
-
-	git_config(git_default_config, NULL);
-
-	parse_options(argc, argv, prefix, opts, for_each_ref_usage, 0);
-	if (maxcount < 0) {
-		error("invalid --count argument: `%d'", maxcount);
-		usage_with_options(for_each_ref_usage, opts);
-	}
-	if (HAS_MULTI_BITS(format.quote_style)) {
-		error("more than one quoting style?");
-		usage_with_options(for_each_ref_usage, opts);
-	}
-	if (verify_ref_format(&format))
-		usage_with_options(for_each_ref_usage, opts);
-
-	if (!sorting)
-		sorting = ref_default_sorting();
-	ref_sorting_icase_all(sorting, icase);
-	filter.ignore_case = icase;
-
-	filter.name_patterns = argv;
-	filter.match_as_path = 1;
-	filter_refs(&array, &filter, FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN);
-	ref_array_sort(sorting, &array);
-
-	if (!maxcount || array.nr < maxcount)
-		maxcount = array.nr;
-	for (i = 0; i < maxcount; i++)
-		show_ref_array_item(array.items[i], &format);
-	ref_array_clear(&array);
-	return 0;
-}
diff --git a/third_party/git/builtin/fsck.c b/third_party/git/builtin/fsck.c
deleted file mode 100644
index fbf26cafcfd7..000000000000
--- a/third_party/git/builtin/fsck.c
+++ /dev/null
@@ -1,961 +0,0 @@
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "cache.h"
-#include "repository.h"
-#include "config.h"
-#include "commit.h"
-#include "tree.h"
-#include "blob.h"
-#include "tag.h"
-#include "refs.h"
-#include "pack.h"
-#include "cache-tree.h"
-#include "tree-walk.h"
-#include "fsck.h"
-#include "parse-options.h"
-#include "dir.h"
-#include "progress.h"
-#include "streaming.h"
-#include "decorate.h"
-#include "packfile.h"
-#include "object-store.h"
-#include "run-command.h"
-#include "worktree.h"
-
-#define REACHABLE 0x0001
-#define SEEN      0x0002
-#define HAS_OBJ   0x0004
-/* This flag is set if something points to this object. */
-#define USED      0x0008
-
-static int show_root;
-static int show_tags;
-static int show_unreachable;
-static int include_reflogs = 1;
-static int check_full = 1;
-static int connectivity_only;
-static int check_strict;
-static int keep_cache_objects;
-static struct fsck_options fsck_walk_options = FSCK_OPTIONS_DEFAULT;
-static struct fsck_options fsck_obj_options = FSCK_OPTIONS_DEFAULT;
-static int errors_found;
-static int write_lost_and_found;
-static int verbose;
-static int show_progress = -1;
-static int show_dangling = 1;
-static int name_objects;
-#define ERROR_OBJECT 01
-#define ERROR_REACHABLE 02
-#define ERROR_PACK 04
-#define ERROR_REFS 010
-#define ERROR_COMMIT_GRAPH 020
-#define ERROR_MULTI_PACK_INDEX 040
-
-static const char *describe_object(const struct object_id *oid)
-{
-	return fsck_describe_object(&fsck_walk_options, oid);
-}
-
-static const char *printable_type(const struct object_id *oid,
-				  enum object_type type)
-{
-	const char *ret;
-
-	if (type == OBJ_NONE)
-		type = oid_object_info(the_repository, oid, NULL);
-
-	ret = type_name(type);
-	if (!ret)
-		ret = _("unknown");
-
-	return ret;
-}
-
-static int fsck_config(const char *var, const char *value, void *cb)
-{
-	if (strcmp(var, "fsck.skiplist") == 0) {
-		const char *path;
-		struct strbuf sb = STRBUF_INIT;
-
-		if (git_config_pathname(&path, var, value))
-			return 1;
-		strbuf_addf(&sb, "skiplist=%s", path);
-		free((char *)path);
-		fsck_set_msg_types(&fsck_obj_options, sb.buf);
-		strbuf_release(&sb);
-		return 0;
-	}
-
-	if (skip_prefix(var, "fsck.", &var)) {
-		fsck_set_msg_type(&fsck_obj_options, var, value);
-		return 0;
-	}
-
-	return git_default_config(var, value, cb);
-}
-
-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);
-	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)
-{
-	switch (msg_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);
-		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);
-		return 1;
-	default:
-		BUG("%d (FSCK_IGNORE?) should never trigger this callback",
-		    msg_type);
-	}
-}
-
-static struct object_array pending;
-
-static int mark_object(struct object *obj, int type, void *data, struct fsck_options *options)
-{
-	struct object *parent = data;
-
-	/*
-	 * The only case data is NULL or type is OBJ_ANY is when
-	 * mark_object_reachable() calls us.  All the callers of
-	 * that function has non-NULL obj hence ...
-	 */
-	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));
-		printf_ln(_("broken link from %7s %s"),
-			  (type == OBJ_ANY ? _("unknown") : type_name(type)),
-			  _("unknown"));
-		errors_found |= ERROR_REACHABLE;
-		return 1;
-	}
-
-	if (type != OBJ_ANY && obj->type != type)
-		/* ... and the reference to parent is safe here */
-		objerror(parent, _("wrong object type in link"));
-
-	if (obj->flags & REACHABLE)
-		return 0;
-	obj->flags |= REACHABLE;
-
-	if (is_promisor_object(&obj->oid))
-		/*
-		 * Further recursion does not need to be performed on this
-		 * object since it is a promisor object (so it does not need to
-		 * be added to "pending").
-		 */
-		return 0;
-
-	if (!(obj->flags & HAS_OBJ)) {
-		if (parent && !has_object(the_repository, &obj->oid, 1)) {
-			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));
-			errors_found |= ERROR_REACHABLE;
-		}
-		return 1;
-	}
-
-	add_object_array(obj, NULL, &pending);
-	return 0;
-}
-
-static void mark_object_reachable(struct object *obj)
-{
-	mark_object(obj, OBJ_ANY, NULL, NULL);
-}
-
-static int traverse_one_object(struct object *obj)
-{
-	int result = fsck_walk(obj, obj, &fsck_walk_options);
-
-	if (obj->type == OBJ_TREE) {
-		struct tree *tree = (struct tree *)obj;
-		free_tree_buffer(tree);
-	}
-	return result;
-}
-
-static int traverse_reachable(void)
-{
-	struct progress *progress = NULL;
-	unsigned int nr = 0;
-	int result = 0;
-	if (show_progress)
-		progress = start_delayed_progress(_("Checking connectivity"), 0);
-	while (pending.nr) {
-		result |= traverse_one_object(object_array_pop(&pending));
-		display_progress(progress, ++nr);
-	}
-	stop_progress(&progress);
-	return !!result;
-}
-
-static int mark_used(struct object *obj, int type, void *data, struct fsck_options *options)
-{
-	if (!obj)
-		return 1;
-	obj->flags |= USED;
-	return 0;
-}
-
-static void mark_unreachable_referents(const struct object_id *oid)
-{
-	struct fsck_options options = FSCK_OPTIONS_DEFAULT;
-	struct object *obj = lookup_object(the_repository, oid);
-
-	if (!obj || !(obj->flags & HAS_OBJ))
-		return; /* not part of our original set */
-	if (obj->flags & REACHABLE)
-		return; /* reachable objects already traversed */
-
-	/*
-	 * Avoid passing OBJ_NONE to fsck_walk, which will parse the object
-	 * (and we want to avoid parsing blobs).
-	 */
-	if (obj->type == OBJ_NONE) {
-		enum object_type type = oid_object_info(the_repository,
-							&obj->oid, NULL);
-		if (type > 0)
-			object_as_type(obj, type, 0);
-	}
-
-	options.walk = mark_used;
-	fsck_walk(obj, NULL, &options);
-}
-
-static int mark_loose_unreachable_referents(const struct object_id *oid,
-					    const char *path,
-					    void *data)
-{
-	mark_unreachable_referents(oid);
-	return 0;
-}
-
-static int mark_packed_unreachable_referents(const struct object_id *oid,
-					     struct packed_git *pack,
-					     uint32_t pos,
-					     void *data)
-{
-	mark_unreachable_referents(oid);
-	return 0;
-}
-
-/*
- * Check a single reachable object
- */
-static void check_reachable_object(struct object *obj)
-{
-	/*
-	 * We obviously want the object to be parsed,
-	 * except if it was in a pack-file and we didn't
-	 * do a full fsck
-	 */
-	if (!(obj->flags & HAS_OBJ)) {
-		if (is_promisor_object(&obj->oid))
-			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));
-		errors_found |= ERROR_REACHABLE;
-		return;
-	}
-}
-
-/*
- * Check a single unreachable object
- */
-static void check_unreachable_object(struct object *obj)
-{
-	/*
-	 * Missing unreachable object? Ignore it. It's not like
-	 * we miss it (since it can't be reached), nor do we want
-	 * to complain about it being unreachable (since it does
-	 * not exist).
-	 */
-	if (!(obj->flags & HAS_OBJ))
-		return;
-
-	/*
-	 * Unreachable object that exists? Show it if asked to,
-	 * 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));
-		return;
-	}
-
-	/*
-	 * "!USED" means that nothing at all points to it, including
-	 * other unreachable objects. In other words, it's the "tip"
-	 * of some set of unreachable objects, usually a commit that
-	 * got dropped.
-	 *
-	 * Such starting points are more interesting than some random
-	 * set of unreachable objects, so we show them even if the user
-	 * hasn't asked for _all_ unreachable objects. If you have
-	 * deleted a branch by mistake, this is a prime candidate to
-	 * start looking at, for example.
-	 */
-	if (!(obj->flags & USED)) {
-		if (show_dangling)
-			printf_ln(_("dangling %s %s"),
-				  printable_type(&obj->oid, obj->type),
-				  describe_object(&obj->oid));
-		if (write_lost_and_found) {
-			char *filename = git_pathdup("lost-found/%s/%s",
-				obj->type == OBJ_COMMIT ? "commit" : "other",
-				describe_object(&obj->oid));
-			FILE *f;
-
-			if (safe_create_leading_directories_const(filename)) {
-				error(_("could not create lost-found"));
-				free(filename);
-				return;
-			}
-			f = xfopen(filename, "w");
-			if (obj->type == OBJ_BLOB) {
-				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));
-			if (fclose(f))
-				die_errno(_("could not finish '%s'"),
-					  filename);
-			free(filename);
-		}
-		return;
-	}
-
-	/*
-	 * Otherwise? It's there, it's unreachable, and some other unreachable
-	 * object points to it. Ignore it - it's not interesting, and we showed
-	 * all the interesting cases above.
-	 */
-}
-
-static void check_object(struct object *obj)
-{
-	if (verbose)
-		fprintf_ln(stderr, _("Checking %s"), describe_object(&obj->oid));
-
-	if (obj->flags & REACHABLE)
-		check_reachable_object(obj);
-	else
-		check_unreachable_object(obj);
-}
-
-static void check_connectivity(void)
-{
-	int i, max;
-
-	/* Traverse the pending reachable objects */
-	traverse_reachable();
-
-	/*
-	 * With --connectivity-only, we won't have actually opened and marked
-	 * unreachable objects with USED. Do that now to make --dangling, etc
-	 * accurate.
-	 */
-	if (connectivity_only && (show_dangling || write_lost_and_found)) {
-		/*
-		 * Even though we already have a "struct object" for each of
-		 * these in memory, we must not iterate over the internal
-		 * object hash as we do below. Our loop would potentially
-		 * resize the hash, making our iteration invalid.
-		 *
-		 * Instead, we'll just go back to the source list of objects,
-		 * and ignore any that weren't present in our earlier
-		 * traversal.
-		 */
-		for_each_loose_object(mark_loose_unreachable_referents, NULL, 0);
-		for_each_packed_object(mark_packed_unreachable_referents, NULL, 0);
-	}
-
-	/* Look up all the requirements, warn about missing objects.. */
-	max = get_max_object_index();
-	if (verbose)
-		fprintf_ln(stderr, _("Checking connectivity (%d objects)"), max);
-
-	for (i = 0; i < max; i++) {
-		struct object *obj = get_indexed_object(i);
-
-		if (obj)
-			check_object(obj);
-	}
-}
-
-static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
-{
-	int err;
-
-	if (obj->flags & SEEN)
-		return 0;
-	obj->flags |= SEEN;
-
-	if (verbose)
-		fprintf_ln(stderr, _("Checking %s %s"),
-			   printable_type(&obj->oid, obj->type),
-			   describe_object(&obj->oid));
-
-	if (fsck_walk(obj, NULL, &fsck_obj_options))
-		objerror(obj, _("broken links"));
-	err = fsck_object(obj, buffer, size, &fsck_obj_options);
-	if (err)
-		goto out;
-
-	if (obj->type == OBJ_COMMIT) {
-		struct commit *commit = (struct commit *) obj;
-
-		if (!commit->parents && show_root)
-			printf_ln(_("root %s"),
-				  describe_object(&commit->object.oid));
-	}
-
-	if (obj->type == OBJ_TAG) {
-		struct tag *tag = (struct tag *) obj;
-
-		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),
-				  tag->tag,
-				  describe_object(&tag->object.oid));
-		}
-	}
-
-out:
-	if (obj->type == OBJ_TREE)
-		free_tree_buffer((struct tree *)obj);
-	if (obj->type == OBJ_COMMIT)
-		free_commit_buffer(the_repository->parsed_objects,
-				   (struct commit *)obj);
-	return err;
-}
-
-static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
-			   unsigned long size, void *buffer, int *eaten)
-{
-	/*
-	 * Note, buffer may be NULL if type is OBJ_BLOB. See
-	 * verify_packfile(), data_valid variable for details.
-	 */
-	struct object *obj;
-	obj = parse_object_buffer(the_repository, oid, type, size, buffer,
-				  eaten);
-	if (!obj) {
-		errors_found |= ERROR_OBJECT;
-		return error(_("%s: object corrupt or missing"),
-			     oid_to_hex(oid));
-	}
-	obj->flags &= ~(REACHABLE | SEEN);
-	obj->flags |= HAS_OBJ;
-	return fsck_obj(obj, buffer, size);
-}
-
-static int default_refs;
-
-static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,
-	timestamp_t timestamp)
-{
-	struct object *obj;
-
-	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);
-			obj->flags |= USED;
-			mark_object_reachable(obj);
-		} else if (!is_promisor_object(oid)) {
-			error(_("%s: invalid reflog entry %s"),
-			      refname, oid_to_hex(oid));
-			errors_found |= ERROR_REACHABLE;
-		}
-	}
-}
-
-static int fsck_handle_reflog_ent(struct object_id *ooid, struct object_id *noid,
-		const char *email, timestamp_t timestamp, int tz,
-		const char *message, void *cb_data)
-{
-	const char *refname = cb_data;
-
-	if (verbose)
-		fprintf_ln(stderr, _("Checking reflog %s->%s"),
-			   oid_to_hex(ooid), oid_to_hex(noid));
-
-	fsck_handle_reflog_oid(refname, ooid, 0);
-	fsck_handle_reflog_oid(refname, noid, timestamp);
-	return 0;
-}
-
-static int fsck_handle_reflog(const char *logname, const struct object_id *oid,
-			      int flag, void *cb_data)
-{
-	struct strbuf refname = STRBUF_INIT;
-
-	strbuf_worktree_ref(cb_data, &refname, logname);
-	for_each_reflog_ent(refname.buf, fsck_handle_reflog_ent, refname.buf);
-	strbuf_release(&refname);
-	return 0;
-}
-
-static int fsck_handle_ref(const char *refname, const struct object_id *oid,
-			   int flag, void *cb_data)
-{
-	struct object *obj;
-
-	obj = parse_object(the_repository, oid);
-	if (!obj) {
-		if (is_promisor_object(oid)) {
-			/*
-			 * Increment default_refs anyway, because this is a
-			 * valid ref.
-			 */
-			 default_refs++;
-			 return 0;
-		}
-		error(_("%s: invalid sha1 pointer %s"),
-		      refname, oid_to_hex(oid));
-		errors_found |= ERROR_REACHABLE;
-		/* We'll continue with the rest despite the error.. */
-		return 0;
-	}
-	if (obj->type != OBJ_COMMIT && is_branch(refname)) {
-		error(_("%s: not a commit"), refname);
-		errors_found |= ERROR_REFS;
-	}
-	default_refs++;
-	obj->flags |= USED;
-	fsck_put_object_name(&fsck_walk_options,
-			     oid, "%s", refname);
-	mark_object_reachable(obj);
-
-	return 0;
-}
-
-static int fsck_head_link(const char *head_ref_name,
-			  const char **head_points_at,
-			  struct object_id *head_oid);
-
-static void get_default_heads(void)
-{
-	struct worktree **worktrees, **p;
-	const char *head_points_at;
-	struct object_id head_oid;
-
-	for_each_rawref(fsck_handle_ref, NULL);
-
-	worktrees = get_worktrees();
-	for (p = worktrees; *p; p++) {
-		struct worktree *wt = *p;
-		struct strbuf ref = STRBUF_INIT;
-
-		strbuf_worktree_ref(wt, &ref, "HEAD");
-		fsck_head_link(ref.buf, &head_points_at, &head_oid);
-		if (head_points_at && !is_null_oid(&head_oid))
-			fsck_handle_ref(ref.buf, &head_oid, 0, NULL);
-		strbuf_release(&ref);
-
-		if (include_reflogs)
-			refs_for_each_reflog(get_worktree_ref_store(wt),
-					     fsck_handle_reflog, wt);
-	}
-	free_worktrees(worktrees);
-
-	/*
-	 * Not having any default heads isn't really fatal, but
-	 * it does mean that "--unreachable" no longer makes any
-	 * sense (since in this case everything will obviously
-	 * be unreachable by definition.
-	 *
-	 * Showing dangling objects is valid, though (as those
-	 * dangling objects are likely lost heads).
-	 *
-	 * So we just print a warning about it, and clear the
-	 * "show_unreachable" flag.
-	 */
-	if (!default_refs) {
-		fprintf_ln(stderr, _("notice: No default references"));
-		show_unreachable = 0;
-	}
-}
-
-static int fsck_loose(const struct object_id *oid, const char *path, void *data)
-{
-	struct object *obj;
-	enum object_type type;
-	unsigned long size;
-	void *contents;
-	int eaten;
-
-	if (read_loose_object(path, oid, &type, &size, &contents) < 0) {
-		errors_found |= ERROR_OBJECT;
-		error(_("%s: object corrupt or missing: %s"),
-		      oid_to_hex(oid), path);
-		return 0; /* keep checking other objects */
-	}
-
-	if (!contents && type != OBJ_BLOB)
-		BUG("read_loose_object streamed a non-blob");
-
-	obj = parse_object_buffer(the_repository, oid, type, size,
-				  contents, &eaten);
-
-	if (!obj) {
-		errors_found |= ERROR_OBJECT;
-		error(_("%s: object could not be parsed: %s"),
-		      oid_to_hex(oid), path);
-		if (!eaten)
-			free(contents);
-		return 0; /* keep checking other objects */
-	}
-
-	obj->flags &= ~(REACHABLE | SEEN);
-	obj->flags |= HAS_OBJ;
-	if (fsck_obj(obj, contents, size))
-		errors_found |= ERROR_OBJECT;
-
-	if (!eaten)
-		free(contents);
-	return 0; /* keep checking other objects, even if we saw an error */
-}
-
-static int fsck_cruft(const char *basename, const char *path, void *data)
-{
-	if (!starts_with(basename, "tmp_obj_"))
-		fprintf_ln(stderr, _("bad sha1 file: %s"), path);
-	return 0;
-}
-
-static int fsck_subdir(unsigned int nr, const char *path, void *progress)
-{
-	display_progress(progress, nr + 1);
-	return 0;
-}
-
-static void fsck_object_dir(const char *path)
-{
-	struct progress *progress = NULL;
-
-	if (verbose)
-		fprintf_ln(stderr, _("Checking object directory"));
-
-	if (show_progress)
-		progress = start_progress(_("Checking object directories"), 256);
-
-	for_each_loose_file_in_objdir(path, fsck_loose, fsck_cruft, fsck_subdir,
-				      progress);
-	display_progress(progress, 256);
-	stop_progress(&progress);
-}
-
-static int fsck_head_link(const char *head_ref_name,
-			  const char **head_points_at,
-			  struct object_id *head_oid)
-{
-	int null_is_error = 0;
-
-	if (verbose)
-		fprintf_ln(stderr, _("Checking %s link"), head_ref_name);
-
-	*head_points_at = resolve_ref_unsafe(head_ref_name, 0, head_oid, NULL);
-	if (!*head_points_at) {
-		errors_found |= ERROR_REFS;
-		return error(_("invalid %s"), head_ref_name);
-	}
-	if (!strcmp(*head_points_at, head_ref_name))
-		/* detached HEAD */
-		null_is_error = 1;
-	else if (!starts_with(*head_points_at, "refs/heads/")) {
-		errors_found |= ERROR_REFS;
-		return error(_("%s points to something strange (%s)"),
-			     head_ref_name, *head_points_at);
-	}
-	if (is_null_oid(head_oid)) {
-		if (null_is_error) {
-			errors_found |= ERROR_REFS;
-			return error(_("%s: detached HEAD points at nothing"),
-				     head_ref_name);
-		}
-		fprintf_ln(stderr,
-			   _("notice: %s points to an unborn branch (%s)"),
-			   head_ref_name, *head_points_at + 11);
-	}
-	return 0;
-}
-
-static int fsck_cache_tree(struct cache_tree *it)
-{
-	int i;
-	int err = 0;
-
-	if (verbose)
-		fprintf_ln(stderr, _("Checking cache tree"));
-
-	if (0 <= it->entry_count) {
-		struct object *obj = parse_object(the_repository, &it->oid);
-		if (!obj) {
-			error(_("%s: invalid sha1 pointer in cache-tree"),
-			      oid_to_hex(&it->oid));
-			errors_found |= ERROR_REFS;
-			return 1;
-		}
-		obj->flags |= USED;
-		fsck_put_object_name(&fsck_walk_options, &it->oid, ":");
-		mark_object_reachable(obj);
-		if (obj->type != OBJ_TREE)
-			err |= objerror(obj, _("non-tree in cache-tree"));
-	}
-	for (i = 0; i < it->subtree_nr; i++)
-		err |= fsck_cache_tree(it->down[i]->cache_tree);
-	return err;
-}
-
-static void mark_object_for_connectivity(const struct object_id *oid)
-{
-	struct object *obj = lookup_unknown_object(oid);
-	obj->flags |= HAS_OBJ;
-}
-
-static int mark_loose_for_connectivity(const struct object_id *oid,
-				       const char *path,
-				       void *data)
-{
-	mark_object_for_connectivity(oid);
-	return 0;
-}
-
-static int mark_packed_for_connectivity(const struct object_id *oid,
-					struct packed_git *pack,
-					uint32_t pos,
-					void *data)
-{
-	mark_object_for_connectivity(oid);
-	return 0;
-}
-
-static char const * const fsck_usage[] = {
-	N_("git fsck [<options>] [<object>...]"),
-	NULL
-};
-
-static struct option fsck_opts[] = {
-	OPT__VERBOSE(&verbose, N_("be verbose")),
-	OPT_BOOL(0, "unreachable", &show_unreachable, N_("show unreachable objects")),
-	OPT_BOOL(0, "dangling", &show_dangling, N_("show dangling objects")),
-	OPT_BOOL(0, "tags", &show_tags, N_("report tags")),
-	OPT_BOOL(0, "root", &show_root, N_("report root nodes")),
-	OPT_BOOL(0, "cache", &keep_cache_objects, N_("make index objects head nodes")),
-	OPT_BOOL(0, "reflogs", &include_reflogs, N_("make reflogs head nodes (default)")),
-	OPT_BOOL(0, "full", &check_full, N_("also consider packs and alternate objects")),
-	OPT_BOOL(0, "connectivity-only", &connectivity_only, N_("check only connectivity")),
-	OPT_BOOL(0, "strict", &check_strict, N_("enable more strict checking")),
-	OPT_BOOL(0, "lost-found", &write_lost_and_found,
-				N_("write dangling objects in .git/lost-found")),
-	OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
-	OPT_BOOL(0, "name-objects", &name_objects, N_("show verbose names for reachable objects")),
-	OPT_END(),
-};
-
-int cmd_fsck(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	struct object_directory *odb;
-
-	/* fsck knows how to handle missing promisor objects */
-	fetch_if_missing = 0;
-
-	errors_found = 0;
-	read_replace_refs = 0;
-
-	argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
-
-	fsck_walk_options.walk = mark_object;
-	fsck_obj_options.walk = mark_used;
-	fsck_obj_options.error_func = fsck_error_func;
-	if (check_strict)
-		fsck_obj_options.strict = 1;
-
-	if (show_progress == -1)
-		show_progress = isatty(2);
-	if (verbose)
-		show_progress = 0;
-
-	if (write_lost_and_found) {
-		check_full = 1;
-		include_reflogs = 0;
-	}
-
-	if (name_objects)
-		fsck_enable_object_names(&fsck_walk_options);
-
-	git_config(fsck_config, NULL);
-
-	if (connectivity_only) {
-		for_each_loose_object(mark_loose_for_connectivity, NULL, 0);
-		for_each_packed_object(mark_packed_for_connectivity, NULL, 0);
-	} else {
-		prepare_alt_odb(the_repository);
-		for (odb = the_repository->objects->odb; odb; odb = odb->next)
-			fsck_object_dir(odb->path);
-
-		if (check_full) {
-			struct packed_git *p;
-			uint32_t total = 0, count = 0;
-			struct progress *progress = NULL;
-
-			if (show_progress) {
-				for (p = get_all_packs(the_repository); p;
-				     p = p->next) {
-					if (open_pack_index(p))
-						continue;
-					total += p->num_objects;
-				}
-
-				progress = start_progress(_("Checking objects"), total);
-			}
-			for (p = get_all_packs(the_repository); p;
-			     p = p->next) {
-				/* verify gives error messages itself */
-				if (verify_pack(the_repository,
-						p, fsck_obj_buffer,
-						progress, count))
-					errors_found |= ERROR_PACK;
-				count += p->num_objects;
-			}
-			stop_progress(&progress);
-		}
-
-		if (fsck_finish(&fsck_obj_options))
-			errors_found |= ERROR_OBJECT;
-	}
-
-	for (i = 0; i < argc; i++) {
-		const char *arg = argv[i];
-		struct object_id oid;
-		if (!get_oid(arg, &oid)) {
-			struct object *obj = lookup_object(the_repository,
-							   &oid);
-
-			if (!obj || !(obj->flags & HAS_OBJ)) {
-				if (is_promisor_object(&oid))
-					continue;
-				error(_("%s: object missing"), oid_to_hex(&oid));
-				errors_found |= ERROR_OBJECT;
-				continue;
-			}
-
-			obj->flags |= USED;
-			fsck_put_object_name(&fsck_walk_options, &oid,
-					     "%s", arg);
-			mark_object_reachable(obj);
-			continue;
-		}
-		error(_("invalid parameter: expected sha1, got '%s'"), arg);
-		errors_found |= ERROR_OBJECT;
-	}
-
-	/*
-	 * If we've not been given any explicit head information, do the
-	 * default ones from .git/refs. We also consider the index file
-	 * in this case (ie this implies --cache).
-	 */
-	if (!argc) {
-		get_default_heads();
-		keep_cache_objects = 1;
-	}
-
-	if (keep_cache_objects) {
-		verify_index_checksum = 1;
-		verify_ce_order = 1;
-		read_cache();
-		for (i = 0; i < active_nr; i++) {
-			unsigned int mode;
-			struct blob *blob;
-			struct object *obj;
-
-			mode = active_cache[i]->ce_mode;
-			if (S_ISGITLINK(mode))
-				continue;
-			blob = lookup_blob(the_repository,
-					   &active_cache[i]->oid);
-			if (!blob)
-				continue;
-			obj = &blob->object;
-			obj->flags |= USED;
-			fsck_put_object_name(&fsck_walk_options, &obj->oid,
-					     ":%s", active_cache[i]->name);
-			mark_object_reachable(obj);
-		}
-		if (active_cache_tree)
-			fsck_cache_tree(active_cache_tree);
-	}
-
-	check_connectivity();
-
-	if (!git_config_get_bool("core.commitgraph", &i) && i) {
-		struct child_process commit_graph_verify = CHILD_PROCESS_INIT;
-		const char *verify_argv[] = { "commit-graph", "verify", NULL, NULL, NULL };
-
-		prepare_alt_odb(the_repository);
-		for (odb = the_repository->objects->odb; odb; odb = odb->next) {
-			child_process_init(&commit_graph_verify);
-			commit_graph_verify.argv = verify_argv;
-			commit_graph_verify.git_cmd = 1;
-			verify_argv[2] = "--object-dir";
-			verify_argv[3] = odb->path;
-			if (run_command(&commit_graph_verify))
-				errors_found |= ERROR_COMMIT_GRAPH;
-		}
-	}
-
-	if (!git_config_get_bool("core.multipackindex", &i) && i) {
-		struct child_process midx_verify = CHILD_PROCESS_INIT;
-		const char *midx_argv[] = { "multi-pack-index", "verify", NULL, NULL, NULL };
-
-		prepare_alt_odb(the_repository);
-		for (odb = the_repository->objects->odb; odb; odb = odb->next) {
-			child_process_init(&midx_verify);
-			midx_verify.argv = midx_argv;
-			midx_verify.git_cmd = 1;
-			midx_argv[2] = "--object-dir";
-			midx_argv[3] = odb->path;
-			if (run_command(&midx_verify))
-				errors_found |= ERROR_MULTI_PACK_INDEX;
-		}
-	}
-
-	return errors_found;
-}
diff --git a/third_party/git/builtin/gc.c b/third_party/git/builtin/gc.c
deleted file mode 100644
index 090959350e06..000000000000
--- a/third_party/git/builtin/gc.c
+++ /dev/null
@@ -1,1038 +0,0 @@
-/*
- * git gc builtin command
- *
- * Cleanup unreachable files and optimize the repository.
- *
- * Copyright (c) 2007 James Bowes
- *
- * Based on git-gc.sh, which is
- *
- * Copyright (c) 2006 Shawn O. Pearce
- */
-
-#include "builtin.h"
-#include "repository.h"
-#include "config.h"
-#include "tempfile.h"
-#include "lockfile.h"
-#include "parse-options.h"
-#include "run-command.h"
-#include "sigchain.h"
-#include "strvec.h"
-#include "commit.h"
-#include "commit-graph.h"
-#include "packfile.h"
-#include "object-store.h"
-#include "pack.h"
-#include "pack-objects.h"
-#include "blob.h"
-#include "tree.h"
-#include "promisor-remote.h"
-#include "refs.h"
-
-#define FAILED_RUN "failed to run %s"
-
-static const char * const builtin_gc_usage[] = {
-	N_("git gc [<options>]"),
-	NULL
-};
-
-static int pack_refs = 1;
-static int prune_reflogs = 1;
-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 detach_auto = 1;
-static timestamp_t gc_log_expire_time;
-static const char *gc_log_expire = "1.day.ago";
-static const char *prune_expire = "2.weeks.ago";
-static const char *prune_worktrees_expire = "3.months.ago";
-static unsigned long big_pack_threshold;
-static unsigned long max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE;
-
-static struct strvec pack_refs_cmd = STRVEC_INIT;
-static struct strvec reflog = STRVEC_INIT;
-static struct strvec repack = STRVEC_INIT;
-static struct strvec prune = STRVEC_INIT;
-static struct strvec prune_worktrees = STRVEC_INIT;
-static struct strvec rerere = STRVEC_INIT;
-
-static struct tempfile *pidfile;
-static struct lock_file log_lock;
-
-static struct string_list pack_garbage = STRING_LIST_INIT_DUP;
-
-static void clean_pack_garbage(void)
-{
-	int i;
-	for (i = 0; i < pack_garbage.nr; i++)
-		unlink_or_warn(pack_garbage.items[i].string);
-	string_list_clear(&pack_garbage, 0);
-}
-
-static void report_pack_garbage(unsigned seen_bits, const char *path)
-{
-	if (seen_bits == PACKDIR_FILE_IDX)
-		string_list_append(&pack_garbage, path);
-}
-
-static void process_log_file(void)
-{
-	struct stat st;
-	if (fstat(get_lock_file_fd(&log_lock), &st)) {
-		/*
-		 * Perhaps there was an i/o error or another
-		 * unlikely situation.  Try to make a note of
-		 * this in gc.log along with any existing
-		 * messages.
-		 */
-		int saved_errno = errno;
-		fprintf(stderr, _("Failed to fstat %s: %s"),
-			get_tempfile_path(log_lock.tempfile),
-			strerror(saved_errno));
-		fflush(stderr);
-		commit_lock_file(&log_lock);
-		errno = saved_errno;
-	} else if (st.st_size) {
-		/* There was some error recorded in the lock file */
-		commit_lock_file(&log_lock);
-	} else {
-		/* No error, clean up any old gc.log */
-		unlink(git_path("gc.log"));
-		rollback_lock_file(&log_lock);
-	}
-}
-
-static void process_log_file_at_exit(void)
-{
-	fflush(stderr);
-	process_log_file();
-}
-
-static void process_log_file_on_signal(int signo)
-{
-	process_log_file();
-	sigchain_pop(signo);
-	raise(signo);
-}
-
-static int gc_config_is_timestamp_never(const char *var)
-{
-	const char *value;
-	timestamp_t expire;
-
-	if (!git_config_get_value(var, &value) && value) {
-		if (parse_expiry_date(value, &expire))
-			die(_("failed to parse '%s' value '%s'"), var, value);
-		return expire == 0;
-	}
-	return 0;
-}
-
-static void gc_config(void)
-{
-	const char *value;
-
-	if (!git_config_get_value("gc.packrefs", &value)) {
-		if (value && !strcmp(value, "notbare"))
-			pack_refs = -1;
-		else
-			pack_refs = git_config_bool("gc.packrefs", value);
-	}
-
-	if (gc_config_is_timestamp_never("gc.reflogexpire") &&
-	    gc_config_is_timestamp_never("gc.reflogexpireunreachable"))
-		prune_reflogs = 0;
-
-	git_config_get_int("gc.aggressivewindow", &aggressive_window);
-	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.autodetach", &detach_auto);
-	git_config_get_expiry("gc.pruneexpire", &prune_expire);
-	git_config_get_expiry("gc.worktreepruneexpire", &prune_worktrees_expire);
-	git_config_get_expiry("gc.logexpiry", &gc_log_expire);
-
-	git_config_get_ulong("gc.bigpackthreshold", &big_pack_threshold);
-	git_config_get_ulong("pack.deltacachesize", &max_delta_cache_size);
-
-	git_config(git_default_config, NULL);
-}
-
-static int too_many_loose_objects(void)
-{
-	/*
-	 * Quickly check if a "gc" is needed, by estimating how
-	 * many loose objects there are.  Because SHA-1 is evenly
-	 * distributed, we can check only one and get a reasonable
-	 * estimate.
-	 */
-	DIR *dir;
-	struct dirent *ent;
-	int auto_threshold;
-	int num_loose = 0;
-	int needed = 0;
-	const unsigned hexsz_loose = the_hash_algo->hexsz - 2;
-
-	dir = opendir(git_path("objects/17"));
-	if (!dir)
-		return 0;
-
-	auto_threshold = DIV_ROUND_UP(gc_auto_threshold, 256);
-	while ((ent = readdir(dir)) != NULL) {
-		if (strspn(ent->d_name, "0123456789abcdef") != hexsz_loose ||
-		    ent->d_name[hexsz_loose] != '\0')
-			continue;
-		if (++num_loose > auto_threshold) {
-			needed = 1;
-			break;
-		}
-	}
-	closedir(dir);
-	return needed;
-}
-
-static struct packed_git *find_base_packs(struct string_list *packs,
-					  unsigned long limit)
-{
-	struct packed_git *p, *base = NULL;
-
-	for (p = get_all_packs(the_repository); p; p = p->next) {
-		if (!p->pack_local)
-			continue;
-		if (limit) {
-			if (p->pack_size >= limit)
-				string_list_append(packs, p->pack_name);
-		} else if (!base || base->pack_size < p->pack_size) {
-			base = p;
-		}
-	}
-
-	if (base)
-		string_list_append(packs, base->pack_name);
-
-	return base;
-}
-
-static int too_many_packs(void)
-{
-	struct packed_git *p;
-	int cnt;
-
-	if (gc_auto_pack_limit <= 0)
-		return 0;
-
-	for (cnt = 0, p = get_all_packs(the_repository); p; p = p->next) {
-		if (!p->pack_local)
-			continue;
-		if (p->pack_keep)
-			continue;
-		/*
-		 * Perhaps check the size of the pack and count only
-		 * very small ones here?
-		 */
-		cnt++;
-	}
-	return gc_auto_pack_limit < cnt;
-}
-
-static uint64_t total_ram(void)
-{
-#if defined(HAVE_SYSINFO)
-	struct sysinfo si;
-
-	if (!sysinfo(&si))
-		return si.totalram;
-#elif defined(HAVE_BSD_SYSCTL) && (defined(HW_MEMSIZE) || defined(HW_PHYSMEM))
-	int64_t physical_memory;
-	int mib[2];
-	size_t length;
-
-	mib[0] = CTL_HW;
-# if defined(HW_MEMSIZE)
-	mib[1] = HW_MEMSIZE;
-# else
-	mib[1] = HW_PHYSMEM;
-# endif
-	length = sizeof(int64_t);
-	if (!sysctl(mib, 2, &physical_memory, &length, NULL, 0))
-		return physical_memory;
-#elif defined(GIT_WINDOWS_NATIVE)
-	MEMORYSTATUSEX memInfo;
-
-	memInfo.dwLength = sizeof(MEMORYSTATUSEX);
-	if (GlobalMemoryStatusEx(&memInfo))
-		return memInfo.ullTotalPhys;
-#endif
-	return 0;
-}
-
-static uint64_t estimate_repack_memory(struct packed_git *pack)
-{
-	unsigned long nr_objects = approximate_object_count();
-	size_t os_cache, heap;
-
-	if (!pack || !nr_objects)
-		return 0;
-
-	/*
-	 * First we have to scan through at least one pack.
-	 * Assume enough room in OS file cache to keep the entire pack
-	 * or we may accidentally evict data of other processes from
-	 * the cache.
-	 */
-	os_cache = pack->pack_size + pack->index_size;
-	/* then pack-objects needs lots more for book keeping */
-	heap = sizeof(struct object_entry) * nr_objects;
-	/*
-	 * internal rev-list --all --objects takes up some memory too,
-	 * let's say half of it is for blobs
-	 */
-	heap += sizeof(struct blob) * nr_objects / 2;
-	/*
-	 * and the other half is for trees (commits and tags are
-	 * usually insignificant)
-	 */
-	heap += sizeof(struct tree) * nr_objects / 2;
-	/* and then obj_hash[], underestimated in fact */
-	heap += sizeof(struct object *) * nr_objects;
-	/* revindex is used also */
-	heap += sizeof(struct revindex_entry) * nr_objects;
-	/*
-	 * read_sha1_file() (either at delta calculation phase, or
-	 * writing phase) also fills up the delta base cache
-	 */
-	heap += delta_base_cache_limit;
-	/* and of course pack-objects has its own delta cache */
-	heap += max_delta_cache_size;
-
-	return os_cache + heap;
-}
-
-static int keep_one_pack(struct string_list_item *item, void *data)
-{
-	strvec_pushf(&repack, "--keep-pack=%s", basename(item->string));
-	return 0;
-}
-
-static void add_repack_all_option(struct string_list *keep_pack)
-{
-	if (prune_expire && !strcmp(prune_expire, "now"))
-		strvec_push(&repack, "-a");
-	else {
-		strvec_push(&repack, "-A");
-		if (prune_expire)
-			strvec_pushf(&repack, "--unpack-unreachable=%s", prune_expire);
-	}
-
-	if (keep_pack)
-		for_each_string_list(keep_pack, keep_one_pack, NULL);
-}
-
-static void add_repack_incremental_option(void)
-{
-	strvec_push(&repack, "--no-write-bitmap-index");
-}
-
-static int need_to_gc(void)
-{
-	/*
-	 * Setting gc.auto to 0 or negative can disable the
-	 * automatic gc.
-	 */
-	if (gc_auto_threshold <= 0)
-		return 0;
-
-	/*
-	 * If there are too many loose objects, but not too many
-	 * packs, we run "repack -d -l".  If there are too many packs,
-	 * we run "repack -A -d -l".  Otherwise we tell the caller
-	 * there is no need.
-	 */
-	if (too_many_packs()) {
-		struct string_list keep_pack = STRING_LIST_INIT_NODUP;
-
-		if (big_pack_threshold) {
-			find_base_packs(&keep_pack, big_pack_threshold);
-			if (keep_pack.nr >= gc_auto_pack_limit) {
-				big_pack_threshold = 0;
-				string_list_clear(&keep_pack, 0);
-				find_base_packs(&keep_pack, 0);
-			}
-		} else {
-			struct packed_git *p = find_base_packs(&keep_pack, 0);
-			uint64_t mem_have, mem_want;
-
-			mem_have = total_ram();
-			mem_want = estimate_repack_memory(p);
-
-			/*
-			 * Only allow 1/2 of memory for pack-objects, leave
-			 * the rest for the OS and other processes in the
-			 * system.
-			 */
-			if (!mem_have || mem_want < mem_have / 2)
-				string_list_clear(&keep_pack, 0);
-		}
-
-		add_repack_all_option(&keep_pack);
-		string_list_clear(&keep_pack, 0);
-	} else if (too_many_loose_objects())
-		add_repack_incremental_option();
-	else
-		return 0;
-
-	if (run_hook_le(NULL, "pre-auto-gc", NULL))
-		return 0;
-	return 1;
-}
-
-/* return NULL on success, else hostname running the gc */
-static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
-{
-	struct lock_file lock = LOCK_INIT;
-	char my_host[HOST_NAME_MAX + 1];
-	struct strbuf sb = STRBUF_INIT;
-	struct stat st;
-	uintmax_t pid;
-	FILE *fp;
-	int fd;
-	char *pidfile_path;
-
-	if (is_tempfile_active(pidfile))
-		/* already locked */
-		return NULL;
-
-	if (xgethostname(my_host, sizeof(my_host)))
-		xsnprintf(my_host, sizeof(my_host), "unknown");
-
-	pidfile_path = git_pathdup("gc.pid");
-	fd = hold_lock_file_for_update(&lock, pidfile_path,
-				       LOCK_DIE_ON_ERROR);
-	if (!force) {
-		static char locking_host[HOST_NAME_MAX + 1];
-		static char *scan_fmt;
-		int should_exit;
-
-		if (!scan_fmt)
-			scan_fmt = xstrfmt("%s %%%ds", "%"SCNuMAX, HOST_NAME_MAX);
-		fp = fopen(pidfile_path, "r");
-		memset(locking_host, 0, sizeof(locking_host));
-		should_exit =
-			fp != NULL &&
-			!fstat(fileno(fp), &st) &&
-			/*
-			 * 12 hour limit is very generous as gc should
-			 * never take that long. On the other hand we
-			 * don't really need a strict limit here,
-			 * running gc --auto one day late is not a big
-			 * problem. --force can be used in manual gc
-			 * after the user verifies that no gc is
-			 * running.
-			 */
-			time(NULL) - st.st_mtime <= 12 * 3600 &&
-			fscanf(fp, scan_fmt, &pid, locking_host) == 2 &&
-			/* be gentle to concurrent "gc" on remote hosts */
-			(strcmp(locking_host, my_host) || !kill(pid, 0) || errno == EPERM);
-		if (fp != NULL)
-			fclose(fp);
-		if (should_exit) {
-			if (fd >= 0)
-				rollback_lock_file(&lock);
-			*ret_pid = pid;
-			free(pidfile_path);
-			return locking_host;
-		}
-	}
-
-	strbuf_addf(&sb, "%"PRIuMAX" %s",
-		    (uintmax_t) getpid(), my_host);
-	write_in_full(fd, sb.buf, sb.len);
-	strbuf_release(&sb);
-	commit_lock_file(&lock);
-	pidfile = register_tempfile(pidfile_path);
-	free(pidfile_path);
-	return NULL;
-}
-
-/*
- * 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
- */
-static int report_last_gc_error(void)
-{
-	struct strbuf sb = STRBUF_INIT;
-	int ret = 0;
-	ssize_t len;
-	struct stat st;
-	char *gc_log_path = git_pathdup("gc.log");
-
-	if (stat(gc_log_path, &st)) {
-		if (errno == ENOENT)
-			goto done;
-
-		ret = error_errno(_("cannot stat '%s'"), gc_log_path);
-		goto done;
-	}
-
-	if (st.st_mtime < gc_log_expire_time)
-		goto done;
-
-	len = strbuf_read_file(&sb, gc_log_path, 0);
-	if (len < 0)
-		ret = error_errno(_("cannot read '%s'"), gc_log_path);
-	else if (len > 0) {
-		/*
-		 * A previous gc failed.  Report the error, and don't
-		 * bother with an automatic gc run since it is likely
-		 * to fail in the same way.
-		 */
-		warning(_("The last gc run reported the following. "
-			       "Please correct the root cause\n"
-			       "and remove %s.\n"
-			       "Automatic cleanup will not be performed "
-			       "until the file is removed.\n\n"
-			       "%s"),
-			    gc_log_path, sb.buf);
-		ret = 1;
-	}
-	strbuf_release(&sb);
-done:
-	free(gc_log_path);
-	return ret;
-}
-
-static void gc_before_repack(void)
-{
-	/*
-	 * We may be called twice, as both the pre- and
-	 * post-daemonized phases will call us, but running these
-	 * commands more than once is pointless and wasteful.
-	 */
-	static int done = 0;
-	if (done++)
-		return;
-
-	if (pack_refs && run_command_v_opt(pack_refs_cmd.v, RUN_GIT_CMD))
-		die(FAILED_RUN, pack_refs_cmd.v[0]);
-
-	if (prune_reflogs && run_command_v_opt(reflog.v, RUN_GIT_CMD))
-		die(FAILED_RUN, reflog.v[0]);
-}
-
-int cmd_gc(int argc, const char **argv, const char *prefix)
-{
-	int aggressive = 0;
-	int auto_gc = 0;
-	int quiet = 0;
-	int force = 0;
-	const char *name;
-	pid_t pid;
-	int daemonized = 0;
-	int keep_base_pack = -1;
-	timestamp_t dummy;
-
-	struct option builtin_gc_options[] = {
-		OPT__QUIET(&quiet, N_("suppress progress reporting")),
-		{ OPTION_STRING, 0, "prune", &prune_expire, N_("date"),
-			N_("prune unreferenced objects"),
-			PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire },
-		OPT_BOOL(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")),
-		OPT_BOOL_F(0, "auto", &auto_gc, N_("enable auto-gc mode"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT_BOOL_F(0, "force", &force,
-			   N_("force running gc even if there may be another gc running"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT_BOOL(0, "keep-largest-pack", &keep_base_pack,
-			 N_("repack all other packs except the largest pack")),
-		OPT_END()
-	};
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage_with_options(builtin_gc_usage, builtin_gc_options);
-
-	strvec_pushl(&pack_refs_cmd, "pack-refs", "--all", "--prune", NULL);
-	strvec_pushl(&reflog, "reflog", "expire", "--all", NULL);
-	strvec_pushl(&repack, "repack", "-d", "-l", NULL);
-	strvec_pushl(&prune, "prune", "--expire", NULL);
-	strvec_pushl(&prune_worktrees, "worktree", "prune", "--expire", NULL);
-	strvec_pushl(&rerere, "rerere", "gc", NULL);
-
-	/* default expiry time, overwritten in gc_config */
-	gc_config();
-	if (parse_expiry_date(gc_log_expire, &gc_log_expire_time))
-		die(_("failed to parse gc.logexpiry value %s"), gc_log_expire);
-
-	if (pack_refs < 0)
-		pack_refs = !is_bare_repository();
-
-	argc = parse_options(argc, argv, prefix, builtin_gc_options,
-			     builtin_gc_usage, 0);
-	if (argc > 0)
-		usage_with_options(builtin_gc_usage, builtin_gc_options);
-
-	if (prune_expire && parse_expiry_date(prune_expire, &dummy))
-		die(_("failed to parse prune expiry value %s"), prune_expire);
-
-	if (aggressive) {
-		strvec_push(&repack, "-f");
-		if (aggressive_depth > 0)
-			strvec_pushf(&repack, "--depth=%d", aggressive_depth);
-		if (aggressive_window > 0)
-			strvec_pushf(&repack, "--window=%d", aggressive_window);
-	}
-	if (quiet)
-		strvec_push(&repack, "-q");
-
-	if (auto_gc) {
-		/*
-		 * Auto-gc should be least intrusive as possible.
-		 */
-		if (!need_to_gc())
-			return 0;
-		if (!quiet) {
-			if (detach_auto)
-				fprintf(stderr, _("Auto packing the repository in background for optimum performance.\n"));
-			else
-				fprintf(stderr, _("Auto packing the repository for optimum performance.\n"));
-			fprintf(stderr, _("See \"git help gc\" for manual housekeeping.\n"));
-		}
-		if (detach_auto) {
-			int ret = report_last_gc_error();
-			if (ret < 0)
-				/* an I/O error occurred, already reported */
-				exit(128);
-			if (ret == 1)
-				/* Last gc --auto failed. Skip this one. */
-				return 0;
-
-			if (lock_repo_for_gc(force, &pid))
-				return 0;
-			gc_before_repack(); /* dies on failure */
-			delete_tempfile(&pidfile);
-
-			/*
-			 * failure to daemonize is ok, we'll continue
-			 * in foreground
-			 */
-			daemonized = !daemonize();
-		}
-	} else {
-		struct string_list keep_pack = STRING_LIST_INIT_NODUP;
-
-		if (keep_base_pack != -1) {
-			if (keep_base_pack)
-				find_base_packs(&keep_pack, 0);
-		} else if (big_pack_threshold) {
-			find_base_packs(&keep_pack, big_pack_threshold);
-		}
-
-		add_repack_all_option(&keep_pack);
-		string_list_clear(&keep_pack, 0);
-	}
-
-	name = lock_repo_for_gc(force, &pid);
-	if (name) {
-		if (auto_gc)
-			return 0; /* be quiet on --auto */
-		die(_("gc is already running on machine '%s' pid %"PRIuMAX" (use --force if not)"),
-		    name, (uintmax_t)pid);
-	}
-
-	if (daemonized) {
-		hold_lock_file_for_update(&log_lock,
-					  git_path("gc.log"),
-					  LOCK_DIE_ON_ERROR);
-		dup2(get_lock_file_fd(&log_lock), 2);
-		sigchain_push_common(process_log_file_on_signal);
-		atexit(process_log_file_at_exit);
-	}
-
-	gc_before_repack();
-
-	if (!repository_format_precious_objects) {
-		close_object_store(the_repository->objects);
-		if (run_command_v_opt(repack.v, RUN_GIT_CMD))
-			die(FAILED_RUN, repack.v[0]);
-
-		if (prune_expire) {
-			strvec_push(&prune, prune_expire);
-			if (quiet)
-				strvec_push(&prune, "--no-progress");
-			if (has_promisor_remote())
-				strvec_push(&prune,
-					    "--exclude-promisor-objects");
-			if (run_command_v_opt(prune.v, RUN_GIT_CMD))
-				die(FAILED_RUN, prune.v[0]);
-		}
-	}
-
-	if (prune_worktrees_expire) {
-		strvec_push(&prune_worktrees, prune_worktrees_expire);
-		if (run_command_v_opt(prune_worktrees.v, RUN_GIT_CMD))
-			die(FAILED_RUN, prune_worktrees.v[0]);
-	}
-
-	if (run_command_v_opt(rerere.v, RUN_GIT_CMD))
-		die(FAILED_RUN, rerere.v[0]);
-
-	report_garbage = report_pack_garbage;
-	reprepare_packed_git(the_repository);
-	if (pack_garbage.nr > 0) {
-		close_object_store(the_repository->objects);
-		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 (auto_gc && too_many_loose_objects())
-		warning(_("There are too many unreachable loose objects; "
-			"run 'git prune' to remove them."));
-
-	if (!daemonized)
-		unlink(git_path("gc.log"));
-
-	return 0;
-}
-
-static const char * const builtin_maintenance_run_usage[] = {
-	N_("git maintenance run [--auto] [--[no-]quiet] [--task=<task>]"),
-	NULL
-};
-
-struct maintenance_run_opts {
-	int auto_flag;
-	int quiet;
-};
-
-/* Remember to update object flag allocation in object.h */
-#define SEEN		(1u<<0)
-
-struct cg_auto_data {
-	int num_not_in_graph;
-	int limit;
-};
-
-static int dfs_on_ref(const char *refname,
-		      const struct object_id *oid, int flags,
-		      void *cb_data)
-{
-	struct cg_auto_data *data = (struct cg_auto_data *)cb_data;
-	int result = 0;
-	struct object_id peeled;
-	struct commit_list *stack = NULL;
-	struct commit *commit;
-
-	if (!peel_ref(refname, &peeled))
-		oid = &peeled;
-	if (oid_object_info(the_repository, oid, NULL) != OBJ_COMMIT)
-		return 0;
-
-	commit = lookup_commit(the_repository, oid);
-	if (!commit)
-		return 0;
-	if (parse_commit(commit))
-		return 0;
-
-	commit_list_append(commit, &stack);
-
-	while (!result && stack) {
-		struct commit_list *parent;
-
-		commit = pop_commit(&stack);
-
-		for (parent = commit->parents; parent; parent = parent->next) {
-			if (parse_commit(parent->item) ||
-			    commit_graph_position(parent->item) != COMMIT_NOT_FROM_GRAPH ||
-			    parent->item->object.flags & SEEN)
-				continue;
-
-			parent->item->object.flags |= SEEN;
-			data->num_not_in_graph++;
-
-			if (data->num_not_in_graph >= data->limit) {
-				result = 1;
-				break;
-			}
-
-			commit_list_append(parent->item, &stack);
-		}
-	}
-
-	free_commit_list(stack);
-	return result;
-}
-
-static int should_write_commit_graph(void)
-{
-	int result;
-	struct cg_auto_data data;
-
-	data.num_not_in_graph = 0;
-	data.limit = 100;
-	git_config_get_int("maintenance.commit-graph.auto",
-			   &data.limit);
-
-	if (!data.limit)
-		return 0;
-	if (data.limit < 0)
-		return 1;
-
-	result = for_each_ref(dfs_on_ref, &data);
-
-	clear_commit_marks_all(SEEN);
-
-	return result;
-}
-
-static int run_write_commit_graph(struct maintenance_run_opts *opts)
-{
-	struct child_process child = CHILD_PROCESS_INIT;
-
-	child.git_cmd = 1;
-	strvec_pushl(&child.args, "commit-graph", "write",
-		     "--split", "--reachable", NULL);
-
-	if (opts->quiet)
-		strvec_push(&child.args, "--no-progress");
-
-	return !!run_command(&child);
-}
-
-static int maintenance_task_commit_graph(struct maintenance_run_opts *opts)
-{
-	close_object_store(the_repository->objects);
-	if (run_write_commit_graph(opts)) {
-		error(_("failed to write commit-graph"));
-		return 1;
-	}
-
-	return 0;
-}
-
-static int maintenance_task_gc(struct maintenance_run_opts *opts)
-{
-	struct child_process child = CHILD_PROCESS_INIT;
-
-	child.git_cmd = 1;
-	strvec_push(&child.args, "gc");
-
-	if (opts->auto_flag)
-		strvec_push(&child.args, "--auto");
-	if (opts->quiet)
-		strvec_push(&child.args, "--quiet");
-	else
-		strvec_push(&child.args, "--no-quiet");
-
-	close_object_store(the_repository->objects);
-	return run_command(&child);
-}
-
-typedef int maintenance_task_fn(struct maintenance_run_opts *opts);
-
-/*
- * An auto condition function returns 1 if the task should run
- * and 0 if the task should NOT run. See needs_to_gc() for an
- * example.
- */
-typedef int maintenance_auto_fn(void);
-
-struct maintenance_task {
-	const char *name;
-	maintenance_task_fn *fn;
-	maintenance_auto_fn *auto_condition;
-	unsigned enabled:1;
-
-	/* -1 if not selected. */
-	int selected_order;
-};
-
-enum maintenance_task_label {
-	TASK_GC,
-	TASK_COMMIT_GRAPH,
-
-	/* Leave as final value */
-	TASK__COUNT
-};
-
-static struct maintenance_task tasks[] = {
-	[TASK_GC] = {
-		"gc",
-		maintenance_task_gc,
-		need_to_gc,
-		1,
-	},
-	[TASK_COMMIT_GRAPH] = {
-		"commit-graph",
-		maintenance_task_commit_graph,
-		should_write_commit_graph,
-	},
-};
-
-static int compare_tasks_by_selection(const void *a_, const void *b_)
-{
-	const struct maintenance_task *a, *b;
-
-	a = (const struct maintenance_task *)&a_;
-	b = (const struct maintenance_task *)&b_;
-
-	return b->selected_order - a->selected_order;
-}
-
-static int maintenance_run_tasks(struct maintenance_run_opts *opts)
-{
-	int i, found_selected = 0;
-	int result = 0;
-	struct lock_file lk;
-	struct repository *r = the_repository;
-	char *lock_path = xstrfmt("%s/maintenance", r->objects->odb->path);
-
-	if (hold_lock_file_for_update(&lk, lock_path, LOCK_NO_DEREF) < 0) {
-		/*
-		 * Another maintenance command is running.
-		 *
-		 * If --auto was provided, then it is likely due to a
-		 * recursive process stack. Do not report an error in
-		 * that case.
-		 */
-		if (!opts->auto_flag && !opts->quiet)
-			warning(_("lock file '%s' exists, skipping maintenance"),
-				lock_path);
-		free(lock_path);
-		return 0;
-	}
-	free(lock_path);
-
-	for (i = 0; !found_selected && i < TASK__COUNT; i++)
-		found_selected = tasks[i].selected_order >= 0;
-
-	if (found_selected)
-		QSORT(tasks, TASK__COUNT, compare_tasks_by_selection);
-
-	for (i = 0; i < TASK__COUNT; i++) {
-		if (found_selected && tasks[i].selected_order < 0)
-			continue;
-
-		if (!found_selected && !tasks[i].enabled)
-			continue;
-
-		if (opts->auto_flag &&
-		    (!tasks[i].auto_condition ||
-		     !tasks[i].auto_condition()))
-			continue;
-
-		trace2_region_enter("maintenance", tasks[i].name, r);
-		if (tasks[i].fn(opts)) {
-			error(_("task '%s' failed"), tasks[i].name);
-			result = 1;
-		}
-		trace2_region_leave("maintenance", tasks[i].name, r);
-	}
-
-	rollback_lock_file(&lk);
-	return result;
-}
-
-static void initialize_task_config(void)
-{
-	int i;
-	struct strbuf config_name = STRBUF_INIT;
-	gc_config();
-
-	for (i = 0; i < TASK__COUNT; i++) {
-		int config_value;
-
-		strbuf_setlen(&config_name, 0);
-		strbuf_addf(&config_name, "maintenance.%s.enabled",
-			    tasks[i].name);
-
-		if (!git_config_get_bool(config_name.buf, &config_value))
-			tasks[i].enabled = config_value;
-	}
-
-	strbuf_release(&config_name);
-}
-
-static int task_option_parse(const struct option *opt,
-			     const char *arg, int unset)
-{
-	int i, num_selected = 0;
-	struct maintenance_task *task = NULL;
-
-	BUG_ON_OPT_NEG(unset);
-
-	for (i = 0; i < TASK__COUNT; i++) {
-		if (tasks[i].selected_order >= 0)
-			num_selected++;
-		if (!strcasecmp(tasks[i].name, arg)) {
-			task = &tasks[i];
-		}
-	}
-
-	if (!task) {
-		error(_("'%s' is not a valid task"), arg);
-		return 1;
-	}
-
-	if (task->selected_order >= 0) {
-		error(_("task '%s' cannot be selected multiple times"), arg);
-		return 1;
-	}
-
-	task->selected_order = num_selected + 1;
-
-	return 0;
-}
-
-static int maintenance_run(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	struct maintenance_run_opts opts;
-	struct option builtin_maintenance_run_options[] = {
-		OPT_BOOL(0, "auto", &opts.auto_flag,
-			 N_("run tasks based on the state of the repository")),
-		OPT_BOOL(0, "quiet", &opts.quiet,
-			 N_("do not report progress or other information over stderr")),
-		OPT_CALLBACK_F(0, "task", NULL, N_("task"),
-			N_("run a specific task"),
-			PARSE_OPT_NONEG, task_option_parse),
-		OPT_END()
-	};
-	memset(&opts, 0, sizeof(opts));
-
-	opts.quiet = !isatty(2);
-	initialize_task_config();
-
-	for (i = 0; i < TASK__COUNT; i++)
-		tasks[i].selected_order = -1;
-
-	argc = parse_options(argc, argv, prefix,
-			     builtin_maintenance_run_options,
-			     builtin_maintenance_run_usage,
-			     PARSE_OPT_STOP_AT_NON_OPTION);
-
-	if (argc != 0)
-		usage_with_options(builtin_maintenance_run_usage,
-				   builtin_maintenance_run_options);
-	return maintenance_run_tasks(&opts);
-}
-
-static const char builtin_maintenance_usage[] = N_("git maintenance run [<options>]");
-
-int cmd_maintenance(int argc, const char **argv, const char *prefix)
-{
-	if (argc < 2 ||
-	    (argc == 2 && !strcmp(argv[1], "-h")))
-		usage(builtin_maintenance_usage);
-
-	if (!strcmp(argv[1], "run"))
-		return maintenance_run(argc - 1, argv + 1, prefix);
-
-	die(_("invalid subcommand: %s"), argv[1]);
-}
diff --git a/third_party/git/builtin/get-tar-commit-id.c b/third_party/git/builtin/get-tar-commit-id.c
deleted file mode 100644
index 491af9202dc9..000000000000
--- a/third_party/git/builtin/get-tar-commit-id.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2005, 2006 Rene Scharfe
- */
-#include "cache.h"
-#include "commit.h"
-#include "tar.h"
-#include "builtin.h"
-#include "quote.h"
-
-static const char builtin_get_tar_commit_id_usage[] =
-"git get-tar-commit-id";
-
-/* ustar header + extended global header content */
-#define RECORDSIZE	(512)
-#define HEADERSIZE (2 * RECORDSIZE)
-
-int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix)
-{
-	char buffer[HEADERSIZE];
-	struct ustar_header *header = (struct ustar_header *)buffer;
-	char *content = buffer + RECORDSIZE;
-	const char *comment;
-	ssize_t n;
-	long len;
-	char *end;
-
-	if (argc != 1)
-		usage(builtin_get_tar_commit_id_usage);
-
-	n = read_in_full(0, buffer, HEADERSIZE);
-	if (n < 0)
-		die_errno("git get-tar-commit-id: read error");
-	if (n != HEADERSIZE)
-		die_errno("git get-tar-commit-id: EOF before reading tar header");
-	if (header->typeflag[0] != 'g')
-		return 1;
-
-	len = strtol(content, &end, 10);
-	if (errno == ERANGE || end == content || len < 0)
-		return 1;
-	if (!skip_prefix(end, " comment=", &comment))
-		return 1;
-	len -= comment - content;
-	if (len < 1 || !(len % 2) ||
-	    hash_algo_by_length((len - 1) / 2) == GIT_HASH_UNKNOWN)
-		return 1;
-
-	if (write_in_full(1, comment, len) < 0)
-		die_errno("git get-tar-commit-id: write error");
-
-	return 0;
-}
diff --git a/third_party/git/builtin/grep.c b/third_party/git/builtin/grep.c
deleted file mode 100644
index c8037388c6e7..000000000000
--- a/third_party/git/builtin/grep.c
+++ /dev/null
@@ -1,1175 +0,0 @@
-/*
- * Builtin "git grep"
- *
- * Copyright (c) 2006 Junio C Hamano
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "repository.h"
-#include "config.h"
-#include "blob.h"
-#include "tree.h"
-#include "commit.h"
-#include "tag.h"
-#include "tree-walk.h"
-#include "builtin.h"
-#include "parse-options.h"
-#include "string-list.h"
-#include "run-command.h"
-#include "userdiff.h"
-#include "grep.h"
-#include "quote.h"
-#include "dir.h"
-#include "pathspec.h"
-#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>...]"),
-	NULL
-};
-
-static int recurse_submodules;
-
-static int num_threads;
-
-static pthread_t *threads;
-
-/* We use one producer thread and THREADS consumer
- * threads. The producer adds struct work_items to 'todo' and the
- * consumers pick work items from the same array.
- */
-struct work_item {
-	struct grep_source source;
-	char done;
-	struct strbuf out;
-};
-
-/* In the range [todo_done, todo_start) in 'todo' we have work_items
- * that have been or are processed by a consumer thread. We haven't
- * written the result for these to stdout yet.
- *
- * The work_items in [todo_start, todo_end) are waiting to be picked
- * up by a consumer thread.
- *
- * The ranges are modulo TODO_SIZE.
- */
-#define TODO_SIZE 128
-static struct work_item todo[TODO_SIZE];
-static int todo_start;
-static int todo_end;
-static int todo_done;
-
-/* Has all work items been added? */
-static int all_work_added;
-
-/* This lock protects all the variables above. */
-static pthread_mutex_t grep_mutex;
-
-static inline void grep_lock(void)
-{
-	pthread_mutex_lock(&grep_mutex);
-}
-
-static inline void grep_unlock(void)
-{
-	pthread_mutex_unlock(&grep_mutex);
-}
-
-/* Signalled when a new work_item is added to todo. */
-static pthread_cond_t cond_add;
-
-/* Signalled when the result from one work_item is written to
- * stdout.
- */
-static pthread_cond_t cond_write;
-
-/* Signalled when we are finished with everything. */
-static pthread_cond_t cond_result;
-
-static int skip_first_line;
-
-static void add_work(struct grep_opt *opt, 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) {
-		pthread_cond_wait(&cond_write, &grep_mutex);
-	}
-
-	todo[todo_end].source = *gs;
-	todo[todo_end].done = 0;
-	strbuf_reset(&todo[todo_end].out);
-	todo_end = (todo_end + 1) % ARRAY_SIZE(todo);
-
-	pthread_cond_signal(&cond_add);
-	grep_unlock();
-}
-
-static struct work_item *get_work(void)
-{
-	struct work_item *ret;
-
-	grep_lock();
-	while (todo_start == todo_end && !all_work_added) {
-		pthread_cond_wait(&cond_add, &grep_mutex);
-	}
-
-	if (todo_start == todo_end && all_work_added) {
-		ret = NULL;
-	} else {
-		ret = &todo[todo_start];
-		todo_start = (todo_start + 1) % ARRAY_SIZE(todo);
-	}
-	grep_unlock();
-	return ret;
-}
-
-static void work_done(struct work_item *w)
-{
-	int old_done;
-
-	grep_lock();
-	w->done = 1;
-	old_done = todo_done;
-	for(; todo[todo_done].done && todo_done != todo_start;
-	    todo_done = (todo_done+1) % ARRAY_SIZE(todo)) {
-		w = &todo[todo_done];
-		if (w->out.len) {
-			const char *p = w->out.buf;
-			size_t len = w->out.len;
-
-			/* Skip the leading hunk mark of the first file. */
-			if (skip_first_line) {
-				while (len) {
-					len--;
-					if (*p++ == '\n')
-						break;
-				}
-				skip_first_line = 0;
-			}
-
-			write_or_die(1, p, len);
-		}
-		grep_source_clear(&w->source);
-	}
-
-	if (old_done != todo_done)
-		pthread_cond_signal(&cond_write);
-
-	if (all_work_added && todo_done == todo_end)
-		pthread_cond_signal(&cond_result);
-
-	grep_unlock();
-}
-
-static void *run(void *arg)
-{
-	int hit = 0;
-	struct grep_opt *opt = arg;
-
-	while (1) {
-		struct work_item *w = get_work();
-		if (!w)
-			break;
-
-		opt->output_priv = w;
-		hit |= grep_source(opt, &w->source);
-		grep_source_clear_data(&w->source);
-		work_done(w);
-	}
-	free_grep_patterns(arg);
-	free(arg);
-
-	return (void*) (intptr_t) hit;
-}
-
-static void strbuf_out(struct grep_opt *opt, const void *buf, size_t size)
-{
-	struct work_item *w = opt->output_priv;
-	strbuf_add(&w->out, buf, size);
-}
-
-static void start_threads(struct grep_opt *opt)
-{
-	int i;
-
-	pthread_mutex_init(&grep_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);
-	}
-
-	threads = xcalloc(num_threads, sizeof(*threads));
-	for (i = 0; i < num_threads; i++) {
-		int err;
-		struct grep_opt *o = grep_opt_dup(opt);
-		o->output = strbuf_out;
-		if (i)
-			o->debug = 0;
-		compile_grep_patterns(o);
-		err = pthread_create(&threads[i], NULL, run, o);
-
-		if (err)
-			die(_("grep: failed to create thread: %s"),
-			    strerror(err));
-	}
-}
-
-static int wait_all(void)
-{
-	int hit = 0;
-	int i;
-
-	if (!HAVE_THREADS)
-		BUG("Never call this function unless you have started threads");
-
-	grep_lock();
-	all_work_added = 1;
-
-	/* Wait until all work is done. */
-	while (todo_done != todo_end)
-		pthread_cond_wait(&cond_result, &grep_mutex);
-
-	/* Wake up all the consumer threads so they can see that there
-	 * is no more work to do.
-	 */
-	pthread_cond_broadcast(&cond_add);
-	grep_unlock();
-
-	for (i = 0; i < num_threads; i++) {
-		void *h;
-		pthread_join(threads[i], &h);
-		hit |= (int) (intptr_t) h;
-	}
-
-	free(threads);
-
-	pthread_mutex_destroy(&grep_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;
-}
-
-static int grep_cmd_config(const char *var, const char *value, void *cb)
-{
-	int st = grep_config(var, value, cb);
-	if (git_color_default_config(var, value, cb) < 0)
-		st = -1;
-
-	if (!strcmp(var, "grep.threads")) {
-		num_threads = git_config_int(var, value);
-		if (num_threads < 0)
-			die(_("invalid number of threads specified (%d) for %s"),
-			    num_threads, var);
-		else if (!HAVE_THREADS && num_threads > 1) {
-			/*
-			 * TRANSLATORS: %s is the configuration
-			 * variable for tweaking threads, currently
-			 * grep.threads
-			 */
-			warning(_("no threads support, ignoring %s"), var);
-			num_threads = 1;
-		}
-	}
-
-	if (!strcmp(var, "submodule.recurse"))
-		recurse_submodules = git_config_bool(var, value);
-
-	return st;
-}
-
-static void grep_source_name(struct grep_opt *opt, const char *filename,
-			     int tree_name_len, struct strbuf *out)
-{
-	strbuf_reset(out);
-
-	if (opt->null_following_name) {
-		if (opt->relative && opt->prefix_length) {
-			struct strbuf rel_buf = STRBUF_INIT;
-			const char *rel_name =
-				relative_path(filename + tree_name_len,
-					      opt->prefix, &rel_buf);
-
-			if (tree_name_len)
-				strbuf_add(out, filename, tree_name_len);
-
-			strbuf_addstr(out, rel_name);
-			strbuf_release(&rel_buf);
-		} else {
-			strbuf_addstr(out, filename);
-		}
-		return;
-	}
-
-	if (opt->relative && opt->prefix_length)
-		quote_path(filename + tree_name_len, opt->prefix, out, 0);
-	else
-		quote_c_style(filename + tree_name_len, out, NULL, 0);
-
-	if (tree_name_len)
-		strbuf_insert(out, 0, filename, tree_name_len);
-}
-
-static int grep_oid(struct grep_opt *opt, const struct object_id *oid,
-		     const char *filename, int tree_name_len,
-		     const char *path)
-{
-	struct strbuf pathbuf = STRBUF_INIT;
-	struct grep_source gs;
-
-	grep_source_name(opt, filename, tree_name_len, &pathbuf);
-	grep_source_init(&gs, GREP_SOURCE_OID, pathbuf.buf, path, oid);
-	strbuf_release(&pathbuf);
-
-	if (num_threads > 1) {
-		/*
-		 * add_work() copies gs and thus assumes ownership of
-		 * its fields, so do not call grep_source_clear()
-		 */
-		add_work(opt, &gs);
-		return 0;
-	} else {
-		int hit;
-
-		hit = grep_source(opt, &gs);
-
-		grep_source_clear(&gs);
-		return hit;
-	}
-}
-
-static int grep_file(struct grep_opt *opt, const char *filename)
-{
-	struct strbuf buf = STRBUF_INIT;
-	struct grep_source gs;
-
-	grep_source_name(opt, filename, 0, &buf);
-	grep_source_init(&gs, GREP_SOURCE_FILE, buf.buf, filename, filename);
-	strbuf_release(&buf);
-
-	if (num_threads > 1) {
-		/*
-		 * add_work() copies gs and thus assumes ownership of
-		 * its fields, so do not call grep_source_clear()
-		 */
-		add_work(opt, &gs);
-		return 0;
-	} else {
-		int hit;
-
-		hit = grep_source(opt, &gs);
-
-		grep_source_clear(&gs);
-		return hit;
-	}
-}
-
-static void append_path(struct grep_opt *opt, const void *data, size_t len)
-{
-	struct string_list *path_list = opt->output_priv;
-
-	if (len == 1 && *(const char *)data == '\0')
-		return;
-	string_list_append(path_list, xstrndup(data, len));
-}
-
-static void run_pager(struct grep_opt *opt, const char *prefix)
-{
-	struct string_list *path_list = opt->output_priv;
-	struct child_process child = CHILD_PROCESS_INIT;
-	int i, status;
-
-	for (i = 0; i < path_list->nr; i++)
-		strvec_push(&child.args, path_list->items[i].string);
-	child.dir = prefix;
-	child.use_shell = 1;
-
-	status = run_command(&child);
-	if (status)
-		exit(status);
-}
-
-static int grep_cache(struct grep_opt *opt,
-		      const struct pathspec *pathspec, int cached);
-static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
-		     struct tree_desc *tree, struct strbuf *base, int tn_len,
-		     int check_attr);
-
-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)
-{
-	struct repository subrepo;
-	struct repository *superproject = opt->repo;
-	const struct submodule *sub;
-	struct grep_opt subopt;
-	int hit;
-
-	sub = submodule_from_path(superproject, &null_oid, path);
-
-	if (!is_submodule_active(superproject, path))
-		return 0;
-
-	if (repo_submodule_init(&subrepo, superproject, sub))
-		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);
-
-	/*
-	 * NEEDSWORK: This adds the submodule's object directory to the list of
-	 * alternates for the single in-memory object store.  This has some bad
-	 * consequences for memory (processed objects will never be freed) and
-	 * performance (this increases the number of pack files git has to pay
-	 * attention to, to the sum of the number of pack files in all the
-	 * repositories processed so far).  This can be removed once the object
-	 * store is no longer global and instead is a member of the repository
-	 * object.
-	 */
-	add_to_alternates_memory(subrepo.objects->odb->path);
-	obj_read_unlock();
-
-	memcpy(&subopt, opt, sizeof(subopt));
-	subopt.repo = &subrepo;
-
-	if (oid) {
-		struct object *object;
-		struct tree_desc tree;
-		void *data;
-		unsigned long size;
-		struct strbuf base = STRBUF_INIT;
-
-		obj_read_lock();
-		object = parse_object_or_die(oid, NULL);
-		obj_read_unlock();
-		data = read_object_with_reference(&subrepo,
-						  &object->oid, tree_type,
-						  &size, NULL);
-		if (!data)
-			die(_("unable to read tree (%s)"), oid_to_hex(&object->oid));
-
-		strbuf_addstr(&base, filename);
-		strbuf_addch(&base, '/');
-
-		init_tree_desc(&tree, data, size);
-		hit = grep_tree(&subopt, pathspec, &tree, &base, base.len,
-				object->type == OBJ_COMMIT);
-		strbuf_release(&base);
-		free(data);
-	} else {
-		hit = grep_cache(&subopt, pathspec, cached);
-	}
-
-	repo_clear(&subrepo);
-	return hit;
-}
-
-static int grep_cache(struct grep_opt *opt,
-		      const struct pathspec *pathspec, int cached)
-{
-	struct repository *repo = opt->repo;
-	int hit = 0;
-	int nr;
-	struct strbuf name = STRBUF_INIT;
-	int name_base_len = 0;
-	if (repo->submodule_prefix) {
-		name_base_len = strlen(repo->submodule_prefix);
-		strbuf_addstr(&name, repo->submodule_prefix);
-	}
-
-	if (repo_read_index(repo) < 0)
-		die(_("index file corrupt"));
-
-	for (nr = 0; nr < repo->index->cache_nr; nr++) {
-		const struct cache_entry *ce = repo->index->cache[nr];
-		strbuf_setlen(&name, name_base_len);
-		strbuf_addstr(&name, ce->name);
-
-		if (S_ISREG(ce->ce_mode) &&
-		    match_pathspec(repo->index, pathspec, name.buf, name.len, 0, NULL,
-				   S_ISDIR(ce->ce_mode) ||
-				   S_ISGITLINK(ce->ce_mode))) {
-			/*
-			 * If CE_VALID is on, we assume worktree file and its
-			 * cache entry are identical, even if worktree file has
-			 * been modified, so use cache version instead
-			 */
-			if (cached || (ce->ce_flags & CE_VALID) ||
-			    ce_skip_worktree(ce)) {
-				if (ce_stage(ce) || ce_intent_to_add(ce))
-					continue;
-				hit |= grep_oid(opt, &ce->oid, name.buf,
-						 0, name.buf);
-			} else {
-				hit |= grep_file(opt, name.buf);
-			}
-		} 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);
-		} else {
-			continue;
-		}
-
-		if (ce_stage(ce)) {
-			do {
-				nr++;
-			} while (nr < repo->index->cache_nr &&
-				 !strcmp(ce->name, repo->index->cache[nr]->name));
-			nr--; /* compensate for loop control */
-		}
-		if (hit && opt->status_only)
-			break;
-	}
-
-	strbuf_release(&name);
-	return hit;
-}
-
-static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
-		     struct tree_desc *tree, struct strbuf *base, int tn_len,
-		     int check_attr)
-{
-	struct repository *repo = opt->repo;
-	int hit = 0;
-	enum interesting match = entry_not_interesting;
-	struct name_entry entry;
-	int old_baselen = base->len;
-	struct strbuf name = STRBUF_INIT;
-	int name_base_len = 0;
-	if (repo->submodule_prefix) {
-		strbuf_addstr(&name, repo->submodule_prefix);
-		name_base_len = name.len;
-	}
-
-	while (tree_entry(tree, &entry)) {
-		int te_len = tree_entry_len(&entry);
-
-		if (match != all_entries_interesting) {
-			strbuf_addstr(&name, base->buf + tn_len);
-			match = tree_entry_interesting(repo->index,
-						       &entry, &name,
-						       0, pathspec);
-			strbuf_setlen(&name, name_base_len);
-
-			if (match == all_entries_not_interesting)
-				break;
-			if (match == entry_not_interesting)
-				continue;
-		}
-
-		strbuf_add(base, entry.path, te_len);
-
-		if (S_ISREG(entry.mode)) {
-			hit |= grep_oid(opt, &entry.oid, base->buf, tn_len,
-					 check_attr ? base->buf + tn_len : NULL);
-		} else if (S_ISDIR(entry.mode)) {
-			enum object_type type;
-			struct tree_desc sub;
-			void *data;
-			unsigned long size;
-
-			data = read_object_file(&entry.oid, &type, &size);
-			if (!data)
-				die(_("unable to read tree (%s)"),
-				    oid_to_hex(&entry.oid));
-
-			strbuf_addch(base, '/');
-			init_tree_desc(&sub, data, size);
-			hit |= grep_tree(opt, pathspec, &sub, base, tn_len,
-					 check_attr);
-			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 */
-		}
-
-		strbuf_setlen(base, old_baselen);
-
-		if (hit && opt->status_only)
-			break;
-	}
-
-	strbuf_release(&name);
-	return hit;
-}
-
-static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
-		       struct object *obj, const char *name, const char *path)
-{
-	if (obj->type == OBJ_BLOB)
-		return grep_oid(opt, &obj->oid, name, 0, path);
-	if (obj->type == OBJ_COMMIT || obj->type == OBJ_TREE) {
-		struct tree_desc tree;
-		void *data;
-		unsigned long size;
-		struct strbuf base;
-		int hit, len;
-
-		data = read_object_with_reference(opt->repo,
-						  &obj->oid, tree_type,
-						  &size, NULL);
-		if (!data)
-			die(_("unable to read tree (%s)"), oid_to_hex(&obj->oid));
-
-		len = name ? strlen(name) : 0;
-		strbuf_init(&base, PATH_MAX + len + 1);
-		if (len) {
-			strbuf_add(&base, name, len);
-			strbuf_addch(&base, ':');
-		}
-		init_tree_desc(&tree, data, size);
-		hit = grep_tree(opt, pathspec, &tree, &base, base.len,
-				obj->type == OBJ_COMMIT);
-		strbuf_release(&base);
-		free(data);
-		return hit;
-	}
-	die(_("unable to grep from object of type %s"), type_name(obj->type));
-}
-
-static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
-			const struct object_array *list)
-{
-	unsigned int i;
-	int hit = 0;
-	const unsigned int nr = list->nr;
-
-	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)) {
-			hit = 1;
-			if (opt->status_only)
-				break;
-		}
-	}
-	return hit;
-}
-
-static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec,
-			  int exc_std, int use_index)
-{
-	struct dir_struct dir;
-	int i, hit = 0;
-
-	dir_init(&dir);
-	if (!use_index)
-		dir.flags |= DIR_NO_GITLINKS;
-	if (exc_std)
-		setup_standard_excludes(&dir);
-
-	fill_directory(&dir, opt->repo->index, pathspec);
-	for (i = 0; i < dir.nr; i++) {
-		hit |= grep_file(opt, dir.entries[i]->name);
-		if (hit && opt->status_only)
-			break;
-	}
-	dir_clear(&dir);
-	return hit;
-}
-
-static int context_callback(const struct option *opt, const char *arg,
-			    int unset)
-{
-	struct grep_opt *grep_opt = opt->value;
-	int value;
-	const char *endp;
-
-	if (unset) {
-		grep_opt->pre_context = grep_opt->post_context = 0;
-		return 0;
-	}
-	value = strtol(arg, (char **)&endp, 10);
-	if (*endp) {
-		return error(_("switch `%c' expects a numerical value"),
-			     opt->short_name);
-	}
-	grep_opt->pre_context = grep_opt->post_context = value;
-	return 0;
-}
-
-static int file_callback(const struct option *opt, const char *arg, int unset)
-{
-	struct grep_opt *grep_opt = opt->value;
-	int from_stdin;
-	FILE *patterns;
-	int lno = 0;
-	struct strbuf sb = STRBUF_INIT;
-
-	BUG_ON_OPT_NEG(unset);
-
-	from_stdin = !strcmp(arg, "-");
-	patterns = from_stdin ? stdin : fopen(arg, "r");
-	if (!patterns)
-		die_errno(_("cannot open '%s'"), arg);
-	while (strbuf_getline(&sb, patterns) == 0) {
-		/* ignore empty line like grep does */
-		if (sb.len == 0)
-			continue;
-
-		append_grep_pat(grep_opt, sb.buf, sb.len, arg, ++lno,
-				GREP_PATTERN);
-	}
-	if (!from_stdin)
-		fclose(patterns);
-	strbuf_release(&sb);
-	return 0;
-}
-
-static int not_callback(const struct option *opt, const char *arg, int unset)
-{
-	struct grep_opt *grep_opt = opt->value;
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-	append_grep_pattern(grep_opt, "--not", "command line", 0, GREP_NOT);
-	return 0;
-}
-
-static int and_callback(const struct option *opt, const char *arg, int unset)
-{
-	struct grep_opt *grep_opt = opt->value;
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-	append_grep_pattern(grep_opt, "--and", "command line", 0, GREP_AND);
-	return 0;
-}
-
-static int open_callback(const struct option *opt, const char *arg, int unset)
-{
-	struct grep_opt *grep_opt = opt->value;
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-	append_grep_pattern(grep_opt, "(", "command line", 0, GREP_OPEN_PAREN);
-	return 0;
-}
-
-static int close_callback(const struct option *opt, const char *arg, int unset)
-{
-	struct grep_opt *grep_opt = opt->value;
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-	append_grep_pattern(grep_opt, ")", "command line", 0, GREP_CLOSE_PAREN);
-	return 0;
-}
-
-static int pattern_callback(const struct option *opt, const char *arg,
-			    int unset)
-{
-	struct grep_opt *grep_opt = opt->value;
-	BUG_ON_OPT_NEG(unset);
-	append_grep_pattern(grep_opt, arg, "-e option", 0, GREP_PATTERN);
-	return 0;
-}
-
-int cmd_grep(int argc, const char **argv, const char *prefix)
-{
-	int hit = 0;
-	int cached = 0, untracked = 0, opt_exclude = -1;
-	int seen_dashdash = 0;
-	int external_grep_allowed__ignored;
-	const char *show_in_pager = NULL, *default_pager = "dummy";
-	struct grep_opt opt;
-	struct object_array list = OBJECT_ARRAY_INIT;
-	struct pathspec pathspec;
-	struct string_list path_list = STRING_LIST_INIT_NODUP;
-	int i;
-	int dummy;
-	int use_index = 1;
-	int pattern_type_arg = GREP_PATTERN_TYPE_UNSPECIFIED;
-	int allow_revs;
-
-	struct option options[] = {
-		OPT_BOOL(0, "cached", &cached,
-			N_("search in index instead of in the work tree")),
-		OPT_NEGBIT(0, "no-index", &use_index,
-			 N_("find in contents not managed by git"), 1),
-		OPT_BOOL(0, "untracked", &untracked,
-			N_("search in both tracked and untracked files")),
-		OPT_SET_INT(0, "exclude-standard", &opt_exclude,
-			    N_("ignore files specified via '.gitignore'"), 1),
-		OPT_BOOL(0, "recurse-submodules", &recurse_submodules,
-			 N_("recursively search in each submodule")),
-		OPT_GROUP(""),
-		OPT_BOOL('v', "invert-match", &opt.invert,
-			N_("show non-matching lines")),
-		OPT_BOOL('i', "ignore-case", &opt.ignore_case,
-			N_("case insensitive matching")),
-		OPT_BOOL('w', "word-regexp", &opt.word_regexp,
-			N_("match patterns only at word boundaries")),
-		OPT_SET_INT('a', "text", &opt.binary,
-			N_("process binary files as text"), GREP_BINARY_TEXT),
-		OPT_SET_INT('I', NULL, &opt.binary,
-			N_("don't match patterns in binary files"),
-			GREP_BINARY_NOMATCH),
-		OPT_BOOL(0, "textconv", &opt.allow_textconv,
-			 N_("process binary files with textconv filters")),
-		OPT_SET_INT('r', "recursive", &opt.max_depth,
-			    N_("search in subdirectories (default)"), -1),
-		{ OPTION_INTEGER, 0, "max-depth", &opt.max_depth, N_("depth"),
-			N_("descend at most <depth> levels"), PARSE_OPT_NONEG,
-			NULL, 1 },
-		OPT_GROUP(""),
-		OPT_SET_INT('E', "extended-regexp", &pattern_type_arg,
-			    N_("use extended POSIX regular expressions"),
-			    GREP_PATTERN_TYPE_ERE),
-		OPT_SET_INT('G', "basic-regexp", &pattern_type_arg,
-			    N_("use basic POSIX regular expressions (default)"),
-			    GREP_PATTERN_TYPE_BRE),
-		OPT_SET_INT('F', "fixed-strings", &pattern_type_arg,
-			    N_("interpret patterns as fixed strings"),
-			    GREP_PATTERN_TYPE_FIXED),
-		OPT_SET_INT('P', "perl-regexp", &pattern_type_arg,
-			    N_("use Perl-compatible regular expressions"),
-			    GREP_PATTERN_TYPE_PCRE),
-		OPT_GROUP(""),
-		OPT_BOOL('n', "line-number", &opt.linenum, N_("show line numbers")),
-		OPT_BOOL(0, "column", &opt.columnnum, N_("show column number of first match")),
-		OPT_NEGBIT('h', NULL, &opt.pathname, N_("don't show filenames"), 1),
-		OPT_BIT('H', NULL, &opt.pathname, N_("show filenames"), 1),
-		OPT_NEGBIT(0, "full-name", &opt.relative,
-			N_("show filenames relative to top directory"), 1),
-		OPT_BOOL('l', "files-with-matches", &opt.name_only,
-			N_("show only filenames instead of matching lines")),
-		OPT_BOOL(0, "name-only", &opt.name_only,
-			N_("synonym for --files-with-matches")),
-		OPT_BOOL('L', "files-without-match",
-			&opt.unmatch_name_only,
-			N_("show only the names of files without match")),
-		OPT_BOOL_F('z', "null", &opt.null_following_name,
-			   N_("print NUL after filenames"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT_BOOL('o', "only-matching", &opt.only_matching,
-			N_("show only matching parts of a line")),
-		OPT_BOOL('c', "count", &opt.count,
-			N_("show the number of matches instead of matching lines")),
-		OPT__COLOR(&opt.color, N_("highlight matches")),
-		OPT_BOOL(0, "break", &opt.file_break,
-			N_("print empty line between matches from different files")),
-		OPT_BOOL(0, "heading", &opt.heading,
-			N_("show filename only once above matches from same file")),
-		OPT_GROUP(""),
-		OPT_CALLBACK('C', "context", &opt, N_("n"),
-			N_("show <n> context lines before and after matches"),
-			context_callback),
-		OPT_INTEGER('B', "before-context", &opt.pre_context,
-			N_("show <n> context lines before matches")),
-		OPT_INTEGER('A', "after-context", &opt.post_context,
-			N_("show <n> context lines after matches")),
-		OPT_INTEGER(0, "threads", &num_threads,
-			N_("use <n> worker threads")),
-		OPT_NUMBER_CALLBACK(&opt, N_("shortcut for -C NUM"),
-			context_callback),
-		OPT_BOOL('p', "show-function", &opt.funcname,
-			N_("show a line with the function name before matches")),
-		OPT_BOOL('W', "function-context", &opt.funcbody,
-			N_("show the surrounding function")),
-		OPT_GROUP(""),
-		OPT_CALLBACK('f', NULL, &opt, N_("file"),
-			N_("read patterns from file"), file_callback),
-		OPT_CALLBACK_F('e', NULL, &opt, N_("pattern"),
-			N_("match <pattern>"), PARSE_OPT_NONEG, pattern_callback),
-		OPT_CALLBACK_F(0, "and", &opt, NULL,
-			N_("combine patterns specified with -e"),
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback),
-		OPT_BOOL(0, "or", &dummy, ""),
-		OPT_CALLBACK_F(0, "not", &opt, NULL, "",
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG, not_callback),
-		OPT_CALLBACK_F('(', NULL, &opt, NULL, "",
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
-			open_callback),
-		OPT_CALLBACK_F(')', NULL, &opt, NULL, "",
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
-			close_callback),
-		OPT__QUIET(&opt.status_only,
-			   N_("indicate hit with exit status without output")),
-		OPT_BOOL(0, "all-match", &opt.all_match,
-			N_("show only matches from files that match all patterns")),
-		OPT_SET_INT_F(0, "debug", &opt.debug,
-			      N_("show parse tree for grep expression"),
-			      1, PARSE_OPT_HIDDEN),
-		OPT_GROUP(""),
-		{ OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager,
-			N_("pager"), N_("show matching files in the pager"),
-			PARSE_OPT_OPTARG | PARSE_OPT_NOCOMPLETE,
-			NULL, (intptr_t)default_pager },
-		OPT_BOOL_F(0, "ext-grep", &external_grep_allowed__ignored,
-			   N_("allow calling of grep(1) (ignored by this build)"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT_END()
-	};
-
-	init_grep_defaults(the_repository);
-	git_config(grep_cmd_config, NULL);
-	grep_init(&opt, the_repository, prefix);
-
-	/*
-	 * If there is no -- then the paths must exist in the working
-	 * tree.  If there is no explicit pattern specified with -e or
-	 * -f, we take the first unrecognized non option to be the
-	 * pattern, but then what follows it must be zero or more
-	 * valid refs up to the -- (if exists), and then existing
-	 * paths.  If there is an explicit pattern, then the first
-	 * unrecognized non option is the beginning of the refs list
-	 * that continues up to the -- (if exists), and then paths.
-	 */
-	argc = parse_options(argc, argv, prefix, options, grep_usage,
-			     PARSE_OPT_KEEP_DASHDASH |
-			     PARSE_OPT_STOP_AT_NON_OPTION);
-	grep_commit_pattern_type(pattern_type_arg, &opt);
-
-	if (use_index && !startup_info->have_repository) {
-		int fallback = 0;
-		git_config_get_bool("grep.fallbacktonoindex", &fallback);
-		if (fallback)
-			use_index = 0;
-		else
-			/* 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
-	 * separating revisions from pathnames if
-	 * we haven't even had any patterns yet
-	 */
-	if (argc > 0 && !opt.pattern_list && !strcmp(argv[0], "--")) {
-		argv++;
-		argc--;
-	}
-
-	/* First unrecognized non-option token */
-	if (argc > 0 && !opt.pattern_list) {
-		append_grep_pattern(&opt, argv[0], "command line", 0,
-				    GREP_PATTERN);
-		argv++;
-		argc--;
-	}
-
-	if (show_in_pager == default_pager)
-		show_in_pager = git_pager(1);
-	if (show_in_pager) {
-		opt.color = 0;
-		opt.name_only = 1;
-		opt.null_following_name = 1;
-		opt.output_priv = &path_list;
-		opt.output = append_path;
-		string_list_append(&path_list, show_in_pager);
-	}
-
-	if (!opt.pattern_list)
-		die(_("no pattern given"));
-
-	/* --only-matching has no effect with --invert. */
-	if (opt.invert)
-		opt.only_matching = 0;
-
-	/*
-	 * We have to find "--" in a separate pass, because its presence
-	 * influences how we will parse arguments that come before it.
-	 */
-	for (i = 0; i < argc; i++) {
-		if (!strcmp(argv[i], "--")) {
-			seen_dashdash = 1;
-			break;
-		}
-	}
-
-	/*
-	 * Resolve any rev arguments. If we have a dashdash, then everything up
-	 * to it must resolve as a rev. If not, then we stop at the first
-	 * non-rev and assume everything else is a path.
-	 */
-	allow_revs = use_index && !untracked;
-	for (i = 0; i < argc; i++) {
-		const char *arg = argv[i];
-		struct object_id oid;
-		struct object_context oc;
-		struct object *object;
-
-		if (!strcmp(arg, "--")) {
-			i++;
-			break;
-		}
-
-		if (!allow_revs) {
-			if (seen_dashdash)
-				die(_("--no-index or --untracked cannot be used with revs"));
-			break;
-		}
-
-		if (get_oid_with_context(the_repository, arg,
-					 GET_OID_RECORD_PATH,
-					 &oid, &oc)) {
-			if (seen_dashdash)
-				die(_("unable to resolve revision: %s"), arg);
-			break;
-		}
-
-		object = parse_object_or_die(&oid, arg);
-		if (!seen_dashdash)
-			verify_non_filename(prefix, arg);
-		add_object_array_with_path(object, arg, &list, oc.mode, oc.path);
-		free(oc.path);
-	}
-
-	/*
-	 * Anything left over is presumed to be a path. But in the non-dashdash
-	 * "do what I mean" case, we verify and complain when that isn't true.
-	 */
-	if (!seen_dashdash) {
-		int j;
-		for (j = i; j < argc; j++)
-			verify_filename(prefix, argv[j], j == i && allow_revs);
-	}
-
-	parse_pathspec(&pathspec, 0,
-		       PATHSPEC_PREFER_CWD |
-		       (opt.max_depth != -1 ? PATHSPEC_MAXDEPTH_VALID : 0),
-		       prefix, argv + i);
-	pathspec.max_depth = opt.max_depth;
-	pathspec.recursive = 1;
-	pathspec.recurse_submodules = !!recurse_submodules;
-
-	if (recurse_submodules && untracked)
-		die(_("--untracked not supported with --recurse-submodules"));
-
-	if (show_in_pager) {
-		if (num_threads > 1)
-			warning(_("invalid option combination, ignoring --threads"));
-		num_threads = 1;
-	} else if (!HAVE_THREADS && num_threads > 1) {
-		warning(_("no threads support, ignoring --threads"));
-		num_threads = 1;
-	} 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;
-
-	if (num_threads > 1) {
-		if (!HAVE_THREADS)
-			BUG("Somebody got num_threads calculation wrong!");
-		if (!(opt.name_only || opt.unmatch_name_only || opt.count)
-		    && (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 {
-		/*
-		 * The compiled patterns on the main path are only
-		 * used when not using threading. Otherwise
-		 * start_threads() above calls compile_grep_patterns()
-		 * for each thread.
-		 */
-		compile_grep_patterns(&opt);
-	}
-
-	if (show_in_pager && (cached || list.nr))
-		die(_("--open-files-in-pager only works on the worktree"));
-
-	if (show_in_pager && opt.pattern_list && !opt.pattern_list->next) {
-		const char *pager = path_list.items[0].string;
-		int len = strlen(pager);
-
-		if (len > 4 && is_dir_sep(pager[len - 5]))
-			pager += len - 4;
-
-		if (opt.ignore_case && !strcmp("less", pager))
-			string_list_append(&path_list, "-I");
-
-		if (!strcmp("less", pager) || !strcmp("vi", pager)) {
-			struct strbuf buf = STRBUF_INIT;
-			strbuf_addf(&buf, "+/%s%s",
-					strcmp("less", pager) ? "" : "*",
-					opt.pattern_list->pattern);
-			string_list_append(&path_list,
-					   strbuf_detach(&buf, NULL));
-		}
-	}
-
-	if (!show_in_pager && !opt.status_only)
-		setup_pager();
-
-	if (!use_index && (untracked || cached))
-		die(_("--cached or --untracked cannot be used with --no-index"));
-
-	if (!use_index || untracked) {
-		int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;
-		hit = grep_directory(&opt, &pathspec, use_exclude, use_index);
-	} else if (0 <= opt_exclude) {
-		die(_("--[no-]exclude-standard cannot be used for tracked contents"));
-	} else if (!list.nr) {
-		if (!cached)
-			setup_work_tree();
-
-		hit = grep_cache(&opt, &pathspec, cached);
-	} else {
-		if (cached)
-			die(_("both --cached and trees are given"));
-
-		hit = grep_objects(&opt, &pathspec, &list);
-	}
-
-	if (num_threads > 1)
-		hit |= wait_all();
-	if (hit && show_in_pager)
-		run_pager(&opt, prefix);
-	clear_pathspec(&pathspec);
-	free_grep_patterns(&opt);
-	grep_destroy();
-	return !hit;
-}
diff --git a/third_party/git/builtin/hash-object.c b/third_party/git/builtin/hash-object.c
deleted file mode 100644
index 640ef4ded595..000000000000
--- a/third_party/git/builtin/hash-object.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * GIT - The information manager from hell
- *
- * Copyright (C) Linus Torvalds, 2005
- * Copyright (C) Junio C Hamano, 2005
- */
-#include "builtin.h"
-#include "config.h"
-#include "object-store.h"
-#include "blob.h"
-#include "quote.h"
-#include "parse-options.h"
-#include "exec-cmd.h"
-
-/*
- * This is to create corrupt objects for debugging and as such it
- * needs to bypass the data conversion performed by, and the type
- * limitation imposed by, index_fd() and its callees.
- */
-static int hash_literally(struct object_id *oid, int fd, const char *type, unsigned flags)
-{
-	struct strbuf buf = STRBUF_INIT;
-	int ret;
-
-	if (strbuf_read(&buf, fd, 4096) < 0)
-		ret = -1;
-	else
-		ret = hash_object_file_literally(buf.buf, buf.len, type, oid,
-						 flags);
-	strbuf_release(&buf);
-	return ret;
-}
-
-static void hash_fd(int fd, const char *type, const char *path, unsigned flags,
-		    int literally)
-{
-	struct stat st;
-	struct object_id oid;
-
-	if (fstat(fd, &st) < 0 ||
-	    (literally
-	     ? hash_literally(&oid, fd, type, flags)
-	     : index_fd(the_repository->index, &oid, fd, &st,
-			type_from_string(type), path, flags)))
-		die((flags & HASH_WRITE_OBJECT)
-		    ? "Unable to add %s to database"
-		    : "Unable to hash %s", path);
-	printf("%s\n", oid_to_hex(&oid));
-	maybe_flush_or_die(stdout, "hash to stdout");
-}
-
-static void hash_object(const char *path, const char *type, const char *vpath,
-			unsigned flags, int literally)
-{
-	int fd;
-	fd = open(path, O_RDONLY);
-	if (fd < 0)
-		die_errno("Cannot open '%s'", path);
-	hash_fd(fd, type, vpath, flags, literally);
-}
-
-static void hash_stdin_paths(const char *type, int no_filters, unsigned flags,
-			     int literally)
-{
-	struct strbuf buf = STRBUF_INIT;
-	struct strbuf unquoted = STRBUF_INIT;
-
-	while (strbuf_getline(&buf, stdin) != EOF) {
-		if (buf.buf[0] == '"') {
-			strbuf_reset(&unquoted);
-			if (unquote_c_style(&unquoted, buf.buf, NULL))
-				die("line is badly quoted");
-			strbuf_swap(&buf, &unquoted);
-		}
-		hash_object(buf.buf, type, no_filters ? NULL : buf.buf, flags,
-			    literally);
-	}
-	strbuf_release(&buf);
-	strbuf_release(&unquoted);
-}
-
-int cmd_hash_object(int argc, const char **argv, const char *prefix)
-{
-	static const char * const hash_object_usage[] = {
-		N_("git hash-object [-t <type>] [-w] [--path=<file> | --no-filters] [--stdin] [--] <file>..."),
-		N_("git hash-object  --stdin-paths"),
-		NULL
-	};
-	const char *type = blob_type;
-	int hashstdin = 0;
-	int stdin_paths = 0;
-	int no_filters = 0;
-	int literally = 0;
-	int nongit = 0;
-	unsigned flags = HASH_FORMAT_CHECK;
-	const char *vpath = NULL;
-	const struct option hash_object_options[] = {
-		OPT_STRING('t', NULL, &type, N_("type"), N_("object type")),
-		OPT_BIT('w', NULL, &flags, N_("write the object into the object database"),
-			HASH_WRITE_OBJECT),
-		OPT_COUNTUP( 0 , "stdin", &hashstdin, N_("read the object from stdin")),
-		OPT_BOOL( 0 , "stdin-paths", &stdin_paths, N_("read file names from stdin")),
-		OPT_BOOL( 0 , "no-filters", &no_filters, N_("store file as is without filters")),
-		OPT_BOOL( 0, "literally", &literally, N_("just hash any random garbage to create corrupt objects for debugging Git")),
-		OPT_STRING( 0 , "path", &vpath, N_("file"), N_("process file as it were from this path")),
-		OPT_END()
-	};
-	int i;
-	const char *errstr = NULL;
-
-	argc = parse_options(argc, argv, prefix, hash_object_options,
-			     hash_object_usage, 0);
-
-	if (flags & HASH_WRITE_OBJECT)
-		prefix = setup_git_directory();
-	else
-		prefix = setup_git_directory_gently(&nongit);
-
-	if (vpath && prefix)
-		vpath = xstrdup(prefix_filename(prefix, vpath));
-
-	git_config(git_default_config, NULL);
-
-	if (stdin_paths) {
-		if (hashstdin)
-			errstr = "Can't use --stdin-paths with --stdin";
-		else if (argc)
-			errstr = "Can't specify files with --stdin-paths";
-		else if (vpath)
-			errstr = "Can't use --stdin-paths with --path";
-	}
-	else {
-		if (hashstdin > 1)
-			errstr = "Multiple --stdin arguments are not supported";
-		if (vpath && no_filters)
-			errstr = "Can't use --path with --no-filters";
-	}
-
-	if (errstr) {
-		error("%s", errstr);
-		usage_with_options(hash_object_usage, hash_object_options);
-	}
-
-	if (hashstdin)
-		hash_fd(0, type, vpath, flags, literally);
-
-	for (i = 0 ; i < argc; i++) {
-		const char *arg = argv[i];
-		char *to_free = NULL;
-
-		if (prefix)
-			arg = to_free = prefix_filename(prefix, arg);
-		hash_object(arg, type, no_filters ? NULL : vpath ? vpath : arg,
-			    flags, literally);
-		free(to_free);
-	}
-
-	if (stdin_paths)
-		hash_stdin_paths(type, no_filters, flags, literally);
-
-	return 0;
-}
diff --git a/third_party/git/builtin/help.c b/third_party/git/builtin/help.c
deleted file mode 100644
index bb339f0fc802..000000000000
--- a/third_party/git/builtin/help.c
+++ /dev/null
@@ -1,623 +0,0 @@
-/*
- * Builtin help command
- */
-#include "cache.h"
-#include "config.h"
-#include "builtin.h"
-#include "exec-cmd.h"
-#include "parse-options.h"
-#include "run-command.h"
-#include "column.h"
-#include "config-list.h"
-#include "help.h"
-#include "alias.h"
-
-#ifndef DEFAULT_HELP_FORMAT
-#define DEFAULT_HELP_FORMAT "man"
-#endif
-
-static struct man_viewer_list {
-	struct man_viewer_list *next;
-	char name[FLEX_ARRAY];
-} *man_viewer_list;
-
-static struct man_viewer_info_list {
-	struct man_viewer_info_list *next;
-	const char *info;
-	char name[FLEX_ARRAY];
-} *man_viewer_info_list;
-
-enum help_format {
-	HELP_FORMAT_NONE,
-	HELP_FORMAT_MAN,
-	HELP_FORMAT_INFO,
-	HELP_FORMAT_WEB
-};
-
-static const char *html_path;
-
-static int show_all = 0;
-static int show_guides = 0;
-static int show_config;
-static int verbose = 1;
-static unsigned int colopts;
-static enum help_format help_format = HELP_FORMAT_NONE;
-static int exclude_guides;
-static struct option builtin_help_options[] = {
-	OPT_BOOL('a', "all", &show_all, N_("print all available commands")),
-	OPT_HIDDEN_BOOL(0, "exclude-guides", &exclude_guides, N_("exclude guides")),
-	OPT_BOOL('g', "guides", &show_guides, N_("print list of useful guides")),
-	OPT_BOOL('c', "config", &show_config, N_("print all configuration variable names")),
-	OPT_SET_INT_F(0, "config-for-completion", &show_config, "", 2, PARSE_OPT_HIDDEN),
-	OPT_SET_INT('m', "man", &help_format, N_("show man page"), HELP_FORMAT_MAN),
-	OPT_SET_INT('w', "web", &help_format, N_("show manual in web browser"),
-			HELP_FORMAT_WEB),
-	OPT_SET_INT('i', "info", &help_format, N_("show info page"),
-			HELP_FORMAT_INFO),
-	OPT__VERBOSE(&verbose, N_("print command description")),
-	OPT_END(),
-};
-
-static const char * const builtin_help_usage[] = {
-	N_("git help [--all] [--guides] [--man | --web | --info] [<command>]"),
-	NULL
-};
-
-struct slot_expansion {
-	const char *prefix;
-	const char *placeholder;
-	void (*fn)(struct string_list *list, const char *prefix);
-	int found;
-};
-
-static void list_config_help(int for_human)
-{
-	struct slot_expansion slot_expansions[] = {
-		{ "advice", "*", list_config_advices },
-		{ "color.branch", "<slot>", list_config_color_branch_slots },
-		{ "color.decorate", "<slot>", list_config_color_decorate_slots },
-		{ "color.diff", "<slot>", list_config_color_diff_slots },
-		{ "color.grep", "<slot>", list_config_color_grep_slots },
-		{ "color.interactive", "<slot>", list_config_color_interactive_slots },
-		{ "color.remote", "<slot>", list_config_color_sideband_slots },
-		{ "color.status", "<slot>", list_config_color_status_slots },
-		{ "fsck", "<msg-id>", list_config_fsck_msg_ids },
-		{ "receive.fsck", "<msg-id>", list_config_fsck_msg_ids },
-		{ NULL, NULL, NULL }
-	};
-	const char **p;
-	struct slot_expansion *e;
-	struct string_list keys = STRING_LIST_INIT_DUP;
-	int i;
-
-	for (p = config_name_list; *p; p++) {
-		const char *var = *p;
-		struct strbuf sb = STRBUF_INIT;
-
-		for (e = slot_expansions; e->prefix; e++) {
-
-			strbuf_reset(&sb);
-			strbuf_addf(&sb, "%s.%s", e->prefix, e->placeholder);
-			if (!strcasecmp(var, sb.buf)) {
-				e->fn(&keys, e->prefix);
-				e->found++;
-				break;
-			}
-		}
-		strbuf_release(&sb);
-		if (!e->prefix)
-			string_list_append(&keys, var);
-	}
-
-	for (e = slot_expansions; e->prefix; e++)
-		if (!e->found)
-			BUG("slot_expansion %s.%s is not used",
-			    e->prefix, e->placeholder);
-
-	string_list_sort(&keys);
-	for (i = 0; i < keys.nr; i++) {
-		const char *var = keys.items[i].string;
-		const char *wildcard, *tag, *cut;
-
-		if (for_human) {
-			puts(var);
-			continue;
-		}
-
-		wildcard = strchr(var, '*');
-		tag = strchr(var, '<');
-
-		if (!wildcard && !tag) {
-			puts(var);
-			continue;
-		}
-
-		if (wildcard && !tag)
-			cut = wildcard;
-		else if (!wildcard && tag)
-			cut = tag;
-		else
-			cut = wildcard < tag ? wildcard : tag;
-
-		/*
-		 * We may produce duplicates, but that's up to
-		 * git-completion.bash to handle
-		 */
-		printf("%.*s\n", (int)(cut - var), var);
-	}
-	string_list_clear(&keys, 0);
-}
-
-static enum help_format parse_help_format(const char *format)
-{
-	if (!strcmp(format, "man"))
-		return HELP_FORMAT_MAN;
-	if (!strcmp(format, "info"))
-		return HELP_FORMAT_INFO;
-	if (!strcmp(format, "web") || !strcmp(format, "html"))
-		return HELP_FORMAT_WEB;
-	/*
-	 * Please update _git_config() in git-completion.bash when you
-	 * add new help formats.
-	 */
-	die(_("unrecognized help format '%s'"), format);
-}
-
-static const char *get_man_viewer_info(const char *name)
-{
-	struct man_viewer_info_list *viewer;
-
-	for (viewer = man_viewer_info_list; viewer; viewer = viewer->next)
-	{
-		if (!strcasecmp(name, viewer->name))
-			return viewer->info;
-	}
-	return NULL;
-}
-
-static int check_emacsclient_version(void)
-{
-	struct strbuf buffer = STRBUF_INIT;
-	struct child_process ec_process = CHILD_PROCESS_INIT;
-	const char *argv_ec[] = { "emacsclient", "--version", NULL };
-	int version;
-
-	/* emacsclient prints its version number on stderr */
-	ec_process.argv = argv_ec;
-	ec_process.err = -1;
-	ec_process.stdout_to_stderr = 1;
-	if (start_command(&ec_process))
-		return error(_("Failed to start emacsclient."));
-
-	strbuf_read(&buffer, ec_process.err, 20);
-	close(ec_process.err);
-
-	/*
-	 * Don't bother checking return value, because "emacsclient --version"
-	 * seems to always exits with code 1.
-	 */
-	finish_command(&ec_process);
-
-	if (!starts_with(buffer.buf, "emacsclient")) {
-		strbuf_release(&buffer);
-		return error(_("Failed to parse emacsclient version."));
-	}
-
-	strbuf_remove(&buffer, 0, strlen("emacsclient"));
-	version = atoi(buffer.buf);
-
-	if (version < 22) {
-		strbuf_release(&buffer);
-		return error(_("emacsclient version '%d' too old (< 22)."),
-			version);
-	}
-
-	strbuf_release(&buffer);
-	return 0;
-}
-
-static void exec_woman_emacs(const char *path, const char *page)
-{
-	if (!check_emacsclient_version()) {
-		/* This works only with emacsclient version >= 22. */
-		struct strbuf man_page = STRBUF_INIT;
-
-		if (!path)
-			path = "emacsclient";
-		strbuf_addf(&man_page, "(woman \"%s\")", page);
-		execlp(path, "emacsclient", "-e", man_page.buf, (char *)NULL);
-		warning_errno(_("failed to exec '%s'"), path);
-		strbuf_release(&man_page);
-	}
-}
-
-static void exec_man_konqueror(const char *path, const char *page)
-{
-	const char *display = getenv("DISPLAY");
-	if (display && *display) {
-		struct strbuf man_page = STRBUF_INIT;
-		const char *filename = "kfmclient";
-
-		/* It's simpler to launch konqueror using kfmclient. */
-		if (path) {
-			size_t len;
-			if (strip_suffix(path, "/konqueror", &len))
-				path = xstrfmt("%.*s/kfmclient", (int)len, path);
-			filename = basename((char *)path);
-		} else
-			path = "kfmclient";
-		strbuf_addf(&man_page, "man:%s(1)", page);
-		execlp(path, filename, "newTab", man_page.buf, (char *)NULL);
-		warning_errno(_("failed to exec '%s'"), path);
-		strbuf_release(&man_page);
-	}
-}
-
-static void exec_man_man(const char *path, const char *page)
-{
-	if (!path)
-		path = "man";
-	execlp(path, "man", page, (char *)NULL);
-	warning_errno(_("failed to exec '%s'"), path);
-}
-
-static void exec_man_cmd(const char *cmd, const char *page)
-{
-	struct strbuf shell_cmd = STRBUF_INIT;
-	strbuf_addf(&shell_cmd, "%s %s", cmd, page);
-	execl(SHELL_PATH, SHELL_PATH, "-c", shell_cmd.buf, (char *)NULL);
-	warning(_("failed to exec '%s'"), cmd);
-	strbuf_release(&shell_cmd);
-}
-
-static void add_man_viewer(const char *name)
-{
-	struct man_viewer_list **p = &man_viewer_list;
-
-	while (*p)
-		p = &((*p)->next);
-	FLEX_ALLOC_STR(*p, name, name);
-}
-
-static int supported_man_viewer(const char *name, size_t len)
-{
-	return (!strncasecmp("man", name, len) ||
-		!strncasecmp("woman", name, len) ||
-		!strncasecmp("konqueror", name, len));
-}
-
-static void do_add_man_viewer_info(const char *name,
-				   size_t len,
-				   const char *value)
-{
-	struct man_viewer_info_list *new_man_viewer;
-	FLEX_ALLOC_MEM(new_man_viewer, name, name, len);
-	new_man_viewer->info = xstrdup(value);
-	new_man_viewer->next = man_viewer_info_list;
-	man_viewer_info_list = new_man_viewer;
-}
-
-static int add_man_viewer_path(const char *name,
-			       size_t len,
-			       const char *value)
-{
-	if (supported_man_viewer(name, len))
-		do_add_man_viewer_info(name, len, value);
-	else
-		warning(_("'%s': path for unsupported man viewer.\n"
-			  "Please consider using 'man.<tool>.cmd' instead."),
-			name);
-
-	return 0;
-}
-
-static int add_man_viewer_cmd(const char *name,
-			      size_t len,
-			      const char *value)
-{
-	if (supported_man_viewer(name, len))
-		warning(_("'%s': cmd for supported man viewer.\n"
-			  "Please consider using 'man.<tool>.path' instead."),
-			name);
-	else
-		do_add_man_viewer_info(name, len, value);
-
-	return 0;
-}
-
-static int add_man_viewer_info(const char *var, const char *value)
-{
-	const char *name, *subkey;
-	size_t namelen;
-
-	if (parse_config_key(var, "man", &name, &namelen, &subkey) < 0 || !name)
-		return 0;
-
-	if (!strcmp(subkey, "path")) {
-		if (!value)
-			return config_error_nonbool(var);
-		return add_man_viewer_path(name, namelen, value);
-	}
-	if (!strcmp(subkey, "cmd")) {
-		if (!value)
-			return config_error_nonbool(var);
-		return add_man_viewer_cmd(name, namelen, value);
-	}
-
-	return 0;
-}
-
-static int git_help_config(const char *var, const char *value, void *cb)
-{
-	if (starts_with(var, "column."))
-		return git_column_config(var, value, "help", &colopts);
-	if (!strcmp(var, "help.format")) {
-		if (!value)
-			return config_error_nonbool(var);
-		help_format = parse_help_format(value);
-		return 0;
-	}
-	if (!strcmp(var, "help.htmlpath")) {
-		if (!value)
-			return config_error_nonbool(var);
-		html_path = xstrdup(value);
-		return 0;
-	}
-	if (!strcmp(var, "man.viewer")) {
-		if (!value)
-			return config_error_nonbool(var);
-		add_man_viewer(value);
-		return 0;
-	}
-	if (starts_with(var, "man."))
-		return add_man_viewer_info(var, value);
-
-	return git_default_config(var, value, cb);
-}
-
-static struct cmdnames main_cmds, other_cmds;
-
-static int is_git_command(const char *s)
-{
-	if (is_builtin(s))
-		return 1;
-
-	load_command_list("git-", &main_cmds, &other_cmds);
-	return is_in_cmdlist(&main_cmds, s) ||
-		is_in_cmdlist(&other_cmds, s);
-}
-
-static const char *cmd_to_page(const char *git_cmd)
-{
-	if (!git_cmd)
-		return "git";
-	else if (starts_with(git_cmd, "git"))
-		return git_cmd;
-	else if (is_git_command(git_cmd))
-		return xstrfmt("git-%s", git_cmd);
-	else
-		return xstrfmt("git%s", git_cmd);
-}
-
-static void setup_man_path(void)
-{
-	struct strbuf new_path = STRBUF_INIT;
-	const char *old_path = getenv("MANPATH");
-	char *git_man_path = system_path(GIT_MAN_PATH);
-
-	/* We should always put ':' after our path. If there is no
-	 * old_path, the ':' at the end will let 'man' to try
-	 * system-wide paths after ours to find the manual page. If
-	 * there is old_path, we need ':' as delimiter. */
-	strbuf_addstr(&new_path, git_man_path);
-	strbuf_addch(&new_path, ':');
-	if (old_path)
-		strbuf_addstr(&new_path, old_path);
-
-	free(git_man_path);
-	setenv("MANPATH", new_path.buf, 1);
-
-	strbuf_release(&new_path);
-}
-
-static void exec_viewer(const char *name, const char *page)
-{
-	const char *info = get_man_viewer_info(name);
-
-	if (!strcasecmp(name, "man"))
-		exec_man_man(info, page);
-	else if (!strcasecmp(name, "woman"))
-		exec_woman_emacs(info, page);
-	else if (!strcasecmp(name, "konqueror"))
-		exec_man_konqueror(info, page);
-	else if (info)
-		exec_man_cmd(info, page);
-	else
-		warning(_("'%s': unknown man viewer."), name);
-}
-
-static void show_man_page(const char *git_cmd)
-{
-	struct man_viewer_list *viewer;
-	const char *page = cmd_to_page(git_cmd);
-	const char *fallback = getenv("GIT_MAN_VIEWER");
-
-	setup_man_path();
-	for (viewer = man_viewer_list; viewer; viewer = viewer->next)
-	{
-		exec_viewer(viewer->name, page); /* will return when unable */
-	}
-	if (fallback)
-		exec_viewer(fallback, page);
-	exec_viewer("man", page);
-	die(_("no man viewer handled the request"));
-}
-
-static void show_info_page(const char *git_cmd)
-{
-	const char *page = cmd_to_page(git_cmd);
-	setenv("INFOPATH", system_path(GIT_INFO_PATH), 1);
-	execlp("info", "info", "gitman", page, (char *)NULL);
-	die(_("no info viewer handled the request"));
-}
-
-static void get_html_page_path(struct strbuf *page_path, const char *page)
-{
-	struct stat st;
-	char *to_free = NULL;
-
-	if (!html_path)
-		html_path = to_free = system_path(GIT_HTML_PATH);
-
-	/* Check that we have a git documentation directory. */
-	if (!strstr(html_path, "://")) {
-		if (stat(mkpath("%s/git.html", html_path), &st)
-		    || !S_ISREG(st.st_mode))
-			die("'%s': not a documentation directory.", html_path);
-	}
-
-	strbuf_init(page_path, 0);
-	strbuf_addf(page_path, "%s/%s.html", html_path, page);
-	free(to_free);
-}
-
-static void open_html(const char *path)
-{
-	execl_git_cmd("web--browse", "-c", "help.browser", path, (char *)NULL);
-}
-
-static void show_html_page(const char *git_cmd)
-{
-	const char *page = cmd_to_page(git_cmd);
-	struct strbuf page_path; /* it leaks but we exec bellow */
-
-	get_html_page_path(&page_path, page);
-
-	open_html(page_path.buf);
-}
-
-static const char *check_git_cmd(const char* cmd)
-{
-	char *alias;
-
-	if (is_git_command(cmd))
-		return cmd;
-
-	alias = alias_lookup(cmd);
-	if (alias) {
-		const char **argv;
-		int count;
-
-		/*
-		 * handle_builtin() in git.c rewrites "git cmd --help"
-		 * to "git help --exclude-guides cmd", so we can use
-		 * exclude_guides to distinguish "git cmd --help" from
-		 * "git help cmd". In the latter case, or if cmd is an
-		 * alias for a shell command, just print the alias
-		 * definition.
-		 */
-		if (!exclude_guides || alias[0] == '!') {
-			printf_ln(_("'%s' is aliased to '%s'"), cmd, alias);
-			free(alias);
-			exit(0);
-		}
-		/*
-		 * Otherwise, we pretend that the command was "git
-		 * word0 --help". We use split_cmdline() to get the
-		 * first word of the alias, to ensure that we use the
-		 * same rules as when the alias is actually
-		 * used. split_cmdline() modifies alias in-place.
-		 */
-		fprintf_ln(stderr, _("'%s' is aliased to '%s'"), cmd, alias);
-		count = split_cmdline(alias, &argv);
-		if (count < 0)
-			die(_("bad alias.%s string: %s"), cmd,
-			    split_cmdline_strerror(count));
-		free(argv);
-		UNLEAK(alias);
-		return alias;
-	}
-
-	if (exclude_guides)
-		return help_unknown_cmd(cmd);
-
-	return cmd;
-}
-
-int cmd_help(int argc, const char **argv, const char *prefix)
-{
-	int nongit;
-	enum help_format parsed_help_format;
-
-	argc = parse_options(argc, argv, prefix, builtin_help_options,
-			builtin_help_usage, 0);
-	parsed_help_format = help_format;
-
-	if (show_all) {
-		git_config(git_help_config, NULL);
-		if (verbose) {
-			setup_pager();
-			list_all_cmds_help();
-			return 0;
-		}
-		printf(_("usage: %s%s"), _(git_usage_string), "\n\n");
-		load_command_list("git-", &main_cmds, &other_cmds);
-		list_commands(colopts, &main_cmds, &other_cmds);
-	}
-
-	if (show_config) {
-		int for_human = show_config == 1;
-
-		if (!for_human) {
-			list_config_help(for_human);
-			return 0;
-		}
-		setup_pager();
-		list_config_help(for_human);
-		printf("\n%s\n", _("'git help config' for more information"));
-		return 0;
-	}
-
-	if (show_guides)
-		list_guides_help();
-
-	if (show_all || show_guides) {
-		printf("%s\n", _(git_more_info_string));
-		/*
-		* We're done. Ignore any remaining args
-		*/
-		return 0;
-	}
-
-	if (!argv[0]) {
-		printf(_("usage: %s%s"), _(git_usage_string), "\n\n");
-		list_common_cmds_help();
-		printf("\n%s\n", _(git_more_info_string));
-		return 0;
-	}
-
-	setup_git_directory_gently(&nongit);
-	git_config(git_help_config, NULL);
-
-	if (parsed_help_format != HELP_FORMAT_NONE)
-		help_format = parsed_help_format;
-	if (help_format == HELP_FORMAT_NONE)
-		help_format = parse_help_format(DEFAULT_HELP_FORMAT);
-
-	argv[0] = check_git_cmd(argv[0]);
-
-	switch (help_format) {
-	case HELP_FORMAT_NONE:
-	case HELP_FORMAT_MAN:
-		show_man_page(argv[0]);
-		break;
-	case HELP_FORMAT_INFO:
-		show_info_page(argv[0]);
-		break;
-	case HELP_FORMAT_WEB:
-		show_html_page(argv[0]);
-		break;
-	}
-
-	return 0;
-}
diff --git a/third_party/git/builtin/index-pack.c b/third_party/git/builtin/index-pack.c
deleted file mode 100644
index 0d03cb442df3..000000000000
--- a/third_party/git/builtin/index-pack.c
+++ /dev/null
@@ -1,1908 +0,0 @@
-#include "builtin.h"
-#include "config.h"
-#include "delta.h"
-#include "pack.h"
-#include "csum-file.h"
-#include "blob.h"
-#include "commit.h"
-#include "tag.h"
-#include "tree.h"
-#include "progress.h"
-#include "fsck.h"
-#include "exec-cmd.h"
-#include "streaming.h"
-#include "thread-utils.h"
-#include "packfile.h"
-#include "object-store.h"
-#include "promisor-remote.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>])";
-
-struct object_entry {
-	struct pack_idx_entry idx;
-	unsigned long size;
-	unsigned char hdr_size;
-	signed char type;
-	signed char real_type;
-};
-
-struct object_stat {
-	unsigned delta_depth;
-	int base_object_no;
-};
-
-struct base_data {
-	/* Initialized by make_base(). */
-	struct base_data *base;
-	struct object_entry *obj;
-	int ref_first, ref_last;
-	int ofs_first, ofs_last;
-	/*
-	 * Threads should increment retain_data if they are about to call
-	 * patch_delta() using this struct's data as a base, and decrement this
-	 * when they are done. While retain_data is nonzero, this struct's data
-	 * will not be freed even if the delta base cache limit is exceeded.
-	 */
-	int retain_data;
-	/*
-	 * The number of direct children that have not been fully processed
-	 * (entered work_head, entered done_head, left done_head). When this
-	 * number reaches zero, this struct base_data can be freed.
-	 */
-	int children_remaining;
-
-	/* Not initialized by make_base(). */
-	struct list_head list;
-	void *data;
-	unsigned long size;
-};
-
-/*
- * Stack of struct base_data that have unprocessed children.
- * threaded_second_pass() uses this as a source of work (the other being the
- * objects array).
- *
- * Guarded by work_mutex.
- */
-static LIST_HEAD(work_head);
-
-/*
- * Stack of struct base_data that have children, all of whom have been
- * processed or are being processed, and at least one child is being processed.
- * These struct base_data must be kept around until the last child is
- * processed.
- *
- * Guarded by work_mutex.
- */
-static LIST_HEAD(done_head);
-
-/*
- * All threads share one delta base cache.
- *
- * base_cache_used is guarded by work_mutex, and base_cache_limit is read-only
- * in a thread.
- */
-static size_t base_cache_used;
-static size_t base_cache_limit;
-
-struct thread_local {
-	pthread_t thread;
-	int pack_fd;
-};
-
-/* Remember to update object flag allocation in object.h */
-#define FLAG_LINK (1u<<20)
-#define FLAG_CHECKED (1u<<21)
-
-struct ofs_delta_entry {
-	off_t offset;
-	int obj_no;
-};
-
-struct ref_delta_entry {
-	struct object_id oid;
-	int obj_no;
-};
-
-static struct object_entry *objects;
-static struct object_stat *obj_stat;
-static struct ofs_delta_entry *ofs_deltas;
-static struct ref_delta_entry *ref_deltas;
-static struct thread_local nothread_data;
-static int nr_objects;
-static int nr_ofs_deltas;
-static int nr_ref_deltas;
-static int ref_deltas_alloc;
-static int nr_resolved_deltas;
-static int nr_threads;
-
-static int from_stdin;
-static int strict;
-static int do_fsck_object;
-static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
-static int verbose;
-static int show_resolving_progress;
-static int show_stat;
-static int check_self_contained_and_connected;
-
-static struct progress *progress;
-
-/* We always read in 4kB chunks. */
-static unsigned char input_buffer[4096];
-static unsigned int input_offset, input_len;
-static off_t consumed_bytes;
-static off_t max_input_size;
-static unsigned deepest_delta;
-static git_hash_ctx input_ctx;
-static uint32_t input_crc32;
-static int input_fd, output_fd;
-static const char *curr_pack;
-
-static struct thread_local *thread_data;
-static int nr_dispatched;
-static int threads_active;
-
-static pthread_mutex_t read_mutex;
-#define read_lock()		lock_mutex(&read_mutex)
-#define read_unlock()		unlock_mutex(&read_mutex)
-
-static pthread_mutex_t counter_mutex;
-#define counter_lock()		lock_mutex(&counter_mutex)
-#define counter_unlock()	unlock_mutex(&counter_mutex)
-
-static pthread_mutex_t work_mutex;
-#define work_lock()		lock_mutex(&work_mutex)
-#define work_unlock()		unlock_mutex(&work_mutex)
-
-static pthread_mutex_t deepest_delta_mutex;
-#define deepest_delta_lock()	lock_mutex(&deepest_delta_mutex)
-#define deepest_delta_unlock()	unlock_mutex(&deepest_delta_mutex)
-
-static pthread_key_t key;
-
-static inline void lock_mutex(pthread_mutex_t *mutex)
-{
-	if (threads_active)
-		pthread_mutex_lock(mutex);
-}
-
-static inline void unlock_mutex(pthread_mutex_t *mutex)
-{
-	if (threads_active)
-		pthread_mutex_unlock(mutex);
-}
-
-/*
- * Mutex and conditional variable can't be statically-initialized on Windows.
- */
-static void init_thread(void)
-{
-	int i;
-	init_recursive_mutex(&read_mutex);
-	pthread_mutex_init(&counter_mutex, NULL);
-	pthread_mutex_init(&work_mutex, NULL);
-	if (show_stat)
-		pthread_mutex_init(&deepest_delta_mutex, NULL);
-	pthread_key_create(&key, NULL);
-	thread_data = xcalloc(nr_threads, sizeof(*thread_data));
-	for (i = 0; i < nr_threads; i++) {
-		thread_data[i].pack_fd = open(curr_pack, O_RDONLY);
-		if (thread_data[i].pack_fd == -1)
-			die_errno(_("unable to open %s"), curr_pack);
-	}
-
-	threads_active = 1;
-}
-
-static void cleanup_thread(void)
-{
-	int i;
-	if (!threads_active)
-		return;
-	threads_active = 0;
-	pthread_mutex_destroy(&read_mutex);
-	pthread_mutex_destroy(&counter_mutex);
-	pthread_mutex_destroy(&work_mutex);
-	if (show_stat)
-		pthread_mutex_destroy(&deepest_delta_mutex);
-	for (i = 0; i < nr_threads; i++)
-		close(thread_data[i].pack_fd);
-	pthread_key_delete(key);
-	free(thread_data);
-}
-
-static int mark_link(struct object *obj, int type, void *data, struct fsck_options *options)
-{
-	if (!obj)
-		return -1;
-
-	if (type != OBJ_ANY && obj->type != type)
-		die(_("object type mismatch at %s"), oid_to_hex(&obj->oid));
-
-	obj->flags |= FLAG_LINK;
-	return 0;
-}
-
-/* The content of each linked object must have been checked
-   or it must be already present in the object database */
-static unsigned check_object(struct object *obj)
-{
-	if (!obj)
-		return 0;
-
-	if (!(obj->flags & FLAG_LINK))
-		return 0;
-
-	if (!(obj->flags & FLAG_CHECKED)) {
-		unsigned long size;
-		int type = oid_object_info(the_repository, &obj->oid, &size);
-		if (type <= 0)
-			die(_("did not receive expected object %s"),
-			      oid_to_hex(&obj->oid));
-		if (type != obj->type)
-			die(_("object %s: expected type %s, found %s"),
-			    oid_to_hex(&obj->oid),
-			    type_name(obj->type), type_name(type));
-		obj->flags |= FLAG_CHECKED;
-		return 1;
-	}
-
-	return 0;
-}
-
-static unsigned check_objects(void)
-{
-	unsigned i, max, foreign_nr = 0;
-
-	max = get_max_object_index();
-
-	if (verbose)
-		progress = start_delayed_progress(_("Checking objects"), max);
-
-	for (i = 0; i < max; i++) {
-		foreign_nr += check_object(get_indexed_object(i));
-		display_progress(progress, i + 1);
-	}
-
-	stop_progress(&progress);
-	return foreign_nr;
-}
-
-
-/* Discard current buffer used content. */
-static void flush(void)
-{
-	if (input_offset) {
-		if (output_fd >= 0)
-			write_or_die(output_fd, input_buffer, input_offset);
-		the_hash_algo->update_fn(&input_ctx, input_buffer, input_offset);
-		memmove(input_buffer, input_buffer + input_offset, input_len);
-		input_offset = 0;
-	}
-}
-
-/*
- * Make sure at least "min" bytes are available in the buffer, and
- * return the pointer to the buffer.
- */
-static void *fill(int min)
-{
-	if (min <= input_len)
-		return input_buffer + input_offset;
-	if (min > sizeof(input_buffer))
-		die(Q_("cannot fill %d byte",
-		       "cannot fill %d bytes",
-		       min),
-		    min);
-	flush();
-	do {
-		ssize_t ret = xread(input_fd, input_buffer + input_len,
-				sizeof(input_buffer) - input_len);
-		if (ret <= 0) {
-			if (!ret)
-				die(_("early EOF"));
-			die_errno(_("read error on input"));
-		}
-		input_len += ret;
-		if (from_stdin)
-			display_throughput(progress, consumed_bytes + input_len);
-	} while (input_len < min);
-	return input_buffer;
-}
-
-static void use(int bytes)
-{
-	if (bytes > input_len)
-		die(_("used more bytes than were available"));
-	input_crc32 = crc32(input_crc32, input_buffer + input_offset, bytes);
-	input_len -= bytes;
-	input_offset += bytes;
-
-	/* make sure off_t is sufficiently large not to wrap */
-	if (signed_add_overflows(consumed_bytes, bytes))
-		die(_("pack too large for current definition of off_t"));
-	consumed_bytes += bytes;
-	if (max_input_size && consumed_bytes > max_input_size)
-		die(_("pack exceeds maximum allowed size"));
-}
-
-static const char *open_pack_file(const char *pack_name)
-{
-	if (from_stdin) {
-		input_fd = 0;
-		if (!pack_name) {
-			struct strbuf tmp_file = STRBUF_INIT;
-			output_fd = odb_mkstemp(&tmp_file,
-						"pack/tmp_pack_XXXXXX");
-			pack_name = strbuf_detach(&tmp_file, NULL);
-		} else {
-			output_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600);
-			if (output_fd < 0)
-				die_errno(_("unable to create '%s'"), pack_name);
-		}
-		nothread_data.pack_fd = output_fd;
-	} else {
-		input_fd = open(pack_name, O_RDONLY);
-		if (input_fd < 0)
-			die_errno(_("cannot open packfile '%s'"), pack_name);
-		output_fd = -1;
-		nothread_data.pack_fd = input_fd;
-	}
-	the_hash_algo->init_fn(&input_ctx);
-	return pack_name;
-}
-
-static void parse_pack_header(void)
-{
-	struct pack_header *hdr = fill(sizeof(struct pack_header));
-
-	/* Header consistency check */
-	if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
-		die(_("pack signature mismatch"));
-	if (!pack_version_ok(hdr->hdr_version))
-		die(_("pack version %"PRIu32" unsupported"),
-			ntohl(hdr->hdr_version));
-
-	nr_objects = ntohl(hdr->hdr_entries);
-	use(sizeof(struct pack_header));
-}
-
-static NORETURN void bad_object(off_t offset, const char *format,
-		       ...) __attribute__((format (printf, 2, 3)));
-
-static NORETURN void bad_object(off_t offset, const char *format, ...)
-{
-	va_list params;
-	char buf[1024];
-
-	va_start(params, format);
-	vsnprintf(buf, sizeof(buf), format, params);
-	va_end(params);
-	die(_("pack has bad object at offset %"PRIuMAX": %s"),
-	    (uintmax_t)offset, buf);
-}
-
-static inline struct thread_local *get_thread_data(void)
-{
-	if (HAVE_THREADS) {
-		if (threads_active)
-			return pthread_getspecific(key);
-		assert(!threads_active &&
-		       "This should only be reached when all threads are gone");
-	}
-	return &nothread_data;
-}
-
-static void set_thread_data(struct thread_local *data)
-{
-	if (threads_active)
-		pthread_setspecific(key, data);
-}
-
-static void free_base_data(struct base_data *c)
-{
-	if (c->data) {
-		FREE_AND_NULL(c->data);
-		base_cache_used -= c->size;
-	}
-}
-
-static void prune_base_data(struct base_data *retain)
-{
-	struct list_head *pos;
-
-	if (base_cache_used <= base_cache_limit)
-		return;
-
-	list_for_each_prev(pos, &done_head) {
-		struct base_data *b = list_entry(pos, struct base_data, list);
-		if (b->retain_data || b == retain)
-			continue;
-		if (b->data) {
-			free_base_data(b);
-			if (base_cache_used <= base_cache_limit)
-				return;
-		}
-	}
-
-	list_for_each_prev(pos, &work_head) {
-		struct base_data *b = list_entry(pos, struct base_data, list);
-		if (b->retain_data || b == retain)
-			continue;
-		if (b->data) {
-			free_base_data(b);
-			if (base_cache_used <= base_cache_limit)
-				return;
-		}
-	}
-}
-
-static int is_delta_type(enum object_type type)
-{
-	return (type == OBJ_REF_DELTA || type == OBJ_OFS_DELTA);
-}
-
-static void *unpack_entry_data(off_t offset, unsigned long size,
-			       enum object_type type, struct object_id *oid)
-{
-	static char fixed_buf[8192];
-	int status;
-	git_zstream stream;
-	void *buf;
-	git_hash_ctx c;
-	char hdr[32];
-	int hdrlen;
-
-	if (!is_delta_type(type)) {
-		hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX,
-				   type_name(type),(uintmax_t)size) + 1;
-		the_hash_algo->init_fn(&c);
-		the_hash_algo->update_fn(&c, hdr, hdrlen);
-	} else
-		oid = NULL;
-	if (type == OBJ_BLOB && size > big_file_threshold)
-		buf = fixed_buf;
-	else
-		buf = xmallocz(size);
-
-	memset(&stream, 0, sizeof(stream));
-	git_inflate_init(&stream);
-	stream.next_out = buf;
-	stream.avail_out = buf == fixed_buf ? sizeof(fixed_buf) : size;
-
-	do {
-		unsigned char *last_out = stream.next_out;
-		stream.next_in = fill(1);
-		stream.avail_in = input_len;
-		status = git_inflate(&stream, 0);
-		use(input_len - stream.avail_in);
-		if (oid)
-			the_hash_algo->update_fn(&c, last_out, stream.next_out - last_out);
-		if (buf == fixed_buf) {
-			stream.next_out = buf;
-			stream.avail_out = sizeof(fixed_buf);
-		}
-	} while (status == Z_OK);
-	if (stream.total_out != size || status != Z_STREAM_END)
-		bad_object(offset, _("inflate returned %d"), status);
-	git_inflate_end(&stream);
-	if (oid)
-		the_hash_algo->final_fn(oid->hash, &c);
-	return buf == fixed_buf ? NULL : buf;
-}
-
-static void *unpack_raw_entry(struct object_entry *obj,
-			      off_t *ofs_offset,
-			      struct object_id *ref_oid,
-			      struct object_id *oid)
-{
-	unsigned char *p;
-	unsigned long size, c;
-	off_t base_offset;
-	unsigned shift;
-	void *data;
-
-	obj->idx.offset = consumed_bytes;
-	input_crc32 = crc32(0, NULL, 0);
-
-	p = fill(1);
-	c = *p;
-	use(1);
-	obj->type = (c >> 4) & 7;
-	size = (c & 15);
-	shift = 4;
-	while (c & 0x80) {
-		p = fill(1);
-		c = *p;
-		use(1);
-		size += (c & 0x7f) << shift;
-		shift += 7;
-	}
-	obj->size = size;
-
-	switch (obj->type) {
-	case OBJ_REF_DELTA:
-		hashcpy(ref_oid->hash, fill(the_hash_algo->rawsz));
-		use(the_hash_algo->rawsz);
-		break;
-	case OBJ_OFS_DELTA:
-		p = fill(1);
-		c = *p;
-		use(1);
-		base_offset = c & 127;
-		while (c & 128) {
-			base_offset += 1;
-			if (!base_offset || MSB(base_offset, 7))
-				bad_object(obj->idx.offset, _("offset value overflow for delta base object"));
-			p = fill(1);
-			c = *p;
-			use(1);
-			base_offset = (base_offset << 7) + (c & 127);
-		}
-		*ofs_offset = obj->idx.offset - base_offset;
-		if (*ofs_offset <= 0 || *ofs_offset >= obj->idx.offset)
-			bad_object(obj->idx.offset, _("delta base offset is out of bound"));
-		break;
-	case OBJ_COMMIT:
-	case OBJ_TREE:
-	case OBJ_BLOB:
-	case OBJ_TAG:
-		break;
-	default:
-		bad_object(obj->idx.offset, _("unknown object type %d"), obj->type);
-	}
-	obj->hdr_size = consumed_bytes - obj->idx.offset;
-
-	data = unpack_entry_data(obj->idx.offset, obj->size, obj->type, oid);
-	obj->idx.crc32 = input_crc32;
-	return data;
-}
-
-static void *unpack_data(struct object_entry *obj,
-			 int (*consume)(const unsigned char *, unsigned long, void *),
-			 void *cb_data)
-{
-	off_t from = obj[0].idx.offset + obj[0].hdr_size;
-	off_t len = obj[1].idx.offset - from;
-	unsigned char *data, *inbuf;
-	git_zstream stream;
-	int status;
-
-	data = xmallocz(consume ? 64*1024 : obj->size);
-	inbuf = xmalloc((len < 64*1024) ? (int)len : 64*1024);
-
-	memset(&stream, 0, sizeof(stream));
-	git_inflate_init(&stream);
-	stream.next_out = data;
-	stream.avail_out = consume ? 64*1024 : obj->size;
-
-	do {
-		ssize_t n = (len < 64*1024) ? (ssize_t)len : 64*1024;
-		n = xpread(get_thread_data()->pack_fd, inbuf, n, from);
-		if (n < 0)
-			die_errno(_("cannot pread pack file"));
-		if (!n)
-			die(Q_("premature end of pack file, %"PRIuMAX" byte missing",
-			       "premature end of pack file, %"PRIuMAX" bytes missing",
-			       (unsigned int)len),
-			    (uintmax_t)len);
-		from += n;
-		len -= n;
-		stream.next_in = inbuf;
-		stream.avail_in = n;
-		if (!consume)
-			status = git_inflate(&stream, 0);
-		else {
-			do {
-				status = git_inflate(&stream, 0);
-				if (consume(data, stream.next_out - data, cb_data)) {
-					free(inbuf);
-					free(data);
-					return NULL;
-				}
-				stream.next_out = data;
-				stream.avail_out = 64*1024;
-			} while (status == Z_OK && stream.avail_in);
-		}
-	} while (len && status == Z_OK && !stream.avail_in);
-
-	/* This has been inflated OK when first encountered, so... */
-	if (status != Z_STREAM_END || stream.total_out != obj->size)
-		die(_("serious inflate inconsistency"));
-
-	git_inflate_end(&stream);
-	free(inbuf);
-	if (consume) {
-		FREE_AND_NULL(data);
-	}
-	return data;
-}
-
-static void *get_data_from_pack(struct object_entry *obj)
-{
-	return unpack_data(obj, NULL, NULL);
-}
-
-static int compare_ofs_delta_bases(off_t offset1, off_t offset2,
-				   enum object_type type1,
-				   enum object_type type2)
-{
-	int cmp = type1 - type2;
-	if (cmp)
-		return cmp;
-	return offset1 < offset2 ? -1 :
-	       offset1 > offset2 ?  1 :
-	       0;
-}
-
-static int find_ofs_delta(const off_t offset)
-{
-	int first = 0, last = nr_ofs_deltas;
-
-	while (first < last) {
-		int next = first + (last - first) / 2;
-		struct ofs_delta_entry *delta = &ofs_deltas[next];
-		int cmp;
-
-		cmp = compare_ofs_delta_bases(offset, delta->offset,
-					      OBJ_OFS_DELTA,
-					      objects[delta->obj_no].type);
-		if (!cmp)
-			return next;
-		if (cmp < 0) {
-			last = next;
-			continue;
-		}
-		first = next+1;
-	}
-	return -first-1;
-}
-
-static void find_ofs_delta_children(off_t offset,
-				    int *first_index, int *last_index)
-{
-	int first = find_ofs_delta(offset);
-	int last = first;
-	int end = nr_ofs_deltas - 1;
-
-	if (first < 0) {
-		*first_index = 0;
-		*last_index = -1;
-		return;
-	}
-	while (first > 0 && ofs_deltas[first - 1].offset == offset)
-		--first;
-	while (last < end && ofs_deltas[last + 1].offset == offset)
-		++last;
-	*first_index = first;
-	*last_index = last;
-}
-
-static int compare_ref_delta_bases(const struct object_id *oid1,
-				   const struct object_id *oid2,
-				   enum object_type type1,
-				   enum object_type type2)
-{
-	int cmp = type1 - type2;
-	if (cmp)
-		return cmp;
-	return oidcmp(oid1, oid2);
-}
-
-static int find_ref_delta(const struct object_id *oid)
-{
-	int first = 0, last = nr_ref_deltas;
-
-	while (first < last) {
-		int next = first + (last - first) / 2;
-		struct ref_delta_entry *delta = &ref_deltas[next];
-		int cmp;
-
-		cmp = compare_ref_delta_bases(oid, &delta->oid,
-					      OBJ_REF_DELTA,
-					      objects[delta->obj_no].type);
-		if (!cmp)
-			return next;
-		if (cmp < 0) {
-			last = next;
-			continue;
-		}
-		first = next+1;
-	}
-	return -first-1;
-}
-
-static void find_ref_delta_children(const struct object_id *oid,
-				    int *first_index, int *last_index)
-{
-	int first = find_ref_delta(oid);
-	int last = first;
-	int end = nr_ref_deltas - 1;
-
-	if (first < 0) {
-		*first_index = 0;
-		*last_index = -1;
-		return;
-	}
-	while (first > 0 && oideq(&ref_deltas[first - 1].oid, oid))
-		--first;
-	while (last < end && oideq(&ref_deltas[last + 1].oid, oid))
-		++last;
-	*first_index = first;
-	*last_index = last;
-}
-
-struct compare_data {
-	struct object_entry *entry;
-	struct git_istream *st;
-	unsigned char *buf;
-	unsigned long buf_size;
-};
-
-static int compare_objects(const unsigned char *buf, unsigned long size,
-			   void *cb_data)
-{
-	struct compare_data *data = cb_data;
-
-	if (data->buf_size < size) {
-		free(data->buf);
-		data->buf = xmalloc(size);
-		data->buf_size = size;
-	}
-
-	while (size) {
-		ssize_t len = read_istream(data->st, data->buf, size);
-		if (len == 0)
-			die(_("SHA1 COLLISION FOUND WITH %s !"),
-			    oid_to_hex(&data->entry->idx.oid));
-		if (len < 0)
-			die(_("unable to read %s"),
-			    oid_to_hex(&data->entry->idx.oid));
-		if (memcmp(buf, data->buf, len))
-			die(_("SHA1 COLLISION FOUND WITH %s !"),
-			    oid_to_hex(&data->entry->idx.oid));
-		size -= len;
-		buf += len;
-	}
-	return 0;
-}
-
-static int check_collison(struct object_entry *entry)
-{
-	struct compare_data data;
-	enum object_type type;
-	unsigned long size;
-
-	if (entry->size <= big_file_threshold || entry->type != OBJ_BLOB)
-		return -1;
-
-	memset(&data, 0, sizeof(data));
-	data.entry = entry;
-	data.st = open_istream(the_repository, &entry->idx.oid, &type, &size,
-			       NULL);
-	if (!data.st)
-		return -1;
-	if (size != entry->size || type != entry->type)
-		die(_("SHA1 COLLISION FOUND WITH %s !"),
-		    oid_to_hex(&entry->idx.oid));
-	unpack_data(entry, compare_objects, &data);
-	close_istream(data.st);
-	free(data.buf);
-	return 0;
-}
-
-static void sha1_object(const void *data, struct object_entry *obj_entry,
-			unsigned long size, enum object_type type,
-			const struct object_id *oid)
-{
-	void *new_data = NULL;
-	int collision_test_needed = 0;
-
-	assert(data || obj_entry);
-
-	if (startup_info->have_repository) {
-		read_lock();
-		collision_test_needed =
-			has_object_file_with_flags(oid, OBJECT_INFO_QUICK);
-		read_unlock();
-	}
-
-	if (collision_test_needed && !data) {
-		read_lock();
-		if (!check_collison(obj_entry))
-			collision_test_needed = 0;
-		read_unlock();
-	}
-	if (collision_test_needed) {
-		void *has_data;
-		enum object_type has_type;
-		unsigned long has_size;
-		read_lock();
-		has_type = oid_object_info(the_repository, oid, &has_size);
-		if (has_type < 0)
-			die(_("cannot read existing object info %s"), oid_to_hex(oid));
-		if (has_type != type || has_size != size)
-			die(_("SHA1 COLLISION FOUND WITH %s !"), oid_to_hex(oid));
-		has_data = read_object_file(oid, &has_type, &has_size);
-		read_unlock();
-		if (!data)
-			data = new_data = get_data_from_pack(obj_entry);
-		if (!has_data)
-			die(_("cannot read existing object %s"), oid_to_hex(oid));
-		if (size != has_size || type != has_type ||
-		    memcmp(data, has_data, size) != 0)
-			die(_("SHA1 COLLISION FOUND WITH %s !"), oid_to_hex(oid));
-		free(has_data);
-	}
-
-	if (strict || do_fsck_object) {
-		read_lock();
-		if (type == OBJ_BLOB) {
-			struct blob *blob = lookup_blob(the_repository, oid);
-			if (blob)
-				blob->object.flags |= FLAG_CHECKED;
-			else
-				die(_("invalid blob object %s"), oid_to_hex(oid));
-			if (do_fsck_object &&
-			    fsck_object(&blob->object, (void *)data, size, &fsck_options))
-				die(_("fsck error in packed object"));
-		} else {
-			struct object *obj;
-			int eaten;
-			void *buf = (void *) data;
-
-			assert(data && "data can only be NULL for large _blobs_");
-
-			/*
-			 * we do not need to free the memory here, as the
-			 * buf is deleted by the caller.
-			 */
-			obj = parse_object_buffer(the_repository, oid, type,
-						  size, buf,
-						  &eaten);
-			if (!obj)
-				die(_("invalid %s"), type_name(type));
-			if (do_fsck_object &&
-			    fsck_object(obj, buf, size, &fsck_options))
-				die(_("fsck error in packed object"));
-			if (strict && fsck_walk(obj, NULL, &fsck_options))
-				die(_("Not all child objects of %s are reachable"), oid_to_hex(&obj->oid));
-
-			if (obj->type == OBJ_TREE) {
-				struct tree *item = (struct tree *) obj;
-				item->buffer = NULL;
-				obj->parsed = 0;
-			}
-			if (obj->type == OBJ_COMMIT) {
-				struct commit *commit = (struct commit *) obj;
-				if (detach_commit_buffer(commit, NULL) != data)
-					BUG("parse_object_buffer transmogrified our buffer");
-			}
-			obj->flags |= FLAG_CHECKED;
-		}
-		read_unlock();
-	}
-
-	free(new_data);
-}
-
-/*
- * Ensure that this node has been reconstructed and return its contents.
- *
- * In the typical and best case, this node would already be reconstructed
- * (through the invocation to resolve_delta() in threaded_second_pass()) and it
- * would not be pruned. However, if pruning of this node was necessary due to
- * reaching delta_base_cache_limit, this function will find the closest
- * ancestor with reconstructed data that has not been pruned (or if there is
- * none, the ultimate base object), and reconstruct each node in the delta
- * chain in order to generate the reconstructed data for this node.
- */
-static void *get_base_data(struct base_data *c)
-{
-	if (!c->data) {
-		struct object_entry *obj = c->obj;
-		struct base_data **delta = NULL;
-		int delta_nr = 0, delta_alloc = 0;
-
-		while (is_delta_type(c->obj->type) && !c->data) {
-			ALLOC_GROW(delta, delta_nr + 1, delta_alloc);
-			delta[delta_nr++] = c;
-			c = c->base;
-		}
-		if (!delta_nr) {
-			c->data = get_data_from_pack(obj);
-			c->size = obj->size;
-			base_cache_used += c->size;
-			prune_base_data(c);
-		}
-		for (; delta_nr > 0; delta_nr--) {
-			void *base, *raw;
-			c = delta[delta_nr - 1];
-			obj = c->obj;
-			base = get_base_data(c->base);
-			raw = get_data_from_pack(obj);
-			c->data = patch_delta(
-				base, c->base->size,
-				raw, obj->size,
-				&c->size);
-			free(raw);
-			if (!c->data)
-				bad_object(obj->idx.offset, _("failed to apply delta"));
-			base_cache_used += c->size;
-			prune_base_data(c);
-		}
-		free(delta);
-	}
-	return c->data;
-}
-
-static struct base_data *make_base(struct object_entry *obj,
-				   struct base_data *parent)
-{
-	struct base_data *base = xcalloc(1, sizeof(struct base_data));
-	base->base = parent;
-	base->obj = obj;
-	find_ref_delta_children(&obj->idx.oid,
-				&base->ref_first, &base->ref_last);
-	find_ofs_delta_children(obj->idx.offset,
-				&base->ofs_first, &base->ofs_last);
-	base->children_remaining = base->ref_last - base->ref_first +
-		base->ofs_last - base->ofs_first + 2;
-	return base;
-}
-
-static struct base_data *resolve_delta(struct object_entry *delta_obj,
-				       struct base_data *base)
-{
-	void *delta_data, *result_data;
-	struct base_data *result;
-	unsigned long result_size;
-
-	if (show_stat) {
-		int i = delta_obj - objects;
-		int j = base->obj - objects;
-		obj_stat[i].delta_depth = obj_stat[j].delta_depth + 1;
-		deepest_delta_lock();
-		if (deepest_delta < obj_stat[i].delta_depth)
-			deepest_delta = obj_stat[i].delta_depth;
-		deepest_delta_unlock();
-		obj_stat[i].base_object_no = j;
-	}
-	delta_data = get_data_from_pack(delta_obj);
-	assert(base->data);
-	result_data = patch_delta(base->data, base->size,
-				  delta_data, delta_obj->size, &result_size);
-	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,
-			 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);
-
-	result = make_base(delta_obj, base);
-	result->data = result_data;
-	result->size = result_size;
-
-	counter_lock();
-	nr_resolved_deltas++;
-	counter_unlock();
-
-	return result;
-}
-
-static int compare_ofs_delta_entry(const void *a, const void *b)
-{
-	const struct ofs_delta_entry *delta_a = a;
-	const struct ofs_delta_entry *delta_b = b;
-
-	return delta_a->offset < delta_b->offset ? -1 :
-	       delta_a->offset > delta_b->offset ?  1 :
-	       0;
-}
-
-static int compare_ref_delta_entry(const void *a, const void *b)
-{
-	const struct ref_delta_entry *delta_a = a;
-	const struct ref_delta_entry *delta_b = b;
-
-	return oidcmp(&delta_a->oid, &delta_b->oid);
-}
-
-static void *threaded_second_pass(void *data)
-{
-	if (data)
-		set_thread_data(data);
-	for (;;) {
-		struct base_data *parent = NULL;
-		struct object_entry *child_obj;
-		struct base_data *child;
-
-		counter_lock();
-		display_progress(progress, nr_resolved_deltas);
-		counter_unlock();
-
-		work_lock();
-		if (list_empty(&work_head)) {
-			/*
-			 * Take an object from the object array.
-			 */
-			while (nr_dispatched < nr_objects &&
-			       is_delta_type(objects[nr_dispatched].type))
-				nr_dispatched++;
-			if (nr_dispatched >= nr_objects) {
-				work_unlock();
-				break;
-			}
-			child_obj = &objects[nr_dispatched++];
-		} else {
-			/*
-			 * Peek at the top of the stack, and take a child from
-			 * it.
-			 */
-			parent = list_first_entry(&work_head, struct base_data,
-						  list);
-
-			if (parent->ref_first <= parent->ref_last) {
-				int offset = ref_deltas[parent->ref_first++].obj_no;
-				child_obj = objects + offset;
-				if (child_obj->real_type != OBJ_REF_DELTA)
-					die("REF_DELTA at offset %"PRIuMAX" already resolved (duplicate base %s?)",
-					    (uintmax_t) child_obj->idx.offset,
-					    oid_to_hex(&parent->obj->idx.oid));
-				child_obj->real_type = parent->obj->real_type;
-			} else {
-				child_obj = objects +
-					ofs_deltas[parent->ofs_first++].obj_no;
-				assert(child_obj->real_type == OBJ_OFS_DELTA);
-				child_obj->real_type = parent->obj->real_type;
-			}
-
-			if (parent->ref_first > parent->ref_last &&
-			    parent->ofs_first > parent->ofs_last) {
-				/*
-				 * This parent has run out of children, so move
-				 * it to done_head.
-				 */
-				list_del(&parent->list);
-				list_add(&parent->list, &done_head);
-			}
-
-			/*
-			 * Ensure that the parent has data, since we will need
-			 * it later.
-			 *
-			 * NEEDSWORK: If parent data needs to be reloaded, this
-			 * prolongs the time that the current thread spends in
-			 * the mutex. A mitigating factor is that parent data
-			 * needs to be reloaded only if the delta base cache
-			 * limit is exceeded, so in the typical case, this does
-			 * not happen.
-			 */
-			get_base_data(parent);
-			parent->retain_data++;
-		}
-		work_unlock();
-
-		if (parent) {
-			child = resolve_delta(child_obj, parent);
-			if (!child->children_remaining)
-				FREE_AND_NULL(child->data);
-		} else {
-			child = make_base(child_obj, NULL);
-			if (child->children_remaining) {
-				/*
-				 * Since this child has its own delta children,
-				 * we will need this data in the future.
-				 * Inflate now so that future iterations will
-				 * have access to this object's data while
-				 * outside the work mutex.
-				 */
-				child->data = get_data_from_pack(child_obj);
-				child->size = child_obj->size;
-			}
-		}
-
-		work_lock();
-		if (parent)
-			parent->retain_data--;
-		if (child->data) {
-			/*
-			 * This child has its own children, so add it to
-			 * work_head.
-			 */
-			list_add(&child->list, &work_head);
-			base_cache_used += child->size;
-			prune_base_data(NULL);
-		} else {
-			/*
-			 * This child does not have its own children. It may be
-			 * the last descendant of its ancestors; free those
-			 * that we can.
-			 */
-			struct base_data *p = parent;
-
-			while (p) {
-				struct base_data *next_p;
-
-				p->children_remaining--;
-				if (p->children_remaining)
-					break;
-
-				next_p = p->base;
-				free_base_data(p);
-				list_del(&p->list);
-				free(p);
-
-				p = next_p;
-			}
-		}
-		work_unlock();
-	}
-	return NULL;
-}
-
-/*
- * First pass:
- * - find locations of all objects;
- * - calculate SHA1 of all non-delta objects;
- * - remember base (SHA1 or offset) for all deltas.
- */
-static void parse_pack_objects(unsigned char *hash)
-{
-	int i, nr_delays = 0;
-	struct ofs_delta_entry *ofs_delta = ofs_deltas;
-	struct object_id ref_delta_oid;
-	struct stat st;
-
-	if (verbose)
-		progress = start_progress(
-				from_stdin ? _("Receiving objects") : _("Indexing objects"),
-				nr_objects);
-	for (i = 0; i < nr_objects; i++) {
-		struct object_entry *obj = &objects[i];
-		void *data = unpack_raw_entry(obj, &ofs_delta->offset,
-					      &ref_delta_oid,
-					      &obj->idx.oid);
-		obj->real_type = obj->type;
-		if (obj->type == OBJ_OFS_DELTA) {
-			nr_ofs_deltas++;
-			ofs_delta->obj_no = i;
-			ofs_delta++;
-		} else if (obj->type == OBJ_REF_DELTA) {
-			ALLOC_GROW(ref_deltas, nr_ref_deltas + 1, ref_deltas_alloc);
-			oidcpy(&ref_deltas[nr_ref_deltas].oid, &ref_delta_oid);
-			ref_deltas[nr_ref_deltas].obj_no = i;
-			nr_ref_deltas++;
-		} else if (!data) {
-			/* large blobs, check later */
-			obj->real_type = OBJ_BAD;
-			nr_delays++;
-		} else
-			sha1_object(data, NULL, obj->size, obj->type,
-				    &obj->idx.oid);
-		free(data);
-		display_progress(progress, i+1);
-	}
-	objects[i].idx.offset = consumed_bytes;
-	stop_progress(&progress);
-
-	/* Check pack integrity */
-	flush();
-	the_hash_algo->final_fn(hash, &input_ctx);
-	if (!hasheq(fill(the_hash_algo->rawsz), hash))
-		die(_("pack is corrupted (SHA1 mismatch)"));
-	use(the_hash_algo->rawsz);
-
-	/* If input_fd is a file, we should have reached its end now. */
-	if (fstat(input_fd, &st))
-		die_errno(_("cannot fstat packfile"));
-	if (S_ISREG(st.st_mode) &&
-			lseek(input_fd, 0, SEEK_CUR) - input_len != st.st_size)
-		die(_("pack has junk at the end"));
-
-	for (i = 0; i < nr_objects; i++) {
-		struct object_entry *obj = &objects[i];
-		if (obj->real_type != OBJ_BAD)
-			continue;
-		obj->real_type = obj->type;
-		sha1_object(NULL, obj, obj->size, obj->type,
-			    &obj->idx.oid);
-		nr_delays--;
-	}
-	if (nr_delays)
-		die(_("confusion beyond insanity in parse_pack_objects()"));
-}
-
-/*
- * Second pass:
- * - for all non-delta objects, look if it is used as a base for
- *   deltas;
- * - if used as a base, uncompress the object and apply all deltas,
- *   recursively checking if the resulting object is used as a base
- *   for some more deltas.
- */
-static void resolve_deltas(void)
-{
-	int i;
-
-	if (!nr_ofs_deltas && !nr_ref_deltas)
-		return;
-
-	/* Sort deltas by base SHA1/offset for fast searching */
-	QSORT(ofs_deltas, nr_ofs_deltas, compare_ofs_delta_entry);
-	QSORT(ref_deltas, nr_ref_deltas, compare_ref_delta_entry);
-
-	if (verbose || show_resolving_progress)
-		progress = start_progress(_("Resolving deltas"),
-					  nr_ref_deltas + nr_ofs_deltas);
-
-	nr_dispatched = 0;
-	base_cache_limit = delta_base_cache_limit * nr_threads;
-	if (nr_threads > 1 || getenv("GIT_FORCE_THREADS")) {
-		init_thread();
-		for (i = 0; i < nr_threads; i++) {
-			int ret = pthread_create(&thread_data[i].thread, NULL,
-						 threaded_second_pass, thread_data + i);
-			if (ret)
-				die(_("unable to create thread: %s"),
-				    strerror(ret));
-		}
-		for (i = 0; i < nr_threads; i++)
-			pthread_join(thread_data[i].thread, NULL);
-		cleanup_thread();
-		return;
-	}
-	threaded_second_pass(&nothread_data);
-}
-
-/*
- * Third pass:
- * - append objects to convert thin pack to full pack if required
- * - write the final pack hash
- */
-static void fix_unresolved_deltas(struct hashfile *f);
-static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned char *pack_hash)
-{
-	if (nr_ref_deltas + nr_ofs_deltas == nr_resolved_deltas) {
-		stop_progress(&progress);
-		/* Flush remaining pack final hash. */
-		flush();
-		return;
-	}
-
-	if (fix_thin_pack) {
-		struct hashfile *f;
-		unsigned char read_hash[GIT_MAX_RAWSZ], tail_hash[GIT_MAX_RAWSZ];
-		struct strbuf msg = STRBUF_INIT;
-		int nr_unresolved = nr_ofs_deltas + nr_ref_deltas - nr_resolved_deltas;
-		int nr_objects_initial = nr_objects;
-		if (nr_unresolved <= 0)
-			die(_("confusion beyond insanity"));
-		REALLOC_ARRAY(objects, nr_objects + nr_unresolved + 1);
-		memset(objects + nr_objects + 1, 0,
-		       nr_unresolved * sizeof(*objects));
-		f = hashfd(output_fd, curr_pack);
-		fix_unresolved_deltas(f);
-		strbuf_addf(&msg, Q_("completed with %d local object",
-				     "completed with %d local objects",
-				     nr_objects - nr_objects_initial),
-			    nr_objects - nr_objects_initial);
-		stop_progress_msg(&progress, msg.buf);
-		strbuf_release(&msg);
-		finalize_hashfile(f, tail_hash, 0);
-		hashcpy(read_hash, pack_hash);
-		fixup_pack_header_footer(output_fd, pack_hash,
-					 curr_pack, nr_objects,
-					 read_hash, consumed_bytes-the_hash_algo->rawsz);
-		if (!hasheq(read_hash, tail_hash))
-			die(_("Unexpected tail checksum for %s "
-			      "(disk corruption?)"), curr_pack);
-	}
-	if (nr_ofs_deltas + nr_ref_deltas != nr_resolved_deltas)
-		die(Q_("pack has %d unresolved delta",
-		       "pack has %d unresolved deltas",
-		       nr_ofs_deltas + nr_ref_deltas - nr_resolved_deltas),
-		    nr_ofs_deltas + nr_ref_deltas - nr_resolved_deltas);
-}
-
-static int write_compressed(struct hashfile *f, void *in, unsigned int size)
-{
-	git_zstream stream;
-	int status;
-	unsigned char outbuf[4096];
-
-	git_deflate_init(&stream, zlib_compression_level);
-	stream.next_in = in;
-	stream.avail_in = size;
-
-	do {
-		stream.next_out = outbuf;
-		stream.avail_out = sizeof(outbuf);
-		status = git_deflate(&stream, Z_FINISH);
-		hashwrite(f, outbuf, sizeof(outbuf) - stream.avail_out);
-	} while (status == Z_OK);
-
-	if (status != Z_STREAM_END)
-		die(_("unable to deflate appended object (%d)"), status);
-	size = stream.total_out;
-	git_deflate_end(&stream);
-	return size;
-}
-
-static struct object_entry *append_obj_to_pack(struct hashfile *f,
-			       const unsigned char *sha1, void *buf,
-			       unsigned long size, enum object_type type)
-{
-	struct object_entry *obj = &objects[nr_objects++];
-	unsigned char header[10];
-	unsigned long s = size;
-	int n = 0;
-	unsigned char c = (type << 4) | (s & 15);
-	s >>= 4;
-	while (s) {
-		header[n++] = c | 0x80;
-		c = s & 0x7f;
-		s >>= 7;
-	}
-	header[n++] = c;
-	crc32_begin(f);
-	hashwrite(f, header, n);
-	obj[0].size = size;
-	obj[0].hdr_size = n;
-	obj[0].type = type;
-	obj[0].real_type = type;
-	obj[1].idx.offset = obj[0].idx.offset + n;
-	obj[1].idx.offset += write_compressed(f, buf, size);
-	obj[0].idx.crc32 = crc32_end(f);
-	hashflush(f);
-	hashcpy(obj->idx.oid.hash, sha1);
-	return obj;
-}
-
-static int delta_pos_compare(const void *_a, const void *_b)
-{
-	struct ref_delta_entry *a = *(struct ref_delta_entry **)_a;
-	struct ref_delta_entry *b = *(struct ref_delta_entry **)_b;
-	return a->obj_no - b->obj_no;
-}
-
-static void fix_unresolved_deltas(struct hashfile *f)
-{
-	struct ref_delta_entry **sorted_by_pos;
-	int i;
-
-	/*
-	 * Since many unresolved deltas may well be themselves base objects
-	 * for more unresolved deltas, we really want to include the
-	 * smallest number of base objects that would cover as much delta
-	 * as possible by picking the
-	 * trunc deltas first, allowing for other deltas to resolve without
-	 * additional base objects.  Since most base objects are to be found
-	 * before deltas depending on them, a good heuristic is to start
-	 * resolving deltas in the same order as their position in the pack.
-	 */
-	ALLOC_ARRAY(sorted_by_pos, nr_ref_deltas);
-	for (i = 0; i < nr_ref_deltas; i++)
-		sorted_by_pos[i] = &ref_deltas[i];
-	QSORT(sorted_by_pos, nr_ref_deltas, delta_pos_compare);
-
-	if (has_promisor_remote()) {
-		/*
-		 * Prefetch the delta bases.
-		 */
-		struct oid_array to_fetch = OID_ARRAY_INIT;
-		for (i = 0; i < nr_ref_deltas; i++) {
-			struct ref_delta_entry *d = sorted_by_pos[i];
-			if (!oid_object_info_extended(the_repository, &d->oid,
-						      NULL,
-						      OBJECT_INFO_FOR_PREFETCH))
-				continue;
-			oid_array_append(&to_fetch, &d->oid);
-		}
-		promisor_remote_get_direct(the_repository,
-					   to_fetch.oid, to_fetch.nr);
-		oid_array_clear(&to_fetch);
-	}
-
-	for (i = 0; i < nr_ref_deltas; i++) {
-		struct ref_delta_entry *d = sorted_by_pos[i];
-		enum object_type type;
-		void *data;
-		unsigned long size;
-
-		if (objects[d->obj_no].real_type != OBJ_REF_DELTA)
-			continue;
-		data = read_object_file(&d->oid, &type, &size);
-		if (!data)
-			continue;
-
-		if (check_object_signature(the_repository, &d->oid,
-					   data, size,
-					   type_name(type)))
-			die(_("local object %s is corrupt"), oid_to_hex(&d->oid));
-
-		/*
-		 * Add this as an object to the objects array and call
-		 * threaded_second_pass() (which will pick up the added
-		 * object).
-		 */
-		append_obj_to_pack(f, d->oid.hash, data, size, type);
-		threaded_second_pass(NULL);
-
-		display_progress(progress, nr_resolved_deltas);
-	}
-	free(sorted_by_pos);
-}
-
-static const char *derive_filename(const char *pack_name, const char *suffix,
-				   struct strbuf *buf)
-{
-	size_t len;
-	if (!strip_suffix(pack_name, ".pack", &len))
-		die(_("packfile name '%s' does not end with '.pack'"),
-		    pack_name);
-	strbuf_add(buf, pack_name, len);
-	strbuf_addch(buf, '.');
-	strbuf_addstr(buf, suffix);
-	return buf->buf;
-}
-
-static void write_special_file(const char *suffix, const char *msg,
-			       const char *pack_name, const unsigned char *hash,
-			       const char **report)
-{
-	struct strbuf name_buf = STRBUF_INIT;
-	const char *filename;
-	int fd;
-	int msg_len = strlen(msg);
-
-	if (pack_name)
-		filename = derive_filename(pack_name, suffix, &name_buf);
-	else
-		filename = odb_pack_name(&name_buf, hash, suffix);
-
-	fd = odb_pack_keep(filename);
-	if (fd < 0) {
-		if (errno != EEXIST)
-			die_errno(_("cannot write %s file '%s'"),
-				  suffix, filename);
-	} else {
-		if (msg_len > 0) {
-			write_or_die(fd, msg, msg_len);
-			write_or_die(fd, "\n", 1);
-		}
-		if (close(fd) != 0)
-			die_errno(_("cannot close written %s file '%s'"),
-				  suffix, filename);
-		if (report)
-			*report = suffix;
-	}
-	strbuf_release(&name_buf);
-}
-
-static void final(const char *final_pack_name, const char *curr_pack_name,
-		  const char *final_index_name, const char *curr_index_name,
-		  const char *keep_msg, const char *promisor_msg,
-		  unsigned char *hash)
-{
-	const char *report = "pack";
-	struct strbuf pack_name = STRBUF_INIT;
-	struct strbuf index_name = STRBUF_INIT;
-	int err;
-
-	if (!from_stdin) {
-		close(input_fd);
-	} else {
-		fsync_or_die(output_fd, curr_pack_name);
-		err = close(output_fd);
-		if (err)
-			die_errno(_("error while closing pack file"));
-	}
-
-	if (keep_msg)
-		write_special_file("keep", keep_msg, final_pack_name, hash,
-				   &report);
-	if (promisor_msg)
-		write_special_file("promisor", promisor_msg, final_pack_name,
-				   hash, NULL);
-
-	if (final_pack_name != curr_pack_name) {
-		if (!final_pack_name)
-			final_pack_name = odb_pack_name(&pack_name, hash, "pack");
-		if (finalize_object_file(curr_pack_name, final_pack_name))
-			die(_("cannot store pack file"));
-	} else if (from_stdin)
-		chmod(final_pack_name, 0444);
-
-	if (final_index_name != curr_index_name) {
-		if (!final_index_name)
-			final_index_name = odb_pack_name(&index_name, hash, "idx");
-		if (finalize_object_file(curr_index_name, final_index_name))
-			die(_("cannot store index file"));
-	} else
-		chmod(final_index_name, 0444);
-
-	if (do_fsck_object) {
-		struct packed_git *p;
-		p = add_packed_git(final_index_name, strlen(final_index_name), 0);
-		if (p)
-			install_packed_git(the_repository, p);
-	}
-
-	if (!from_stdin) {
-		printf("%s\n", hash_to_hex(hash));
-	} else {
-		struct strbuf buf = STRBUF_INIT;
-
-		strbuf_addf(&buf, "%s\t%s\n", report, hash_to_hex(hash));
-		write_or_die(1, buf.buf, buf.len);
-		strbuf_release(&buf);
-
-		/*
-		 * Let's just mimic git-unpack-objects here and write
-		 * the last part of the input buffer to stdout.
-		 */
-		while (input_len) {
-			err = xwrite(1, input_buffer + input_offset, input_len);
-			if (err <= 0)
-				break;
-			input_len -= err;
-			input_offset += err;
-		}
-	}
-
-	strbuf_release(&index_name);
-	strbuf_release(&pack_name);
-}
-
-static int git_index_pack_config(const char *k, const char *v, void *cb)
-{
-	struct pack_idx_option *opts = cb;
-
-	if (!strcmp(k, "pack.indexversion")) {
-		opts->version = git_config_int(k, v);
-		if (opts->version > 2)
-			die(_("bad pack.indexversion=%"PRIu32), opts->version);
-		return 0;
-	}
-	if (!strcmp(k, "pack.threads")) {
-		nr_threads = git_config_int(k, v);
-		if (nr_threads < 0)
-			die(_("invalid number of threads specified (%d)"),
-			    nr_threads);
-		if (!HAVE_THREADS && nr_threads != 1) {
-			warning(_("no threads support, ignoring %s"), k);
-			nr_threads = 1;
-		}
-		return 0;
-	}
-	return git_default_config(k, v, cb);
-}
-
-static int cmp_uint32(const void *a_, const void *b_)
-{
-	uint32_t a = *((uint32_t *)a_);
-	uint32_t b = *((uint32_t *)b_);
-
-	return (a < b) ? -1 : (a != b);
-}
-
-static void read_v2_anomalous_offsets(struct packed_git *p,
-				      struct pack_idx_option *opts)
-{
-	const uint32_t *idx1, *idx2;
-	uint32_t i;
-
-	/* The address of the 4-byte offset table */
-	idx1 = (((const uint32_t *)((const uint8_t *)p->index_data + p->crc_offset))
-		+ p->num_objects /* CRC32 table */
-		);
-
-	/* The address of the 8-byte offset table */
-	idx2 = idx1 + p->num_objects;
-
-	for (i = 0; i < p->num_objects; i++) {
-		uint32_t off = ntohl(idx1[i]);
-		if (!(off & 0x80000000))
-			continue;
-		off = off & 0x7fffffff;
-		check_pack_index_ptr(p, &idx2[off * 2]);
-		if (idx2[off * 2])
-			continue;
-		/*
-		 * The real offset is ntohl(idx2[off * 2]) in high 4
-		 * octets, and ntohl(idx2[off * 2 + 1]) in low 4
-		 * octets.  But idx2[off * 2] is Zero!!!
-		 */
-		ALLOC_GROW(opts->anomaly, opts->anomaly_nr + 1, opts->anomaly_alloc);
-		opts->anomaly[opts->anomaly_nr++] = ntohl(idx2[off * 2 + 1]);
-	}
-
-	QSORT(opts->anomaly, opts->anomaly_nr, cmp_uint32);
-}
-
-static void read_idx_option(struct pack_idx_option *opts, const char *pack_name)
-{
-	struct packed_git *p = add_packed_git(pack_name, strlen(pack_name), 1);
-
-	if (!p)
-		die(_("Cannot open existing pack file '%s'"), pack_name);
-	if (open_pack_index(p))
-		die(_("Cannot open existing pack idx file for '%s'"), pack_name);
-
-	/* Read the attributes from the existing idx file */
-	opts->version = p->index_version;
-
-	if (opts->version == 2)
-		read_v2_anomalous_offsets(p, opts);
-
-	/*
-	 * Get rid of the idx file as we do not need it anymore.
-	 * NEEDSWORK: extract this bit from free_pack_by_name() in
-	 * sha1-file.c, perhaps?  It shouldn't matter very much as we
-	 * know we haven't installed this pack (hence we never have
-	 * read anything from it).
-	 */
-	close_pack_index(p);
-	free(p);
-}
-
-static void show_pack_info(int stat_only)
-{
-	int i, baseobjects = nr_objects - nr_ref_deltas - nr_ofs_deltas;
-	unsigned long *chain_histogram = NULL;
-
-	if (deepest_delta)
-		chain_histogram = xcalloc(deepest_delta, sizeof(unsigned long));
-
-	for (i = 0; i < nr_objects; i++) {
-		struct object_entry *obj = &objects[i];
-
-		if (is_delta_type(obj->type))
-			chain_histogram[obj_stat[i].delta_depth - 1]++;
-		if (stat_only)
-			continue;
-		printf("%s %-6s %"PRIuMAX" %"PRIuMAX" %"PRIuMAX,
-		       oid_to_hex(&obj->idx.oid),
-		       type_name(obj->real_type), (uintmax_t)obj->size,
-		       (uintmax_t)(obj[1].idx.offset - obj->idx.offset),
-		       (uintmax_t)obj->idx.offset);
-		if (is_delta_type(obj->type)) {
-			struct object_entry *bobj = &objects[obj_stat[i].base_object_no];
-			printf(" %u %s", obj_stat[i].delta_depth,
-			       oid_to_hex(&bobj->idx.oid));
-		}
-		putchar('\n');
-	}
-
-	if (baseobjects)
-		printf_ln(Q_("non delta: %d object",
-			     "non delta: %d objects",
-			     baseobjects),
-			  baseobjects);
-	for (i = 0; i < deepest_delta; i++) {
-		if (!chain_histogram[i])
-			continue;
-		printf_ln(Q_("chain length = %d: %lu object",
-			     "chain length = %d: %lu objects",
-			     chain_histogram[i]),
-			  i + 1,
-			  chain_histogram[i]);
-	}
-}
-
-int cmd_index_pack(int argc, const char **argv, const char *prefix)
-{
-	int i, fix_thin_pack = 0, verify = 0, stat_only = 0;
-	const char *curr_index;
-	const char *index_name = NULL, *pack_name = NULL;
-	const char *keep_msg = NULL;
-	const char *promisor_msg = NULL;
-	struct strbuf index_name_buf = STRBUF_INIT;
-	struct pack_idx_entry **idx_objects;
-	struct pack_idx_option opts;
-	unsigned char pack_hash[GIT_MAX_RAWSZ];
-	unsigned foreign_nr = 1;	/* zero is a "good" value, assume bad */
-	int report_end_of_input = 0;
-	int hash_algo = 0;
-
-	/*
-	 * index-pack never needs to fetch missing objects except when
-	 * REF_DELTA bases are missing (which are explicitly handled). It only
-	 * accesses the repo to do hash collision checks and to check which
-	 * REF_DELTA bases need to be fetched.
-	 */
-	fetch_if_missing = 0;
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage(index_pack_usage);
-
-	read_replace_refs = 0;
-	fsck_options.walk = mark_link;
-
-	reset_pack_idx_option(&opts);
-	git_config(git_index_pack_config, &opts);
-	if (prefix && chdir(prefix))
-		die(_("Cannot come back to cwd"));
-
-	for (i = 1; i < argc; i++) {
-		const char *arg = argv[i];
-
-		if (*arg == '-') {
-			if (!strcmp(arg, "--stdin")) {
-				from_stdin = 1;
-			} else if (!strcmp(arg, "--fix-thin")) {
-				fix_thin_pack = 1;
-			} else if (skip_to_optional_arg(arg, "--strict", &arg)) {
-				strict = 1;
-				do_fsck_object = 1;
-				fsck_set_msg_types(&fsck_options, arg);
-			} else if (!strcmp(arg, "--check-self-contained-and-connected")) {
-				strict = 1;
-				check_self_contained_and_connected = 1;
-			} else if (!strcmp(arg, "--fsck-objects")) {
-				do_fsck_object = 1;
-			} else if (!strcmp(arg, "--verify")) {
-				verify = 1;
-			} else if (!strcmp(arg, "--verify-stat")) {
-				verify = 1;
-				show_stat = 1;
-			} else if (!strcmp(arg, "--verify-stat-only")) {
-				verify = 1;
-				show_stat = 1;
-				stat_only = 1;
-			} else if (skip_to_optional_arg(arg, "--keep", &keep_msg)) {
-				; /* nothing to do */
-			} else if (skip_to_optional_arg(arg, "--promisor", &promisor_msg)) {
-				; /* already parsed */
-			} else if (starts_with(arg, "--threads=")) {
-				char *end;
-				nr_threads = strtoul(arg+10, &end, 0);
-				if (!arg[10] || *end || nr_threads < 0)
-					usage(index_pack_usage);
-				if (!HAVE_THREADS && nr_threads != 1) {
-					warning(_("no threads support, ignoring %s"), arg);
-					nr_threads = 1;
-				}
-			} else if (starts_with(arg, "--pack_header=")) {
-				struct pack_header *hdr;
-				char *c;
-
-				hdr = (struct pack_header *)input_buffer;
-				hdr->hdr_signature = htonl(PACK_SIGNATURE);
-				hdr->hdr_version = htonl(strtoul(arg + 14, &c, 10));
-				if (*c != ',')
-					die(_("bad %s"), arg);
-				hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10));
-				if (*c)
-					die(_("bad %s"), arg);
-				input_len = sizeof(*hdr);
-			} else if (!strcmp(arg, "-v")) {
-				verbose = 1;
-			} else if (!strcmp(arg, "--show-resolving-progress")) {
-				show_resolving_progress = 1;
-			} else if (!strcmp(arg, "--report-end-of-input")) {
-				report_end_of_input = 1;
-			} else if (!strcmp(arg, "-o")) {
-				if (index_name || (i+1) >= argc)
-					usage(index_pack_usage);
-				index_name = argv[++i];
-			} else if (starts_with(arg, "--index-version=")) {
-				char *c;
-				opts.version = strtoul(arg + 16, &c, 10);
-				if (opts.version > 2)
-					die(_("bad %s"), arg);
-				if (*c == ',')
-					opts.off32_limit = strtoul(c+1, &c, 0);
-				if (*c || opts.off32_limit & 0x80000000)
-					die(_("bad %s"), arg);
-			} else if (skip_prefix(arg, "--max-input-size=", &arg)) {
-				max_input_size = strtoumax(arg, NULL, 10);
-			} else if (skip_prefix(arg, "--object-format=", &arg)) {
-				hash_algo = hash_algo_by_name(arg);
-				if (hash_algo == GIT_HASH_UNKNOWN)
-					die(_("unknown hash algorithm '%s'"), arg);
-				repo_set_hash_algo(the_repository, hash_algo);
-			} else
-				usage(index_pack_usage);
-			continue;
-		}
-
-		if (pack_name)
-			usage(index_pack_usage);
-		pack_name = arg;
-	}
-
-	if (!pack_name && !from_stdin)
-		usage(index_pack_usage);
-	if (fix_thin_pack && !from_stdin)
-		die(_("--fix-thin cannot be used without --stdin"));
-	if (from_stdin && !startup_info->have_repository)
-		die(_("--stdin requires a git repository"));
-	if (from_stdin && hash_algo)
-		die(_("--object-format cannot be used with --stdin"));
-	if (!index_name && pack_name)
-		index_name = derive_filename(pack_name, "idx", &index_name_buf);
-
-	if (verify) {
-		if (!index_name)
-			die(_("--verify with no packfile name given"));
-		read_idx_option(&opts, index_name);
-		opts.flags |= WRITE_IDX_VERIFY | WRITE_IDX_STRICT;
-	}
-	if (strict)
-		opts.flags |= WRITE_IDX_STRICT;
-
-	if (HAVE_THREADS && !nr_threads) {
-		nr_threads = online_cpus();
-		/*
-		 * Experiments show that going above 20 threads doesn't help,
-		 * no matter how many cores you have. Below that, we tend to
-		 * max at half the number of online_cpus(), presumably because
-		 * half of those are hyperthreads rather than full cores. We'll
-		 * never reduce the level below "3", though, to match a
-		 * historical value that nobody complained about.
-		 */
-		if (nr_threads < 4)
-			; /* too few cores to consider capping */
-		else if (nr_threads < 6)
-			nr_threads = 3; /* historic cap */
-		else if (nr_threads < 40)
-			nr_threads /= 2;
-		else
-			nr_threads = 20; /* hard cap */
-	}
-
-	curr_pack = open_pack_file(pack_name);
-	parse_pack_header();
-	objects = xcalloc(st_add(nr_objects, 1), sizeof(struct object_entry));
-	if (show_stat)
-		obj_stat = xcalloc(st_add(nr_objects, 1), sizeof(struct object_stat));
-	ofs_deltas = xcalloc(nr_objects, sizeof(struct ofs_delta_entry));
-	parse_pack_objects(pack_hash);
-	if (report_end_of_input)
-		write_in_full(2, "\0", 1);
-	resolve_deltas();
-	conclude_pack(fix_thin_pack, curr_pack, pack_hash);
-	free(ofs_deltas);
-	free(ref_deltas);
-	if (strict)
-		foreign_nr = check_objects();
-
-	if (show_stat)
-		show_pack_info(stat_only);
-
-	ALLOC_ARRAY(idx_objects, nr_objects);
-	for (i = 0; i < nr_objects; i++)
-		idx_objects[i] = &objects[i].idx;
-	curr_index = write_idx_file(index_name, idx_objects, nr_objects, &opts, pack_hash);
-	free(idx_objects);
-
-	if (!verify)
-		final(pack_name, curr_pack,
-		      index_name, curr_index,
-		      keep_msg, promisor_msg,
-		      pack_hash);
-	else
-		close(input_fd);
-
-	if (do_fsck_object && fsck_finish(&fsck_options))
-		die(_("fsck error in pack objects"));
-
-	free(objects);
-	strbuf_release(&index_name_buf);
-	if (pack_name == NULL)
-		free((void *) curr_pack);
-	if (index_name == NULL)
-		free((void *) curr_index);
-
-	/*
-	 * Let the caller know this pack is not self contained
-	 */
-	if (check_self_contained_and_connected && foreign_nr)
-		return 1;
-
-	return 0;
-}
diff --git a/third_party/git/builtin/init-db.c b/third_party/git/builtin/init-db.c
deleted file mode 100644
index 01bc648d416f..000000000000
--- a/third_party/git/builtin/init-db.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * GIT - The information manager from hell
- *
- * Copyright (C) Linus Torvalds, 2005
- */
-#include "cache.h"
-#include "config.h"
-#include "refs.h"
-#include "builtin.h"
-#include "exec-cmd.h"
-#include "parse-options.h"
-#include "worktree.h"
-
-#ifndef DEFAULT_GIT_TEMPLATE_DIR
-#define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates"
-#endif
-
-#ifdef NO_TRUSTABLE_FILEMODE
-#define TEST_FILEMODE 0
-#else
-#define TEST_FILEMODE 1
-#endif
-
-#define GIT_DEFAULT_HASH_ENVIRONMENT "GIT_DEFAULT_HASH"
-
-static int init_is_bare_repository = 0;
-static int init_shared_repository = -1;
-static const char *init_db_template_dir;
-
-static void copy_templates_1(struct strbuf *path, struct strbuf *template_path,
-			     DIR *dir)
-{
-	size_t path_baselen = path->len;
-	size_t template_baselen = template_path->len;
-	struct dirent *de;
-
-	/* Note: if ".git/hooks" file exists in the repository being
-	 * re-initialized, /etc/core-git/templates/hooks/update would
-	 * cause "git init" to fail here.  I think this is sane but
-	 * it means that the set of templates we ship by default, along
-	 * with the way the namespace under .git/ is organized, should
-	 * be really carefully chosen.
-	 */
-	safe_create_dir(path->buf, 1);
-	while ((de = readdir(dir)) != NULL) {
-		struct stat st_git, st_template;
-		int exists = 0;
-
-		strbuf_setlen(path, path_baselen);
-		strbuf_setlen(template_path, template_baselen);
-
-		if (de->d_name[0] == '.')
-			continue;
-		strbuf_addstr(path, de->d_name);
-		strbuf_addstr(template_path, de->d_name);
-		if (lstat(path->buf, &st_git)) {
-			if (errno != ENOENT)
-				die_errno(_("cannot stat '%s'"), path->buf);
-		}
-		else
-			exists = 1;
-
-		if (lstat(template_path->buf, &st_template))
-			die_errno(_("cannot stat template '%s'"), template_path->buf);
-
-		if (S_ISDIR(st_template.st_mode)) {
-			DIR *subdir = opendir(template_path->buf);
-			if (!subdir)
-				die_errno(_("cannot opendir '%s'"), template_path->buf);
-			strbuf_addch(path, '/');
-			strbuf_addch(template_path, '/');
-			copy_templates_1(path, template_path, subdir);
-			closedir(subdir);
-		}
-		else if (exists)
-			continue;
-		else if (S_ISLNK(st_template.st_mode)) {
-			struct strbuf lnk = STRBUF_INIT;
-			if (strbuf_readlink(&lnk, template_path->buf,
-					    st_template.st_size) < 0)
-				die_errno(_("cannot readlink '%s'"), template_path->buf);
-			if (symlink(lnk.buf, path->buf))
-				die_errno(_("cannot symlink '%s' '%s'"),
-					  lnk.buf, path->buf);
-			strbuf_release(&lnk);
-		}
-		else if (S_ISREG(st_template.st_mode)) {
-			if (copy_file(path->buf, template_path->buf, st_template.st_mode))
-				die_errno(_("cannot copy '%s' to '%s'"),
-					  template_path->buf, path->buf);
-		}
-		else
-			error(_("ignoring template %s"), template_path->buf);
-	}
-}
-
-static void copy_templates(const char *template_dir)
-{
-	struct strbuf path = STRBUF_INIT;
-	struct strbuf template_path = STRBUF_INIT;
-	size_t template_len;
-	struct repository_format template_format = REPOSITORY_FORMAT_INIT;
-	struct strbuf err = STRBUF_INIT;
-	DIR *dir;
-	char *to_free = NULL;
-
-	if (!template_dir)
-		template_dir = getenv(TEMPLATE_DIR_ENVIRONMENT);
-	if (!template_dir)
-		template_dir = init_db_template_dir;
-	if (!template_dir)
-		template_dir = to_free = system_path(DEFAULT_GIT_TEMPLATE_DIR);
-	if (!template_dir[0]) {
-		free(to_free);
-		return;
-	}
-
-	strbuf_addstr(&template_path, template_dir);
-	strbuf_complete(&template_path, '/');
-	template_len = template_path.len;
-
-	dir = opendir(template_path.buf);
-	if (!dir) {
-		warning(_("templates not found in %s"), template_dir);
-		goto free_return;
-	}
-
-	/* Make sure that template is from the correct vintage */
-	strbuf_addstr(&template_path, "config");
-	read_repository_format(&template_format, template_path.buf);
-	strbuf_setlen(&template_path, template_len);
-
-	/*
-	 * No mention of version at all is OK, but anything else should be
-	 * verified.
-	 */
-	if (template_format.version >= 0 &&
-	    verify_repository_format(&template_format, &err) < 0) {
-		warning(_("not copying templates from '%s': %s"),
-			  template_dir, err.buf);
-		strbuf_release(&err);
-		goto close_free_return;
-	}
-
-	strbuf_addstr(&path, get_git_common_dir());
-	strbuf_complete(&path, '/');
-	copy_templates_1(&path, &template_path, dir);
-close_free_return:
-	closedir(dir);
-free_return:
-	free(to_free);
-	strbuf_release(&path);
-	strbuf_release(&template_path);
-	clear_repository_format(&template_format);
-}
-
-static int git_init_db_config(const char *k, const char *v, void *cb)
-{
-	if (!strcmp(k, "init.templatedir"))
-		return git_config_pathname(&init_db_template_dir, k, v);
-
-	if (starts_with(k, "core."))
-		return platform_core_config(k, v, cb);
-
-	return 0;
-}
-
-/*
- * If the git_dir is not directly inside the working tree, then git will not
- * find it by default, and we need to set the worktree explicitly.
- */
-static int needs_work_tree_config(const char *git_dir, const char *work_tree)
-{
-	if (!strcmp(work_tree, "/") && !strcmp(git_dir, "/.git"))
-		return 0;
-	if (skip_prefix(git_dir, work_tree, &git_dir) &&
-	    !strcmp(git_dir, "/.git"))
-		return 0;
-	return 1;
-}
-
-void initialize_repository_version(int hash_algo, int reinit)
-{
-	char repo_version_string[10];
-	int repo_version = GIT_REPO_VERSION;
-
-	if (hash_algo != GIT_HASH_SHA1)
-		repo_version = GIT_REPO_VERSION_READ;
-
-	/* This forces creation of new config file */
-	xsnprintf(repo_version_string, sizeof(repo_version_string),
-		  "%d", repo_version);
-	git_config_set("core.repositoryformatversion", repo_version_string);
-
-	if (hash_algo != GIT_HASH_SHA1)
-		git_config_set("extensions.objectformat",
-			       hash_algos[hash_algo].name);
-	else if (reinit)
-		git_config_set_gently("extensions.objectformat", NULL);
-}
-
-static int create_default_files(const char *template_path,
-				const char *original_git_dir,
-				const char *initial_branch,
-				const struct repository_format *fmt)
-{
-	struct stat st1;
-	struct strbuf buf = STRBUF_INIT;
-	char *path;
-	char junk[2];
-	int reinit;
-	int filemode;
-	struct strbuf err = STRBUF_INIT;
-
-	/* Just look for `init.templatedir` */
-	init_db_template_dir = NULL; /* re-set in case it was set before */
-	git_config(git_init_db_config, NULL);
-
-	/*
-	 * First copy the templates -- we might have the default
-	 * config file there, in which case we would want to read
-	 * from it after installing.
-	 *
-	 * Before reading that config, we also need to clear out any cached
-	 * values (since we've just potentially changed what's available on
-	 * disk).
-	 */
-	copy_templates(template_path);
-	git_config_clear();
-	reset_shared_repository();
-	git_config(git_default_config, NULL);
-
-	/*
-	 * We must make sure command-line options continue to override any
-	 * values we might have just re-read from the config.
-	 */
-	is_bare_repository_cfg = init_is_bare_repository;
-	if (init_shared_repository != -1)
-		set_shared_repository(init_shared_repository);
-
-	/*
-	 * We would have created the above under user's umask -- under
-	 * shared-repository settings, we would need to fix them up.
-	 */
-	if (get_shared_repository()) {
-		adjust_shared_perm(get_git_dir());
-	}
-
-	/*
-	 * We need to create a "refs" dir in any case so that older
-	 * versions of git can tell that this is a repository.
-	 */
-	safe_create_dir(git_path("refs"), 1);
-	adjust_shared_perm(git_path("refs"));
-
-	if (refs_init_db(&err))
-		die("failed to set up refs db: %s", err.buf);
-
-	/*
-	 * Point the HEAD symref to the initial branch with if HEAD does
-	 * not yet exist.
-	 */
-	path = git_path_buf(&buf, "HEAD");
-	reinit = (!access(path, R_OK)
-		  || readlink(path, junk, sizeof(junk)-1) != -1);
-	if (!reinit) {
-		char *ref;
-
-		if (!initial_branch)
-			initial_branch = git_default_branch_name();
-
-		ref = xstrfmt("refs/heads/%s", initial_branch);
-		if (check_refname_format(ref, 0) < 0)
-			die(_("invalid initial branch name: '%s'"),
-			    initial_branch);
-
-		if (create_symref("HEAD", ref, NULL) < 0)
-			exit(1);
-		free(ref);
-	}
-
-	initialize_repository_version(fmt->hash_algo, 0);
-
-	/* Check filemode trustability */
-	path = git_path_buf(&buf, "config");
-	filemode = TEST_FILEMODE;
-	if (TEST_FILEMODE && !lstat(path, &st1)) {
-		struct stat st2;
-		filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) &&
-				!lstat(path, &st2) &&
-				st1.st_mode != st2.st_mode &&
-				!chmod(path, st1.st_mode));
-		if (filemode && !reinit && (st1.st_mode & S_IXUSR))
-			filemode = 0;
-	}
-	git_config_set("core.filemode", filemode ? "true" : "false");
-
-	if (is_bare_repository())
-		git_config_set("core.bare", "true");
-	else {
-		const char *work_tree = get_git_work_tree();
-		git_config_set("core.bare", "false");
-		/* allow template config file to override the default */
-		if (log_all_ref_updates == LOG_REFS_UNSET)
-			git_config_set("core.logallrefupdates", "true");
-		if (needs_work_tree_config(original_git_dir, work_tree))
-			git_config_set("core.worktree", work_tree);
-	}
-
-	if (!reinit) {
-		/* Check if symlink is supported in the work tree */
-		path = git_path_buf(&buf, "tXXXXXX");
-		if (!close(xmkstemp(path)) &&
-		    !unlink(path) &&
-		    !symlink("testing", path) &&
-		    !lstat(path, &st1) &&
-		    S_ISLNK(st1.st_mode))
-			unlink(path); /* good */
-		else
-			git_config_set("core.symlinks", "false");
-
-		/* Check if the filesystem is case-insensitive */
-		path = git_path_buf(&buf, "CoNfIg");
-		if (!access(path, F_OK))
-			git_config_set("core.ignorecase", "true");
-		probe_utf8_pathname_composition();
-	}
-
-	strbuf_release(&buf);
-	return reinit;
-}
-
-static void create_object_directory(void)
-{
-	struct strbuf path = STRBUF_INIT;
-	size_t baselen;
-
-	strbuf_addstr(&path, get_object_directory());
-	baselen = path.len;
-
-	safe_create_dir(path.buf, 1);
-
-	strbuf_setlen(&path, baselen);
-	strbuf_addstr(&path, "/pack");
-	safe_create_dir(path.buf, 1);
-
-	strbuf_setlen(&path, baselen);
-	strbuf_addstr(&path, "/info");
-	safe_create_dir(path.buf, 1);
-
-	strbuf_release(&path);
-}
-
-static void separate_git_dir(const char *git_dir, const char *git_link)
-{
-	struct stat st;
-
-	if (!stat(git_link, &st)) {
-		const char *src;
-
-		if (S_ISREG(st.st_mode))
-			src = read_gitfile(git_link);
-		else if (S_ISDIR(st.st_mode))
-			src = git_link;
-		else
-			die(_("unable to handle file type %d"), (int)st.st_mode);
-
-		if (rename(src, git_dir))
-			die_errno(_("unable to move %s to %s"), src, git_dir);
-		repair_worktrees(NULL, NULL);
-	}
-
-	write_file(git_link, "gitdir: %s", git_dir);
-}
-
-static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash)
-{
-	const char *env = getenv(GIT_DEFAULT_HASH_ENVIRONMENT);
-	/*
-	 * If we already have an initialized repo, don't allow the user to
-	 * specify a different algorithm, as that could cause corruption.
-	 * Otherwise, if the user has specified one on the command line, use it.
-	 */
-	if (repo_fmt->version >= 0 && hash != GIT_HASH_UNKNOWN && hash != repo_fmt->hash_algo)
-		die(_("attempt to reinitialize repository with different hash"));
-	else if (hash != GIT_HASH_UNKNOWN)
-		repo_fmt->hash_algo = hash;
-	else if (env) {
-		int env_algo = hash_algo_by_name(env);
-		if (env_algo == GIT_HASH_UNKNOWN)
-			die(_("unknown hash algorithm '%s'"), env);
-		repo_fmt->hash_algo = env_algo;
-	}
-}
-
-int init_db(const char *git_dir, const char *real_git_dir,
-	    const char *template_dir, int hash, const char *initial_branch,
-	    unsigned int flags)
-{
-	int reinit;
-	int exist_ok = flags & INIT_DB_EXIST_OK;
-	char *original_git_dir = real_pathdup(git_dir, 1);
-	struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
-
-	if (real_git_dir) {
-		struct stat st;
-
-		if (!exist_ok && !stat(git_dir, &st))
-			die(_("%s already exists"), git_dir);
-
-		if (!exist_ok && !stat(real_git_dir, &st))
-			die(_("%s already exists"), real_git_dir);
-
-		set_git_dir(real_git_dir, 1);
-		git_dir = get_git_dir();
-		separate_git_dir(git_dir, original_git_dir);
-	}
-	else {
-		set_git_dir(git_dir, 1);
-		git_dir = get_git_dir();
-	}
-	startup_info->have_repository = 1;
-
-	/* Just look for `core.hidedotfiles` */
-	git_config(git_init_db_config, NULL);
-
-	safe_create_dir(git_dir, 0);
-
-	init_is_bare_repository = is_bare_repository();
-
-	/* Check to see if the repository version is right.
-	 * Note that a newly created repository does not have
-	 * config file, so this will not fail.  What we are catching
-	 * is an attempt to reinitialize new repository with an old tool.
-	 */
-	check_repository_format(&repo_fmt);
-
-	validate_hash_algorithm(&repo_fmt, hash);
-
-	reinit = create_default_files(template_dir, original_git_dir,
-				      initial_branch, &repo_fmt);
-	if (reinit && initial_branch)
-		warning(_("re-init: ignored --initial-branch=%s"),
-			initial_branch);
-
-	create_object_directory();
-
-	if (get_shared_repository()) {
-		char buf[10];
-		/* We do not spell "group" and such, so that
-		 * the configuration can be read by older version
-		 * of git. Note, we use octal numbers for new share modes,
-		 * and compatibility values for PERM_GROUP and
-		 * PERM_EVERYBODY.
-		 */
-		if (get_shared_repository() < 0)
-			/* force to the mode value */
-			xsnprintf(buf, sizeof(buf), "0%o", -get_shared_repository());
-		else if (get_shared_repository() == PERM_GROUP)
-			xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_GROUP);
-		else if (get_shared_repository() == PERM_EVERYBODY)
-			xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_EVERYBODY);
-		else
-			BUG("invalid value for shared_repository");
-		git_config_set("core.sharedrepository", buf);
-		git_config_set("receive.denyNonFastforwards", "true");
-	}
-
-	if (!(flags & INIT_DB_QUIET)) {
-		int len = strlen(git_dir);
-
-		if (reinit)
-			printf(get_shared_repository()
-			       ? _("Reinitialized existing shared Git repository in %s%s\n")
-			       : _("Reinitialized existing Git repository in %s%s\n"),
-			       git_dir, len && git_dir[len-1] != '/' ? "/" : "");
-		else
-			printf(get_shared_repository()
-			       ? _("Initialized empty shared Git repository in %s%s\n")
-			       : _("Initialized empty Git repository in %s%s\n"),
-			       git_dir, len && git_dir[len-1] != '/' ? "/" : "");
-	}
-
-	free(original_git_dir);
-	return 0;
-}
-
-static int guess_repository_type(const char *git_dir)
-{
-	const char *slash;
-	char *cwd;
-	int cwd_is_git_dir;
-
-	/*
-	 * "GIT_DIR=. git init" is always bare.
-	 * "GIT_DIR=`pwd` git init" too.
-	 */
-	if (!strcmp(".", git_dir))
-		return 1;
-	cwd = xgetcwd();
-	cwd_is_git_dir = !strcmp(git_dir, cwd);
-	free(cwd);
-	if (cwd_is_git_dir)
-		return 1;
-	/*
-	 * "GIT_DIR=.git or GIT_DIR=something/.git is usually not.
-	 */
-	if (!strcmp(git_dir, ".git"))
-		return 0;
-	slash = strrchr(git_dir, '/');
-	if (slash && !strcmp(slash, "/.git"))
-		return 0;
-
-	/*
-	 * Otherwise it is often bare.  At this point
-	 * we are just guessing.
-	 */
-	return 1;
-}
-
-static int shared_callback(const struct option *opt, const char *arg, int unset)
-{
-	BUG_ON_OPT_NEG(unset);
-	*((int *) opt->value) = (arg) ? git_config_perm("arg", arg) : PERM_GROUP;
-	return 0;
-}
-
-static const char *const init_db_usage[] = {
-	N_("git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]] [<directory>]"),
-	NULL
-};
-
-/*
- * If you want to, you can share the DB area with any number of branches.
- * That has advantages: you can save space by sharing all the SHA1 objects.
- * On the other hand, it might just make lookup slower and messier. You
- * be the judge.  The default case is to have one DB per managed directory.
- */
-int cmd_init_db(int argc, const char **argv, const char *prefix)
-{
-	const char *git_dir;
-	const char *real_git_dir = NULL;
-	const char *work_tree;
-	const char *template_dir = NULL;
-	unsigned int flags = 0;
-	const char *object_format = NULL;
-	const char *initial_branch = NULL;
-	int hash_algo = GIT_HASH_UNKNOWN;
-	const struct option init_db_options[] = {
-		OPT_STRING(0, "template", &template_dir, N_("template-directory"),
-				N_("directory from which templates will be used")),
-		OPT_SET_INT(0, "bare", &is_bare_repository_cfg,
-				N_("create a bare repository"), 1),
-		{ OPTION_CALLBACK, 0, "shared", &init_shared_repository,
-			N_("permissions"),
-			N_("specify that the git repository is to be shared amongst several users"),
-			PARSE_OPT_OPTARG | PARSE_OPT_NONEG, shared_callback, 0},
-		OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
-		OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
-			   N_("separate git dir from working tree")),
-		OPT_STRING('b', "initial-branch", &initial_branch, N_("name"),
-			   N_("override the name of the initial branch")),
-		OPT_STRING(0, "object-format", &object_format, N_("hash"),
-			   N_("specify the hash algorithm to use")),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
-
-	if (real_git_dir && is_bare_repository_cfg == 1)
-		die(_("--separate-git-dir and --bare are mutually exclusive"));
-
-	if (real_git_dir && !is_absolute_path(real_git_dir))
-		real_git_dir = real_pathdup(real_git_dir, 1);
-
-	if (template_dir && *template_dir && !is_absolute_path(template_dir))
-		template_dir = absolute_pathdup(template_dir);
-
-	if (argc == 1) {
-		int mkdir_tried = 0;
-	retry:
-		if (chdir(argv[0]) < 0) {
-			if (!mkdir_tried) {
-				int saved;
-				/*
-				 * At this point we haven't read any configuration,
-				 * and we know shared_repository should always be 0;
-				 * but just in case we play safe.
-				 */
-				saved = get_shared_repository();
-				set_shared_repository(0);
-				switch (safe_create_leading_directories_const(argv[0])) {
-				case SCLD_OK:
-				case SCLD_PERMS:
-					break;
-				case SCLD_EXISTS:
-					errno = EEXIST;
-					/* fallthru */
-				default:
-					die_errno(_("cannot mkdir %s"), argv[0]);
-					break;
-				}
-				set_shared_repository(saved);
-				if (mkdir(argv[0], 0777) < 0)
-					die_errno(_("cannot mkdir %s"), argv[0]);
-				mkdir_tried = 1;
-				goto retry;
-			}
-			die_errno(_("cannot chdir to %s"), argv[0]);
-		}
-	} else if (0 < argc) {
-		usage(init_db_usage[0]);
-	}
-	if (is_bare_repository_cfg == 1) {
-		char *cwd = xgetcwd();
-		setenv(GIT_DIR_ENVIRONMENT, cwd, argc > 0);
-		free(cwd);
-	}
-
-	if (object_format) {
-		hash_algo = hash_algo_by_name(object_format);
-		if (hash_algo == GIT_HASH_UNKNOWN)
-			die(_("unknown hash algorithm '%s'"), object_format);
-	}
-
-	if (init_shared_repository != -1)
-		set_shared_repository(init_shared_repository);
-
-	/*
-	 * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR
-	 * without --bare.  Catch the error early.
-	 */
-	git_dir = xstrdup_or_null(getenv(GIT_DIR_ENVIRONMENT));
-	work_tree = xstrdup_or_null(getenv(GIT_WORK_TREE_ENVIRONMENT));
-	if ((!git_dir || is_bare_repository_cfg == 1) && work_tree)
-		die(_("%s (or --work-tree=<directory>) not allowed without "
-			  "specifying %s (or --git-dir=<directory>)"),
-		    GIT_WORK_TREE_ENVIRONMENT,
-		    GIT_DIR_ENVIRONMENT);
-
-	/*
-	 * Set up the default .git directory contents
-	 */
-	if (!git_dir)
-		git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;
-
-	/*
-	 * When --separate-git-dir is used inside a linked worktree, take
-	 * care to ensure that the common .git/ directory is relocated, not
-	 * the worktree-specific .git/worktrees/<id>/ directory.
-	 */
-	if (real_git_dir) {
-		int err;
-		const char *p;
-		struct strbuf sb = STRBUF_INIT;
-
-		p = read_gitfile_gently(git_dir, &err);
-		if (p && get_common_dir(&sb, p)) {
-			struct strbuf mainwt = STRBUF_INIT;
-
-			strbuf_addbuf(&mainwt, &sb);
-			strbuf_strip_suffix(&mainwt, "/.git");
-			if (chdir(mainwt.buf) < 0)
-				die_errno(_("cannot chdir to %s"), mainwt.buf);
-			strbuf_release(&mainwt);
-			git_dir = strbuf_detach(&sb, NULL);
-		}
-		strbuf_release(&sb);
-	}
-
-	if (is_bare_repository_cfg < 0)
-		is_bare_repository_cfg = guess_repository_type(git_dir);
-
-	if (!is_bare_repository_cfg) {
-		const char *git_dir_parent = strrchr(git_dir, '/');
-		if (git_dir_parent) {
-			char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
-			git_work_tree_cfg = real_pathdup(rel, 1);
-			free(rel);
-		}
-		if (!git_work_tree_cfg)
-			git_work_tree_cfg = xgetcwd();
-		if (work_tree)
-			set_git_work_tree(work_tree);
-		else
-			set_git_work_tree(git_work_tree_cfg);
-		if (access(get_git_work_tree(), X_OK))
-			die_errno (_("Cannot access work tree '%s'"),
-				   get_git_work_tree());
-	}
-	else {
-		if (real_git_dir)
-			die(_("--separate-git-dir incompatible with bare repository"));
-		if (work_tree)
-			set_git_work_tree(work_tree);
-	}
-
-	UNLEAK(real_git_dir);
-	UNLEAK(git_dir);
-	UNLEAK(work_tree);
-
-	flags |= INIT_DB_EXIST_OK;
-	return init_db(git_dir, real_git_dir, template_dir, hash_algo,
-		       initial_branch, flags);
-}
diff --git a/third_party/git/builtin/interpret-trailers.c b/third_party/git/builtin/interpret-trailers.c
deleted file mode 100644
index 84748eafc01b..000000000000
--- a/third_party/git/builtin/interpret-trailers.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Builtin "git interpret-trailers"
- *
- * Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org>
- *
- */
-
-#include "cache.h"
-#include "builtin.h"
-#include "parse-options.h"
-#include "string-list.h"
-#include "trailer.h"
-#include "config.h"
-
-static const char * const git_interpret_trailers_usage[] = {
-	N_("git interpret-trailers [--in-place] [--trim-empty] [(--trailer <token>[(=|:)<value>])...] [<file>...]"),
-	NULL
-};
-
-static enum trailer_where where;
-static enum trailer_if_exists if_exists;
-static enum trailer_if_missing if_missing;
-
-static int option_parse_where(const struct option *opt,
-			      const char *arg, int unset)
-{
-	return trailer_set_where(&where, arg);
-}
-
-static int option_parse_if_exists(const struct option *opt,
-				  const char *arg, int unset)
-{
-	return trailer_set_if_exists(&if_exists, arg);
-}
-
-static int option_parse_if_missing(const struct option *opt,
-				   const char *arg, int unset)
-{
-	return trailer_set_if_missing(&if_missing, arg);
-}
-
-static void new_trailers_clear(struct list_head *trailers)
-{
-	struct list_head *pos, *tmp;
-	struct new_trailer_item *item;
-
-	list_for_each_safe(pos, tmp, trailers) {
-		item = list_entry(pos, struct new_trailer_item, list);
-		list_del(pos);
-		free(item);
-	}
-}
-
-static int option_parse_trailer(const struct option *opt,
-				   const char *arg, int unset)
-{
-	struct list_head *trailers = opt->value;
-	struct new_trailer_item *item;
-
-	if (unset) {
-		new_trailers_clear(trailers);
-		return 0;
-	}
-
-	if (!arg)
-		return -1;
-
-	item = xmalloc(sizeof(*item));
-	item->text = arg;
-	item->where = where;
-	item->if_exists = if_exists;
-	item->if_missing = if_missing;
-	list_add_tail(&item->list, trailers);
-	return 0;
-}
-
-static int parse_opt_parse(const struct option *opt, const char *arg,
-			   int unset)
-{
-	struct process_trailer_options *v = opt->value;
-	v->only_trailers = 1;
-	v->only_input = 1;
-	v->unfold = 1;
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-	return 0;
-}
-
-int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
-{
-	struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
-	LIST_HEAD(trailers);
-
-	struct option options[] = {
-		OPT_BOOL(0, "in-place", &opts.in_place, N_("edit files in place")),
-		OPT_BOOL(0, "trim-empty", &opts.trim_empty, N_("trim empty trailers")),
-
-		OPT_CALLBACK(0, "where", NULL, N_("action"),
-			     N_("where to place the new trailer"), option_parse_where),
-		OPT_CALLBACK(0, "if-exists", NULL, N_("action"),
-			     N_("action if trailer already exists"), option_parse_if_exists),
-		OPT_CALLBACK(0, "if-missing", NULL, N_("action"),
-			     N_("action if trailer is missing"), option_parse_if_missing),
-
-		OPT_BOOL(0, "only-trailers", &opts.only_trailers, N_("output only the trailers")),
-		OPT_BOOL(0, "only-input", &opts.only_input, N_("do not apply config rules")),
-		OPT_BOOL(0, "unfold", &opts.unfold, N_("join whitespace-continued values")),
-		OPT_CALLBACK_F(0, "parse", &opts, NULL, N_("set parsing options"),
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG, parse_opt_parse),
-		OPT_BOOL(0, "no-divider", &opts.no_divider, N_("do not treat --- specially")),
-		OPT_CALLBACK(0, "trailer", &trailers, N_("trailer"),
-				N_("trailer(s) to add"), option_parse_trailer),
-		OPT_END()
-	};
-
-	git_config(git_default_config, NULL);
-
-	argc = parse_options(argc, argv, prefix, options,
-			     git_interpret_trailers_usage, 0);
-
-	if (opts.only_input && !list_empty(&trailers))
-		usage_msg_opt(
-			_("--trailer with --only-input does not make sense"),
-			git_interpret_trailers_usage,
-			options);
-
-	if (argc) {
-		int i;
-		for (i = 0; i < argc; i++)
-			process_trailers(argv[i], &opts, &trailers);
-	} else {
-		if (opts.in_place)
-			die(_("no input file given for in-place editing"));
-		process_trailers(NULL, &opts, &trailers);
-	}
-
-	new_trailers_clear(&trailers);
-
-	return 0;
-}
diff --git a/third_party/git/builtin/log.c b/third_party/git/builtin/log.c
deleted file mode 100644
index 0a7ed4bef92b..000000000000
--- a/third_party/git/builtin/log.c
+++ /dev/null
@@ -1,2336 +0,0 @@
-/*
- * Builtin "git log" and related commands (show, whatchanged)
- *
- * (C) Copyright 2006 Linus Torvalds
- *		 2006 Junio Hamano
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "config.h"
-#include "refs.h"
-#include "object-store.h"
-#include "color.h"
-#include "commit.h"
-#include "diff.h"
-#include "revision.h"
-#include "log-tree.h"
-#include "builtin.h"
-#include "tag.h"
-#include "reflog-walk.h"
-#include "patch-ids.h"
-#include "run-command.h"
-#include "shortlog.h"
-#include "remote.h"
-#include "string-list.h"
-#include "parse-options.h"
-#include "line-log.h"
-#include "branch.h"
-#include "streaming.h"
-#include "version.h"
-#include "mailmap.h"
-#include "gpg-interface.h"
-#include "progress.h"
-#include "commit-slab.h"
-#include "repository.h"
-#include "commit-reach.h"
-#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;
-
-static int default_abbrev_commit;
-static int default_show_root = 1;
-static int default_follow;
-static int default_show_signature;
-static int default_encode_email_headers = 1;
-static int decoration_style;
-static int decoration_given;
-static int use_mailmap_config = 1;
-static const char *fmt_patch_subject_prefix = "PATCH";
-static const char *fmt_pretty;
-
-static const char * const builtin_log_usage[] = {
-	N_("git log [<options>] [<revision-range>] [[--] <path>...]"),
-	N_("git show [<options>] <object>..."),
-	NULL
-};
-
-struct line_opt_callback_data {
-	struct rev_info *rev;
-	const char *prefix;
-	struct string_list args;
-};
-
-static int session_is_interactive(void)
-{
-	return isatty(1) || pager_in_use();
-}
-
-static int auto_decoration_style(void)
-{
-	return session_is_interactive() ? DECORATE_SHORT_REFS : 0;
-}
-
-static int parse_decoration_style(const char *value)
-{
-	switch (git_parse_maybe_bool(value)) {
-	case 1:
-		return DECORATE_SHORT_REFS;
-	case 0:
-		return 0;
-	default:
-		break;
-	}
-	if (!strcmp(value, "full"))
-		return DECORATE_FULL_REFS;
-	else if (!strcmp(value, "short"))
-		return DECORATE_SHORT_REFS;
-	else if (!strcmp(value, "auto"))
-		return auto_decoration_style();
-	/*
-	 * Please update _git_log() in git-completion.bash when you
-	 * add new decoration styles.
-	 */
-	return -1;
-}
-
-static int decorate_callback(const struct option *opt, const char *arg, int unset)
-{
-	if (unset)
-		decoration_style = 0;
-	else if (arg)
-		decoration_style = parse_decoration_style(arg);
-	else
-		decoration_style = DECORATE_SHORT_REFS;
-
-	if (decoration_style < 0)
-		die(_("invalid --decorate option: %s"), arg);
-
-	decoration_given = 1;
-
-	return 0;
-}
-
-static int log_line_range_callback(const struct option *option, const char *arg, int unset)
-{
-	struct line_opt_callback_data *data = option->value;
-
-	BUG_ON_OPT_NEG(unset);
-
-	if (!arg)
-		return -1;
-
-	data->rev->line_level_traverse = 1;
-	string_list_append(&data->args, arg);
-
-	return 0;
-}
-
-static void init_log_defaults(void)
-{
-	init_grep_defaults(the_repository);
-	init_diff_ui_defaults();
-
-	decoration_style = auto_decoration_style();
-}
-
-static void cmd_log_init_defaults(struct rev_info *rev)
-{
-	if (fmt_pretty)
-		get_commit_format(fmt_pretty, rev);
-	if (default_follow)
-		rev->diffopt.flags.default_follow_renames = 1;
-	rev->verbose_header = 1;
-	rev->diffopt.flags.recursive = 1;
-	rev->diffopt.stat_width = -1; /* use full terminal width */
-	rev->diffopt.stat_graph_width = -1; /* respect statGraphWidth config */
-	rev->abbrev_commit = default_abbrev_commit;
-	rev->show_root_diff = default_show_root;
-	rev->subject_prefix = fmt_patch_subject_prefix;
-	rev->show_signature = default_show_signature;
-	rev->encode_email_headers = default_encode_email_headers;
-	rev->diffopt.flags.allow_textconv = 1;
-
-	if (default_date_mode)
-		parse_date_format(default_date_mode, &rev->date_mode);
-}
-
-static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
-			 struct rev_info *rev, struct setup_revision_opt *opt)
-{
-	struct userformat_want w;
-	int quiet = 0, source = 0, mailmap;
-	static struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};
-	static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;
-	static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;
-	static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;
-	struct decoration_filter decoration_filter = {&decorate_refs_include,
-						      &decorate_refs_exclude,
-						      &decorate_refs_exclude_config};
-	static struct revision_sources revision_sources;
-
-	const struct option builtin_log_options[] = {
-		OPT__QUIET(&quiet, N_("suppress diff output")),
-		OPT_BOOL(0, "source", &source, N_("show source")),
-		OPT_BOOL(0, "use-mailmap", &mailmap, N_("Use mail map file")),
-		OPT_ALIAS(0, "mailmap", "use-mailmap"),
-		OPT_STRING_LIST(0, "decorate-refs", &decorate_refs_include,
-				N_("pattern"), N_("only decorate refs that match <pattern>")),
-		OPT_STRING_LIST(0, "decorate-refs-exclude", &decorate_refs_exclude,
-				N_("pattern"), N_("do not decorate refs that match <pattern>")),
-		OPT_CALLBACK_F(0, "decorate", NULL, NULL, N_("decorate options"),
-			       PARSE_OPT_OPTARG, decorate_callback),
-		OPT_CALLBACK('L', NULL, &line_cb, "n,m:file",
-			     N_("Process line range n,m in file, counting from 1"),
-			     log_line_range_callback),
-		OPT_END()
-	};
-
-	line_cb.rev = rev;
-	line_cb.prefix = prefix;
-
-	mailmap = use_mailmap_config;
-	argc = parse_options(argc, argv, prefix,
-			     builtin_log_options, builtin_log_usage,
-			     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
-			     PARSE_OPT_KEEP_DASHDASH);
-
-	if (quiet)
-		rev->diffopt.output_format |= DIFF_FORMAT_NO_OUTPUT;
-	argc = setup_revisions(argc, argv, rev, opt);
-
-	/* Any arguments at this point are not recognized */
-	if (argc > 1)
-		die(_("unrecognized argument: %s"), argv[1]);
-
-	memset(&w, 0, sizeof(w));
-	userformat_find_requirements(NULL, &w);
-
-	if (!rev->show_notes_given && (!rev->pretty_given || w.notes))
-		rev->show_notes = 1;
-	if (rev->show_notes)
-		load_display_notes(&rev->notes_opt);
-
-	if ((rev->diffopt.pickaxe_opts & DIFF_PICKAXE_KINDS_MASK) ||
-	    rev->diffopt.filter || rev->diffopt.flags.follow_renames)
-		rev->always_show_header = 0;
-
-	if (source || w.source) {
-		init_revision_sources(&revision_sources);
-		rev->sources = &revision_sources;
-	}
-
-	if (mailmap) {
-		rev->mailmap = xcalloc(1, sizeof(struct string_list));
-		read_mailmap(rev->mailmap, NULL);
-	}
-
-	if (rev->pretty_given && rev->commit_format == CMIT_FMT_RAW) {
-		/*
-		 * "log --pretty=raw" is special; ignore UI oriented
-		 * configuration variables such as decoration.
-		 */
-		if (!decoration_given)
-			decoration_style = 0;
-		if (!rev->abbrev_commit_given)
-			rev->abbrev_commit = 0;
-	}
-
-	if (decoration_style) {
-		const struct string_list *config_exclude =
-			repo_config_get_value_multi(the_repository,
-						    "log.excludeDecoration");
-
-		if (config_exclude) {
-			struct string_list_item *item;
-			for_each_string_list_item(item, config_exclude)
-				string_list_append(&decorate_refs_exclude_config,
-						   item->string);
-		}
-
-		rev->show_decorations = 1;
-
-		load_ref_decorations(&decoration_filter, decoration_style);
-	}
-
-	if (rev->line_level_traverse)
-		line_log_init(rev, line_cb.prefix, &line_cb.args);
-
-	setup_pager();
-}
-
-static void cmd_log_init(int argc, const char **argv, const char *prefix,
-			 struct rev_info *rev, struct setup_revision_opt *opt)
-{
-	cmd_log_init_defaults(rev);
-	cmd_log_init_finish(argc, argv, prefix, rev, opt);
-}
-
-/*
- * This gives a rough estimate for how many commits we
- * will print out in the list.
- */
-static int estimate_commit_count(struct commit_list *list)
-{
-	int n = 0;
-
-	while (list) {
-		struct commit *commit = list->item;
-		unsigned int flags = commit->object.flags;
-		list = list->next;
-		if (!(flags & (TREESAME | UNINTERESTING)))
-			n++;
-	}
-	return n;
-}
-
-static void show_early_header(struct rev_info *rev, const char *stage, int nr)
-{
-	if (rev->shown_one) {
-		rev->shown_one = 0;
-		if (rev->commit_format != CMIT_FMT_ONELINE)
-			putchar(rev->diffopt.line_termination);
-	}
-	fprintf(rev->diffopt.file, _("Final output: %d %s\n"), nr, stage);
-}
-
-static struct itimerval early_output_timer;
-
-static void log_show_early(struct rev_info *revs, struct commit_list *list)
-{
-	int i = revs->early_output, close_file = revs->diffopt.close_file;
-	int show_header = 1;
-
-	revs->diffopt.close_file = 0;
-	sort_in_topological_order(&list, revs->sort_order);
-	while (list && i) {
-		struct commit *commit = list->item;
-		switch (simplify_commit(revs, commit)) {
-		case commit_show:
-			if (show_header) {
-				int n = estimate_commit_count(list);
-				show_early_header(revs, "incomplete", n);
-				show_header = 0;
-			}
-			log_tree_commit(revs, commit);
-			i--;
-			break;
-		case commit_ignore:
-			break;
-		case commit_error:
-			if (close_file)
-				fclose(revs->diffopt.file);
-			return;
-		}
-		list = list->next;
-	}
-
-	/* Did we already get enough commits for the early output? */
-	if (!i) {
-		if (close_file)
-			fclose(revs->diffopt.file);
-		return;
-	}
-
-	/*
-	 * ..if no, then repeat it twice a second until we
-	 * do.
-	 *
-	 * NOTE! We don't use "it_interval", because if the
-	 * reader isn't listening, we want our output to be
-	 * throttled by the writing, and not have the timer
-	 * trigger every second even if we're blocked on a
-	 * reader!
-	 */
-	early_output_timer.it_value.tv_sec = 0;
-	early_output_timer.it_value.tv_usec = 500000;
-	setitimer(ITIMER_REAL, &early_output_timer, NULL);
-}
-
-static void early_output(int signal)
-{
-	show_early_output = log_show_early;
-}
-
-static void setup_early_output(void)
-{
-	struct sigaction sa;
-
-	/*
-	 * Set up the signal handler, minimally intrusively:
-	 * we only set a single volatile integer word (not
-	 * using sigatomic_t - trying to avoid unnecessary
-	 * system dependencies and headers), and using
-	 * SA_RESTART.
-	 */
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = early_output;
-	sigemptyset(&sa.sa_mask);
-	sa.sa_flags = SA_RESTART;
-	sigaction(SIGALRM, &sa, NULL);
-
-	/*
-	 * If we can get the whole output in less than a
-	 * tenth of a second, don't even bother doing the
-	 * early-output thing..
-	 *
-	 * This is a one-time-only trigger.
-	 */
-	early_output_timer.it_value.tv_sec = 0;
-	early_output_timer.it_value.tv_usec = 100000;
-	setitimer(ITIMER_REAL, &early_output_timer, NULL);
-}
-
-static void finish_early_output(struct rev_info *rev)
-{
-	int n = estimate_commit_count(rev->commits);
-	signal(SIGALRM, SIG_IGN);
-	show_early_header(rev, "done", n);
-}
-
-static int cmd_log_walk(struct rev_info *rev)
-{
-	struct commit *commit;
-	int saved_nrl = 0;
-	int saved_dcctc = 0, close_file = rev->diffopt.close_file;
-
-	if (rev->early_output)
-		setup_early_output();
-
-	if (prepare_revision_walk(rev))
-		die(_("revision walk setup failed"));
-
-	if (rev->early_output)
-		finish_early_output(rev);
-
-	/*
-	 * For --check and --exit-code, the exit code is based on CHECK_FAILED
-	 * and HAS_CHANGES being accumulated in rev->diffopt, so be careful to
-	 * retain that state information if replacing rev->diffopt in this loop
-	 */
-	rev->diffopt.close_file = 0;
-	while ((commit = get_revision(rev)) != NULL) {
-		if (!log_tree_commit(rev, commit) && rev->max_count >= 0)
-			/*
-			 * We decremented max_count in get_revision,
-			 * but we didn't actually show the commit.
-			 */
-			rev->max_count++;
-		if (!rev->reflog_info) {
-			/*
-			 * We may show a given commit multiple times when
-			 * walking the reflogs.
-			 */
-			free_commit_buffer(the_repository->parsed_objects,
-					   commit);
-			free_commit_list(commit->parents);
-			commit->parents = NULL;
-		}
-		if (saved_nrl < rev->diffopt.needed_rename_limit)
-			saved_nrl = rev->diffopt.needed_rename_limit;
-		if (rev->diffopt.degraded_cc_to_c)
-			saved_dcctc = 1;
-	}
-	rev->diffopt.degraded_cc_to_c = saved_dcctc;
-	rev->diffopt.needed_rename_limit = saved_nrl;
-	if (close_file)
-		fclose(rev->diffopt.file);
-
-	if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF &&
-	    rev->diffopt.flags.check_failed) {
-		return 02;
-	}
-	return diff_result_code(&rev->diffopt, 0);
-}
-
-static int git_log_config(const char *var, const char *value, void *cb)
-{
-	const char *slot_name;
-
-	if (!strcmp(var, "format.pretty"))
-		return git_config_string(&fmt_pretty, var, value);
-	if (!strcmp(var, "format.subjectprefix"))
-		return git_config_string(&fmt_patch_subject_prefix, var, value);
-	if (!strcmp(var, "format.encodeemailheaders")) {
-		default_encode_email_headers = git_config_bool(var, value);
-		return 0;
-	}
-	if (!strcmp(var, "log.abbrevcommit")) {
-		default_abbrev_commit = git_config_bool(var, value);
-		return 0;
-	}
-	if (!strcmp(var, "log.date"))
-		return git_config_string(&default_date_mode, var, value);
-	if (!strcmp(var, "log.decorate")) {
-		decoration_style = parse_decoration_style(value);
-		if (decoration_style < 0)
-			decoration_style = 0; /* maybe warn? */
-		return 0;
-	}
-	if (!strcmp(var, "log.showroot")) {
-		default_show_root = git_config_bool(var, value);
-		return 0;
-	}
-	if (!strcmp(var, "log.follow")) {
-		default_follow = git_config_bool(var, value);
-		return 0;
-	}
-	if (skip_prefix(var, "color.decorate.", &slot_name))
-		return parse_decorate_color_config(var, slot_name, value);
-	if (!strcmp(var, "log.mailmap")) {
-		use_mailmap_config = git_config_bool(var, value);
-		return 0;
-	}
-	if (!strcmp(var, "log.showsignature")) {
-		default_show_signature = git_config_bool(var, value);
-		return 0;
-	}
-
-	if (grep_config(var, value, cb) < 0)
-		return -1;
-	if (git_gpg_config(var, value, cb) < 0)
-		return -1;
-	return git_diff_ui_config(var, value, cb);
-}
-
-int cmd_whatchanged(int argc, const char **argv, const char *prefix)
-{
-	struct rev_info rev;
-	struct setup_revision_opt opt;
-
-	init_log_defaults();
-	git_config(git_log_config, NULL);
-
-	repo_init_revisions(the_repository, &rev, prefix);
-	rev.diff = 1;
-	rev.simplify_history = 0;
-	memset(&opt, 0, sizeof(opt));
-	opt.def = "HEAD";
-	opt.revarg_opt = REVARG_COMMITTISH;
-	cmd_log_init(argc, argv, prefix, &rev, &opt);
-	if (!rev.diffopt.output_format)
-		rev.diffopt.output_format = DIFF_FORMAT_RAW;
-	return cmd_log_walk(&rev);
-}
-
-static void show_tagger(const char *buf, struct rev_info *rev)
-{
-	struct strbuf out = STRBUF_INIT;
-	struct pretty_print_context pp = {0};
-
-	pp.fmt = rev->commit_format;
-	pp.date_mode = rev->date_mode;
-	pp_user_info(&pp, "Tagger", &out, buf, get_log_output_encoding());
-	fprintf(rev->diffopt.file, "%s", out.buf);
-	strbuf_release(&out);
-}
-
-static int show_blob_object(const struct object_id *oid, struct rev_info *rev, const char *obj_name)
-{
-	struct object_id oidc;
-	struct object_context obj_context;
-	char *buf;
-	unsigned long size;
-
-	fflush(rev->diffopt.file);
-	if (!rev->diffopt.flags.textconv_set_via_cmdline ||
-	    !rev->diffopt.flags.allow_textconv)
-		return stream_blob_to_fd(1, oid, NULL, 0);
-
-	if (get_oid_with_context(the_repository, obj_name,
-				 GET_OID_RECORD_PATH,
-				 &oidc, &obj_context))
-		die(_("not a valid object name %s"), obj_name);
-	if (!obj_context.path ||
-	    !textconv_object(the_repository, obj_context.path,
-			     obj_context.mode, &oidc, 1, &buf, &size)) {
-		free(obj_context.path);
-		return stream_blob_to_fd(1, oid, NULL, 0);
-	}
-
-	if (!buf)
-		die(_("git show %s: bad file"), obj_name);
-
-	write_or_die(1, buf, size);
-	free(obj_context.path);
-	return 0;
-}
-
-static int show_tag_object(const struct object_id *oid, struct rev_info *rev)
-{
-	unsigned long size;
-	enum object_type type;
-	char *buf = read_object_file(oid, &type, &size);
-	int offset = 0;
-
-	if (!buf)
-		return error(_("could not read object %s"), oid_to_hex(oid));
-
-	assert(type == OBJ_TAG);
-	while (offset < size && buf[offset] != '\n') {
-		int new_offset = offset + 1;
-		const char *ident;
-		while (new_offset < size && buf[new_offset++] != '\n')
-			; /* do nothing */
-		if (skip_prefix(buf + offset, "tagger ", &ident))
-			show_tagger(ident, rev);
-		offset = new_offset;
-	}
-
-	if (offset < size)
-		fwrite(buf + offset, size - offset, 1, rev->diffopt.file);
-	free(buf);
-	return 0;
-}
-
-static int show_tree_object(const struct object_id *oid,
-		struct strbuf *base,
-		const char *pathname, unsigned mode, int stage, void *context)
-{
-	FILE *file = context;
-	fprintf(file, "%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
-	return 0;
-}
-
-static void show_setup_revisions_tweak(struct rev_info *rev,
-				       struct setup_revision_opt *opt)
-{
-	if (rev->ignore_merges < 0) {
-		/* There was no "-m" variant on the command line */
-		rev->ignore_merges = 0;
-		if (!rev->first_parent_only && !rev->combine_merges) {
-			/* No "--first-parent", "-c", or "--cc" */
-			rev->combine_merges = 1;
-			rev->dense_combined_merges = 1;
-		}
-	}
-	if (!rev->diffopt.output_format)
-		rev->diffopt.output_format = DIFF_FORMAT_PATCH;
-}
-
-int cmd_show(int argc, const char **argv, const char *prefix)
-{
-	struct rev_info rev;
-	struct object_array_entry *objects;
-	struct setup_revision_opt opt;
-	struct pathspec match_all;
-	int i, count, ret = 0;
-
-	init_log_defaults();
-	git_config(git_log_config, NULL);
-
-	memset(&match_all, 0, sizeof(match_all));
-	repo_init_revisions(the_repository, &rev, prefix);
-	rev.diff = 1;
-	rev.always_show_header = 1;
-	rev.no_walk = REVISION_WALK_NO_WALK_SORTED;
-	rev.diffopt.stat_width = -1; 	/* Scale to real terminal size */
-
-	memset(&opt, 0, sizeof(opt));
-	opt.def = "HEAD";
-	opt.tweak = show_setup_revisions_tweak;
-	cmd_log_init(argc, argv, prefix, &rev, &opt);
-
-	if (!rev.no_walk)
-		return cmd_log_walk(&rev);
-
-	count = rev.pending.nr;
-	objects = rev.pending.objects;
-	for (i = 0; i < count && !ret; i++) {
-		struct object *o = objects[i].item;
-		const char *name = objects[i].name;
-		switch (o->type) {
-		case OBJ_BLOB:
-			ret = show_blob_object(&o->oid, &rev, name);
-			break;
-		case OBJ_TAG: {
-			struct tag *t = (struct tag *)o;
-			struct object_id *oid = get_tagged_oid(t);
-
-			if (rev.shown_one)
-				putchar('\n');
-			fprintf(rev.diffopt.file, "%stag %s%s\n",
-					diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
-					t->tag,
-					diff_get_color_opt(&rev.diffopt, DIFF_RESET));
-			ret = show_tag_object(&o->oid, &rev);
-			rev.shown_one = 1;
-			if (ret)
-				break;
-			o = parse_object(the_repository, oid);
-			if (!o)
-				ret = error(_("could not read object %s"),
-					    oid_to_hex(oid));
-			objects[i].item = o;
-			i--;
-			break;
-		}
-		case OBJ_TREE:
-			if (rev.shown_one)
-				putchar('\n');
-			fprintf(rev.diffopt.file, "%stree %s%s\n\n",
-					diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
-					name,
-					diff_get_color_opt(&rev.diffopt, DIFF_RESET));
-			read_tree_recursive(the_repository, (struct tree *)o, "",
-					    0, 0, &match_all, show_tree_object,
-					    rev.diffopt.file);
-			rev.shown_one = 1;
-			break;
-		case OBJ_COMMIT:
-			rev.pending.nr = rev.pending.alloc = 0;
-			rev.pending.objects = NULL;
-			add_object_array(o, name, &rev.pending);
-			ret = cmd_log_walk(&rev);
-			break;
-		default:
-			ret = error(_("unknown type: %d"), o->type);
-		}
-	}
-	free(objects);
-	return ret;
-}
-
-/*
- * This is equivalent to "git log -g --abbrev-commit --pretty=oneline"
- */
-int cmd_log_reflog(int argc, const char **argv, const char *prefix)
-{
-	struct rev_info rev;
-	struct setup_revision_opt opt;
-
-	init_log_defaults();
-	git_config(git_log_config, NULL);
-
-	repo_init_revisions(the_repository, &rev, prefix);
-	init_reflog_walk(&rev.reflog_info);
-	rev.verbose_header = 1;
-	memset(&opt, 0, sizeof(opt));
-	opt.def = "HEAD";
-	cmd_log_init_defaults(&rev);
-	rev.abbrev_commit = 1;
-	rev.commit_format = CMIT_FMT_ONELINE;
-	rev.use_terminator = 1;
-	rev.always_show_header = 1;
-	cmd_log_init_finish(argc, argv, prefix, &rev, &opt);
-
-	return cmd_log_walk(&rev);
-}
-
-static void log_setup_revisions_tweak(struct rev_info *rev,
-				      struct setup_revision_opt *opt)
-{
-	if (rev->diffopt.flags.default_follow_renames &&
-	    rev->prune_data.nr == 1)
-		rev->diffopt.flags.follow_renames = 1;
-
-	/* Turn --cc/-c into -p --cc/-c when -p was not given */
-	if (!rev->diffopt.output_format && rev->combine_merges)
-		rev->diffopt.output_format = DIFF_FORMAT_PATCH;
-
-	if (rev->first_parent_only && rev->ignore_merges < 0)
-		rev->ignore_merges = 0;
-}
-
-int cmd_log(int argc, const char **argv, const char *prefix)
-{
-	struct rev_info rev;
-	struct setup_revision_opt opt;
-
-	init_log_defaults();
-	git_config(git_log_config, NULL);
-
-	repo_init_revisions(the_repository, &rev, prefix);
-	rev.always_show_header = 1;
-	memset(&opt, 0, sizeof(opt));
-	opt.def = "HEAD";
-	opt.revarg_opt = REVARG_COMMITTISH;
-	opt.tweak = log_setup_revisions_tweak;
-	cmd_log_init(argc, argv, prefix, &rev, &opt);
-	return cmd_log_walk(&rev);
-}
-
-/* format-patch */
-
-static const char *fmt_patch_suffix = ".patch";
-static int numbered = 0;
-static int auto_number = 1;
-
-static char *default_attach = NULL;
-
-static struct string_list extra_hdr = STRING_LIST_INIT_NODUP;
-static struct string_list extra_to = STRING_LIST_INIT_NODUP;
-static struct string_list extra_cc = STRING_LIST_INIT_NODUP;
-
-static void add_header(const char *value)
-{
-	struct string_list_item *item;
-	int len = strlen(value);
-	while (len && value[len - 1] == '\n')
-		len--;
-
-	if (!strncasecmp(value, "to: ", 4)) {
-		item = string_list_append(&extra_to, value + 4);
-		len -= 4;
-	} else if (!strncasecmp(value, "cc: ", 4)) {
-		item = string_list_append(&extra_cc, value + 4);
-		len -= 4;
-	} else {
-		item = string_list_append(&extra_hdr, 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
-};
-
-enum auto_base_setting {
-	AUTO_BASE_NEVER,
-	AUTO_BASE_ALWAYS,
-	AUTO_BASE_WHEN_ABLE
-};
-
-static enum thread_level thread;
-static int do_signoff;
-static enum auto_base_setting auto_base;
-static char *from;
-static const char *signature = git_version_string;
-static const char *signature_file;
-static enum cover_setting 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);
-}
-
-static int git_format_config(const char *var, const char *value, void *cb)
-{
-	if (!strcmp(var, "format.headers")) {
-		if (!value)
-			die(_("format.headers without value"));
-		add_header(value);
-		return 0;
-	}
-	if (!strcmp(var, "format.suffix"))
-		return git_config_string(&fmt_patch_suffix, var, value);
-	if (!strcmp(var, "format.to")) {
-		if (!value)
-			return config_error_nonbool(var);
-		string_list_append(&extra_to, value);
-		return 0;
-	}
-	if (!strcmp(var, "format.cc")) {
-		if (!value)
-			return config_error_nonbool(var);
-		string_list_append(&extra_cc, value);
-		return 0;
-	}
-	if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff") ||
-	    !strcmp(var, "color.ui") || !strcmp(var, "diff.submodule")) {
-		return 0;
-	}
-	if (!strcmp(var, "format.numbered")) {
-		if (value && !strcasecmp(value, "auto")) {
-			auto_number = 1;
-			return 0;
-		}
-		numbered = git_config_bool(var, value);
-		auto_number = auto_number && numbered;
-		return 0;
-	}
-	if (!strcmp(var, "format.attach")) {
-		if (value && *value)
-			default_attach = xstrdup(value);
-		else
-			default_attach = xstrdup(git_version_string);
-		return 0;
-	}
-	if (!strcmp(var, "format.thread")) {
-		if (value && !strcasecmp(value, "deep")) {
-			thread = THREAD_DEEP;
-			return 0;
-		}
-		if (value && !strcasecmp(value, "shallow")) {
-			thread = THREAD_SHALLOW;
-			return 0;
-		}
-		thread = git_config_bool(var, value) ? THREAD_SHALLOW : THREAD_UNSET;
-		return 0;
-	}
-	if (!strcmp(var, "format.signoff")) {
-		do_signoff = git_config_bool(var, value);
-		return 0;
-	}
-	if (!strcmp(var, "format.signature"))
-		return git_config_string(&signature, var, value);
-	if (!strcmp(var, "format.signaturefile"))
-		return git_config_pathname(&signature_file, var, value);
-	if (!strcmp(var, "format.coverletter")) {
-		if (value && !strcasecmp(value, "auto")) {
-			config_cover_letter = COVER_AUTO;
-			return 0;
-		}
-		config_cover_letter = git_config_bool(var, value) ? COVER_ON : COVER_OFF;
-		return 0;
-	}
-	if (!strcmp(var, "format.outputdirectory"))
-		return git_config_string(&config_output_directory, var, value);
-	if (!strcmp(var, "format.useautobase")) {
-		if (value && !strcasecmp(value, "whenAble")) {
-			auto_base = AUTO_BASE_WHEN_ABLE;
-			return 0;
-		}
-		auto_base = git_config_bool(var, value) ? AUTO_BASE_ALWAYS : AUTO_BASE_NEVER;
-		return 0;
-	}
-	if (!strcmp(var, "format.from")) {
-		int b = git_parse_maybe_bool(value);
-		free(from);
-		if (b < 0)
-			from = xstrdup(value);
-		else if (b)
-			from = xstrdup(git_committer_info(IDENT_NO_DATE));
-		else
-			from = NULL;
-		return 0;
-	}
-	if (!strcmp(var, "format.notes")) {
-		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);
-		return 0;
-	}
-
-	return git_log_config(var, value, cb);
-}
-
-static const char *output_directory = NULL;
-static int outdir_offset;
-
-static int open_next_file(struct commit *commit, const char *subject,
-			 struct rev_info *rev, int quiet)
-{
-	struct strbuf filename = STRBUF_INIT;
-	int suffix_len = strlen(rev->patch_suffix) + 1;
-
-	if (output_directory) {
-		strbuf_addstr(&filename, output_directory);
-		if (filename.len >=
-		    PATH_MAX - FORMAT_PATCH_NAME_MAX - suffix_len) {
-			strbuf_release(&filename);
-			return error(_("name of output directory is too long"));
-		}
-		strbuf_complete(&filename, '/');
-	}
-
-	if (rev->numbered_files)
-		strbuf_addf(&filename, "%d", rev->nr);
-	else if (commit)
-		fmt_output_commit(&filename, commit, rev);
-	else
-		fmt_output_subject(&filename, subject, rev);
-
-	if (!quiet)
-		printf("%s\n", filename.buf + outdir_offset);
-
-	if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL) {
-		error_errno(_("cannot open patch file %s"), filename.buf);
-		strbuf_release(&filename);
-		return -1;
-	}
-
-	strbuf_release(&filename);
-	return 0;
-}
-
-static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids)
-{
-	struct rev_info check_rev;
-	struct commit *commit, *c1, *c2;
-	struct object *o1, *o2;
-	unsigned flags1, flags2;
-
-	if (rev->pending.nr != 2)
-		die(_("need exactly one range"));
-
-	o1 = rev->pending.objects[0].item;
-	o2 = rev->pending.objects[1].item;
-	flags1 = o1->flags;
-	flags2 = o2->flags;
-	c1 = lookup_commit_reference(the_repository, &o1->oid);
-	c2 = lookup_commit_reference(the_repository, &o2->oid);
-
-	if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING))
-		die(_("not a range"));
-
-	init_patch_ids(the_repository, ids);
-
-	/* given a range a..b get all patch ids for b..a */
-	repo_init_revisions(the_repository, &check_rev, rev->prefix);
-	check_rev.max_parents = 1;
-	o1->flags ^= UNINTERESTING;
-	o2->flags ^= UNINTERESTING;
-	add_pending_object(&check_rev, o1, "o1");
-	add_pending_object(&check_rev, o2, "o2");
-	if (prepare_revision_walk(&check_rev))
-		die(_("revision walk setup failed"));
-
-	while ((commit = get_revision(&check_rev)) != NULL) {
-		add_commit_patch_id(commit, ids);
-	}
-
-	/* reset for next revision walk */
-	clear_commit_marks(c1, SEEN | UNINTERESTING | SHOWN | ADDED);
-	clear_commit_marks(c2, SEEN | UNINTERESTING | SHOWN | ADDED);
-	o1->flags = flags1;
-	o2->flags = flags2;
-}
-
-static void gen_message_id(struct rev_info *info, char *base)
-{
-	struct strbuf buf = STRBUF_INIT;
-	strbuf_addf(&buf, "%s.%"PRItime".git.%s", base,
-		    (timestamp_t) time(NULL),
-		    git_committer_info(IDENT_NO_NAME|IDENT_NO_DATE|IDENT_STRICT));
-	info->message_id = strbuf_detach(&buf, NULL);
-}
-
-static void print_signature(FILE *file)
-{
-	if (!signature || !*signature)
-		return;
-
-	fprintf(file, "-- \n%s", signature);
-	if (signature[strlen(signature)-1] != '\n')
-		putc('\n', file);
-	putc('\n', file);
-}
-
-static char *find_branch_name(struct rev_info *rev)
-{
-	int i, positive = -1;
-	struct object_id branch_oid;
-	const struct object_id *tip_oid;
-	const char *ref, *v;
-	char *full_ref, *branch = NULL;
-
-	for (i = 0; i < rev->cmdline.nr; i++) {
-		if (rev->cmdline.rev[i].flags & UNINTERESTING)
-			continue;
-		if (positive < 0)
-			positive = i;
-		else
-			return NULL;
-	}
-	if (positive < 0)
-		return NULL;
-	ref = rev->cmdline.rev[positive].name;
-	tip_oid = &rev->cmdline.rev[positive].item->oid;
-	if (dwim_ref(ref, strlen(ref), &branch_oid, &full_ref, 0) &&
-	    skip_prefix(full_ref, "refs/heads/", &v) &&
-	    oideq(tip_oid, &branch_oid))
-		branch = xstrdup(v);
-	free(full_ref);
-	return branch;
-}
-
-static void show_diffstat(struct rev_info *rev,
-			  struct commit *origin, struct commit *head)
-{
-	struct diff_options opts;
-
-	memcpy(&opts, &rev->diffopt, sizeof(opts));
-	opts.output_format = DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
-	diff_setup_done(&opts);
-
-	diff_tree_oid(get_commit_tree_oid(origin),
-		      get_commit_tree_oid(head),
-		      "", &opts);
-	diffcore_std(&opts);
-	diff_flush(&opts);
-
-	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)
-{
-	strvec_pushf(arg, "--notes=%s", item->string);
-	return 0;
-}
-
-static void get_notes_args(struct strvec *arg, struct rev_info *rev)
-{
-	if (!rev->show_notes) {
-		strvec_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)) {
-		strvec_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,
-			      const char *branch_name,
-			      int quiet)
-{
-	const char *committer;
-	struct shortlog log;
-	struct strbuf sb = STRBUF_INIT;
-	int i;
-	const char *encoding = "UTF-8";
-	int need_8bit_cte = 0;
-	struct pretty_print_context pp = {0};
-	struct commit *head = list[0];
-
-	if (!cmit_fmt_is_mail(rev->commit_format))
-		die(_("cover letter needs email format"));
-
-	committer = git_committer_info(0);
-
-	if (!use_stdout &&
-	    open_next_file(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
-		die(_("failed to create cover-letter file"));
-
-	log_write_email_headers(rev, head, &pp.after_subject, &need_8bit_cte, 0);
-
-	for (i = 0; !need_8bit_cte && i < nr; i++) {
-		const char *buf = get_commit_buffer(list[i], NULL);
-		if (has_non_ascii(buf))
-			need_8bit_cte = 1;
-		unuse_commit_buffer(list[i], buf);
-	}
-
-	if (!branch_name)
-		branch_name = find_branch_name(rev);
-
-	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);
-	fprintf(rev->diffopt.file, "%s\n", sb.buf);
-
-	strbuf_release(&sb);
-
-	shortlog_init(&log);
-	log.wrap_lines = 1;
-	log.wrap = MAIL_DEFAULT_WRAP;
-	log.in1 = 2;
-	log.in2 = 4;
-	log.file = rev->diffopt.file;
-	log.groups = SHORTLOG_GROUP_AUTHOR;
-	for (i = 0; i < nr; i++)
-		shortlog_add_commit(&log, list[i]);
-
-	shortlog_output(&log);
-
-	/* We can only do diffstat with a unique reference point */
-	if (origin)
-		show_diffstat(rev, origin, head);
-
-	if (rev->idiff_oid1) {
-		fprintf_ln(rev->diffopt.file, "%s", rev->idiff_title);
-		show_interdiff(rev->idiff_oid1, rev->idiff_oid2, 0,
-			       &rev->diffopt);
-	}
-
-	if (rev->rdiff1) {
-		/*
-		 * Pass minimum required diff-options to range-diff; others
-		 * can be added later if deemed desirable.
-		 */
-		struct diff_options opts;
-		struct strvec other_arg = STRVEC_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);
-		strvec_clear(&other_arg);
-	}
-}
-
-static const char *clean_message_id(const char *msg_id)
-{
-	char ch;
-	const char *a, *z, *m;
-
-	m = msg_id;
-	while ((ch = *m) && (isspace(ch) || (ch == '<')))
-		m++;
-	a = m;
-	z = NULL;
-	while ((ch = *m)) {
-		if (!isspace(ch) && (ch != '>'))
-			z = m;
-		m++;
-	}
-	if (!z)
-		die(_("insane in-reply-to: %s"), msg_id);
-	if (++z == m)
-		return a;
-	return xmemdupz(a, z - a);
-}
-
-static const char *set_outdir(const char *prefix, const char *output_directory)
-{
-	if (output_directory && is_absolute_path(output_directory))
-		return output_directory;
-
-	if (!prefix || !*prefix) {
-		if (output_directory)
-			return output_directory;
-		/* The user did not explicitly ask for "./" */
-		outdir_offset = 2;
-		return "./";
-	}
-
-	outdir_offset = strlen(prefix);
-	if (!output_directory)
-		return prefix;
-
-	return prefix_filename(prefix, output_directory);
-}
-
-static const char * const builtin_format_patch_usage[] = {
-	N_("git format-patch [<options>] [<since> | <revision-range>]"),
-	NULL
-};
-
-static int keep_subject = 0;
-
-static int keep_callback(const struct option *opt, const char *arg, int unset)
-{
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-	((struct rev_info *)opt->value)->total = -1;
-	keep_subject = 1;
-	return 0;
-}
-
-static int subject_prefix = 0;
-
-static int subject_prefix_callback(const struct option *opt, const char *arg,
-			    int unset)
-{
-	BUG_ON_OPT_NEG(unset);
-	subject_prefix = 1;
-	((struct rev_info *)opt->value)->subject_prefix = arg;
-	return 0;
-}
-
-static int rfc_callback(const struct option *opt, const char *arg, int unset)
-{
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-	return subject_prefix_callback(opt, "RFC PATCH", unset);
-}
-
-static int numbered_cmdline_opt = 0;
-
-static int numbered_callback(const struct option *opt, const char *arg,
-			     int unset)
-{
-	BUG_ON_OPT_ARG(arg);
-	*(int *)opt->value = numbered_cmdline_opt = unset ? 0 : 1;
-	if (unset)
-		auto_number =  0;
-	return 0;
-}
-
-static int no_numbered_callback(const struct option *opt, const char *arg,
-				int unset)
-{
-	BUG_ON_OPT_NEG(unset);
-	return numbered_callback(opt, arg, 1);
-}
-
-static int output_directory_callback(const struct option *opt, const char *arg,
-			      int unset)
-{
-	const char **dir = (const char **)opt->value;
-	BUG_ON_OPT_NEG(unset);
-	if (*dir)
-		die(_("two output directories?"));
-	*dir = arg;
-	return 0;
-}
-
-static int thread_callback(const struct option *opt, const char *arg, int unset)
-{
-	enum thread_level *thread = (enum thread_level *)opt->value;
-	if (unset)
-		*thread = THREAD_UNSET;
-	else if (!arg || !strcmp(arg, "shallow"))
-		*thread = THREAD_SHALLOW;
-	else if (!strcmp(arg, "deep"))
-		*thread = THREAD_DEEP;
-	/*
-	 * Please update _git_formatpatch() in git-completion.bash
-	 * when you add new options.
-	 */
-	else
-		return 1;
-	return 0;
-}
-
-static int attach_callback(const struct option *opt, const char *arg, int unset)
-{
-	struct rev_info *rev = (struct rev_info *)opt->value;
-	if (unset)
-		rev->mime_boundary = NULL;
-	else if (arg)
-		rev->mime_boundary = arg;
-	else
-		rev->mime_boundary = git_version_string;
-	rev->no_inline = unset ? 0 : 1;
-	return 0;
-}
-
-static int inline_callback(const struct option *opt, const char *arg, int unset)
-{
-	struct rev_info *rev = (struct rev_info *)opt->value;
-	if (unset)
-		rev->mime_boundary = NULL;
-	else if (arg)
-		rev->mime_boundary = arg;
-	else
-		rev->mime_boundary = git_version_string;
-	rev->no_inline = 0;
-	return 0;
-}
-
-static int header_callback(const struct option *opt, const char *arg, int unset)
-{
-	if (unset) {
-		string_list_clear(&extra_hdr, 0);
-		string_list_clear(&extra_to, 0);
-		string_list_clear(&extra_cc, 0);
-	} else {
-		add_header(arg);
-	}
-	return 0;
-}
-
-static int to_callback(const struct option *opt, const char *arg, int unset)
-{
-	if (unset)
-		string_list_clear(&extra_to, 0);
-	else
-		string_list_append(&extra_to, arg);
-	return 0;
-}
-
-static int cc_callback(const struct option *opt, const char *arg, int unset)
-{
-	if (unset)
-		string_list_clear(&extra_cc, 0);
-	else
-		string_list_append(&extra_cc, arg);
-	return 0;
-}
-
-static int from_callback(const struct option *opt, const char *arg, int unset)
-{
-	char **from = opt->value;
-
-	free(*from);
-
-	if (unset)
-		*from = NULL;
-	else if (arg)
-		*from = xstrdup(arg);
-	else
-		*from = xstrdup(git_committer_info(IDENT_NO_DATE));
-	return 0;
-}
-
-static int base_callback(const struct option *opt, const char *arg, int unset)
-{
-	const char **base_commit = opt->value;
-
-	if (unset) {
-		auto_base = AUTO_BASE_NEVER;
-		*base_commit = NULL;
-	} else if (!strcmp(arg, "auto")) {
-		auto_base = AUTO_BASE_ALWAYS;
-		*base_commit = NULL;
-	} else {
-		auto_base = AUTO_BASE_NEVER;
-		*base_commit = arg;
-	}
-	return 0;
-}
-
-struct base_tree_info {
-	struct object_id base_commit;
-	int nr_patch_id, alloc_patch_id;
-	struct object_id *patch_id;
-};
-
-static struct commit *get_base_commit(const char *base_commit,
-				      struct commit **list,
-				      int total)
-{
-	struct commit *base = NULL;
-	struct commit **rev;
-	int i = 0, rev_nr = 0, auto_select, die_on_failure;
-
-	switch (auto_base) {
-	case AUTO_BASE_NEVER:
-		if (base_commit) {
-			auto_select = 0;
-			die_on_failure = 1;
-		} else {
-			/* no base information is requested */
-			return NULL;
-		}
-		break;
-	case AUTO_BASE_ALWAYS:
-	case AUTO_BASE_WHEN_ABLE:
-		if (base_commit) {
-			BUG("requested automatic base selection but a commit was provided");
-		} else {
-			auto_select = 1;
-			die_on_failure = auto_base == AUTO_BASE_ALWAYS;
-		}
-		break;
-	default:
-		BUG("unexpected automatic base selection method");
-	}
-
-	if (!auto_select) {
-		base = lookup_commit_reference_by_name(base_commit);
-		if (!base)
-			die(_("unknown commit %s"), base_commit);
-	} else {
-		struct branch *curr_branch = branch_get(NULL);
-		const char *upstream = branch_get_upstream(curr_branch, NULL);
-		if (upstream) {
-			struct commit_list *base_list;
-			struct commit *commit;
-			struct object_id oid;
-
-			if (get_oid(upstream, &oid)) {
-				if (die_on_failure)
-					die(_("failed to resolve '%s' as a valid ref"), upstream);
-				else
-					return NULL;
-			}
-			commit = lookup_commit_or_die(&oid, "upstream base");
-			base_list = get_merge_bases_many(commit, total, list);
-			/* There should be one and only one merge base. */
-			if (!base_list || base_list->next) {
-				if (die_on_failure) {
-					die(_("could not find exact merge base"));
-				} else {
-					free_commit_list(base_list);
-					return NULL;
-				}
-			}
-			base = base_list->item;
-			free_commit_list(base_list);
-		} else {
-			if (die_on_failure)
-				die(_("failed to get upstream, if you want to record base commit automatically,\n"
-				      "please use git branch --set-upstream-to to track a remote branch.\n"
-				      "Or you could specify base commit by --base=<base-commit-id> manually"));
-			else
-				return NULL;
-		}
-	}
-
-	ALLOC_ARRAY(rev, total);
-	for (i = 0; i < total; i++)
-		rev[i] = list[i];
-
-	rev_nr = total;
-	/*
-	 * Get merge base through pair-wise computations
-	 * and store it in rev[0].
-	 */
-	while (rev_nr > 1) {
-		for (i = 0; i < rev_nr / 2; i++) {
-			struct commit_list *merge_base;
-			merge_base = get_merge_bases(rev[2 * i], rev[2 * i + 1]);
-			if (!merge_base || merge_base->next) {
-				if (die_on_failure) {
-					die(_("failed to find exact merge base"));
-				} else {
-					free(rev);
-					return NULL;
-				}
-			}
-
-			rev[i] = merge_base->item;
-		}
-
-		if (rev_nr % 2)
-			rev[i] = rev[2 * i];
-		rev_nr = DIV_ROUND_UP(rev_nr, 2);
-	}
-
-	if (!in_merge_bases(base, rev[0])) {
-		if (die_on_failure) {
-			die(_("base commit should be the ancestor of revision list"));
-		} else {
-			free(rev);
-			return NULL;
-		}
-	}
-
-	for (i = 0; i < total; i++) {
-		if (base == list[i]) {
-			if (die_on_failure) {
-				die(_("base commit shouldn't be in revision list"));
-			} else {
-				free(rev);
-				return NULL;
-			}
-		}
-	}
-
-	free(rev);
-	return base;
-}
-
-define_commit_slab(commit_base, int);
-
-static void prepare_bases(struct base_tree_info *bases,
-			  struct commit *base,
-			  struct commit **list,
-			  int total)
-{
-	struct commit *commit;
-	struct rev_info revs;
-	struct diff_options diffopt;
-	struct commit_base commit_base;
-	int i;
-
-	if (!base)
-		return;
-
-	init_commit_base(&commit_base);
-	repo_diff_setup(the_repository, &diffopt);
-	diffopt.flags.recursive = 1;
-	diff_setup_done(&diffopt);
-
-	oidcpy(&bases->base_commit, &base->object.oid);
-
-	repo_init_revisions(the_repository, &revs, NULL);
-	revs.max_parents = 1;
-	revs.topo_order = 1;
-	for (i = 0; i < total; i++) {
-		list[i]->object.flags &= ~UNINTERESTING;
-		add_pending_object(&revs, &list[i]->object, "rev_list");
-		*commit_base_at(&commit_base, list[i]) = 1;
-	}
-	base->object.flags |= UNINTERESTING;
-	add_pending_object(&revs, &base->object, "base");
-
-	if (prepare_revision_walk(&revs))
-		die(_("revision walk setup failed"));
-	/*
-	 * Traverse the commits list, get prerequisite patch ids
-	 * and stuff them in bases structure.
-	 */
-	while ((commit = get_revision(&revs)) != NULL) {
-		struct object_id oid;
-		struct object_id *patch_id;
-		if (*commit_base_at(&commit_base, commit))
-			continue;
-		if (commit_patch_id(commit, &diffopt, &oid, 0, 1))
-			die(_("cannot get patch id"));
-		ALLOC_GROW(bases->patch_id, bases->nr_patch_id + 1, bases->alloc_patch_id);
-		patch_id = bases->patch_id + bases->nr_patch_id;
-		oidcpy(patch_id, &oid);
-		bases->nr_patch_id++;
-	}
-	clear_commit_base(&commit_base);
-}
-
-static void print_bases(struct base_tree_info *bases, FILE *file)
-{
-	int i;
-
-	/* Only do this once, either for the cover or for the first one */
-	if (is_null_oid(&bases->base_commit))
-		return;
-
-	/* Show the base commit */
-	fprintf(file, "\nbase-commit: %s\n", oid_to_hex(&bases->base_commit));
-
-	/* Show the prerequisite patches */
-	for (i = bases->nr_patch_id - 1; i >= 0; i--)
-		fprintf(file, "prerequisite-patch-id: %s\n", oid_to_hex(&bases->patch_id[i]));
-
-	free(bases->patch_id);
-	bases->nr_patch_id = 0;
-	bases->alloc_patch_id = 0;
-	oidclr(&bases->base_commit);
-}
-
-static const char *diff_title(struct strbuf *sb, int reroll_count,
-		       const char *generic, const char *rerolled)
-{
-	if (reroll_count <= 0)
-		strbuf_addstr(sb, generic);
-	else /* RFC may be v0, so allow -v1 to diff against v0 */
-		strbuf_addf(sb, rerolled, reroll_count - 1);
-	return sb->buf;
-}
-
-static void infer_range_diff_ranges(struct strbuf *r1,
-				    struct strbuf *r2,
-				    const char *prev,
-				    struct commit *origin,
-				    struct commit *head)
-{
-	const char *head_oid = oid_to_hex(&head->object.oid);
-	int prev_is_range = !!strstr(prev, "..");
-
-	if (prev_is_range)
-		strbuf_addstr(r1, prev);
-	else
-		strbuf_addf(r1, "%s..%s", head_oid, prev);
-
-	if (origin)
-		strbuf_addf(r2, "%s..%s", oid_to_hex(&origin->object.oid), head_oid);
-	else if (prev_is_range)
-		die(_("failed to infer range-diff origin of current series"));
-	else {
-		warning(_("using '%s' as range-diff origin of current series"), prev);
-		strbuf_addf(r2, "%s..%s", prev, head_oid);
-	}
-}
-
-int cmd_format_patch(int argc, const char **argv, const char *prefix)
-{
-	struct commit *commit;
-	struct commit **list = NULL;
-	struct rev_info rev;
-	struct setup_revision_opt s_r_opt;
-	int nr = 0, total, i;
-	int use_stdout = 0;
-	int start_number = -1;
-	int just_numbers = 0;
-	int ignore_if_in_upstream = 0;
-	int cover_letter = -1;
-	int boundary_count = 0;
-	int no_binary_diff = 0;
-	int zero_commit = 0;
-	struct commit *origin = NULL;
-	const char *in_reply_to = NULL;
-	struct patch_ids ids;
-	struct strbuf buf = STRBUF_INIT;
-	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;
-	struct commit *base;
-	int show_progress = 0;
-	struct progress *progress = NULL;
-	struct oid_array idiff_prev = OID_ARRAY_INIT;
-	struct strbuf idiff_title = STRBUF_INIT;
-	const char *rdiff_prev = NULL;
-	struct strbuf rdiff1 = STRBUF_INIT;
-	struct strbuf rdiff2 = STRBUF_INIT;
-	struct strbuf rdiff_title = STRBUF_INIT;
-	int creation_factor = -1;
-
-	const struct option builtin_format_patch_options[] = {
-		OPT_CALLBACK_F('n', "numbered", &numbered, NULL,
-			    N_("use [PATCH n/m] even with a single patch"),
-			    PARSE_OPT_NOARG, numbered_callback),
-		OPT_CALLBACK_F('N', "no-numbered", &numbered, NULL,
-			    N_("use [PATCH] even with multiple patches"),
-			    PARSE_OPT_NOARG | PARSE_OPT_NONEG, no_numbered_callback),
-		OPT_BOOL('s', "signoff", &do_signoff, N_("add Signed-off-by:")),
-		OPT_BOOL(0, "stdout", &use_stdout,
-			    N_("print patches to standard out")),
-		OPT_BOOL(0, "cover-letter", &cover_letter,
-			    N_("generate a cover letter")),
-		OPT_BOOL(0, "numbered-files", &just_numbers,
-			    N_("use simple number sequence for output file names")),
-		OPT_STRING(0, "suffix", &fmt_patch_suffix, N_("sfx"),
-			    N_("use <sfx> instead of '.patch'")),
-		OPT_INTEGER(0, "start-number", &start_number,
-			    N_("start numbering patches at <n> instead of 1")),
-		OPT_INTEGER('v', "reroll-count", &reroll_count,
-			    N_("mark the series as Nth re-roll")),
-		OPT_CALLBACK_F(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")),
-		OPT_CALLBACK_F(0, "subject-prefix", &rev, N_("prefix"),
-			    N_("Use [<prefix>] instead of [PATCH]"),
-			    PARSE_OPT_NONEG, subject_prefix_callback),
-		OPT_CALLBACK_F('o', "output-directory", &output_directory,
-			    N_("dir"), N_("store resulting files in <dir>"),
-			    PARSE_OPT_NONEG, output_directory_callback),
-		OPT_CALLBACK_F('k', "keep-subject", &rev, NULL,
-			    N_("don't strip/add [PATCH]"),
-			    PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback),
-		OPT_BOOL(0, "no-binary", &no_binary_diff,
-			 N_("don't output binary diffs")),
-		OPT_BOOL(0, "zero-commit", &zero_commit,
-			 N_("output all-zero hash in From header")),
-		OPT_BOOL(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
-			 N_("don't include a patch matching a commit upstream")),
-		OPT_SET_INT_F('p', "no-stat", &use_patch_format,
-			      N_("show patch format instead of default (patch + stat)"),
-			      1, PARSE_OPT_NONEG),
-		OPT_GROUP(N_("Messaging")),
-		OPT_CALLBACK(0, "add-header", NULL, N_("header"),
-			    N_("add email header"), header_callback),
-		OPT_CALLBACK(0, "to", NULL, N_("email"), N_("add To: header"), to_callback),
-		OPT_CALLBACK(0, "cc", NULL, N_("email"), N_("add Cc: header"), cc_callback),
-		OPT_CALLBACK_F(0, "from", &from, N_("ident"),
-			    N_("set From address to <ident> (or committer ident if absent)"),
-			    PARSE_OPT_OPTARG, from_callback),
-		OPT_STRING(0, "in-reply-to", &in_reply_to, N_("message-id"),
-			    N_("make first mail a reply to <message-id>")),
-		OPT_CALLBACK_F(0, "attach", &rev, N_("boundary"),
-			    N_("attach the patch"), PARSE_OPT_OPTARG,
-			    attach_callback),
-		OPT_CALLBACK_F(0, "inline", &rev, N_("boundary"),
-			    N_("inline the patch"),
-			    PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
-			    inline_callback),
-		OPT_CALLBACK_F(0, "thread", &thread, N_("style"),
-			    N_("enable message threading, styles: shallow, deep"),
-			    PARSE_OPT_OPTARG, thread_callback),
-		OPT_STRING(0, "signature", &signature, N_("signature"),
-			    N_("add a signature")),
-		OPT_CALLBACK_F(0, "base", &base_commit, N_("base-commit"),
-			       N_("add prerequisite tree info to the patch series"),
-			       0, base_callback),
-		OPT_FILENAME(0, "signature-file", &signature_file,
-				N_("add a signature from a file")),
-		OPT__QUIET(&quiet, N_("don't print the patch filenames")),
-		OPT_BOOL(0, "progress", &show_progress,
-			 N_("show progress while generating patches")),
-		OPT_CALLBACK(0, "interdiff", &idiff_prev, N_("rev"),
-			     N_("show changes against <rev> in cover letter or single patch"),
-			     parse_opt_object_name),
-		OPT_STRING(0, "range-diff", &rdiff_prev, N_("refspec"),
-			   N_("show changes against <refspec> in cover letter or single patch")),
-		OPT_INTEGER(0, "creation-factor", &creation_factor,
-			    N_("percentage by which creation is weighted")),
-		OPT_END()
-	};
-
-	extra_hdr.strdup_strings = 1;
-	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));
-	rev.commit_format = CMIT_FMT_EMAIL;
-	rev.encode_email_headers = default_encode_email_headers;
-	rev.expand_tabs_in_log_default = 0;
-	rev.verbose_header = 1;
-	rev.diff = 1;
-	rev.max_parents = 1;
-	rev.diffopt.flags.recursive = 1;
-	rev.subject_prefix = fmt_patch_subject_prefix;
-	memset(&s_r_opt, 0, sizeof(s_r_opt));
-	s_r_opt.def = "HEAD";
-	s_r_opt.revarg_opt = REVARG_COMMITTISH;
-
-	if (default_attach) {
-		rev.mime_boundary = default_attach;
-		rev.no_inline = 1;
-	}
-
-	/*
-	 * Parse the arguments before setup_revisions(), or something
-	 * like "git format-patch -o a123 HEAD^.." may fail; a123 is
-	 * possibly a valid SHA1.
-	 */
-	argc = parse_options(argc, argv, prefix, builtin_format_patch_options,
-			     builtin_format_patch_usage,
-			     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",
-			    rev.subject_prefix, reroll_count);
-		rev.reroll_count = reroll_count;
-		rev.subject_prefix = strbuf_detach(&sprefix, NULL);
-	}
-
-	for (i = 0; i < extra_hdr.nr; i++) {
-		strbuf_addstr(&buf, extra_hdr.items[i].string);
-		strbuf_addch(&buf, '\n');
-	}
-
-	if (extra_to.nr)
-		strbuf_addstr(&buf, "To: ");
-	for (i = 0; i < extra_to.nr; i++) {
-		if (i)
-			strbuf_addstr(&buf, "    ");
-		strbuf_addstr(&buf, extra_to.items[i].string);
-		if (i + 1 < extra_to.nr)
-			strbuf_addch(&buf, ',');
-		strbuf_addch(&buf, '\n');
-	}
-
-	if (extra_cc.nr)
-		strbuf_addstr(&buf, "Cc: ");
-	for (i = 0; i < extra_cc.nr; i++) {
-		if (i)
-			strbuf_addstr(&buf, "    ");
-		strbuf_addstr(&buf, extra_cc.items[i].string);
-		if (i + 1 < extra_cc.nr)
-			strbuf_addch(&buf, ',');
-		strbuf_addch(&buf, '\n');
-	}
-
-	rev.extra_headers = strbuf_detach(&buf, NULL);
-
-	if (from) {
-		if (split_ident_line(&rev.from_ident, from, strlen(from)))
-			die(_("invalid ident line: %s"), from);
-	}
-
-	if (start_number < 0)
-		start_number = 1;
-
-	/*
-	 * If numbered is set solely due to format.numbered in config,
-	 * and it would conflict with --keep-subject (-k) from the
-	 * command line, reset "numbered".
-	 */
-	if (numbered && keep_subject && !numbered_cmdline_opt)
-		numbered = 0;
-
-	if (numbered && keep_subject)
-		die(_("-n and -k are mutually exclusive"));
-	if (keep_subject && subject_prefix)
-		die(_("--subject-prefix/--rfc and -k are mutually exclusive"));
-	rev.preserve_subject = keep_subject;
-
-	argc = setup_revisions(argc, argv, &rev, &s_r_opt);
-	if (argc > 1)
-		die(_("unrecognized argument: %s"), argv[1]);
-
-	if (rev.diffopt.output_format & DIFF_FORMAT_NAME)
-		die(_("--name-only does not make sense"));
-	if (rev.diffopt.output_format & DIFF_FORMAT_NAME_STATUS)
-		die(_("--name-status does not make sense"));
-	if (rev.diffopt.output_format & DIFF_FORMAT_CHECKDIFF)
-		die(_("--check does not make sense"));
-
-	if (!use_patch_format &&
-		(!rev.diffopt.output_format ||
-		 rev.diffopt.output_format == DIFF_FORMAT_PATCH))
-		rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SUMMARY;
-	if (!rev.diffopt.stat_width)
-		rev.diffopt.stat_width = MAIL_DEFAULT_WRAP;
-
-	/* Always generate a patch */
-	rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
-
-	rev.zero_commit = zero_commit;
-
-	if (!rev.diffopt.flags.text && !no_binary_diff)
-		rev.diffopt.flags.binary = 1;
-
-	if (rev.show_notes)
-		load_display_notes(&rev.notes_opt);
-
-	if (!output_directory && !use_stdout)
-		output_directory = config_output_directory;
-
-	if (!use_stdout)
-		output_directory = set_outdir(prefix, output_directory);
-	else
-		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);
-	}
-
-	if (rev.pending.nr == 1) {
-		int check_head = 0;
-
-		if (rev.max_count < 0 && !rev.show_root_diff) {
-			/*
-			 * This is traditional behaviour of "git format-patch
-			 * origin" that prepares what the origin side still
-			 * does not have.
-			 */
-			rev.pending.objects[0].item->flags |= UNINTERESTING;
-			add_head_to_pending(&rev);
-			check_head = 1;
-		}
-		/*
-		 * Otherwise, it is "format-patch -22 HEAD", and/or
-		 * "format-patch --root HEAD".  The user wants
-		 * get_revision() to do the usual traversal.
-		 */
-
-		if (!strcmp(rev.pending.objects[0].name, "HEAD"))
-			check_head = 1;
-
-		if (check_head) {
-			const char *ref, *v;
-			ref = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
-						 NULL, NULL);
-			if (ref && skip_prefix(ref, "refs/heads/", &v))
-				branch_name = xstrdup(v);
-			else
-				branch_name = xstrdup(""); /* no branch */
-		}
-	}
-
-	/*
-	 * We cannot move this anywhere earlier because we do want to
-	 * know if --root was given explicitly from the command line.
-	 */
-	rev.show_root_diff = 1;
-
-	if (ignore_if_in_upstream) {
-		/* Don't say anything if head and upstream are the same. */
-		if (rev.pending.nr == 2) {
-			struct object_array_entry *o = rev.pending.objects;
-			if (oideq(&o[0].item->oid, &o[1].item->oid))
-				goto done;
-		}
-		get_patch_ids(&rev, &ids);
-	}
-
-	if (prepare_revision_walk(&rev))
-		die(_("revision walk setup failed"));
-	rev.boundary = 1;
-	while ((commit = get_revision(&rev)) != NULL) {
-		if (commit->object.flags & BOUNDARY) {
-			boundary_count++;
-			origin = (boundary_count == 1) ? commit : NULL;
-			continue;
-		}
-
-		if (ignore_if_in_upstream && has_commit_patch_id(commit, &ids))
-			continue;
-
-		nr++;
-		REALLOC_ARRAY(list, nr);
-		list[nr - 1] = commit;
-	}
-	if (nr == 0)
-		/* nothing to do */
-		goto done;
-	total = nr;
-	if (cover_letter == -1) {
-		if (config_cover_letter == COVER_AUTO)
-			cover_letter = (total > 1);
-		else
-			cover_letter = (config_cover_letter == COVER_ON);
-	}
-	if (!keep_subject && auto_number && (total > 1 || cover_letter))
-		numbered = 1;
-	if (numbered)
-		rev.total = total + start_number - 1;
-
-	if (idiff_prev.nr) {
-		if (!cover_letter && total != 1)
-			die(_("--interdiff requires --cover-letter or single patch"));
-		rev.idiff_oid1 = &idiff_prev.oid[idiff_prev.nr - 1];
-		rev.idiff_oid2 = get_commit_tree_oid(list[0]);
-		rev.idiff_title = diff_title(&idiff_title, reroll_count,
-					     _("Interdiff:"),
-					     _("Interdiff against v%d:"));
-	}
-
-	if (creation_factor < 0)
-		creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT;
-	else if (!rdiff_prev)
-		die(_("--creation-factor requires --range-diff"));
-
-	if (rdiff_prev) {
-		if (!cover_letter && total != 1)
-			die(_("--range-diff requires --cover-letter or single patch"));
-
-		infer_range_diff_ranges(&rdiff1, &rdiff2, rdiff_prev,
-					origin, list[0]);
-		rev.rdiff1 = rdiff1.buf;
-		rev.rdiff2 = rdiff2.buf;
-		rev.creation_factor = creation_factor;
-		rev.rdiff_title = diff_title(&rdiff_title, reroll_count,
-					     _("Range-diff:"),
-					     _("Range-diff against v%d:"));
-	}
-
-	if (!signature) {
-		; /* --no-signature inhibits all signatures */
-	} else if (signature && signature != git_version_string) {
-		; /* non-default signature already set */
-	} else if (signature_file) {
-		struct strbuf buf = STRBUF_INIT;
-
-		if (strbuf_read_file(&buf, signature_file, 128) < 0)
-			die_errno(_("unable to read signature file '%s'"), signature_file);
-		signature = strbuf_detach(&buf, NULL);
-	}
-
-	memset(&bases, 0, sizeof(bases));
-	base = get_base_commit(base_commit, list, nr);
-	if (base) {
-		reset_revision_walk();
-		clear_object_flags(UNINTERESTING);
-		prepare_bases(&bases, base, list, nr);
-	}
-
-	if (in_reply_to || thread || cover_letter)
-		rev.ref_message_ids = xcalloc(1, sizeof(struct string_list));
-	if (in_reply_to) {
-		const char *msgid = clean_message_id(in_reply_to);
-		string_list_append(rev.ref_message_ids, msgid);
-	}
-	rev.numbered_files = just_numbers;
-	rev.patch_suffix = fmt_patch_suffix;
-	if (cover_letter) {
-		if (thread)
-			gen_message_id(&rev, "cover");
-		make_cover_letter(&rev, use_stdout,
-				  origin, nr, list, branch_name, quiet);
-		print_bases(&bases, rev.diffopt.file);
-		print_signature(rev.diffopt.file);
-		total++;
-		start_number--;
-		/* interdiff/range-diff in cover-letter; omit from patches */
-		rev.idiff_oid1 = NULL;
-		rev.rdiff1 = NULL;
-	}
-	rev.add_signoff = do_signoff;
-
-	if (show_progress)
-		progress = start_delayed_progress(_("Generating patches"), total);
-	while (0 <= --nr) {
-		int shown;
-		display_progress(progress, total - nr);
-		commit = list[nr];
-		rev.nr = total - nr + (start_number - 1);
-		/* Make the second and subsequent mails replies to the first */
-		if (thread) {
-			/* Have we already had a message ID? */
-			if (rev.message_id) {
-				/*
-				 * For deep threading: make every mail
-				 * a reply to the previous one, no
-				 * matter what other options are set.
-				 *
-				 * For shallow threading:
-				 *
-				 * Without --cover-letter and
-				 * --in-reply-to, make every mail a
-				 * reply to the one before.
-				 *
-				 * With --in-reply-to but no
-				 * --cover-letter, make every mail a
-				 * reply to the <reply-to>.
-				 *
-				 * With --cover-letter, make every
-				 * mail but the cover letter a reply
-				 * to the cover letter.  The cover
-				 * letter is a reply to the
-				 * --in-reply-to, if specified.
-				 */
-				if (thread == THREAD_SHALLOW
-				    && rev.ref_message_ids->nr > 0
-				    && (!cover_letter || rev.nr > 1))
-					free(rev.message_id);
-				else
-					string_list_append(rev.ref_message_ids,
-							   rev.message_id);
-			}
-			gen_message_id(&rev, oid_to_hex(&commit->object.oid));
-		}
-
-		if (!use_stdout &&
-		    open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
-			die(_("failed to create output files"));
-		shown = log_tree_commit(&rev, commit);
-		free_commit_buffer(the_repository->parsed_objects,
-				   commit);
-
-		/* We put one extra blank line between formatted
-		 * patches and this flag is used by log-tree code
-		 * to see if it needs to emit a LF before showing
-		 * the log; when using one file per patch, we do
-		 * not want the extra blank line.
-		 */
-		if (!use_stdout)
-			rev.shown_one = 0;
-		if (shown) {
-			print_bases(&bases, rev.diffopt.file);
-			if (rev.mime_boundary)
-				fprintf(rev.diffopt.file, "\n--%s%s--\n\n\n",
-				       mime_boundary_leader,
-				       rev.mime_boundary);
-			else
-				print_signature(rev.diffopt.file);
-		}
-		if (!use_stdout)
-			fclose(rev.diffopt.file);
-	}
-	stop_progress(&progress);
-	free(list);
-	free(branch_name);
-	string_list_clear(&extra_to, 0);
-	string_list_clear(&extra_cc, 0);
-	string_list_clear(&extra_hdr, 0);
-	if (ignore_if_in_upstream)
-		free_patch_ids(&ids);
-
-done:
-	oid_array_clear(&idiff_prev);
-	strbuf_release(&idiff_title);
-	strbuf_release(&rdiff1);
-	strbuf_release(&rdiff2);
-	strbuf_release(&rdiff_title);
-	return 0;
-}
-
-static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)
-{
-	struct object_id oid;
-	if (get_oid(arg, &oid) == 0) {
-		struct commit *commit = lookup_commit_reference(the_repository,
-								&oid);
-		if (commit) {
-			commit->object.flags |= flags;
-			add_pending_object(revs, &commit->object, arg);
-			return 0;
-		}
-	}
-	return -1;
-}
-
-static const char * const cherry_usage[] = {
-	N_("git cherry [-v] [<upstream> [<head> [<limit>]]]"),
-	NULL
-};
-
-static void print_commit(char sign, struct commit *commit, int verbose,
-			 int abbrev, FILE *file)
-{
-	if (!verbose) {
-		fprintf(file, "%c %s\n", sign,
-		       find_unique_abbrev(&commit->object.oid, abbrev));
-	} else {
-		struct strbuf buf = STRBUF_INIT;
-		pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);
-		fprintf(file, "%c %s %s\n", sign,
-		       find_unique_abbrev(&commit->object.oid, abbrev),
-		       buf.buf);
-		strbuf_release(&buf);
-	}
-}
-
-int cmd_cherry(int argc, const char **argv, const char *prefix)
-{
-	struct rev_info revs;
-	struct patch_ids ids;
-	struct commit *commit;
-	struct commit_list *list = NULL;
-	struct branch *current_branch;
-	const char *upstream;
-	const char *head = "HEAD";
-	const char *limit = NULL;
-	int verbose = 0, abbrev = 0;
-
-	struct option options[] = {
-		OPT__ABBREV(&abbrev),
-		OPT__VERBOSE(&verbose, N_("be verbose")),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, options, cherry_usage, 0);
-
-	switch (argc) {
-	case 3:
-		limit = argv[2];
-		/* FALLTHROUGH */
-	case 2:
-		head = argv[1];
-		/* FALLTHROUGH */
-	case 1:
-		upstream = argv[0];
-		break;
-	default:
-		current_branch = branch_get(NULL);
-		upstream = branch_get_upstream(current_branch, NULL);
-		if (!upstream) {
-			fprintf(stderr, _("Could not find a tracked"
-					" remote branch, please"
-					" specify <upstream> manually.\n"));
-			usage_with_options(cherry_usage, options);
-		}
-	}
-
-	repo_init_revisions(the_repository, &revs, prefix);
-	revs.max_parents = 1;
-
-	if (add_pending_commit(head, &revs, 0))
-		die(_("unknown commit %s"), head);
-	if (add_pending_commit(upstream, &revs, UNINTERESTING))
-		die(_("unknown commit %s"), upstream);
-
-	/* Don't say anything if head and upstream are the same. */
-	if (revs.pending.nr == 2) {
-		struct object_array_entry *o = revs.pending.objects;
-		if (oideq(&o[0].item->oid, &o[1].item->oid))
-			return 0;
-	}
-
-	get_patch_ids(&revs, &ids);
-
-	if (limit && add_pending_commit(limit, &revs, UNINTERESTING))
-		die(_("unknown commit %s"), limit);
-
-	/* reverse the list of commits */
-	if (prepare_revision_walk(&revs))
-		die(_("revision walk setup failed"));
-	while ((commit = get_revision(&revs)) != NULL) {
-		commit_list_insert(commit, &list);
-	}
-
-	while (list) {
-		char sign = '+';
-
-		commit = list->item;
-		if (has_commit_patch_id(commit, &ids))
-			sign = '-';
-		print_commit(sign, commit, verbose, abbrev, revs.diffopt.file);
-		list = list->next;
-	}
-
-	free_patch_ids(&ids);
-	return 0;
-}
diff --git a/third_party/git/builtin/ls-files.c b/third_party/git/builtin/ls-files.c
deleted file mode 100644
index c8eae899b82a..000000000000
--- a/third_party/git/builtin/ls-files.c
+++ /dev/null
@@ -1,693 +0,0 @@
-/*
- * This merges the file listing in the directory cache index
- * with the actual working directory list, and shows different
- * combinations of the two.
- *
- * Copyright (C) Linus Torvalds, 2005
- */
-#include "cache.h"
-#include "repository.h"
-#include "config.h"
-#include "quote.h"
-#include "dir.h"
-#include "builtin.h"
-#include "tree.h"
-#include "parse-options.h"
-#include "resolve-undo.h"
-#include "string-list.h"
-#include "pathspec.h"
-#include "run-command.h"
-#include "submodule.h"
-#include "submodule-config.h"
-
-static int abbrev;
-static int show_deleted;
-static int show_cached;
-static int show_others;
-static int show_stage;
-static int show_unmerged;
-static int show_resolve_undo;
-static int show_modified;
-static int show_killed;
-static int show_valid_bit;
-static int show_fsmonitor_bit;
-static int line_terminator = '\n';
-static int debug_mode;
-static int show_eol;
-static int recurse_submodules;
-
-static const char *prefix;
-static int max_prefix_len;
-static int prefix_len;
-static struct pathspec pathspec;
-static int error_unmatch;
-static char *ps_matched;
-static const char *with_tree;
-static int exc_given;
-static int exclude_args;
-
-static const char *tag_cached = "";
-static const char *tag_unmerged = "";
-static const char *tag_removed = "";
-static const char *tag_other = "";
-static const char *tag_killed = "";
-static const char *tag_modified = "";
-static const char *tag_skip_worktree = "";
-static const char *tag_resolve_undo = "";
-
-static void write_eolinfo(const struct index_state *istate,
-			  const struct cache_entry *ce, const char *path)
-{
-	if (show_eol) {
-		struct stat st;
-		const char *i_txt = "";
-		const char *w_txt = "";
-		const char *a_txt = get_convert_attr_ascii(istate, path);
-		if (ce && S_ISREG(ce->ce_mode))
-			i_txt = get_cached_convert_stats_ascii(istate,
-							       ce->name);
-		if (!lstat(path, &st) && S_ISREG(st.st_mode))
-			w_txt = get_wt_convert_stats_ascii(path);
-		printf("i/%-5s w/%-5s attr/%-17s\t", i_txt, w_txt, a_txt);
-	}
-}
-
-static void write_name(const char *name)
-{
-	/*
-	 * With "--full-name", prefix_len=0; this caller needs to pass
-	 * an empty string in that case (a NULL is good for "").
-	 */
-	write_name_quoted_relative(name, prefix_len ? prefix : NULL,
-				   stdout, line_terminator);
-}
-
-static const char *get_tag(const struct cache_entry *ce, const char *tag)
-{
-	static char alttag[4];
-
-	if (tag && *tag && ((show_valid_bit && (ce->ce_flags & CE_VALID)) ||
-		(show_fsmonitor_bit && (ce->ce_flags & CE_FSMONITOR_VALID)))) {
-		memcpy(alttag, tag, 3);
-
-		if (isalpha(tag[0])) {
-			alttag[0] = tolower(tag[0]);
-		} else if (tag[0] == '?') {
-			alttag[0] = '!';
-		} else {
-			alttag[0] = 'v';
-			alttag[1] = tag[0];
-			alttag[2] = ' ';
-			alttag[3] = 0;
-		}
-
-		tag = alttag;
-	}
-
-	return tag;
-}
-
-static void print_debug(const struct cache_entry *ce)
-{
-	if (debug_mode) {
-		const struct stat_data *sd = &ce->ce_stat_data;
-
-		printf("  ctime: %u:%u\n", sd->sd_ctime.sec, sd->sd_ctime.nsec);
-		printf("  mtime: %u:%u\n", sd->sd_mtime.sec, sd->sd_mtime.nsec);
-		printf("  dev: %u\tino: %u\n", sd->sd_dev, sd->sd_ino);
-		printf("  uid: %u\tgid: %u\n", sd->sd_uid, sd->sd_gid);
-		printf("  size: %u\tflags: %x\n", sd->sd_size, ce->ce_flags);
-	}
-}
-
-static void show_dir_entry(const struct index_state *istate,
-			   const char *tag, struct dir_entry *ent)
-{
-	int len = max_prefix_len;
-
-	if (len > ent->len)
-		die("git ls-files: internal error - directory entry not superset of prefix");
-
-	/* If ps_matches is non-NULL, figure out which pathspec(s) match. */
-	if (ps_matched)
-		dir_path_match(istate, ent, &pathspec, len, ps_matched);
-
-	fputs(tag, stdout);
-	write_eolinfo(istate, NULL, ent->name);
-	write_name(ent->name);
-}
-
-static void show_other_files(const struct index_state *istate,
-			     const struct dir_struct *dir)
-{
-	int i;
-
-	for (i = 0; i < dir->nr; i++) {
-		struct dir_entry *ent = dir->entries[i];
-		if (!index_name_is_other(istate, ent->name, ent->len))
-			continue;
-		show_dir_entry(istate, tag_other, ent);
-	}
-}
-
-static void show_killed_files(const struct index_state *istate,
-			      const struct dir_struct *dir)
-{
-	int i;
-	for (i = 0; i < dir->nr; i++) {
-		struct dir_entry *ent = dir->entries[i];
-		char *cp, *sp;
-		int pos, len, killed = 0;
-
-		for (cp = ent->name; cp - ent->name < ent->len; cp = sp + 1) {
-			sp = strchr(cp, '/');
-			if (!sp) {
-				/* If ent->name is prefix of an entry in the
-				 * cache, it will be killed.
-				 */
-				pos = index_name_pos(istate, ent->name, ent->len);
-				if (0 <= pos)
-					BUG("killed-file %.*s not found",
-						ent->len, ent->name);
-				pos = -pos - 1;
-				while (pos < istate->cache_nr &&
-				       ce_stage(istate->cache[pos]))
-					pos++; /* skip unmerged */
-				if (istate->cache_nr <= pos)
-					break;
-				/* pos points at a name immediately after
-				 * ent->name in the cache.  Does it expect
-				 * ent->name to be a directory?
-				 */
-				len = ce_namelen(istate->cache[pos]);
-				if ((ent->len < len) &&
-				    !strncmp(istate->cache[pos]->name,
-					     ent->name, ent->len) &&
-				    istate->cache[pos]->name[ent->len] == '/')
-					killed = 1;
-				break;
-			}
-			if (0 <= index_name_pos(istate, ent->name, sp - ent->name)) {
-				/* If any of the leading directories in
-				 * ent->name is registered in the cache,
-				 * ent->name will be killed.
-				 */
-				killed = 1;
-				break;
-			}
-		}
-		if (killed)
-			show_dir_entry(istate, tag_killed, dir->entries[i]);
-	}
-}
-
-static void show_files(struct repository *repo, struct dir_struct *dir);
-
-static void show_submodule(struct repository *superproject,
-			   struct dir_struct *dir, const char *path)
-{
-	struct repository subrepo;
-	const struct submodule *sub = submodule_from_path(superproject,
-							  &null_oid, path);
-
-	if (repo_submodule_init(&subrepo, superproject, sub))
-		return;
-
-	if (repo_read_index(&subrepo) < 0)
-		die("index file corrupt");
-
-	show_files(&subrepo, dir);
-
-	repo_clear(&subrepo);
-}
-
-static void show_ce(struct repository *repo, struct dir_struct *dir,
-		    const struct cache_entry *ce, const char *fullname,
-		    const char *tag)
-{
-	if (max_prefix_len > strlen(fullname))
-		die("git ls-files: internal error - cache entry not superset of prefix");
-
-	if (recurse_submodules && S_ISGITLINK(ce->ce_mode) &&
-	    is_submodule_active(repo, ce->name)) {
-		show_submodule(repo, dir, ce->name);
-	} else if (match_pathspec(repo->index, &pathspec, fullname, strlen(fullname),
-				  max_prefix_len, ps_matched,
-				  S_ISDIR(ce->ce_mode) ||
-				  S_ISGITLINK(ce->ce_mode))) {
-		tag = get_tag(ce, tag);
-
-		if (!show_stage) {
-			fputs(tag, stdout);
-		} else {
-			printf("%s%06o %s %d\t",
-			       tag,
-			       ce->ce_mode,
-			       find_unique_abbrev(&ce->oid, abbrev),
-			       ce_stage(ce));
-		}
-		write_eolinfo(repo->index, ce, fullname);
-		write_name(fullname);
-		print_debug(ce);
-	}
-}
-
-static void show_ru_info(const struct index_state *istate)
-{
-	struct string_list_item *item;
-
-	if (!istate->resolve_undo)
-		return;
-
-	for_each_string_list_item(item, istate->resolve_undo) {
-		const char *path = item->string;
-		struct resolve_undo_info *ui = item->util;
-		int i, len;
-
-		len = strlen(path);
-		if (len < max_prefix_len)
-			continue; /* outside of the prefix */
-		if (!match_pathspec(istate, &pathspec, path, len,
-				    max_prefix_len, ps_matched, 0))
-			continue; /* uninterested */
-		for (i = 0; i < 3; i++) {
-			if (!ui->mode[i])
-				continue;
-			printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i],
-			       find_unique_abbrev(&ui->oid[i], abbrev),
-			       i + 1);
-			write_name(path);
-		}
-	}
-}
-
-static int ce_excluded(struct dir_struct *dir, struct index_state *istate,
-		       const char *fullname, const struct cache_entry *ce)
-{
-	int dtype = ce_to_dtype(ce);
-	return is_excluded(dir, istate, fullname, &dtype);
-}
-
-static void construct_fullname(struct strbuf *out, const struct repository *repo,
-			       const struct cache_entry *ce)
-{
-	strbuf_reset(out);
-	if (repo->submodule_prefix)
-		strbuf_addstr(out, repo->submodule_prefix);
-	strbuf_addstr(out, ce->name);
-}
-
-static void show_files(struct repository *repo, struct dir_struct *dir)
-{
-	int i;
-	struct strbuf fullname = STRBUF_INIT;
-
-	/* For cached/deleted files we don't need to even do the readdir */
-	if (show_others || show_killed) {
-		if (!show_others)
-			dir->flags |= DIR_COLLECT_KILLED_ONLY;
-		fill_directory(dir, repo->index, &pathspec);
-		if (show_others)
-			show_other_files(repo->index, dir);
-		if (show_killed)
-			show_killed_files(repo->index, dir);
-	}
-	if (show_cached || show_stage) {
-		for (i = 0; i < repo->index->cache_nr; i++) {
-			const struct cache_entry *ce = repo->index->cache[i];
-
-			construct_fullname(&fullname, repo, ce);
-
-			if ((dir->flags & DIR_SHOW_IGNORED) &&
-			    !ce_excluded(dir, repo->index, fullname.buf, ce))
-				continue;
-			if (show_unmerged && !ce_stage(ce))
-				continue;
-			if (ce->ce_flags & CE_UPDATE)
-				continue;
-			show_ce(repo, dir, ce, fullname.buf,
-				ce_stage(ce) ? tag_unmerged :
-				(ce_skip_worktree(ce) ? tag_skip_worktree :
-				 tag_cached));
-		}
-	}
-	if (show_deleted || show_modified) {
-		for (i = 0; i < repo->index->cache_nr; i++) {
-			const struct cache_entry *ce = repo->index->cache[i];
-			struct stat st;
-			int err;
-
-			construct_fullname(&fullname, repo, ce);
-
-			if ((dir->flags & DIR_SHOW_IGNORED) &&
-			    !ce_excluded(dir, repo->index, fullname.buf, ce))
-				continue;
-			if (ce->ce_flags & CE_UPDATE)
-				continue;
-			if (ce_skip_worktree(ce))
-				continue;
-			err = lstat(fullname.buf, &st);
-			if (show_deleted && err)
-				show_ce(repo, dir, ce, fullname.buf, tag_removed);
-			if (show_modified && ie_modified(repo->index, ce, &st, 0))
-				show_ce(repo, dir, ce, fullname.buf, tag_modified);
-		}
-	}
-
-	strbuf_release(&fullname);
-}
-
-/*
- * Prune the index to only contain stuff starting with "prefix"
- */
-static void prune_index(struct index_state *istate,
-			const char *prefix, size_t prefixlen)
-{
-	int pos;
-	unsigned int first, last;
-
-	if (!prefix || !istate->cache_nr)
-		return;
-	pos = index_name_pos(istate, prefix, prefixlen);
-	if (pos < 0)
-		pos = -pos-1;
-	first = pos;
-	last = istate->cache_nr;
-	while (last > first) {
-		int next = first + ((last - first) >> 1);
-		const struct cache_entry *ce = istate->cache[next];
-		if (!strncmp(ce->name, prefix, prefixlen)) {
-			first = next+1;
-			continue;
-		}
-		last = next;
-	}
-	MOVE_ARRAY(istate->cache, istate->cache + pos, last - pos);
-	istate->cache_nr = last - pos;
-}
-
-static int get_common_prefix_len(const char *common_prefix)
-{
-	int common_prefix_len;
-
-	if (!common_prefix)
-		return 0;
-
-	common_prefix_len = strlen(common_prefix);
-
-	/*
-	 * If the prefix has a trailing slash, strip it so that submodules wont
-	 * be pruned from the index.
-	 */
-	if (common_prefix[common_prefix_len - 1] == '/')
-		common_prefix_len--;
-
-	return common_prefix_len;
-}
-
-/*
- * Read the tree specified with --with-tree option
- * (typically, HEAD) into stage #1 and then
- * squash them down to stage #0.  This is used for
- * --error-unmatch to list and check the path patterns
- * that were given from the command line.  We are not
- * going to write this index out.
- */
-void overlay_tree_on_index(struct index_state *istate,
-			   const char *tree_name, const char *prefix)
-{
-	struct tree *tree;
-	struct object_id oid;
-	struct pathspec pathspec;
-	struct cache_entry *last_stage0 = NULL;
-	int i;
-
-	if (get_oid(tree_name, &oid))
-		die("tree-ish %s not found.", tree_name);
-	tree = parse_tree_indirect(&oid);
-	if (!tree)
-		die("bad tree-ish %s", tree_name);
-
-	/* Hoist the unmerged entries up to stage #3 to make room */
-	for (i = 0; i < istate->cache_nr; i++) {
-		struct cache_entry *ce = istate->cache[i];
-		if (!ce_stage(ce))
-			continue;
-		ce->ce_flags |= CE_STAGEMASK;
-	}
-
-	if (prefix) {
-		static const char *(matchbuf[1]);
-		matchbuf[0] = NULL;
-		parse_pathspec(&pathspec, PATHSPEC_ALL_MAGIC,
-			       PATHSPEC_PREFER_CWD, prefix, matchbuf);
-	} else
-		memset(&pathspec, 0, sizeof(pathspec));
-	if (read_tree(the_repository, tree, 1, &pathspec, istate))
-		die("unable to read tree entries %s", tree_name);
-
-	for (i = 0; i < istate->cache_nr; i++) {
-		struct cache_entry *ce = istate->cache[i];
-		switch (ce_stage(ce)) {
-		case 0:
-			last_stage0 = ce;
-			/* fallthru */
-		default:
-			continue;
-		case 1:
-			/*
-			 * If there is stage #0 entry for this, we do not
-			 * need to show it.  We use CE_UPDATE bit to mark
-			 * such an entry.
-			 */
-			if (last_stage0 &&
-			    !strcmp(last_stage0->name, ce->name))
-				ce->ce_flags |= CE_UPDATE;
-		}
-	}
-}
-
-static const char * const ls_files_usage[] = {
-	N_("git ls-files [<options>] [<file>...]"),
-	NULL
-};
-
-static int option_parse_exclude(const struct option *opt,
-				const char *arg, int unset)
-{
-	struct string_list *exclude_list = opt->value;
-
-	BUG_ON_OPT_NEG(unset);
-
-	exc_given = 1;
-	string_list_append(exclude_list, arg);
-
-	return 0;
-}
-
-static int option_parse_exclude_from(const struct option *opt,
-				     const char *arg, int unset)
-{
-	struct dir_struct *dir = opt->value;
-
-	BUG_ON_OPT_NEG(unset);
-
-	exc_given = 1;
-	add_patterns_from_file(dir, arg);
-
-	return 0;
-}
-
-static int option_parse_exclude_standard(const struct option *opt,
-					 const char *arg, int unset)
-{
-	struct dir_struct *dir = opt->value;
-
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-
-	exc_given = 1;
-	setup_standard_excludes(dir);
-
-	return 0;
-}
-
-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 string_list exclude_list = STRING_LIST_INIT_NODUP;
-	struct option builtin_ls_files_options[] = {
-		/* Think twice before adding "--nul" synonym to this */
-		OPT_SET_INT('z', NULL, &line_terminator,
-			N_("paths are separated with NUL character"), '\0'),
-		OPT_BOOL('t', NULL, &show_tag,
-			N_("identify the file status with tags")),
-		OPT_BOOL('v', NULL, &show_valid_bit,
-			N_("use lowercase letters for 'assume unchanged' files")),
-		OPT_BOOL('f', NULL, &show_fsmonitor_bit,
-			N_("use lowercase letters for 'fsmonitor clean' files")),
-		OPT_BOOL('c', "cached", &show_cached,
-			N_("show cached files in the output (default)")),
-		OPT_BOOL('d', "deleted", &show_deleted,
-			N_("show deleted files in the output")),
-		OPT_BOOL('m', "modified", &show_modified,
-			N_("show modified files in the output")),
-		OPT_BOOL('o', "others", &show_others,
-			N_("show other files in the output")),
-		OPT_BIT('i', "ignored", &dir.flags,
-			N_("show ignored files in the output"),
-			DIR_SHOW_IGNORED),
-		OPT_BOOL('s', "stage", &show_stage,
-			N_("show staged contents' object name in the output")),
-		OPT_BOOL('k', "killed", &show_killed,
-			N_("show files on the filesystem that need to be removed")),
-		OPT_BIT(0, "directory", &dir.flags,
-			N_("show 'other' directories' names only"),
-			DIR_SHOW_OTHER_DIRECTORIES),
-		OPT_BOOL(0, "eol", &show_eol, N_("show line endings of files")),
-		OPT_NEGBIT(0, "empty-directory", &dir.flags,
-			N_("don't show empty directories"),
-			DIR_HIDE_EMPTY_DIRECTORIES),
-		OPT_BOOL('u', "unmerged", &show_unmerged,
-			N_("show unmerged files in the output")),
-		OPT_BOOL(0, "resolve-undo", &show_resolve_undo,
-			    N_("show resolve-undo information")),
-		OPT_CALLBACK_F('x', "exclude", &exclude_list, N_("pattern"),
-			N_("skip files matching pattern"),
-			PARSE_OPT_NONEG, option_parse_exclude),
-		OPT_CALLBACK_F('X', "exclude-from", &dir, N_("file"),
-			N_("exclude patterns are read from <file>"),
-			PARSE_OPT_NONEG, option_parse_exclude_from),
-		OPT_STRING(0, "exclude-per-directory", &dir.exclude_per_dir, N_("file"),
-			N_("read additional per-directory exclude patterns in <file>")),
-		OPT_CALLBACK_F(0, "exclude-standard", &dir, NULL,
-			N_("add the standard git exclusions"),
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG,
-			option_parse_exclude_standard),
-		OPT_SET_INT_F(0, "full-name", &prefix_len,
-			      N_("make the output relative to the project top directory"),
-			      0, PARSE_OPT_NONEG),
-		OPT_BOOL(0, "recurse-submodules", &recurse_submodules,
-			N_("recurse through submodules")),
-		OPT_BOOL(0, "error-unmatch", &error_unmatch,
-			N_("if any <file> is not in the index, treat this as an error")),
-		OPT_STRING(0, "with-tree", &with_tree, N_("tree-ish"),
-			N_("pretend that paths removed since <tree-ish> are still present")),
-		OPT__ABBREV(&abbrev),
-		OPT_BOOL(0, "debug", &debug_mode, N_("show debugging data")),
-		OPT_END()
-	};
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage_with_options(ls_files_usage, builtin_ls_files_options);
-
-	dir_init(&dir);
-	prefix = cmd_prefix;
-	if (prefix)
-		prefix_len = strlen(prefix);
-	git_config(git_default_config, NULL);
-
-	if (repo_read_index(the_repository) < 0)
-		die("index file corrupt");
-
-	argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
-			ls_files_usage, 0);
-	pl = add_pattern_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);
-	}
-	if (show_tag || show_valid_bit || show_fsmonitor_bit) {
-		tag_cached = "H ";
-		tag_unmerged = "M ";
-		tag_removed = "R ";
-		tag_modified = "C ";
-		tag_other = "? ";
-		tag_killed = "K ";
-		tag_skip_worktree = "S ";
-		tag_resolve_undo = "U ";
-	}
-	if (show_modified || show_others || show_deleted || (dir.flags & DIR_SHOW_IGNORED) || show_killed)
-		require_work_tree = 1;
-	if (show_unmerged)
-		/*
-		 * There's no point in showing unmerged unless
-		 * you also show the stage information.
-		 */
-		show_stage = 1;
-	if (dir.exclude_per_dir)
-		exc_given = 1;
-
-	if (require_work_tree && !is_inside_work_tree())
-		setup_work_tree();
-
-	if (recurse_submodules &&
-	    (show_stage || show_deleted || show_others || show_unmerged ||
-	     show_killed || show_modified || show_resolve_undo || with_tree))
-		die("ls-files --recurse-submodules unsupported mode");
-
-	if (recurse_submodules && error_unmatch)
-		die("ls-files --recurse-submodules does not support "
-		    "--error-unmatch");
-
-	parse_pathspec(&pathspec, 0,
-		       PATHSPEC_PREFER_CWD,
-		       prefix, argv);
-
-	/*
-	 * Find common prefix for all pathspec's
-	 * This is used as a performance optimization which unfortunately cannot
-	 * be done when recursing into submodules because when a pathspec is
-	 * given which spans repository boundaries you can't simply remove the
-	 * submodule entry because the pathspec may match something inside the
-	 * submodule.
-	 */
-	if (recurse_submodules)
-		max_prefix = NULL;
-	else
-		max_prefix = common_prefix(&pathspec);
-	max_prefix_len = get_common_prefix_len(max_prefix);
-
-	prune_index(the_repository->index, max_prefix, max_prefix_len);
-
-	/* Treat unmatching pathspec elements as errors */
-	if (pathspec.nr && error_unmatch)
-		ps_matched = xcalloc(pathspec.nr, 1);
-
-	if ((dir.flags & DIR_SHOW_IGNORED) && !exc_given)
-		die("ls-files --ignored needs some exclude pattern");
-
-	/* With no flags, we default to showing the cached files */
-	if (!(show_stage || show_deleted || show_others || show_unmerged ||
-	      show_killed || show_modified || show_resolve_undo))
-		show_cached = 1;
-
-	if (with_tree) {
-		/*
-		 * Basic sanity check; show-stages and show-unmerged
-		 * would not make any sense with this option.
-		 */
-		if (show_stage || show_unmerged)
-			die("ls-files --with-tree is incompatible with -s or -u");
-		overlay_tree_on_index(the_repository->index, with_tree, max_prefix);
-	}
-
-	show_files(the_repository, &dir);
-
-	if (show_resolve_undo)
-		show_ru_info(the_repository->index);
-
-	if (ps_matched) {
-		int bad;
-		bad = report_path_error(ps_matched, &pathspec);
-		if (bad)
-			fprintf(stderr, "Did you forget to 'git add'?\n");
-
-		return bad ? 1 : 0;
-	}
-
-	dir_clear(&dir);
-	return 0;
-}
diff --git a/third_party/git/builtin/ls-remote.c b/third_party/git/builtin/ls-remote.c
deleted file mode 100644
index 092917eca29b..000000000000
--- a/third_party/git/builtin/ls-remote.c
+++ /dev/null
@@ -1,154 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "transport.h"
-#include "ref-filter.h"
-#include "remote.h"
-#include "refs.h"
-
-static const char * const ls_remote_usage[] = {
-	N_("git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n"
-	   "                     [-q | --quiet] [--exit-code] [--get-url]\n"
-	   "                     [--symref] [<repository> [<refs>...]]"),
-	NULL
-};
-
-/*
- * Is there one among the list of patterns that match the tail part
- * of the path?
- */
-static int tail_match(const char **pattern, const char *path)
-{
-	const char *p;
-	char *pathbuf;
-
-	if (!pattern)
-		return 1; /* no restriction */
-
-	pathbuf = xstrfmt("/%s", path);
-	while ((p = *(pattern++)) != NULL) {
-		if (!wildmatch(p, pathbuf, 0)) {
-			free(pathbuf);
-			return 1;
-		}
-	}
-	free(pathbuf);
-	return 0;
-}
-
-int cmd_ls_remote(int argc, const char **argv, const char *prefix)
-{
-	const char *dest = NULL;
-	unsigned flags = 0;
-	int get_url = 0;
-	int quiet = 0;
-	int status = 0;
-	int show_symref_target = 0;
-	const char *uploadpack = NULL;
-	const char **pattern = NULL;
-	struct strvec ref_prefixes = STRVEC_INIT;
-	int i;
-	struct string_list server_options = STRING_LIST_INIT_DUP;
-
-	struct remote *remote;
-	struct transport *transport;
-	const struct ref *ref;
-	struct ref_array ref_array;
-	static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
-
-	struct option options[] = {
-		OPT__QUIET(&quiet, N_("do not print remote URL")),
-		OPT_STRING(0, "upload-pack", &uploadpack, N_("exec"),
-			   N_("path of git-upload-pack on the remote host")),
-		{ OPTION_STRING, 0, "exec", &uploadpack, N_("exec"),
-			   N_("path of git-upload-pack on the remote host"),
-			   PARSE_OPT_HIDDEN },
-		OPT_BIT('t', "tags", &flags, N_("limit to tags"), REF_TAGS),
-		OPT_BIT('h', "heads", &flags, N_("limit to heads"), REF_HEADS),
-		OPT_BIT(0, "refs", &flags, N_("do not show peeled tags"), REF_NORMAL),
-		OPT_BOOL(0, "get-url", &get_url,
-			 N_("take url.<base>.insteadOf into account")),
-		OPT_REF_SORT(sorting_tail),
-		OPT_SET_INT_F(0, "exit-code", &status,
-			      N_("exit with exit code 2 if no matching refs are found"),
-			      2, PARSE_OPT_NOCOMPLETE),
-		OPT_BOOL(0, "symref", &show_symref_target,
-			 N_("show underlying ref in addition to the object pointed by it")),
-		OPT_STRING_LIST('o', "server-option", &server_options, N_("server-specific"), N_("option to transmit")),
-		OPT_END()
-	};
-
-	memset(&ref_array, 0, sizeof(ref_array));
-
-	argc = parse_options(argc, argv, prefix, options, ls_remote_usage,
-			     PARSE_OPT_STOP_AT_NON_OPTION);
-	dest = argv[0];
-
-	UNLEAK(sorting);
-
-	if (argc > 1) {
-		int i;
-		pattern = xcalloc(argc, sizeof(const char *));
-		for (i = 1; i < argc; i++) {
-			pattern[i - 1] = xstrfmt("*/%s", argv[i]);
-		}
-	}
-
-	if (flags & REF_TAGS)
-		strvec_push(&ref_prefixes, "refs/tags/");
-	if (flags & REF_HEADS)
-		strvec_push(&ref_prefixes, "refs/heads/");
-
-	remote = remote_get(dest);
-	if (!remote) {
-		if (dest)
-			die("bad repository '%s'", dest);
-		die("No remote configured to list refs from.");
-	}
-	if (!remote->url_nr)
-		die("remote %s has no configured URL", dest);
-
-	if (get_url) {
-		printf("%s\n", *remote->url);
-		return 0;
-	}
-
-	transport = transport_get(remote, NULL);
-	if (uploadpack != NULL)
-		transport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack);
-	if (server_options.nr)
-		transport->server_options = &server_options;
-
-	ref = transport_get_remote_refs(transport, &ref_prefixes);
-	if (ref) {
-		int hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
-		repo_set_hash_algo(the_repository, hash_algo);
-	}
-	if (transport_disconnect(transport))
-		return 1;
-
-	if (!dest && !quiet)
-		fprintf(stderr, "From %s\n", *remote->url);
-	for ( ; ref; ref = ref->next) {
-		struct ref_array_item *item;
-		if (!check_ref_type(ref, flags))
-			continue;
-		if (!tail_match(pattern, ref->name))
-			continue;
-		item = ref_array_push(&ref_array, ref->name, &ref->old_oid);
-		item->symref = xstrdup_or_null(ref->symref);
-	}
-
-	if (sorting)
-		ref_array_sort(sorting, &ref_array);
-
-	for (i = 0; i < ref_array.nr; i++) {
-		const struct ref_array_item *ref = ref_array.items[i];
-		if (show_symref_target && ref->symref)
-			printf("ref: %s\t%s\n", ref->symref, ref->refname);
-		printf("%s\t%s\n", oid_to_hex(&ref->objectname), ref->refname);
-		status = 0; /* we found something */
-	}
-
-	ref_array_clear(&ref_array);
-	return status;
-}
diff --git a/third_party/git/builtin/ls-tree.c b/third_party/git/builtin/ls-tree.c
deleted file mode 100644
index 7cad3f24ebd0..000000000000
--- a/third_party/git/builtin/ls-tree.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * GIT - The information manager from hell
- *
- * Copyright (C) Linus Torvalds, 2005
- */
-#include "cache.h"
-#include "config.h"
-#include "object-store.h"
-#include "blob.h"
-#include "tree.h"
-#include "commit.h"
-#include "quote.h"
-#include "builtin.h"
-#include "parse-options.h"
-#include "pathspec.h"
-
-static int line_termination = '\n';
-#define LS_RECURSIVE 1
-#define LS_TREE_ONLY 2
-#define LS_SHOW_TREES 4
-#define LS_NAME_ONLY 8
-#define LS_SHOW_SIZE 16
-static int abbrev;
-static int ls_options;
-static struct pathspec pathspec;
-static int chomp_prefix;
-static const char *ls_tree_prefix;
-
-static const  char * const ls_tree_usage[] = {
-	N_("git ls-tree [<options>] <tree-ish> [<path>...]"),
-	NULL
-};
-
-static int show_recursive(const char *base, int baselen, const char *pathname)
-{
-	int i;
-
-	if (ls_options & LS_RECURSIVE)
-		return 1;
-
-	if (!pathspec.nr)
-		return 0;
-
-	for (i = 0; i < pathspec.nr; i++) {
-		const char *spec = pathspec.items[i].match;
-		int len, speclen;
-
-		if (strncmp(base, spec, baselen))
-			continue;
-		len = strlen(pathname);
-		spec += baselen;
-		speclen = strlen(spec);
-		if (speclen <= len)
-			continue;
-		if (spec[len] && spec[len] != '/')
-			continue;
-		if (memcmp(pathname, spec, len))
-			continue;
-		return 1;
-	}
-	return 0;
-}
-
-static int show_tree(const struct object_id *oid, struct strbuf *base,
-		const char *pathname, unsigned mode, int stage, void *context)
-{
-	int retval = 0;
-	int baselen;
-	const char *type = blob_type;
-
-	if (S_ISGITLINK(mode)) {
-		/*
-		 * Maybe we want to have some recursive version here?
-		 *
-		 * Something similar to this incomplete example:
-		 *
-		if (show_subprojects(base, baselen, pathname))
-			retval = READ_TREE_RECURSIVE;
-		 *
-		 */
-		type = commit_type;
-	} else if (S_ISDIR(mode)) {
-		if (show_recursive(base->buf, base->len, pathname)) {
-			retval = READ_TREE_RECURSIVE;
-			if (!(ls_options & LS_SHOW_TREES))
-				return retval;
-		}
-		type = tree_type;
-	}
-	else if (ls_options & LS_TREE_ONLY)
-		return 0;
-
-	if (!(ls_options & LS_NAME_ONLY)) {
-		if (ls_options & LS_SHOW_SIZE) {
-			char size_text[24];
-			if (!strcmp(type, blob_type)) {
-				unsigned long size;
-				if (oid_object_info(the_repository, oid, &size) == OBJ_BAD)
-					xsnprintf(size_text, sizeof(size_text),
-						  "BAD");
-				else
-					xsnprintf(size_text, sizeof(size_text),
-						  "%"PRIuMAX, (uintmax_t)size);
-			} else
-				xsnprintf(size_text, sizeof(size_text), "-");
-			printf("%06o %s %s %7s\t", mode, type,
-			       find_unique_abbrev(oid, abbrev),
-			       size_text);
-		} else
-			printf("%06o %s %s\t", mode, type,
-			       find_unique_abbrev(oid, abbrev));
-	}
-	baselen = base->len;
-	strbuf_addstr(base, pathname);
-	write_name_quoted_relative(base->buf,
-				   chomp_prefix ? ls_tree_prefix : NULL,
-				   stdout, line_termination);
-	strbuf_setlen(base, baselen);
-	return retval;
-}
-
-int cmd_ls_tree(int argc, const char **argv, const char *prefix)
-{
-	struct object_id oid;
-	struct tree *tree;
-	int i, full_tree = 0;
-	const struct option ls_tree_options[] = {
-		OPT_BIT('d', NULL, &ls_options, N_("only show trees"),
-			LS_TREE_ONLY),
-		OPT_BIT('r', NULL, &ls_options, N_("recurse into subtrees"),
-			LS_RECURSIVE),
-		OPT_BIT('t', NULL, &ls_options, N_("show trees when recursing"),
-			LS_SHOW_TREES),
-		OPT_SET_INT('z', NULL, &line_termination,
-			    N_("terminate entries with NUL byte"), 0),
-		OPT_BIT('l', "long", &ls_options, N_("include object size"),
-			LS_SHOW_SIZE),
-		OPT_BIT(0, "name-only", &ls_options, N_("list only filenames"),
-			LS_NAME_ONLY),
-		OPT_BIT(0, "name-status", &ls_options, N_("list only filenames"),
-			LS_NAME_ONLY),
-		OPT_SET_INT(0, "full-name", &chomp_prefix,
-			    N_("use full path names"), 0),
-		OPT_BOOL(0, "full-tree", &full_tree,
-			 N_("list entire tree; not just current directory "
-			    "(implies --full-name)")),
-		OPT__ABBREV(&abbrev),
-		OPT_END()
-	};
-
-	git_config(git_default_config, NULL);
-	ls_tree_prefix = prefix;
-	if (prefix && *prefix)
-		chomp_prefix = strlen(prefix);
-
-	argc = parse_options(argc, argv, prefix, ls_tree_options,
-			     ls_tree_usage, 0);
-	if (full_tree) {
-		ls_tree_prefix = prefix = NULL;
-		chomp_prefix = 0;
-	}
-	/* -d -r should imply -t, but -d by itself should not have to. */
-	if ( (LS_TREE_ONLY|LS_RECURSIVE) ==
-	    ((LS_TREE_ONLY|LS_RECURSIVE) & ls_options))
-		ls_options |= LS_SHOW_TREES;
-
-	if (argc < 1)
-		usage_with_options(ls_tree_usage, ls_tree_options);
-	if (get_oid(argv[0], &oid))
-		die("Not a valid object name %s", argv[0]);
-
-	/*
-	 * show_recursive() rolls its own matching code and is
-	 * generally ignorant of 'struct pathspec'. The magic mask
-	 * cannot be lifted until it is converted to use
-	 * match_pathspec() or tree_entry_interesting()
-	 */
-	parse_pathspec(&pathspec, PATHSPEC_ALL_MAGIC &
-				  ~(PATHSPEC_FROMTOP | PATHSPEC_LITERAL),
-		       PATHSPEC_PREFER_CWD,
-		       prefix, argv + 1);
-	for (i = 0; i < pathspec.nr; i++)
-		pathspec.items[i].nowildcard_len = pathspec.items[i].len;
-	pathspec.has_wildcard = 0;
-	tree = parse_tree_indirect(&oid);
-	if (!tree)
-		die("not a tree object");
-	return !!read_tree_recursive(the_repository, tree, "", 0, 0,
-				     &pathspec, show_tree, NULL);
-}
diff --git a/third_party/git/builtin/mailinfo.c b/third_party/git/builtin/mailinfo.c
deleted file mode 100644
index cfb667a594c8..000000000000
--- a/third_party/git/builtin/mailinfo.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Another stupid program, this one parsing the headers of an
- * email to figure out authorship and subject
- */
-#include "cache.h"
-#include "builtin.h"
-#include "utf8.h"
-#include "strbuf.h"
-#include "mailinfo.h"
-
-static const char mailinfo_usage[] =
-	"git mailinfo [-k | -b] [-m | --message-id] [-u | --encoding=<encoding> | -n] [--scissors | --no-scissors] <msg> <patch> < mail >info";
-
-int cmd_mailinfo(int argc, const char **argv, const char *prefix)
-{
-	const char *def_charset;
-	struct mailinfo mi;
-	int status;
-	char *msgfile, *patchfile;
-
-	setup_mailinfo(&mi);
-
-	def_charset = get_commit_output_encoding();
-	mi.metainfo_charset = def_charset;
-
-	while (1 < argc && argv[1][0] == '-') {
-		if (!strcmp(argv[1], "-k"))
-			mi.keep_subject = 1;
-		else if (!strcmp(argv[1], "-b"))
-			mi.keep_non_patch_brackets_in_subject = 1;
-		else if (!strcmp(argv[1], "-m") || !strcmp(argv[1], "--message-id"))
-			mi.add_message_id = 1;
-		else if (!strcmp(argv[1], "-u"))
-			mi.metainfo_charset = def_charset;
-		else if (!strcmp(argv[1], "-n"))
-			mi.metainfo_charset = NULL;
-		else if (starts_with(argv[1], "--encoding="))
-			mi.metainfo_charset = argv[1] + 11;
-		else if (!strcmp(argv[1], "--scissors"))
-			mi.use_scissors = 1;
-		else if (!strcmp(argv[1], "--no-scissors"))
-			mi.use_scissors = 0;
-		else if (!strcmp(argv[1], "--no-inbody-headers"))
-			mi.use_inbody_headers = 0;
-		else
-			usage(mailinfo_usage);
-		argc--; argv++;
-	}
-
-	if (argc != 3)
-		usage(mailinfo_usage);
-
-	mi.input = stdin;
-	mi.output = stdout;
-
-	msgfile = prefix_filename(prefix, argv[1]);
-	patchfile = prefix_filename(prefix, argv[2]);
-
-	status = !!mailinfo(&mi, msgfile, patchfile);
-	clear_mailinfo(&mi);
-
-	free(msgfile);
-	free(patchfile);
-	return status;
-}
diff --git a/third_party/git/builtin/mailsplit.c b/third_party/git/builtin/mailsplit.c
deleted file mode 100644
index 664400b8169b..000000000000
--- a/third_party/git/builtin/mailsplit.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Totally braindamaged mbox splitter program.
- *
- * It just splits a mbox into a list of files: "0001" "0002" ..
- * so you can process them further from there.
- */
-#include "cache.h"
-#include "builtin.h"
-#include "string-list.h"
-#include "strbuf.h"
-
-static const char git_mailsplit_usage[] =
-"git mailsplit [-d<prec>] [-f<n>] [-b] [--keep-cr] -o<directory> [(<mbox>|<Maildir>)...]";
-
-static int is_from_line(const char *line, int len)
-{
-	const char *colon;
-
-	if (len < 20 || memcmp("From ", line, 5))
-		return 0;
-
-	colon = line + len - 2;
-	line += 5;
-	for (;;) {
-		if (colon < line)
-			return 0;
-		if (*--colon == ':')
-			break;
-	}
-
-	if (!isdigit(colon[-4]) ||
-	    !isdigit(colon[-2]) ||
-	    !isdigit(colon[-1]) ||
-	    !isdigit(colon[ 1]) ||
-	    !isdigit(colon[ 2]))
-		return 0;
-
-	/* year */
-	if (strtol(colon+3, NULL, 10) <= 90)
-		return 0;
-
-	/* Ok, close enough */
-	return 1;
-}
-
-static struct strbuf buf = STRBUF_INIT;
-static int keep_cr;
-static int mboxrd;
-
-static int is_gtfrom(const struct strbuf *buf)
-{
-	size_t min = strlen(">From ");
-	size_t ngt;
-
-	if (buf->len < min)
-		return 0;
-
-	ngt = strspn(buf->buf, ">");
-	return ngt && starts_with(buf->buf + ngt, "From ");
-}
-
-/* Called with the first line (potentially partial)
- * already in buf[] -- normally that should begin with
- * the Unix "From " line.  Write it into the specified
- * file.
- */
-static int split_one(FILE *mbox, const char *name, int allow_bare)
-{
-	FILE *output;
-	int fd;
-	int status = 0;
-	int is_bare = !is_from_line(buf.buf, buf.len);
-
-	if (is_bare && !allow_bare) {
-		fprintf(stderr, "corrupt mailbox\n");
-		exit(1);
-	}
-	fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0666);
-	if (fd < 0)
-		die_errno("cannot open output file '%s'", name);
-	output = xfdopen(fd, "w");
-
-	/* Copy it out, while searching for a line that begins with
-	 * "From " and having something that looks like a date format.
-	 */
-	for (;;) {
-		if (!keep_cr && buf.len > 1 && buf.buf[buf.len-1] == '\n' &&
-			buf.buf[buf.len-2] == '\r') {
-			strbuf_setlen(&buf, buf.len-2);
-			strbuf_addch(&buf, '\n');
-		}
-
-		if (mboxrd && is_gtfrom(&buf))
-			strbuf_remove(&buf, 0, 1);
-
-		if (fwrite(buf.buf, 1, buf.len, output) != buf.len)
-			die_errno("cannot write output");
-
-		if (strbuf_getwholeline(&buf, mbox, '\n')) {
-			if (feof(mbox)) {
-				status = 1;
-				break;
-			}
-			die_errno("cannot read mbox");
-		}
-		if (!is_bare && is_from_line(buf.buf, buf.len))
-			break; /* done with one message */
-	}
-	fclose(output);
-	return status;
-}
-
-static int populate_maildir_list(struct string_list *list, const char *path)
-{
-	DIR *dir;
-	struct dirent *dent;
-	char *name = NULL;
-	char *subs[] = { "cur", "new", NULL };
-	char **sub;
-	int ret = -1;
-
-	for (sub = subs; *sub; ++sub) {
-		free(name);
-		name = xstrfmt("%s/%s", path, *sub);
-		if ((dir = opendir(name)) == NULL) {
-			if (errno == ENOENT)
-				continue;
-			error_errno("cannot opendir %s", name);
-			goto out;
-		}
-
-		while ((dent = readdir(dir)) != NULL) {
-			if (dent->d_name[0] == '.')
-				continue;
-			free(name);
-			name = xstrfmt("%s/%s", *sub, dent->d_name);
-			string_list_insert(list, name);
-		}
-
-		closedir(dir);
-	}
-
-	ret = 0;
-
-out:
-	free(name);
-	return ret;
-}
-
-static int maildir_filename_cmp(const char *a, const char *b)
-{
-	while (*a && *b) {
-		if (isdigit(*a) && isdigit(*b)) {
-			long int na, nb;
-			na = strtol(a, (char **)&a, 10);
-			nb = strtol(b, (char **)&b, 10);
-			if (na != nb)
-				return na - nb;
-			/* strtol advanced our pointers */
-		}
-		else {
-			if (*a != *b)
-				return (unsigned char)*a - (unsigned char)*b;
-			a++;
-			b++;
-		}
-	}
-	return (unsigned char)*a - (unsigned char)*b;
-}
-
-static int split_maildir(const char *maildir, const char *dir,
-	int nr_prec, int skip)
-{
-	char *file = NULL;
-	FILE *f = NULL;
-	int ret = -1;
-	int i;
-	struct string_list list = STRING_LIST_INIT_DUP;
-
-	list.cmp = maildir_filename_cmp;
-
-	if (populate_maildir_list(&list, maildir) < 0)
-		goto out;
-
-	for (i = 0; i < list.nr; i++) {
-		char *name;
-
-		free(file);
-		file = xstrfmt("%s/%s", maildir, list.items[i].string);
-
-		f = fopen(file, "r");
-		if (!f) {
-			error_errno("cannot open mail %s", file);
-			goto out;
-		}
-
-		if (strbuf_getwholeline(&buf, f, '\n')) {
-			error_errno("cannot read mail %s", file);
-			goto out;
-		}
-
-		name = xstrfmt("%s/%0*d", dir, nr_prec, ++skip);
-		split_one(f, name, 1);
-		free(name);
-
-		fclose(f);
-		f = NULL;
-	}
-
-	ret = skip;
-out:
-	if (f)
-		fclose(f);
-	free(file);
-	string_list_clear(&list, 1);
-	return ret;
-}
-
-static int split_mbox(const char *file, const char *dir, int allow_bare,
-		      int nr_prec, int skip)
-{
-	int ret = -1;
-	int peek;
-
-	FILE *f = !strcmp(file, "-") ? stdin : fopen(file, "r");
-	int file_done = 0;
-
-	if (!f) {
-		error_errno("cannot open mbox %s", file);
-		goto out;
-	}
-
-	do {
-		peek = fgetc(f);
-		if (peek == EOF) {
-			if (f == stdin)
-				/* empty stdin is OK */
-				ret = skip;
-			else {
-				fclose(f);
-				error(_("empty mbox: '%s'"), file);
-			}
-			goto out;
-		}
-	} while (isspace(peek));
-	ungetc(peek, f);
-
-	if (strbuf_getwholeline(&buf, f, '\n')) {
-		/* empty stdin is OK */
-		if (f != stdin) {
-			error("cannot read mbox %s", file);
-			goto out;
-		}
-		file_done = 1;
-	}
-
-	while (!file_done) {
-		char *name = xstrfmt("%s/%0*d", dir, nr_prec, ++skip);
-		file_done = split_one(f, name, allow_bare);
-		free(name);
-	}
-
-	if (f != stdin)
-		fclose(f);
-
-	ret = skip;
-out:
-	return ret;
-}
-
-int cmd_mailsplit(int argc, const char **argv, const char *prefix)
-{
-	int nr = 0, nr_prec = 4, num = 0;
-	int allow_bare = 0;
-	const char *dir = NULL;
-	const char **argp;
-	static const char *stdin_only[] = { "-", NULL };
-
-	for (argp = argv+1; *argp; argp++) {
-		const char *arg = *argp;
-
-		if (arg[0] != '-')
-			break;
-		/* do flags here */
-		if ( arg[1] == 'd' ) {
-			nr_prec = strtol(arg+2, NULL, 10);
-			if (nr_prec < 3 || 10 <= nr_prec)
-				usage(git_mailsplit_usage);
-			continue;
-		} else if ( arg[1] == 'f' ) {
-			nr = strtol(arg+2, NULL, 10);
-		} else if ( arg[1] == 'h' ) {
-			usage(git_mailsplit_usage);
-		} else if ( arg[1] == 'b' && !arg[2] ) {
-			allow_bare = 1;
-		} else if (!strcmp(arg, "--keep-cr")) {
-			keep_cr = 1;
-		} else if ( arg[1] == 'o' && arg[2] ) {
-			dir = arg+2;
-		} else if (!strcmp(arg, "--mboxrd")) {
-			mboxrd = 1;
-		} else if ( arg[1] == '-' && !arg[2] ) {
-			argp++;	/* -- marks end of options */
-			break;
-		} else {
-			die("unknown option: %s", arg);
-		}
-	}
-
-	if ( !dir ) {
-		/* Backwards compatibility: if no -o specified, accept
-		   <mbox> <dir> or just <dir> */
-		switch (argc - (argp-argv)) {
-		case 1:
-			dir = argp[0];
-			argp = stdin_only;
-			break;
-		case 2:
-			stdin_only[0] = argp[0];
-			dir = argp[1];
-			argp = stdin_only;
-			break;
-		default:
-			usage(git_mailsplit_usage);
-		}
-	} else {
-		/* New usage: if no more argument, parse stdin */
-		if ( !*argp )
-			argp = stdin_only;
-	}
-
-	while (*argp) {
-		const char *arg = *argp++;
-		struct stat argstat;
-		int ret = 0;
-
-		if (arg[0] == '-' && arg[1] == 0) {
-			ret = split_mbox(arg, dir, allow_bare, nr_prec, nr);
-			if (ret < 0) {
-				error("cannot split patches from stdin");
-				return 1;
-			}
-			num += (ret - nr);
-			nr = ret;
-			continue;
-		}
-
-		if (stat(arg, &argstat) == -1) {
-			error_errno("cannot stat %s", arg);
-			return 1;
-		}
-
-		if (S_ISDIR(argstat.st_mode))
-			ret = split_maildir(arg, dir, nr_prec, nr);
-		else
-			ret = split_mbox(arg, dir, allow_bare, nr_prec, nr);
-
-		if (ret < 0) {
-			error("cannot split patches from %s", arg);
-			return 1;
-		}
-		num += (ret - nr);
-		nr = ret;
-	}
-
-	printf("%d\n", num);
-
-	return 0;
-}
diff --git a/third_party/git/builtin/merge-base.c b/third_party/git/builtin/merge-base.c
deleted file mode 100644
index 6719ac198dc2..000000000000
--- a/third_party/git/builtin/merge-base.c
+++ /dev/null
@@ -1,188 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "commit.h"
-#include "refs.h"
-#include "diff.h"
-#include "revision.h"
-#include "parse-options.h"
-#include "repository.h"
-#include "commit-reach.h"
-
-static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
-{
-	struct commit_list *result, *r;
-
-	result = get_merge_bases_many_dirty(rev[0], rev_nr - 1, rev + 1);
-
-	if (!result)
-		return 1;
-
-	for (r = result; r; r = r->next) {
-		printf("%s\n", oid_to_hex(&r->item->object.oid));
-		if (!show_all)
-			break;
-	}
-
-	free_commit_list(result);
-	return 0;
-}
-
-static const char * const merge_base_usage[] = {
-	N_("git merge-base [-a | --all] <commit> <commit>..."),
-	N_("git merge-base [-a | --all] --octopus <commit>..."),
-	N_("git merge-base --independent <commit>..."),
-	N_("git merge-base --is-ancestor <commit> <commit>"),
-	N_("git merge-base --fork-point <ref> [<commit>]"),
-	NULL
-};
-
-static struct commit *get_commit_reference(const char *arg)
-{
-	struct object_id revkey;
-	struct commit *r;
-
-	if (get_oid(arg, &revkey))
-		die("Not a valid object name %s", arg);
-	r = lookup_commit_reference(the_repository, &revkey);
-	if (!r)
-		die("Not a valid commit name %s", arg);
-
-	return r;
-}
-
-static int handle_independent(int count, const char **args)
-{
-	struct commit_list *revs = NULL, *rev;
-	int i;
-
-	for (i = count - 1; i >= 0; i--)
-		commit_list_insert(get_commit_reference(args[i]), &revs);
-
-	reduce_heads_replace(&revs);
-
-	if (!revs)
-		return 1;
-
-	for (rev = revs; rev; rev = rev->next)
-		printf("%s\n", oid_to_hex(&rev->item->object.oid));
-
-	free_commit_list(revs);
-	return 0;
-}
-
-static int handle_octopus(int count, const char **args, int show_all)
-{
-	struct commit_list *revs = NULL;
-	struct commit_list *result, *rev;
-	int i;
-
-	for (i = count - 1; i >= 0; i--)
-		commit_list_insert(get_commit_reference(args[i]), &revs);
-
-	result = get_octopus_merge_bases(revs);
-	free_commit_list(revs);
-	reduce_heads_replace(&result);
-
-	if (!result)
-		return 1;
-
-	for (rev = result; rev; rev = rev->next) {
-		printf("%s\n", oid_to_hex(&rev->item->object.oid));
-		if (!show_all)
-			break;
-	}
-
-	free_commit_list(result);
-	return 0;
-}
-
-static int handle_is_ancestor(int argc, const char **argv)
-{
-	struct commit *one, *two;
-
-	if (argc != 2)
-		die("--is-ancestor takes exactly two commits");
-	one = get_commit_reference(argv[0]);
-	two = get_commit_reference(argv[1]);
-	if (in_merge_bases(one, two))
-		return 0;
-	else
-		return 1;
-}
-
-static int handle_fork_point(int argc, const char **argv)
-{
-	struct object_id oid;
-	struct commit *derived, *fork_point;
-	const char *commitname;
-
-	commitname = (argc == 2) ? argv[1] : "HEAD";
-	if (get_oid(commitname, &oid))
-		die("Not a valid object name: '%s'", commitname);
-
-	derived = lookup_commit_reference(the_repository, &oid);
-
-	fork_point = get_fork_point(argv[0], derived);
-
-	if (!fork_point)
-		return 1;
-
-	printf("%s\n", oid_to_hex(&fork_point->object.oid));
-	return 0;
-}
-
-int cmd_merge_base(int argc, const char **argv, const char *prefix)
-{
-	struct commit **rev;
-	int rev_nr = 0;
-	int show_all = 0;
-	int cmdmode = 0;
-
-	struct option options[] = {
-		OPT_BOOL('a', "all", &show_all, N_("output all common ancestors")),
-		OPT_CMDMODE(0, "octopus", &cmdmode,
-			    N_("find ancestors for a single n-way merge"), 'o'),
-		OPT_CMDMODE(0, "independent", &cmdmode,
-			    N_("list revs not reachable from others"), 'r'),
-		OPT_CMDMODE(0, "is-ancestor", &cmdmode,
-			    N_("is the first one ancestor of the other?"), 'a'),
-		OPT_CMDMODE(0, "fork-point", &cmdmode,
-			    N_("find where <commit> forked from reflog of <ref>"), 'f'),
-		OPT_END()
-	};
-
-	git_config(git_default_config, NULL);
-	argc = parse_options(argc, argv, prefix, options, merge_base_usage, 0);
-
-	if (cmdmode == 'a') {
-		if (argc < 2)
-			usage_with_options(merge_base_usage, options);
-		if (show_all)
-			die("--is-ancestor cannot be used with --all");
-		return handle_is_ancestor(argc, argv);
-	}
-
-	if (cmdmode == 'r' && show_all)
-		die("--independent cannot be used with --all");
-
-	if (cmdmode == 'o')
-		return handle_octopus(argc, argv, show_all);
-
-	if (cmdmode == 'r')
-		return handle_independent(argc, argv);
-
-	if (cmdmode == 'f') {
-		if (argc < 1 || 2 < argc)
-			usage_with_options(merge_base_usage, options);
-		return handle_fork_point(argc, argv);
-	}
-
-	if (argc < 2)
-		usage_with_options(merge_base_usage, options);
-
-	ALLOC_ARRAY(rev, argc);
-	while (argc-- > 0)
-		rev[rev_nr++] = get_commit_reference(*argv++);
-	return show_merge_base(rev, rev_nr, show_all);
-}
diff --git a/third_party/git/builtin/merge-file.c b/third_party/git/builtin/merge-file.c
deleted file mode 100644
index 06a2f90c4875..000000000000
--- a/third_party/git/builtin/merge-file.c
+++ /dev/null
@@ -1,118 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "xdiff/xdiff.h"
-#include "xdiff-interface.h"
-#include "parse-options.h"
-
-static const char *const merge_file_usage[] = {
-	N_("git merge-file [<options>] [-L <name1> [-L <orig> [-L <name2>]]] <file1> <orig-file> <file2>"),
-	NULL
-};
-
-static int label_cb(const struct option *opt, const char *arg, int unset)
-{
-	static int label_count = 0;
-	const char **names = (const char **)opt->value;
-
-	BUG_ON_OPT_NEG(unset);
-
-	if (label_count >= 3)
-		return error("too many labels on the command line");
-	names[label_count++] = arg;
-	return 0;
-}
-
-int cmd_merge_file(int argc, const char **argv, const char *prefix)
-{
-	const char *names[3] = { NULL, NULL, NULL };
-	mmfile_t mmfs[3];
-	mmbuffer_t result = {NULL, 0};
-	xmparam_t xmp = {{0}};
-	int ret = 0, i = 0, to_stdout = 0;
-	int quiet = 0;
-	struct option options[] = {
-		OPT_BOOL('p', "stdout", &to_stdout, N_("send results to standard output")),
-		OPT_SET_INT(0, "diff3", &xmp.style, N_("use a diff3 based merge"), XDL_MERGE_DIFF3),
-		OPT_SET_INT(0, "ours", &xmp.favor, N_("for conflicts, use our version"),
-			    XDL_MERGE_FAVOR_OURS),
-		OPT_SET_INT(0, "theirs", &xmp.favor, N_("for conflicts, use their version"),
-			    XDL_MERGE_FAVOR_THEIRS),
-		OPT_SET_INT(0, "union", &xmp.favor, N_("for conflicts, use a union version"),
-			    XDL_MERGE_FAVOR_UNION),
-		OPT_INTEGER(0, "marker-size", &xmp.marker_size,
-			    N_("for conflicts, use this marker size")),
-		OPT__QUIET(&quiet, N_("do not warn about conflicts")),
-		OPT_CALLBACK('L', NULL, names, N_("name"),
-			     N_("set labels for file1/orig-file/file2"), &label_cb),
-		OPT_END(),
-	};
-
-	xmp.level = XDL_MERGE_ZEALOUS_ALNUM;
-	xmp.style = 0;
-	xmp.favor = 0;
-
-	if (startup_info->have_repository) {
-		/* Read the configuration file */
-		git_config(git_xmerge_config, NULL);
-		if (0 <= git_xmerge_style)
-			xmp.style = git_xmerge_style;
-	}
-
-	argc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);
-	if (argc != 3)
-		usage_with_options(merge_file_usage, options);
-	if (quiet) {
-		if (!freopen("/dev/null", "w", stderr))
-			return error_errno("failed to redirect stderr to /dev/null");
-	}
-
-	for (i = 0; i < 3; i++) {
-		char *fname;
-		int ret;
-
-		if (!names[i])
-			names[i] = argv[i];
-
-		fname = prefix_filename(prefix, argv[i]);
-		ret = read_mmfile(mmfs + i, fname);
-		free(fname);
-		if (ret)
-			return -1;
-
-		if (mmfs[i].size > MAX_XDIFF_SIZE ||
-		    buffer_is_binary(mmfs[i].ptr, mmfs[i].size))
-			return error("Cannot merge binary files: %s",
-					argv[i]);
-	}
-
-	xmp.ancestor = names[1];
-	xmp.file1 = names[0];
-	xmp.file2 = names[2];
-	ret = xdl_merge(mmfs + 1, mmfs + 0, mmfs + 2, &xmp, &result);
-
-	for (i = 0; i < 3; i++)
-		free(mmfs[i].ptr);
-
-	if (ret >= 0) {
-		const char *filename = argv[0];
-		char *fpath = prefix_filename(prefix, argv[0]);
-		FILE *f = to_stdout ? stdout : fopen(fpath, "wb");
-
-		if (!f)
-			ret = error_errno("Could not open %s for writing",
-					  filename);
-		else if (result.size &&
-			 fwrite(result.ptr, result.size, 1, f) != 1)
-			ret = error_errno("Could not write to %s", filename);
-		else if (fclose(f))
-			ret = error_errno("Could not close %s", filename);
-		free(result.ptr);
-		free(fpath);
-	}
-
-	if (ret > 127)
-		ret = 127;
-
-	return ret;
-}
diff --git a/third_party/git/builtin/merge-index.c b/third_party/git/builtin/merge-index.c
deleted file mode 100644
index 38ea6ad6ca25..000000000000
--- a/third_party/git/builtin/merge-index.c
+++ /dev/null
@@ -1,111 +0,0 @@
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "run-command.h"
-
-static const char *pgm;
-static int one_shot, quiet;
-static int err;
-
-static int merge_entry(int pos, const char *path)
-{
-	int found;
-	const char *arguments[] = { pgm, "", "", "", path, "", "", "", NULL };
-	char hexbuf[4][GIT_MAX_HEXSZ + 1];
-	char ownbuf[4][60];
-
-	if (pos >= active_nr)
-		die("git merge-index: %s not in the cache", path);
-	found = 0;
-	do {
-		const struct cache_entry *ce = active_cache[pos];
-		int stage = ce_stage(ce);
-
-		if (strcmp(ce->name, path))
-			break;
-		found++;
-		oid_to_hex_r(hexbuf[stage], &ce->oid);
-		xsnprintf(ownbuf[stage], sizeof(ownbuf[stage]), "%o", ce->ce_mode);
-		arguments[stage] = hexbuf[stage];
-		arguments[stage + 4] = ownbuf[stage];
-	} while (++pos < active_nr);
-	if (!found)
-		die("git merge-index: %s not in the cache", path);
-
-	if (run_command_v_opt(arguments, 0)) {
-		if (one_shot)
-			err++;
-		else {
-			if (!quiet)
-				die("merge program failed");
-			exit(1);
-		}
-	}
-	return found;
-}
-
-static void merge_one_path(const char *path)
-{
-	int pos = cache_name_pos(path, strlen(path));
-
-	/*
-	 * If it already exists in the cache as stage0, it's
-	 * already merged and there is nothing to do.
-	 */
-	if (pos < 0)
-		merge_entry(-pos-1, path);
-}
-
-static void merge_all(void)
-{
-	int i;
-	for (i = 0; i < active_nr; i++) {
-		const struct cache_entry *ce = active_cache[i];
-		if (!ce_stage(ce))
-			continue;
-		i += merge_entry(i, ce->name)-1;
-	}
-}
-
-int cmd_merge_index(int argc, const char **argv, const char *prefix)
-{
-	int i, force_file = 0;
-
-	/* Without this we cannot rely on waitpid() to tell
-	 * what happened to our children.
-	 */
-	signal(SIGCHLD, SIG_DFL);
-
-	if (argc < 3)
-		usage("git merge-index [-o] [-q] <merge-program> (-a | [--] [<filename>...])");
-
-	read_cache();
-
-	i = 1;
-	if (!strcmp(argv[i], "-o")) {
-		one_shot = 1;
-		i++;
-	}
-	if (!strcmp(argv[i], "-q")) {
-		quiet = 1;
-		i++;
-	}
-	pgm = argv[i++];
-	for (; i < argc; i++) {
-		const char *arg = argv[i];
-		if (!force_file && *arg == '-') {
-			if (!strcmp(arg, "--")) {
-				force_file = 1;
-				continue;
-			}
-			if (!strcmp(arg, "-a")) {
-				merge_all();
-				continue;
-			}
-			die("git merge-index: unknown option %s", arg);
-		}
-		merge_one_path(arg);
-	}
-	if (err && !quiet)
-		die("merge program failed");
-	return err;
-}
diff --git a/third_party/git/builtin/merge-ours.c b/third_party/git/builtin/merge-ours.c
deleted file mode 100644
index 459450742053..000000000000
--- a/third_party/git/builtin/merge-ours.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Implementation of git-merge-ours.sh as builtin
- *
- * Copyright (c) 2007 Thomas Harning Jr
- * Original:
- * Original Copyright (c) 2005 Junio C Hamano
- *
- * Pretend we resolved the heads, but declare our tree trumps everybody else.
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "git-compat-util.h"
-#include "builtin.h"
-#include "diff.h"
-
-static const char builtin_merge_ours_usage[] =
-	"git merge-ours <base>... -- HEAD <remote>...";
-
-int cmd_merge_ours(int argc, const char **argv, const char *prefix)
-{
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage(builtin_merge_ours_usage);
-
-	/*
-	 * The contents of the current index becomes the tree we
-	 * commit.  The index must match HEAD, or this merge cannot go
-	 * through.
-	 */
-	if (read_cache() < 0)
-		die_errno("read_cache failed");
-	if (index_differs_from(the_repository, "HEAD", NULL, 0))
-		exit(2);
-	exit(0);
-}
diff --git a/third_party/git/builtin/merge-recursive.c b/third_party/git/builtin/merge-recursive.c
deleted file mode 100644
index a4bfd8fc51d6..000000000000
--- a/third_party/git/builtin/merge-recursive.c
+++ /dev/null
@@ -1,92 +0,0 @@
-#include "cache.h"
-#include "builtin.h"
-#include "commit.h"
-#include "tag.h"
-#include "merge-recursive.h"
-#include "xdiff-interface.h"
-
-static const char builtin_merge_recursive_usage[] =
-	"git %s <base>... -- <head> <remote> ...";
-
-static char *better_branch_name(const char *branch)
-{
-	static char githead_env[8 + GIT_MAX_HEXSZ + 1];
-	char *name;
-
-	if (strlen(branch) != the_hash_algo->hexsz)
-		return xstrdup(branch);
-	xsnprintf(githead_env, sizeof(githead_env), "GITHEAD_%s", branch);
-	name = getenv(githead_env);
-	return xstrdup(name ? name : branch);
-}
-
-int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
-{
-	const struct object_id *bases[21];
-	unsigned bases_count = 0;
-	int i, failed;
-	struct object_id h1, h2;
-	struct merge_options o;
-	char *better1, *better2;
-	struct commit *result;
-
-	init_merge_options(&o, the_repository);
-	if (argv[0] && ends_with(argv[0], "-subtree"))
-		o.subtree_shift = "";
-
-	if (argc < 4)
-		usagef(builtin_merge_recursive_usage, argv[0]);
-
-	for (i = 1; i < argc; ++i) {
-		const char *arg = argv[i];
-
-		if (starts_with(arg, "--")) {
-			if (!arg[2])
-				break;
-			if (parse_merge_opt(&o, arg + 2))
-				die(_("unknown option %s"), arg);
-			continue;
-		}
-		if (bases_count < ARRAY_SIZE(bases)-1) {
-			struct object_id *oid = xmalloc(sizeof(struct object_id));
-			if (get_oid(argv[i], oid))
-				die(_("could not parse object '%s'"), argv[i]);
-			bases[bases_count++] = oid;
-		}
-		else
-			warning(Q_("cannot handle more than %d base. "
-				   "Ignoring %s.",
-				   "cannot handle more than %d bases. "
-				   "Ignoring %s.",
-				    (int)ARRAY_SIZE(bases)-1),
-				(int)ARRAY_SIZE(bases)-1, argv[i]);
-	}
-	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];
-
-	if (get_oid(o.branch1, &h1))
-		die(_("could not resolve ref '%s'"), o.branch1);
-	if (get_oid(o.branch2, &h2))
-		die(_("could not resolve ref '%s'"), o.branch2);
-
-	o.branch1 = better1 = better_branch_name(o.branch1);
-	o.branch2 = better2 = better_branch_name(o.branch2);
-
-	if (o.verbosity >= 3)
-		printf(_("Merging %s with %s\n"), o.branch1, o.branch2);
-
-	failed = merge_recursive_generic(&o, &h1, &h2, bases_count, bases, &result);
-
-	free(better1);
-	free(better2);
-
-	if (failed < 0)
-		return 128; /* die() error code */
-	return failed;
-}
diff --git a/third_party/git/builtin/merge-tree.c b/third_party/git/builtin/merge-tree.c
deleted file mode 100644
index e72714a5a87d..000000000000
--- a/third_party/git/builtin/merge-tree.c
+++ /dev/null
@@ -1,390 +0,0 @@
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "tree-walk.h"
-#include "xdiff-interface.h"
-#include "object-store.h"
-#include "repository.h"
-#include "blob.h"
-#include "exec-cmd.h"
-#include "merge-blobs.h"
-
-static const char merge_tree_usage[] = "git merge-tree <base-tree> <branch1> <branch2>";
-
-struct merge_list {
-	struct merge_list *next;
-	struct merge_list *link;	/* other stages for this object */
-
-	unsigned int stage : 2;
-	unsigned int mode;
-	const char *path;
-	struct blob *blob;
-};
-
-static struct merge_list *merge_result, **merge_result_end = &merge_result;
-
-static void add_merge_entry(struct merge_list *entry)
-{
-	*merge_result_end = entry;
-	merge_result_end = &entry->next;
-}
-
-static void merge_trees(struct tree_desc t[3], const char *base);
-
-static const char *explanation(struct merge_list *entry)
-{
-	switch (entry->stage) {
-	case 0:
-		return "merged";
-	case 3:
-		return "added in remote";
-	case 2:
-		if (entry->link)
-			return "added in both";
-		return "added in local";
-	}
-
-	/* Existed in base */
-	entry = entry->link;
-	if (!entry)
-		return "removed in both";
-
-	if (entry->link)
-		return "changed in both";
-
-	if (entry->stage == 3)
-		return "removed in local";
-	return "removed in remote";
-}
-
-static void *result(struct merge_list *entry, unsigned long *size)
-{
-	enum object_type type;
-	struct blob *base, *our, *their;
-	const char *path = entry->path;
-
-	if (!entry->stage)
-		return read_object_file(&entry->blob->object.oid, &type, size);
-	base = NULL;
-	if (entry->stage == 1) {
-		base = entry->blob;
-		entry = entry->link;
-	}
-	our = NULL;
-	if (entry && entry->stage == 2) {
-		our = entry->blob;
-		entry = entry->link;
-	}
-	their = NULL;
-	if (entry)
-		their = entry->blob;
-	return merge_blobs(the_repository->index, path,
-			   base, our, their, size);
-}
-
-static void *origin(struct merge_list *entry, unsigned long *size)
-{
-	enum object_type type;
-	while (entry) {
-		if (entry->stage == 2)
-			return read_object_file(&entry->blob->object.oid,
-						&type, size);
-		entry = entry->link;
-	}
-	return NULL;
-}
-
-static int show_outf(void *priv_, mmbuffer_t *mb, int nbuf)
-{
-	int i;
-	for (i = 0; i < nbuf; i++)
-		printf("%.*s", (int) mb[i].size, mb[i].ptr);
-	return 0;
-}
-
-static void show_diff(struct merge_list *entry)
-{
-	unsigned long size;
-	mmfile_t src, dst;
-	xpparam_t xpp;
-	xdemitconf_t xecfg;
-	xdemitcb_t ecb;
-
-	xpp.flags = 0;
-	memset(&xecfg, 0, sizeof(xecfg));
-	xecfg.ctxlen = 3;
-	ecb.out_hunk = NULL;
-	ecb.out_line = show_outf;
-	ecb.priv = NULL;
-
-	src.ptr = origin(entry, &size);
-	if (!src.ptr)
-		size = 0;
-	src.size = size;
-	dst.ptr = result(entry, &size);
-	if (!dst.ptr)
-		size = 0;
-	dst.size = size;
-	if (xdi_diff(&src, &dst, &xpp, &xecfg, &ecb))
-		die("unable to generate diff");
-	free(src.ptr);
-	free(dst.ptr);
-}
-
-static void show_result_list(struct merge_list *entry)
-{
-	printf("%s\n", explanation(entry));
-	do {
-		struct merge_list *link = entry->link;
-		static const char *desc[4] = { "result", "base", "our", "their" };
-		printf("  %-6s %o %s %s\n", desc[entry->stage], entry->mode, oid_to_hex(&entry->blob->object.oid), entry->path);
-		entry = link;
-	} while (entry);
-}
-
-static void show_result(void)
-{
-	struct merge_list *walk;
-
-	walk = merge_result;
-	while (walk) {
-		show_result_list(walk);
-		show_diff(walk);
-		walk = walk->next;
-	}
-}
-
-/* An empty entry never compares same, not even to another empty entry */
-static int same_entry(struct name_entry *a, struct name_entry *b)
-{
-	return	!is_null_oid(&a->oid) &&
-		!is_null_oid(&b->oid) &&
-		oideq(&a->oid, &b->oid) &&
-		a->mode == b->mode;
-}
-
-static int both_empty(struct name_entry *a, struct name_entry *b)
-{
-	return is_null_oid(&a->oid) && is_null_oid(&b->oid);
-}
-
-static struct merge_list *create_entry(unsigned stage, unsigned mode, const struct object_id *oid, const char *path)
-{
-	struct merge_list *res = xcalloc(1, sizeof(*res));
-
-	res->stage = stage;
-	res->path = path;
-	res->mode = mode;
-	res->blob = lookup_blob(the_repository, oid);
-	return res;
-}
-
-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);
-}
-
-static void resolve(const struct traverse_info *info, struct name_entry *ours, struct name_entry *result)
-{
-	struct merge_list *orig, *final;
-	const char *path;
-
-	/* If it's already ours, don't bother showing it */
-	if (!ours)
-		return;
-
-	path = traverse_path(info, result);
-	orig = create_entry(2, ours->mode, &ours->oid, path);
-	final = create_entry(0, result->mode, &result->oid, path);
-
-	final->link = orig;
-
-	add_merge_entry(final);
-}
-
-static void unresolved_directory(const struct traverse_info *info,
-				 struct name_entry n[3])
-{
-	struct repository *r = the_repository;
-	char *newbase;
-	struct name_entry *p;
-	struct tree_desc t[3];
-	void *buf0, *buf1, *buf2;
-
-	for (p = n; p < n + 3; p++) {
-		if (p->mode && S_ISDIR(p->mode))
-			break;
-	}
-	if (n + 3 <= p)
-		return; /* there is no tree here */
-
-	newbase = traverse_path(info, p);
-
-#define ENTRY_OID(e) (((e)->mode && S_ISDIR((e)->mode)) ? &(e)->oid : NULL)
-	buf0 = fill_tree_descriptor(r, t + 0, ENTRY_OID(n + 0));
-	buf1 = fill_tree_descriptor(r, t + 1, ENTRY_OID(n + 1));
-	buf2 = fill_tree_descriptor(r, t + 2, ENTRY_OID(n + 2));
-#undef ENTRY_OID
-
-	merge_trees(t, newbase);
-
-	free(buf0);
-	free(buf1);
-	free(buf2);
-	free(newbase);
-}
-
-
-static struct merge_list *link_entry(unsigned stage, const struct traverse_info *info, struct name_entry *n, struct merge_list *entry)
-{
-	const char *path;
-	struct merge_list *link;
-
-	if (!n->mode)
-		return entry;
-	if (entry)
-		path = entry->path;
-	else
-		path = traverse_path(info, n);
-	link = create_entry(stage, n->mode, &n->oid, path);
-	link->link = entry;
-	return link;
-}
-
-static void unresolved(const struct traverse_info *info, struct name_entry n[3])
-{
-	struct merge_list *entry = NULL;
-	int i;
-	unsigned dirmask = 0, mask = 0;
-
-	for (i = 0; i < 3; i++) {
-		mask |= (1 << i);
-		/*
-		 * Treat missing entries as directories so that we return
-		 * after unresolved_directory has handled this.
-		 */
-		if (!n[i].mode || S_ISDIR(n[i].mode))
-			dirmask |= (1 << i);
-	}
-
-	unresolved_directory(info, n);
-
-	if (dirmask == mask)
-		return;
-
-	if (n[2].mode && !S_ISDIR(n[2].mode))
-		entry = link_entry(3, info, n + 2, entry);
-	if (n[1].mode && !S_ISDIR(n[1].mode))
-		entry = link_entry(2, info, n + 1, entry);
-	if (n[0].mode && !S_ISDIR(n[0].mode))
-		entry = link_entry(1, info, n + 0, entry);
-
-	add_merge_entry(entry);
-}
-
-/*
- * Merge two trees together (t[1] and t[2]), using a common base (t[0])
- * as the origin.
- *
- * This walks the (sorted) trees in lock-step, checking every possible
- * name. Note that directories automatically sort differently from other
- * files (see "base_name_compare"), so you'll never see file/directory
- * conflicts, because they won't ever compare the same.
- *
- * IOW, if a directory changes to a filename, it will automatically be
- * seen as the directory going away, and the filename being created.
- *
- * Think of this as a three-way diff.
- *
- * The output will be either:
- *  - successful merge
- *	 "0 mode sha1 filename"
- *    NOTE NOTE NOTE! FIXME! We really really need to walk the index
- *    in parallel with this too!
- *
- *  - conflict:
- *	"1 mode sha1 filename"
- *	"2 mode sha1 filename"
- *	"3 mode sha1 filename"
- *    where not all of the 1/2/3 lines may exist, of course.
- *
- * The successful merge rules are the same as for the three-way merge
- * in git-read-tree.
- */
-static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, struct name_entry *entry, struct traverse_info *info)
-{
-	/* Same in both? */
-	if (same_entry(entry+1, entry+2) || both_empty(entry+1, entry+2)) {
-		/* Modified, added or removed identically */
-		resolve(info, NULL, entry+1);
-		return mask;
-	}
-
-	if (same_entry(entry+0, entry+1)) {
-		if (!is_null_oid(&entry[2].oid) && !S_ISDIR(entry[2].mode)) {
-			/* We did not touch, they modified -- take theirs */
-			resolve(info, entry+1, entry+2);
-			return mask;
-		}
-		/*
-		 * If we did not touch a directory but they made it
-		 * into a file, we fall through and unresolved()
-		 * recurses down.  Likewise for the opposite case.
-		 */
-	}
-
-	if (same_entry(entry+0, entry+2) || both_empty(entry+0, entry+2)) {
-		/* We added, modified or removed, they did not touch -- take ours */
-		resolve(info, NULL, entry+1);
-		return mask;
-	}
-
-	unresolved(info, entry);
-	return mask;
-}
-
-static void merge_trees(struct tree_desc t[3], const char *base)
-{
-	struct traverse_info info;
-
-	setup_traverse_info(&info, base);
-	info.fn = threeway_callback;
-	traverse_trees(&the_index, 3, t, &info);
-}
-
-static void *get_tree_descriptor(struct repository *r,
-				 struct tree_desc *desc,
-				 const char *rev)
-{
-	struct object_id oid;
-	void *buf;
-
-	if (repo_get_oid(r, rev, &oid))
-		die("unknown rev %s", rev);
-	buf = fill_tree_descriptor(r, desc, &oid);
-	if (!buf)
-		die("%s is not a tree", rev);
-	return buf;
-}
-
-int cmd_merge_tree(int argc, const char **argv, const char *prefix)
-{
-	struct repository *r = the_repository;
-	struct tree_desc t[3];
-	void *buf1, *buf2, *buf3;
-
-	if (argc != 4)
-		usage(merge_tree_usage);
-
-	buf1 = get_tree_descriptor(r, t+0, argv[1]);
-	buf2 = get_tree_descriptor(r, t+1, argv[2]);
-	buf3 = get_tree_descriptor(r, t+2, argv[3]);
-	merge_trees(t, "");
-	free(buf1);
-	free(buf2);
-	free(buf3);
-
-	show_result();
-	return 0;
-}
diff --git a/third_party/git/builtin/merge.c b/third_party/git/builtin/merge.c
deleted file mode 100644
index 9d5359edc2f7..000000000000
--- a/third_party/git/builtin/merge.c
+++ /dev/null
@@ -1,1715 +0,0 @@
-/*
- * Builtin "git merge"
- *
- * Copyright (c) 2008 Miklos Vajna <vmiklos@frugalware.org>
- *
- * Based on git-merge.sh by Junio C Hamano.
- */
-
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "config.h"
-#include "parse-options.h"
-#include "builtin.h"
-#include "lockfile.h"
-#include "run-command.h"
-#include "diff.h"
-#include "refs.h"
-#include "refspec.h"
-#include "commit.h"
-#include "diffcore.h"
-#include "revision.h"
-#include "unpack-trees.h"
-#include "cache-tree.h"
-#include "dir.h"
-#include "utf8.h"
-#include "log-tree.h"
-#include "color.h"
-#include "rerere.h"
-#include "help.h"
-#include "merge-recursive.h"
-#include "resolve-undo.h"
-#include "remote.h"
-#include "fmt-merge-msg.h"
-#include "gpg-interface.h"
-#include "sequencer.h"
-#include "string-list.h"
-#include "packfile.h"
-#include "tag.h"
-#include "alias.h"
-#include "branch.h"
-#include "commit-reach.h"
-#include "wt-status.h"
-#include "commit-graph.h"
-
-#define DEFAULT_TWOHEAD (1<<0)
-#define DEFAULT_OCTOPUS (1<<1)
-#define NO_FAST_FORWARD (1<<2)
-#define NO_TRIVIAL      (1<<3)
-
-struct strategy {
-	const char *name;
-	unsigned attr;
-};
-
-static const char * const builtin_merge_usage[] = {
-	N_("git merge [<options>] [<commit>...]"),
-	N_("git merge --abort"),
-	N_("git merge --continue"),
-	NULL
-};
-
-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;
-static size_t use_strategies_nr, use_strategies_alloc;
-static const char **xopts;
-static size_t xopts_nr, xopts_alloc;
-static const char *branch;
-static char *branch_mergeoptions;
-static int verbosity;
-static int allow_rerere_auto;
-static int abort_current_merge;
-static int quit_current_merge;
-static int continue_current_merge;
-static int allow_unrelated_histories;
-static int show_progress = -1;
-static int default_to_upstream = 1;
-static int signoff;
-static const char *sign_commit;
-static int autostash;
-static int no_verify;
-
-static struct strategy all_strategy[] = {
-	{ "recursive",  DEFAULT_TWOHEAD | NO_TRIVIAL },
-	{ "octopus",    DEFAULT_OCTOPUS },
-	{ "resolve",    0 },
-	{ "ours",       NO_FAST_FORWARD | NO_TRIVIAL },
-	{ "subtree",    NO_FAST_FORWARD | NO_TRIVIAL },
-};
-
-static const char *pull_twohead, *pull_octopus;
-
-enum ff_type {
-	FF_NO,
-	FF_ALLOW,
-	FF_ONLY
-};
-
-static enum ff_type fast_forward = FF_ALLOW;
-
-static const char *cleanup_arg;
-static enum commit_msg_cleanup_mode cleanup_mode;
-
-static int option_parse_message(const struct option *opt,
-				const char *arg, int unset)
-{
-	struct strbuf *buf = opt->value;
-
-	if (unset)
-		strbuf_setlen(buf, 0);
-	else if (arg) {
-		strbuf_addf(buf, "%s%s", buf->len ? "\n\n" : "", arg);
-		have_message = 1;
-	} else
-		return error(_("switch `m' requires a value"));
-	return 0;
-}
-
-static enum parse_opt_result option_read_message(struct parse_opt_ctx_t *ctx,
-						 const struct option *opt,
-						 const char *arg_not_used,
-						 int unset)
-{
-	struct strbuf *buf = opt->value;
-	const char *arg;
-
-	BUG_ON_OPT_ARG(arg_not_used);
-	if (unset)
-		BUG("-F cannot be negated");
-
-	if (ctx->opt) {
-		arg = ctx->opt;
-		ctx->opt = NULL;
-	} else if (ctx->argc > 1) {
-		ctx->argc--;
-		arg = *++ctx->argv;
-	} else
-		return error(_("option `%s' requires a value"), opt->long_name);
-
-	if (buf->len)
-		strbuf_addch(buf, '\n');
-	if (ctx->prefix && !is_absolute_path(arg))
-		arg = prefix_filename(ctx->prefix, arg);
-	if (strbuf_read_file(buf, arg, 0) < 0)
-		return error(_("could not read file '%s'"), arg);
-	have_message = 1;
-
-	return 0;
-}
-
-static struct strategy *get_strategy(const char *name)
-{
-	int i;
-	struct strategy *ret;
-	static struct cmdnames main_cmds, other_cmds;
-	static int loaded;
-
-	if (!name)
-		return NULL;
-
-	for (i = 0; i < ARRAY_SIZE(all_strategy); i++)
-		if (!strcmp(name, all_strategy[i].name))
-			return &all_strategy[i];
-
-	if (!loaded) {
-		struct cmdnames not_strategies;
-		loaded = 1;
-
-		memset(&not_strategies, 0, sizeof(struct cmdnames));
-		load_command_list("git-merge-", &main_cmds, &other_cmds);
-		for (i = 0; i < main_cmds.cnt; i++) {
-			int j, found = 0;
-			struct cmdname *ent = main_cmds.names[i];
-			for (j = 0; j < ARRAY_SIZE(all_strategy); j++)
-				if (!strncmp(ent->name, all_strategy[j].name, ent->len)
-						&& !all_strategy[j].name[ent->len])
-					found = 1;
-			if (!found)
-				add_cmdname(&not_strategies, ent->name, ent->len);
-		}
-		exclude_cmds(&main_cmds, &not_strategies);
-	}
-	if (!is_in_cmdlist(&main_cmds, name) && !is_in_cmdlist(&other_cmds, name)) {
-		fprintf(stderr, _("Could not find merge strategy '%s'.\n"), name);
-		fprintf(stderr, _("Available strategies are:"));
-		for (i = 0; i < main_cmds.cnt; i++)
-			fprintf(stderr, " %s", main_cmds.names[i]->name);
-		fprintf(stderr, ".\n");
-		if (other_cmds.cnt) {
-			fprintf(stderr, _("Available custom strategies are:"));
-			for (i = 0; i < other_cmds.cnt; i++)
-				fprintf(stderr, " %s", other_cmds.names[i]->name);
-			fprintf(stderr, ".\n");
-		}
-		exit(1);
-	}
-
-	ret = xcalloc(1, sizeof(struct strategy));
-	ret->name = xstrdup(name);
-	ret->attr = NO_TRIVIAL;
-	return ret;
-}
-
-static void append_strategy(struct strategy *s)
-{
-	ALLOC_GROW(use_strategies, use_strategies_nr + 1, use_strategies_alloc);
-	use_strategies[use_strategies_nr++] = s;
-}
-
-static int option_parse_strategy(const struct option *opt,
-				 const char *name, int unset)
-{
-	if (unset)
-		return 0;
-
-	append_strategy(get_strategy(name));
-	return 0;
-}
-
-static int option_parse_x(const struct option *opt,
-			  const char *arg, int unset)
-{
-	if (unset)
-		return 0;
-
-	ALLOC_GROW(xopts, xopts_nr + 1, xopts_alloc);
-	xopts[xopts_nr++] = xstrdup(arg);
-	return 0;
-}
-
-static int option_parse_n(const struct option *opt,
-			  const char *arg, int unset)
-{
-	BUG_ON_OPT_ARG(arg);
-	show_diffstat = unset;
-	return 0;
-}
-
-static struct option builtin_merge_options[] = {
-	OPT_CALLBACK_F('n', NULL, NULL, NULL,
-		N_("do not show a diffstat at the end of the merge"),
-		PARSE_OPT_NOARG, option_parse_n),
-	OPT_BOOL(0, "stat", &show_diffstat,
-		N_("show a diffstat at the end of the merge")),
-	OPT_BOOL(0, "summary", &show_diffstat, N_("(synonym to --stat)")),
-	{ OPTION_INTEGER, 0, "log", &shortlog_len, N_("n"),
-	  N_("add (at most <n>) entries from shortlog to merge commit message"),
-	  PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN },
-	OPT_BOOL(0, "squash", &squash,
-		N_("create a single commit instead of doing a merge")),
-	OPT_BOOL(0, "commit", &option_commit,
-		N_("perform a commit if the merge succeeds (default)")),
-	OPT_BOOL('e', "edit", &option_edit,
-		N_("edit message before committing")),
-	OPT_CLEANUP(&cleanup_arg),
-	OPT_SET_INT(0, "ff", &fast_forward, N_("allow fast-forward (default)"), FF_ALLOW),
-	OPT_SET_INT_F(0, "ff-only", &fast_forward,
-		      N_("abort if fast-forward is not possible"),
-		      FF_ONLY, PARSE_OPT_NONEG),
-	OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
-	OPT_BOOL(0, "verify-signatures", &verify_signatures,
-		N_("verify that the named commit has a valid GPG signature")),
-	OPT_CALLBACK('s', "strategy", &use_strategies, N_("strategy"),
-		N_("merge strategy to use"), option_parse_strategy),
-	OPT_CALLBACK('X', "strategy-option", &xopts, N_("option=value"),
-		N_("option for selected merge strategy"), option_parse_x),
-	OPT_CALLBACK('m', "message", &merge_msg, N_("message"),
-		N_("merge commit message (for a non-fast-forward merge)"),
-		option_parse_message),
-	{ OPTION_LOWLEVEL_CALLBACK, 'F', "file", &merge_msg, N_("path"),
-		N_("read message from file"), PARSE_OPT_NONEG,
-		NULL, 0, option_read_message },
-	OPT__VERBOSITY(&verbosity),
-	OPT_BOOL(0, "abort", &abort_current_merge,
-		N_("abort the current in-progress merge")),
-	OPT_BOOL(0, "quit", &quit_current_merge,
-		N_("--abort but leave index and working tree alone")),
-	OPT_BOOL(0, "continue", &continue_current_merge,
-		N_("continue the current in-progress merge")),
-	OPT_BOOL(0, "allow-unrelated-histories", &allow_unrelated_histories,
-		 N_("allow merging unrelated histories")),
-	OPT_SET_INT(0, "progress", &show_progress, N_("force progress reporting"), 1),
-	{ OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
-	  N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
-	OPT_AUTOSTASH(&autostash),
-	OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")),
-	OPT_BOOL(0, "signoff", &signoff, N_("add Signed-off-by:")),
-	OPT_BOOL(0, "no-verify", &no_verify, N_("bypass pre-merge-commit and commit-msg hooks")),
-	OPT_END()
-};
-
-static int save_state(struct object_id *stash)
-{
-	int len;
-	struct child_process cp = CHILD_PROCESS_INIT;
-	struct strbuf buffer = STRBUF_INIT;
-	const char *argv[] = {"stash", "create", NULL};
-	int rc = -1;
-
-	cp.argv = argv;
-	cp.out = -1;
-	cp.git_cmd = 1;
-
-	if (start_command(&cp))
-		die(_("could not run stash."));
-	len = strbuf_read(&buffer, cp.out, 1024);
-	close(cp.out);
-
-	if (finish_command(&cp) || len < 0)
-		die(_("stash failed"));
-	else if (!len)		/* no changes */
-		goto out;
-	strbuf_setlen(&buffer, buffer.len-1);
-	if (get_oid(buffer.buf, stash))
-		die(_("not a valid object: %s"), buffer.buf);
-	rc = 0;
-out:
-	strbuf_release(&buffer);
-	return rc;
-}
-
-static void read_empty(const struct object_id *oid, int verbose)
-{
-	int i = 0;
-	const char *args[7];
-
-	args[i++] = "read-tree";
-	if (verbose)
-		args[i++] = "-v";
-	args[i++] = "-m";
-	args[i++] = "-u";
-	args[i++] = empty_tree_oid_hex();
-	args[i++] = oid_to_hex(oid);
-	args[i] = NULL;
-
-	if (run_command_v_opt(args, RUN_GIT_CMD))
-		die(_("read-tree failed"));
-}
-
-static void reset_hard(const struct object_id *oid, int verbose)
-{
-	int i = 0;
-	const char *args[6];
-
-	args[i++] = "read-tree";
-	if (verbose)
-		args[i++] = "-v";
-	args[i++] = "--reset";
-	args[i++] = "-u";
-	args[i++] = oid_to_hex(oid);
-	args[i] = NULL;
-
-	if (run_command_v_opt(args, RUN_GIT_CMD))
-		die(_("read-tree failed"));
-}
-
-static void restore_state(const struct object_id *head,
-			  const struct object_id *stash)
-{
-	struct strbuf sb = STRBUF_INIT;
-	const char *args[] = { "stash", "apply", NULL, NULL };
-
-	if (is_null_oid(stash))
-		return;
-
-	reset_hard(head, 1);
-
-	args[2] = oid_to_hex(stash);
-
-	/*
-	 * It is OK to ignore error here, for example when there was
-	 * nothing to restore.
-	 */
-	run_command_v_opt(args, RUN_GIT_CMD);
-
-	strbuf_release(&sb);
-	refresh_cache(REFRESH_QUIET);
-}
-
-/* This is called when no merge was necessary. */
-static void finish_up_to_date(const char *msg)
-{
-	if (verbosity >= 0)
-		printf("%s%s\n", squash ? _(" (nothing to squash)") : "", msg);
-	remove_merge_branch_state(the_repository);
-}
-
-static void squash_message(struct commit *commit, struct commit_list *remoteheads)
-{
-	struct rev_info rev;
-	struct strbuf out = STRBUF_INIT;
-	struct commit_list *j;
-	struct pretty_print_context ctx = {0};
-
-	printf(_("Squash commit -- not updating HEAD\n"));
-
-	repo_init_revisions(the_repository, &rev, NULL);
-	rev.ignore_merges = 1;
-	rev.commit_format = CMIT_FMT_MEDIUM;
-
-	commit->object.flags |= UNINTERESTING;
-	add_pending_object(&rev, &commit->object, NULL);
-
-	for (j = remoteheads; j; j = j->next)
-		add_pending_object(&rev, &j->item->object, NULL);
-
-	setup_revisions(0, NULL, &rev, NULL);
-	if (prepare_revision_walk(&rev))
-		die(_("revision walk setup failed"));
-
-	ctx.abbrev = rev.abbrev;
-	ctx.date_mode = rev.date_mode;
-	ctx.fmt = rev.commit_format;
-
-	strbuf_addstr(&out, "Squashed commit of the following:\n");
-	while ((commit = get_revision(&rev)) != NULL) {
-		strbuf_addch(&out, '\n');
-		strbuf_addf(&out, "commit %s\n",
-			oid_to_hex(&commit->object.oid));
-		pretty_print_commit(&ctx, commit, &out);
-	}
-	write_file_buf(git_path_squash_msg(the_repository), out.buf, out.len);
-	strbuf_release(&out);
-}
-
-static void finish(struct commit *head_commit,
-		   struct commit_list *remoteheads,
-		   const struct object_id *new_head, const char *msg)
-{
-	struct strbuf reflog_message = STRBUF_INIT;
-	const struct object_id *head = &head_commit->object.oid;
-
-	if (!msg)
-		strbuf_addstr(&reflog_message, getenv("GIT_REFLOG_ACTION"));
-	else {
-		if (verbosity >= 0)
-			printf("%s\n", msg);
-		strbuf_addf(&reflog_message, "%s: %s",
-			getenv("GIT_REFLOG_ACTION"), msg);
-	}
-	if (squash) {
-		squash_message(head_commit, remoteheads);
-	} else {
-		if (verbosity >= 0 && !merge_msg.len)
-			printf(_("No merge message -- not updating HEAD\n"));
-		else {
-			update_ref(reflog_message.buf, "HEAD", new_head, head,
-				   0, UPDATE_REFS_DIE_ON_ERR);
-			/*
-			 * We ignore errors in 'gc --auto', since the
-			 * user should see them.
-			 */
-			close_object_store(the_repository->objects);
-			run_auto_maintenance(verbosity < 0);
-		}
-	}
-	if (new_head && show_diffstat) {
-		struct diff_options opts;
-		repo_diff_setup(the_repository, &opts);
-		opts.stat_width = -1; /* use full terminal width */
-		opts.stat_graph_width = -1; /* respect statGraphWidth config */
-		opts.output_format |=
-			DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
-		opts.detect_rename = DIFF_DETECT_RENAME;
-		diff_setup_done(&opts);
-		diff_tree_oid(head, new_head, "", &opts);
-		diffcore_std(&opts);
-		diff_flush(&opts);
-	}
-
-	/* Run a post-merge hook */
-	run_hook_le(NULL, "post-merge", squash ? "1" : "0", NULL);
-
-	apply_autostash(git_path_merge_autostash(the_repository));
-	strbuf_release(&reflog_message);
-}
-
-/* Get the name for the merge commit's message. */
-static void merge_name(const char *remote, struct strbuf *msg)
-{
-	struct commit *remote_head;
-	struct object_id branch_head;
-	struct strbuf buf = STRBUF_INIT;
-	struct strbuf bname = STRBUF_INIT;
-	struct merge_remote_desc *desc;
-	const char *ptr;
-	char *found_ref;
-	int len, early;
-
-	strbuf_branchname(&bname, remote, 0);
-	remote = bname.buf;
-
-	oidclr(&branch_head);
-	remote_head = get_merge_parent(remote);
-	if (!remote_head)
-		die(_("'%s' does not point to a commit"), remote);
-
-	if (dwim_ref(remote, strlen(remote), &branch_head, &found_ref, 0) > 0) {
-		if (starts_with(found_ref, "refs/heads/")) {
-			strbuf_addf(msg, "%s\t\tbranch '%s' of .\n",
-				    oid_to_hex(&branch_head), remote);
-			goto cleanup;
-		}
-		if (starts_with(found_ref, "refs/tags/")) {
-			strbuf_addf(msg, "%s\t\ttag '%s' of .\n",
-				    oid_to_hex(&branch_head), remote);
-			goto cleanup;
-		}
-		if (starts_with(found_ref, "refs/remotes/")) {
-			strbuf_addf(msg, "%s\t\tremote-tracking branch '%s' of .\n",
-				    oid_to_hex(&branch_head), remote);
-			goto cleanup;
-		}
-	}
-
-	/* See if remote matches <name>^^^.. or <name>~<number> */
-	for (len = 0, ptr = remote + strlen(remote);
-	     remote < ptr && ptr[-1] == '^';
-	     ptr--)
-		len++;
-	if (len)
-		early = 1;
-	else {
-		early = 0;
-		ptr = strrchr(remote, '~');
-		if (ptr) {
-			int seen_nonzero = 0;
-
-			len++; /* count ~ */
-			while (*++ptr && isdigit(*ptr)) {
-				seen_nonzero |= (*ptr != '0');
-				len++;
-			}
-			if (*ptr)
-				len = 0; /* not ...~<number> */
-			else if (seen_nonzero)
-				early = 1;
-			else if (len == 1)
-				early = 1; /* "name~" is "name~1"! */
-		}
-	}
-	if (len) {
-		struct strbuf truname = STRBUF_INIT;
-		strbuf_addf(&truname, "refs/heads/%s", remote);
-		strbuf_setlen(&truname, truname.len - len);
-		if (ref_exists(truname.buf)) {
-			strbuf_addf(msg,
-				    "%s\t\tbranch '%s'%s of .\n",
-				    oid_to_hex(&remote_head->object.oid),
-				    truname.buf + 11,
-				    (early ? " (early part)" : ""));
-			strbuf_release(&truname);
-			goto cleanup;
-		}
-		strbuf_release(&truname);
-	}
-
-	desc = merge_remote_util(remote_head);
-	if (desc && desc->obj && desc->obj->type == OBJ_TAG) {
-		strbuf_addf(msg, "%s\t\t%s '%s'\n",
-			    oid_to_hex(&desc->obj->oid),
-			    type_name(desc->obj->type),
-			    remote);
-		goto cleanup;
-	}
-
-	strbuf_addf(msg, "%s\t\tcommit '%s'\n",
-		oid_to_hex(&remote_head->object.oid), remote);
-cleanup:
-	strbuf_release(&buf);
-	strbuf_release(&bname);
-}
-
-static void parse_branch_merge_options(char *bmo)
-{
-	const char **argv;
-	int argc;
-
-	if (!bmo)
-		return;
-	argc = split_cmdline(bmo, &argv);
-	if (argc < 0)
-		die(_("Bad branch.%s.mergeoptions string: %s"), branch,
-		    _(split_cmdline_strerror(argc)));
-	REALLOC_ARRAY(argv, argc + 2);
-	MOVE_ARRAY(argv + 1, argv, argc + 1);
-	argc++;
-	argv[0] = "branch.*.mergeoptions";
-	parse_options(argc, argv, NULL, builtin_merge_options,
-		      builtin_merge_usage, 0);
-	free(argv);
-}
-
-static int git_merge_config(const char *k, const char *v, void *cb)
-{
-	int status;
-	const char *str;
-
-	if (branch &&
-	    skip_prefix(k, "branch.", &str) &&
-	    skip_prefix(str, branch, &str) &&
-	    !strcmp(str, ".mergeoptions")) {
-		free(branch_mergeoptions);
-		branch_mergeoptions = xstrdup(v);
-		return 0;
-	}
-
-	if (!strcmp(k, "merge.diffstat") || !strcmp(k, "merge.stat"))
-		show_diffstat = git_config_bool(k, v);
-	else if (!strcmp(k, "merge.verifysignatures"))
-		verify_signatures = git_config_bool(k, v);
-	else if (!strcmp(k, "pull.twohead"))
-		return git_config_string(&pull_twohead, k, v);
-	else if (!strcmp(k, "pull.octopus"))
-		return git_config_string(&pull_octopus, k, v);
-	else if (!strcmp(k, "commit.cleanup"))
-		return git_config_string(&cleanup_arg, k, v);
-	else if (!strcmp(k, "merge.ff")) {
-		int boolval = git_parse_maybe_bool(v);
-		if (0 <= boolval) {
-			fast_forward = boolval ? FF_ALLOW : FF_NO;
-		} else if (v && !strcmp(v, "only")) {
-			fast_forward = FF_ONLY;
-		} /* do not barf on values from future versions of git */
-		return 0;
-	} else if (!strcmp(k, "merge.defaulttoupstream")) {
-		default_to_upstream = git_config_bool(k, v);
-		return 0;
-	} 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;
-	} else if (!strcmp(k, "merge.autostash")) {
-		autostash = git_config_bool(k, v);
-		return 0;
-	}
-
-	status = fmt_merge_msg_config(k, v, cb);
-	if (status)
-		return status;
-	status = git_gpg_config(k, v, NULL);
-	if (status)
-		return status;
-	return git_diff_ui_config(k, v, cb);
-}
-
-static int read_tree_trivial(struct object_id *common, struct object_id *head,
-			     struct object_id *one)
-{
-	int i, nr_trees = 0;
-	struct tree *trees[MAX_UNPACK_TREES];
-	struct tree_desc t[MAX_UNPACK_TREES];
-	struct unpack_trees_options opts;
-
-	memset(&opts, 0, sizeof(opts));
-	opts.head_idx = 2;
-	opts.src_index = &the_index;
-	opts.dst_index = &the_index;
-	opts.update = 1;
-	opts.verbose_update = 1;
-	opts.trivial_merges_only = 1;
-	opts.merge = 1;
-	trees[nr_trees] = parse_tree_indirect(common);
-	if (!trees[nr_trees++])
-		return -1;
-	trees[nr_trees] = parse_tree_indirect(head);
-	if (!trees[nr_trees++])
-		return -1;
-	trees[nr_trees] = parse_tree_indirect(one);
-	if (!trees[nr_trees++])
-		return -1;
-	opts.fn = threeway_merge;
-	cache_tree_free(&active_cache_tree);
-	for (i = 0; i < nr_trees; i++) {
-		parse_tree(trees[i]);
-		init_tree_desc(t+i, trees[i]->buffer, trees[i]->size);
-	}
-	if (unpack_trees(nr_trees, t, &opts))
-		return -1;
-	return 0;
-}
-
-static void write_tree_trivial(struct object_id *oid)
-{
-	if (write_cache_as_tree(oid, 0, NULL))
-		die(_("git write-tree failed to write a tree"));
-}
-
-static int try_merge_strategy(const char *strategy, struct commit_list *common,
-			      struct commit_list *remoteheads,
-			      struct commit *head)
-{
-	const char *head_arg = "HEAD";
-
-	if (refresh_and_write_cache(REFRESH_QUIET, SKIP_IF_UNCHANGED, 0) < 0)
-		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;
-		struct merge_options o;
-		struct commit_list *j;
-
-		if (remoteheads->next) {
-			error(_("Not handling anything other than two heads merge."));
-			return 2;
-		}
-
-		init_merge_options(&o, the_repository);
-		if (!strcmp(strategy, "subtree"))
-			o.subtree_shift = "";
-
-		o.show_rename_progress =
-			show_progress == -1 ? isatty(2) : show_progress;
-
-		for (x = 0; x < xopts_nr; x++)
-			if (parse_merge_opt(&o, xopts[x]))
-				die(_("Unknown option for merge-recursive: -X%s"), xopts[x]);
-
-		o.branch1 = head_arg;
-		o.branch2 = merge_remote_util(remoteheads->item)->name;
-
-		for (j = common; j; j = j->next)
-			commit_list_insert(j->item, &reversed);
-
-		hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
-		clean = merge_recursive(&o, head,
-				remoteheads->item, reversed, &result);
-		if (clean < 0)
-			exit(128);
-		if (write_locked_index(&the_index, &lock,
-				       COMMIT_LOCK | SKIP_IF_UNCHANGED))
-			die(_("unable to write %s"), get_index_file());
-		return clean ? 0 : 1;
-	} else {
-		return try_merge_command(the_repository,
-					 strategy, xopts_nr, xopts,
-					 common, head_arg, remoteheads);
-	}
-}
-
-static void count_diff_files(struct diff_queue_struct *q,
-			     struct diff_options *opt, void *data)
-{
-	int *count = data;
-
-	(*count) += q->nr;
-}
-
-static int count_unmerged_entries(void)
-{
-	int i, ret = 0;
-
-	for (i = 0; i < active_nr; i++)
-		if (ce_stage(active_cache[i]))
-			ret++;
-
-	return ret;
-}
-
-static void add_strategies(const char *string, unsigned attr)
-{
-	int i;
-
-	if (string) {
-		struct string_list list = STRING_LIST_INIT_DUP;
-		struct string_list_item *item;
-		string_list_split(&list, string, ' ', -1);
-		for_each_string_list_item(item, &list)
-			append_strategy(get_strategy(item->string));
-		string_list_clear(&list, 0);
-		return;
-	}
-	for (i = 0; i < ARRAY_SIZE(all_strategy); i++)
-		if (all_strategy[i].attr & attr)
-			append_strategy(&all_strategy[i]);
-
-}
-
-static void read_merge_msg(struct strbuf *msg)
-{
-	const char *filename = git_path_merge_msg(the_repository);
-	strbuf_reset(msg);
-	if (strbuf_read_file(msg, filename, 0) < 0)
-		die_errno(_("Could not read from '%s'"), filename);
-}
-
-static void write_merge_state(struct commit_list *);
-static void abort_commit(struct commit_list *remoteheads, const char *err_msg)
-{
-	if (err_msg)
-		error("%s", err_msg);
-	fprintf(stderr,
-		_("Not committing merge; use 'git commit' to complete the merge.\n"));
-	write_merge_state(remoteheads);
-	exit(1);
-}
-
-static const char merge_editor_comment[] =
-N_("Please enter a commit message to explain why this merge is necessary,\n"
-   "especially if it merges an updated upstream into a topic branch.\n"
-   "\n");
-
-static const char scissors_editor_comment[] =
-N_("An empty message aborts the commit.\n");
-
-static const char no_scissors_editor_comment[] =
-N_("Lines starting with '%c' will be ignored, and an empty message aborts\n"
-   "the commit.\n");
-
-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");
-	if (0 < option_edit) {
-		strbuf_addch(&msg, '\n');
-		if (cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS) {
-			wt_status_append_cut_line(&msg);
-			strbuf_commented_addf(&msg, "\n");
-		}
-		strbuf_commented_addf(&msg, _(merge_editor_comment));
-		strbuf_commented_addf(&msg, _(cleanup_mode == COMMIT_MSG_CLEANUP_SCISSORS ?
-			scissors_editor_comment :
-			no_scissors_editor_comment), comment_line_char);
-	}
-	if (signoff)
-		append_signoff(&msg, ignore_non_trailer(msg.buf, msg.len), 0);
-	write_merge_heads(remoteheads);
-	write_file_buf(git_path_merge_msg(the_repository), msg.buf, msg.len);
-	if (run_commit_hook(0 < option_edit, get_index_file(), "prepare-commit-msg",
-			    git_path_merge_msg(the_repository), "merge", NULL))
-		abort_commit(remoteheads, NULL);
-	if (0 < option_edit) {
-		if (launch_editor(git_path_merge_msg(the_repository), NULL, NULL))
-			abort_commit(remoteheads, NULL);
-	}
-
-	if (!no_verify && run_commit_hook(0 < option_edit, get_index_file(),
-					  "commit-msg",
-					  git_path_merge_msg(the_repository), NULL))
-		abort_commit(remoteheads, NULL);
-
-	read_merge_msg(&msg);
-	cleanup_message(&msg, cleanup_mode, 0);
-	if (!msg.len)
-		abort_commit(remoteheads, _("Empty commit message."));
-	strbuf_release(&merge_msg);
-	strbuf_addbuf(&merge_msg, &msg);
-	strbuf_release(&msg);
-}
-
-static int merge_trivial(struct commit *head, struct commit_list *remoteheads)
-{
-	struct object_id result_tree, result_commit;
-	struct commit_list *parents, **pptr = &parents;
-
-	if (refresh_and_write_cache(REFRESH_QUIET, SKIP_IF_UNCHANGED, 0) < 0)
-		return error(_("Unable to write index."));
-
-	write_tree_trivial(&result_tree);
-	printf(_("Wonderful.\n"));
-	pptr = commit_list_append(head, pptr);
-	pptr = commit_list_append(remoteheads->item, pptr);
-	prepare_to_commit(remoteheads);
-	if (commit_tree(merge_msg.buf, merge_msg.len, &result_tree, parents,
-			&result_commit, NULL, sign_commit))
-		die(_("failed to write commit object"));
-	finish(head, remoteheads, &result_commit, "In-index merge");
-	remove_merge_branch_state(the_repository);
-	return 0;
-}
-
-static int finish_automerge(struct commit *head,
-			    int head_subsumed,
-			    struct commit_list *common,
-			    struct commit_list *remoteheads,
-			    struct object_id *result_tree,
-			    const char *wt_strategy)
-{
-	struct commit_list *parents = NULL;
-	struct strbuf buf = STRBUF_INIT;
-	struct object_id result_commit;
-
-	write_tree_trivial(result_tree);
-	free_commit_list(common);
-	parents = remoteheads;
-	if (!head_subsumed || fast_forward == FF_NO)
-		commit_list_insert(head, &parents);
-	prepare_to_commit(remoteheads);
-	if (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents,
-			&result_commit, NULL, sign_commit))
-		die(_("failed to write commit object"));
-	strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy);
-	finish(head, remoteheads, &result_commit, buf.buf);
-	strbuf_release(&buf);
-	remove_merge_branch_state(the_repository);
-	return 0;
-}
-
-static int suggest_conflicts(void)
-{
-	const char *filename;
-	FILE *fp;
-	struct strbuf msgbuf = STRBUF_INIT;
-
-	filename = git_path_merge_msg(the_repository);
-	fp = xfopen(filename, "a");
-
-	/*
-	 * We can't use cleanup_mode because if we're not using the editor,
-	 * get_cleanup_mode will return COMMIT_MSG_CLEANUP_SPACE instead, even
-	 * though the message is meant to be processed later by git-commit.
-	 * Thus, we will get the cleanup mode which is returned when we _are_
-	 * using an editor.
-	 */
-	append_conflicts_hint(&the_index, &msgbuf,
-			      get_cleanup_mode(cleanup_arg, 1));
-	fputs(msgbuf.buf, fp);
-	strbuf_release(&msgbuf);
-	fclose(fp);
-	repo_rerere(the_repository, allow_rerere_auto);
-	printf(_("Automatic merge failed; "
-			"fix conflicts and then commit the result.\n"));
-	return 1;
-}
-
-static int evaluate_result(void)
-{
-	int cnt = 0;
-	struct rev_info rev;
-
-	/* Check how many files differ. */
-	repo_init_revisions(the_repository, &rev, "");
-	setup_revisions(0, NULL, &rev, NULL);
-	rev.diffopt.output_format |=
-		DIFF_FORMAT_CALLBACK;
-	rev.diffopt.format_callback = count_diff_files;
-	rev.diffopt.format_callback_data = &cnt;
-	run_diff_files(&rev, 0);
-
-	/*
-	 * Check how many unmerged entries are
-	 * there.
-	 */
-	cnt += count_unmerged_entries();
-
-	return cnt;
-}
-
-/*
- * Pretend as if the user told us to merge with the remote-tracking
- * branch we have for the upstream of the current branch
- */
-static int setup_with_upstream(const char ***argv)
-{
-	struct branch *branch = branch_get(NULL);
-	int i;
-	const char **args;
-
-	if (!branch)
-		die(_("No current branch."));
-	if (!branch->remote_name)
-		die(_("No remote for the current branch."));
-	if (!branch->merge_nr)
-		die(_("No default upstream defined for the current branch."));
-
-	args = xcalloc(st_add(branch->merge_nr, 1), sizeof(char *));
-	for (i = 0; i < branch->merge_nr; i++) {
-		if (!branch->merge[i]->dst)
-			die(_("No remote-tracking branch for %s from %s"),
-			    branch->merge[i]->src, branch->remote_name);
-		args[i] = branch->merge[i]->dst;
-	}
-	args[i] = NULL;
-	*argv = args;
-	return i;
-}
-
-static void write_merge_heads(struct commit_list *remoteheads)
-{
-	struct commit_list *j;
-	struct strbuf buf = STRBUF_INIT;
-
-	for (j = remoteheads; j; j = j->next) {
-		struct object_id *oid;
-		struct commit *c = j->item;
-		struct merge_remote_desc *desc;
-
-		desc = merge_remote_util(c);
-		if (desc && desc->obj) {
-			oid = &desc->obj->oid;
-		} else {
-			oid = &c->object.oid;
-		}
-		strbuf_addf(&buf, "%s\n", oid_to_hex(oid));
-	}
-	write_file_buf(git_path_merge_head(the_repository), buf.buf, buf.len);
-
-	strbuf_reset(&buf);
-	if (fast_forward == FF_NO)
-		strbuf_addstr(&buf, "no-ff");
-	write_file_buf(git_path_merge_mode(the_repository), buf.buf, buf.len);
-	strbuf_release(&buf);
-}
-
-static void write_merge_state(struct commit_list *remoteheads)
-{
-	write_merge_heads(remoteheads);
-	strbuf_addch(&merge_msg, '\n');
-	write_file_buf(git_path_merge_msg(the_repository), merge_msg.buf,
-		       merge_msg.len);
-}
-
-static int default_edit_option(void)
-{
-	static const char name[] = "GIT_MERGE_AUTOEDIT";
-	const char *e = getenv(name);
-	struct stat st_stdin, st_stdout;
-
-	if (have_message)
-		/* an explicit -m msg without --[no-]edit */
-		return 0;
-
-	if (e) {
-		int v = git_parse_maybe_bool(e);
-		if (v < 0)
-			die(_("Bad value '%s' in environment '%s'"), e, name);
-		return v;
-	}
-
-	/* Use editor if stdin and stdout are the same and is a tty */
-	return (!fstat(0, &st_stdin) &&
-		!fstat(1, &st_stdout) &&
-		isatty(0) && isatty(1) &&
-		st_stdin.st_dev == st_stdout.st_dev &&
-		st_stdin.st_ino == st_stdout.st_ino &&
-		st_stdin.st_mode == st_stdout.st_mode);
-}
-
-static struct commit_list *reduce_parents(struct commit *head_commit,
-					  int *head_subsumed,
-					  struct commit_list *remoteheads)
-{
-	struct commit_list *parents, **remotes;
-
-	/*
-	 * Is the current HEAD reachable from another commit being
-	 * merged?  If so we do not want to record it as a parent of
-	 * the resulting merge, unless --no-ff is given.  We will flip
-	 * this variable to 0 when we find HEAD among the independent
-	 * tips being merged.
-	 */
-	*head_subsumed = 1;
-
-	/* Find what parents to record by checking independent ones. */
-	parents = reduce_heads(remoteheads);
-	free_commit_list(remoteheads);
-
-	remoteheads = NULL;
-	remotes = &remoteheads;
-	while (parents) {
-		struct commit *commit = pop_commit(&parents);
-		if (commit == head_commit)
-			*head_subsumed = 0;
-		else
-			remotes = &commit_list_insert(commit, remotes)->next;
-	}
-	return remoteheads;
-}
-
-static void prepare_merge_message(struct strbuf *merge_names, struct strbuf *merge_msg)
-{
-	struct fmt_merge_msg_opts opts;
-
-	memset(&opts, 0, sizeof(opts));
-	opts.add_title = !have_message;
-	opts.shortlog_len = shortlog_len;
-	opts.credit_people = (0 < option_edit);
-
-	fmt_merge_msg(merge_names, merge_msg, &opts);
-	if (merge_msg->len)
-		strbuf_setlen(merge_msg, merge_msg->len - 1);
-}
-
-static void handle_fetch_head(struct commit_list **remotes, struct strbuf *merge_names)
-{
-	const char *filename;
-	int fd, pos, npos;
-	struct strbuf fetch_head_file = STRBUF_INIT;
-	const unsigned hexsz = the_hash_algo->hexsz;
-
-	if (!merge_names)
-		merge_names = &fetch_head_file;
-
-	filename = git_path_fetch_head(the_repository);
-	fd = open(filename, O_RDONLY);
-	if (fd < 0)
-		die_errno(_("could not open '%s' for reading"), filename);
-
-	if (strbuf_read(merge_names, fd, 0) < 0)
-		die_errno(_("could not read '%s'"), filename);
-	if (close(fd) < 0)
-		die_errno(_("could not close '%s'"), filename);
-
-	for (pos = 0; pos < merge_names->len; pos = npos) {
-		struct object_id oid;
-		char *ptr;
-		struct commit *commit;
-
-		ptr = strchr(merge_names->buf + pos, '\n');
-		if (ptr)
-			npos = ptr - merge_names->buf + 1;
-		else
-			npos = merge_names->len;
-
-		if (npos - pos < hexsz + 2 ||
-		    get_oid_hex(merge_names->buf + pos, &oid))
-			commit = NULL; /* bad */
-		else if (memcmp(merge_names->buf + pos + hexsz, "\t\t", 2))
-			continue; /* not-for-merge */
-		else {
-			char saved = merge_names->buf[pos + hexsz];
-			merge_names->buf[pos + hexsz] = '\0';
-			commit = get_merge_parent(merge_names->buf + pos);
-			merge_names->buf[pos + hexsz] = saved;
-		}
-		if (!commit) {
-			if (ptr)
-				*ptr = '\0';
-			die(_("not something we can merge in %s: %s"),
-			    filename, merge_names->buf + pos);
-		}
-		remotes = &commit_list_insert(commit, remotes)->next;
-	}
-
-	if (merge_names == &fetch_head_file)
-		strbuf_release(&fetch_head_file);
-}
-
-static struct commit_list *collect_parents(struct commit *head_commit,
-					   int *head_subsumed,
-					   int argc, const char **argv,
-					   struct strbuf *merge_msg)
-{
-	int i;
-	struct commit_list *remoteheads = NULL;
-	struct commit_list **remotes = &remoteheads;
-	struct strbuf merge_names = STRBUF_INIT, *autogen = NULL;
-
-	if (merge_msg && (!have_message || shortlog_len))
-		autogen = &merge_names;
-
-	if (head_commit)
-		remotes = &commit_list_insert(head_commit, remotes)->next;
-
-	if (argc == 1 && !strcmp(argv[0], "FETCH_HEAD")) {
-		handle_fetch_head(remotes, autogen);
-		remoteheads = reduce_parents(head_commit, head_subsumed, remoteheads);
-	} else {
-		for (i = 0; i < argc; i++) {
-			struct commit *commit = get_merge_parent(argv[i]);
-			if (!commit)
-				help_unknown_ref(argv[i], "merge",
-						 _("not something we can merge"));
-			remotes = &commit_list_insert(commit, remotes)->next;
-		}
-		remoteheads = reduce_parents(head_commit, head_subsumed, remoteheads);
-		if (autogen) {
-			struct commit_list *p;
-			for (p = remoteheads; p; p = p->next)
-				merge_name(merge_remote_util(p->item)->name, autogen);
-		}
-	}
-
-	if (autogen) {
-		prepare_merge_message(autogen, merge_msg);
-		strbuf_release(autogen);
-	}
-
-	return remoteheads;
-}
-
-static int merging_a_throwaway_tag(struct commit *commit)
-{
-	char *tag_ref;
-	struct object_id oid;
-	int is_throwaway_tag = 0;
-
-	/* Are we merging a tag? */
-	if (!merge_remote_util(commit) ||
-	    !merge_remote_util(commit)->obj ||
-	    merge_remote_util(commit)->obj->type != OBJ_TAG)
-		return is_throwaway_tag;
-
-	/*
-	 * Now we know we are merging a tag object.  Are we downstream
-	 * and following the tags from upstream?  If so, we must have
-	 * the tag object pointed at by "refs/tags/$T" where $T is the
-	 * tagname recorded in the tag object.  We want to allow such
-	 * a "just to catch up" merge to fast-forward.
-	 *
-	 * Otherwise, we are playing an integrator's role, making a
-	 * merge with a throw-away tag from a contributor with
-	 * something like "git pull $contributor $signed_tag".
-	 * We want to forbid such a merge from fast-forwarding
-	 * by default; otherwise we would not keep the signature
-	 * anywhere.
-	 */
-	tag_ref = xstrfmt("refs/tags/%s",
-			  ((struct tag *)merge_remote_util(commit)->obj)->tag);
-	if (!read_ref(tag_ref, &oid) &&
-	    oideq(&oid, &merge_remote_util(commit)->obj->oid))
-		is_throwaway_tag = 0;
-	else
-		is_throwaway_tag = 1;
-	free(tag_ref);
-	return is_throwaway_tag;
-}
-
-int cmd_merge(int argc, const char **argv, const char *prefix)
-{
-	struct object_id result_tree, stash, head_oid;
-	struct commit *head_commit;
-	struct strbuf buf = STRBUF_INIT;
-	int i, ret = 0, head_subsumed;
-	int best_cnt = -1, merge_was_ok = 0, automerge_was_ok = 0;
-	struct commit_list *common = NULL;
-	const char *best_strategy = NULL, *wt_strategy = NULL;
-	struct commit_list *remoteheads, *p;
-	void *branch_to_free;
-	int orig_argc = argc;
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage_with_options(builtin_merge_usage, builtin_merge_options);
-
-	/*
-	 * Check if we are _not_ on a detached HEAD, i.e. if there is a
-	 * current branch.
-	 */
-	branch = branch_to_free = resolve_refdup("HEAD", 0, &head_oid, NULL);
-	if (branch)
-		skip_prefix(branch, "refs/heads/", &branch);
-
-	init_diff_ui_defaults();
-	git_config(git_merge_config, NULL);
-
-	if (!branch || is_null_oid(&head_oid))
-		head_commit = NULL;
-	else
-		head_commit = lookup_commit_or_die(&head_oid, "HEAD");
-
-	if (branch_mergeoptions)
-		parse_branch_merge_options(branch_mergeoptions);
-	argc = parse_options(argc, argv, prefix, builtin_merge_options,
-			builtin_merge_usage, 0);
-	if (shortlog_len < 0)
-		shortlog_len = (merge_log_config > 0) ? merge_log_config : 0;
-
-	if (verbosity < 0 && show_progress == -1)
-		show_progress = 0;
-
-	if (abort_current_merge) {
-		int nargc = 2;
-		const char *nargv[] = {"reset", "--merge", NULL};
-		struct strbuf stash_oid = STRBUF_INIT;
-
-		if (orig_argc != 2)
-			usage_msg_opt(_("--abort expects no arguments"),
-			      builtin_merge_usage, builtin_merge_options);
-
-		if (!file_exists(git_path_merge_head(the_repository)))
-			die(_("There is no merge to abort (MERGE_HEAD missing)."));
-
-		if (read_oneliner(&stash_oid, git_path_merge_autostash(the_repository),
-		    READ_ONELINER_SKIP_IF_EMPTY))
-			unlink(git_path_merge_autostash(the_repository));
-
-		/* Invoke 'git reset --merge' */
-		ret = cmd_reset(nargc, nargv, prefix);
-
-		if (stash_oid.len)
-			apply_autostash_oid(stash_oid.buf);
-
-		strbuf_release(&stash_oid);
-		goto done;
-	}
-
-	if (quit_current_merge) {
-		if (orig_argc != 2)
-			usage_msg_opt(_("--quit expects no arguments"),
-				      builtin_merge_usage,
-				      builtin_merge_options);
-
-		remove_merge_branch_state(the_repository);
-		goto done;
-	}
-
-	if (continue_current_merge) {
-		int nargc = 1;
-		const char *nargv[] = {"commit", NULL};
-
-		if (orig_argc != 2)
-			usage_msg_opt(_("--continue expects no arguments"),
-			      builtin_merge_usage, builtin_merge_options);
-
-		if (!file_exists(git_path_merge_head(the_repository)))
-			die(_("There is no merge in progress (MERGE_HEAD missing)."));
-
-		/* Invoke 'git commit' */
-		ret = cmd_commit(nargc, nargv, prefix);
-		goto done;
-	}
-
-	if (read_cache_unmerged())
-		die_resolve_conflict("merge");
-
-	if (file_exists(git_path_merge_head(the_repository))) {
-		/*
-		 * There is no unmerged entry, don't advise 'git
-		 * add/rm <file>', just 'git commit'.
-		 */
-		if (advice_resolve_conflict)
-			die(_("You have not concluded your merge (MERGE_HEAD exists).\n"
-				  "Please, commit your changes before you merge."));
-		else
-			die(_("You have not concluded your merge (MERGE_HEAD exists)."));
-	}
-	if (ref_exists("CHERRY_PICK_HEAD")) {
-		if (advice_resolve_conflict)
-			die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
-			    "Please, commit your changes before you merge."));
-		else
-			die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."));
-	}
-	resolve_undo_clear();
-
-	if (option_edit < 0)
-		option_edit = default_edit_option();
-
-	cleanup_mode = get_cleanup_mode(cleanup_arg, 0 < option_edit);
-
-	if (verbosity < 0)
-		show_diffstat = 0;
-
-	if (squash) {
-		if (fast_forward == FF_NO)
-			die(_("You cannot combine --squash with --no-ff."));
-		if (option_commit > 0)
-			die(_("You cannot combine --squash with --commit."));
-		/*
-		 * squash can now silently disable option_commit - this is not
-		 * a problem as it is only overriding the default, not a user
-		 * supplied option.
-		 */
-		option_commit = 0;
-	}
-
-	if (option_commit < 0)
-		option_commit = 1;
-
-	if (!argc) {
-		if (default_to_upstream)
-			argc = setup_with_upstream(&argv);
-		else
-			die(_("No commit specified and merge.defaultToUpstream not set."));
-	} else if (argc == 1 && !strcmp(argv[0], "-")) {
-		argv[0] = "@{-1}";
-	}
-
-	if (!argc)
-		usage_with_options(builtin_merge_usage,
-			builtin_merge_options);
-
-	if (!head_commit) {
-		/*
-		 * If the merged head is a valid one there is no reason
-		 * to forbid "git merge" into a branch yet to be born.
-		 * We do the same for "git pull".
-		 */
-		struct object_id *remote_head_oid;
-		if (squash)
-			die(_("Squash commit into empty head not supported yet"));
-		if (fast_forward == FF_NO)
-			die(_("Non-fast-forward commit does not make sense into "
-			    "an empty head"));
-		remoteheads = collect_parents(head_commit, &head_subsumed,
-					      argc, argv, NULL);
-		if (!remoteheads)
-			die(_("%s - not something we can merge"), argv[0]);
-		if (remoteheads->next)
-			die(_("Can merge only exactly one commit into empty head"));
-
-		if (verify_signatures)
-			verify_merge_signature(remoteheads->item, verbosity,
-					       check_trust_level);
-
-		remote_head_oid = &remoteheads->item->object.oid;
-		read_empty(remote_head_oid, 0);
-		update_ref("initial pull", "HEAD", remote_head_oid, NULL, 0,
-			   UPDATE_REFS_DIE_ON_ERR);
-		goto done;
-	}
-
-	/*
-	 * All the rest are the commits being merged; prepare
-	 * the standard merge summary message to be appended
-	 * to the given message.
-	 */
-	remoteheads = collect_parents(head_commit, &head_subsumed,
-				      argc, argv, &merge_msg);
-
-	if (!head_commit || !argc)
-		usage_with_options(builtin_merge_usage,
-			builtin_merge_options);
-
-	if (verify_signatures) {
-		for (p = remoteheads; p; p = p->next) {
-			verify_merge_signature(p->item, verbosity,
-					       check_trust_level);
-		}
-	}
-
-	strbuf_addstr(&buf, "merge");
-	for (p = remoteheads; p; p = p->next)
-		strbuf_addf(&buf, " %s", merge_remote_util(p->item)->name);
-	setenv("GIT_REFLOG_ACTION", buf.buf, 0);
-	strbuf_reset(&buf);
-
-	for (p = remoteheads; p; p = p->next) {
-		struct commit *commit = p->item;
-		strbuf_addf(&buf, "GITHEAD_%s",
-			    oid_to_hex(&commit->object.oid));
-		setenv(buf.buf, merge_remote_util(commit)->name, 1);
-		strbuf_reset(&buf);
-		if (fast_forward != FF_ONLY && merging_a_throwaway_tag(commit))
-			fast_forward = FF_NO;
-	}
-
-	if (!use_strategies) {
-		if (!remoteheads)
-			; /* already up-to-date */
-		else if (!remoteheads->next)
-			add_strategies(pull_twohead, DEFAULT_TWOHEAD);
-		else
-			add_strategies(pull_octopus, DEFAULT_OCTOPUS);
-	}
-
-	for (i = 0; i < use_strategies_nr; i++) {
-		if (use_strategies[i]->attr & NO_FAST_FORWARD)
-			fast_forward = FF_NO;
-		if (use_strategies[i]->attr & NO_TRIVIAL)
-			allow_trivial = 0;
-	}
-
-	if (!remoteheads)
-		; /* already up-to-date */
-	else if (!remoteheads->next)
-		common = get_merge_bases(head_commit, remoteheads->item);
-	else {
-		struct commit_list *list = remoteheads;
-		commit_list_insert(head_commit, &list);
-		common = get_octopus_merge_bases(list);
-		free(list);
-	}
-
-	update_ref("updating ORIG_HEAD", "ORIG_HEAD",
-		   &head_commit->object.oid, NULL, 0, UPDATE_REFS_DIE_ON_ERR);
-
-	if (remoteheads && !common) {
-		/* No common ancestors found. */
-		if (!allow_unrelated_histories)
-			die(_("refusing to merge unrelated histories"));
-		/* otherwise, we need a real merge. */
-	} else if (!remoteheads ||
-		 (!remoteheads->next && !common->next &&
-		  common->item == remoteheads->item)) {
-		/*
-		 * If head can reach all the merge then we are up to date.
-		 * but first the most common case of merging one remote.
-		 */
-		finish_up_to_date(_("Already up to date."));
-		goto done;
-	} else if (fast_forward != FF_NO && !remoteheads->next &&
-			!common->next &&
-			oideq(&common->item->object.oid, &head_commit->object.oid)) {
-		/* Again the most common case of merging one remote. */
-		struct strbuf msg = STRBUF_INIT;
-		struct commit *commit;
-
-		if (verbosity >= 0) {
-			printf(_("Updating %s..%s\n"),
-			       find_unique_abbrev(&head_commit->object.oid,
-						  DEFAULT_ABBREV),
-			       find_unique_abbrev(&remoteheads->item->object.oid,
-						  DEFAULT_ABBREV));
-		}
-		strbuf_addstr(&msg, "Fast-forward");
-		if (have_message)
-			strbuf_addstr(&msg,
-				" (no commit created; -m option ignored)");
-		commit = remoteheads->item;
-		if (!commit) {
-			ret = 1;
-			goto done;
-		}
-
-		if (autostash)
-			create_autostash(the_repository,
-					 git_path_merge_autostash(the_repository),
-					 "merge");
-		if (checkout_fast_forward(the_repository,
-					  &head_commit->object.oid,
-					  &commit->object.oid,
-					  overwrite_ignore)) {
-			ret = 1;
-			goto done;
-		}
-
-		finish(head_commit, remoteheads, &commit->object.oid, msg.buf);
-		remove_merge_branch_state(the_repository);
-		goto done;
-	} else if (!remoteheads->next && common->next)
-		;
-		/*
-		 * We are not doing octopus and not fast-forward.  Need
-		 * a real merge.
-		 */
-	else if (!remoteheads->next && !common->next && option_commit) {
-		/*
-		 * We are not doing octopus, not fast-forward, and have
-		 * only one common.
-		 */
-		refresh_cache(REFRESH_QUIET);
-		if (allow_trivial && fast_forward != FF_ONLY) {
-			/* See if it is really trivial. */
-			git_committer_info(IDENT_STRICT);
-			printf(_("Trying really trivial in-index merge...\n"));
-			if (!read_tree_trivial(&common->item->object.oid,
-					       &head_commit->object.oid,
-					       &remoteheads->item->object.oid)) {
-				ret = merge_trivial(head_commit, remoteheads);
-				goto done;
-			}
-			printf(_("Nope.\n"));
-		}
-	} else {
-		/*
-		 * An octopus.  If we can reach all the remote we are up
-		 * to date.
-		 */
-		int up_to_date = 1;
-		struct commit_list *j;
-
-		for (j = remoteheads; j; j = j->next) {
-			struct commit_list *common_one;
-
-			/*
-			 * Here we *have* to calculate the individual
-			 * merge_bases again, otherwise "git merge HEAD^
-			 * HEAD^^" would be missed.
-			 */
-			common_one = get_merge_bases(head_commit, j->item);
-			if (!oideq(&common_one->item->object.oid, &j->item->object.oid)) {
-				up_to_date = 0;
-				break;
-			}
-		}
-		if (up_to_date) {
-			finish_up_to_date(_("Already up to date. Yeeah!"));
-			goto done;
-		}
-	}
-
-	if (fast_forward == FF_ONLY)
-		die(_("Not possible to fast-forward, aborting."));
-
-	if (autostash)
-		create_autostash(the_repository,
-				 git_path_merge_autostash(the_repository),
-				 "merge");
-
-	/* We are going to make a new commit. */
-	git_committer_info(IDENT_STRICT);
-
-	/*
-	 * At this point, we need a real merge.  No matter what strategy
-	 * we use, it would operate on the index, possibly affecting the
-	 * working tree, and when resolved cleanly, have the desired
-	 * tree in the index -- this means that the index must be in
-	 * sync with the head commit.  The strategies are responsible
-	 * to ensure this.
-	 */
-	if (use_strategies_nr == 1 ||
-	    /*
-	     * Stash away the local changes so that we can try more than one.
-	     */
-	    save_state(&stash))
-		oidclr(&stash);
-
-	for (i = 0; !merge_was_ok && i < use_strategies_nr; i++) {
-		int ret, cnt;
-		if (i) {
-			printf(_("Rewinding the tree to pristine...\n"));
-			restore_state(&head_commit->object.oid, &stash);
-		}
-		if (use_strategies_nr != 1)
-			printf(_("Trying merge strategy %s...\n"),
-				use_strategies[i]->name);
-		/*
-		 * Remember which strategy left the state in the working
-		 * tree.
-		 */
-		wt_strategy = use_strategies[i]->name;
-
-		ret = try_merge_strategy(use_strategies[i]->name,
-					 common, remoteheads,
-					 head_commit);
-		/*
-		 * The backend exits with 1 when conflicts are
-		 * left to be resolved, with 2 when it does not
-		 * handle the given merge at all.
-		 */
-		if (ret < 2) {
-			if (!ret) {
-				if (option_commit) {
-					/* Automerge succeeded. */
-					automerge_was_ok = 1;
-					break;
-				}
-				merge_was_ok = 1;
-			}
-			cnt = (use_strategies_nr > 1) ? evaluate_result() : 0;
-			if (best_cnt <= 0 || cnt <= best_cnt) {
-				best_strategy = use_strategies[i]->name;
-				best_cnt = cnt;
-			}
-		}
-	}
-
-	/*
-	 * If we have a resulting tree, that means the strategy module
-	 * auto resolved the merge cleanly.
-	 */
-	if (automerge_was_ok) {
-		ret = finish_automerge(head_commit, head_subsumed,
-				       common, remoteheads,
-				       &result_tree, wt_strategy);
-		goto done;
-	}
-
-	/*
-	 * Pick the result from the best strategy and have the user fix
-	 * it up.
-	 */
-	if (!best_strategy) {
-		restore_state(&head_commit->object.oid, &stash);
-		if (use_strategies_nr > 1)
-			fprintf(stderr,
-				_("No merge strategy handled the merge.\n"));
-		else
-			fprintf(stderr, _("Merge with strategy %s failed.\n"),
-				use_strategies[0]->name);
-		ret = 2;
-		goto done;
-	} else if (best_strategy == wt_strategy)
-		; /* We already have its result in the working tree. */
-	else {
-		printf(_("Rewinding the tree to pristine...\n"));
-		restore_state(&head_commit->object.oid, &stash);
-		printf(_("Using the %s to prepare resolving by hand.\n"),
-			best_strategy);
-		try_merge_strategy(best_strategy, common, remoteheads,
-				   head_commit);
-	}
-
-	if (squash) {
-		finish(head_commit, remoteheads, NULL, NULL);
-
-		git_test_write_commit_graph_or_die();
-	} else
-		write_merge_state(remoteheads);
-
-	if (merge_was_ok)
-		fprintf(stderr, _("Automatic merge went well; "
-			"stopped before committing as requested\n"));
-	else
-		ret = suggest_conflicts();
-
-done:
-	free(branch_to_free);
-	return ret;
-}
diff --git a/third_party/git/builtin/mktag.c b/third_party/git/builtin/mktag.c
deleted file mode 100644
index 4982d3a93efb..000000000000
--- a/third_party/git/builtin/mktag.c
+++ /dev/null
@@ -1,179 +0,0 @@
-#include "builtin.h"
-#include "tag.h"
-#include "replace-object.h"
-#include "object-store.h"
-
-/*
- * A signature file has a very simple fixed format: four lines
- * of "object <sha1>" + "type <typename>" + "tag <tagname>" +
- * "tagger <committer>", followed by a blank line, a free-form tag
- * message and a signature block that git itself doesn't care about,
- * but that can be verified with gpg or similar.
- *
- * The first four lines are guaranteed to be at least 83 bytes:
- * "object <sha1>\n" is 48 bytes, "type tag\n" at 9 bytes is the
- * shortest possible type-line, "tag .\n" at 6 bytes is the shortest
- * single-character-tag line, and "tagger . <> 0 +0000\n" at 20 bytes is
- * the shortest possible tagger-line.
- */
-
-/*
- * We refuse to tag something we can't verify. Just because.
- */
-static int verify_object(const struct object_id *oid, const char *expected_type)
-{
-	int ret = -1;
-	enum object_type type;
-	unsigned long size;
-	void *buffer = read_object_file(oid, &type, &size);
-	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);
-		}
-		free(buffer);
-	}
-	return ret;
-}
-
-static int verify_tag(char *buffer, unsigned long size)
-{
-	int typelen;
-	char type[20];
-	struct object_id oid;
-	const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb, *p;
-	size_t len;
-
-	if (size < 84)
-		return error("wanna fool me ? you obviously got the size wrong !");
-
-	buffer[size] = 0;
-
-	/* Verify object line */
-	object = buffer;
-	if (memcmp(object, "object ", 7))
-		return error("char%d: does not start with \"object \"", 0);
-
-	if (parse_oid_hex(object + 7, &oid, &p))
-		return error("char%d: could not get SHA1 hash", 7);
-
-	/* Verify type line */
-	type_line = p + 1;
-	if (memcmp(type_line - 1, "\ntype ", 6))
-		return error("char%d: could not find \"\\ntype \"", 47);
-
-	/* Verify tag-line */
-	tag_line = strchr(type_line, '\n');
-	if (!tag_line)
-		return error("char%"PRIuMAX": could not find next \"\\n\"",
-				(uintmax_t) (type_line - buffer));
-	tag_line++;
-	if (memcmp(tag_line, "tag ", 4) || tag_line[4] == '\n')
-		return error("char%"PRIuMAX": no \"tag \" found",
-				(uintmax_t) (tag_line - buffer));
-
-	/* Get the actual type */
-	typelen = tag_line - type_line - strlen("type \n");
-	if (typelen >= sizeof(type))
-		return error("char%"PRIuMAX": type too long",
-				(uintmax_t) (type_line+5 - buffer));
-
-	memcpy(type, type_line+5, typelen);
-	type[typelen] = 0;
-
-	/* Verify that the object matches */
-	if (verify_object(&oid, type))
-		return error("char%d: could not verify object %s", 7, oid_to_hex(&oid));
-
-	/* Verify the tag-name: we don't allow control characters or spaces in it */
-	tag_line += 4;
-	for (;;) {
-		unsigned char c = *tag_line++;
-		if (c == '\n')
-			break;
-		if (c > ' ')
-			continue;
-		return error("char%"PRIuMAX": could not verify tag name",
-				(uintmax_t) (tag_line - buffer));
-	}
-
-	/* Verify the tagger line */
-	tagger_line = tag_line;
-
-	if (memcmp(tagger_line, "tagger ", 7))
-		return error("char%"PRIuMAX": could not find \"tagger \"",
-			(uintmax_t) (tagger_line - buffer));
-
-	/*
-	 * Check for correct form for name and email
-	 * i.e. " <" followed by "> " on _this_ line
-	 * No angle brackets within the name or email address fields.
-	 * No spaces within the email address field.
-	 */
-	tagger_line += 7;
-	if (!(lb = strstr(tagger_line, " <")) || !(rb = strstr(lb+2, "> ")) ||
-		strpbrk(tagger_line, "<>\n") != lb+1 ||
-		strpbrk(lb+2, "><\n ") != rb)
-		return error("char%"PRIuMAX": malformed tagger field",
-			(uintmax_t) (tagger_line - buffer));
-
-	/* Check for author name, at least one character, space is acceptable */
-	if (lb == tagger_line)
-		return error("char%"PRIuMAX": missing tagger name",
-			(uintmax_t) (tagger_line - buffer));
-
-	/* timestamp, 1 or more digits followed by space */
-	tagger_line = rb + 2;
-	if (!(len = strspn(tagger_line, "0123456789")))
-		return error("char%"PRIuMAX": missing tag timestamp",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line += len;
-	if (*tagger_line != ' ')
-		return error("char%"PRIuMAX": malformed tag timestamp",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line++;
-
-	/* timezone, 5 digits [+-]hhmm, max. 1400 */
-	if (!((tagger_line[0] == '+' || tagger_line[0] == '-') &&
-	      strspn(tagger_line+1, "0123456789") == 4 &&
-	      tagger_line[5] == '\n' && atoi(tagger_line+1) <= 1400))
-		return error("char%"PRIuMAX": malformed tag timezone",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line += 6;
-
-	/* Verify the blank line separating the header from the body */
-	if (*tagger_line != '\n')
-		return error("char%"PRIuMAX": trailing garbage in tag header",
-			(uintmax_t) (tagger_line - buffer));
-
-	/* The actual stuff afterwards we don't care about.. */
-	return 0;
-}
-
-int cmd_mktag(int argc, const char **argv, const char *prefix)
-{
-	struct strbuf buf = STRBUF_INIT;
-	struct object_id result;
-
-	if (argc != 1)
-		usage("git mktag");
-
-	if (strbuf_read(&buf, 0, 4096) < 0) {
-		die_errno("could not read from stdin");
-	}
-
-	/* Verify it for some basic sanity: it needs to start with
-	   "object <sha1>\ntype\ntagger " */
-	if (verify_tag(buf.buf, buf.len) < 0)
-		die("invalid tag signature file");
-
-	if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)
-		die("unable to write tag file");
-
-	strbuf_release(&buf);
-	printf("%s\n", oid_to_hex(&result));
-	return 0;
-}
diff --git a/third_party/git/builtin/mktree.c b/third_party/git/builtin/mktree.c
deleted file mode 100644
index 891991b00d67..000000000000
--- a/third_party/git/builtin/mktree.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * GIT - the stupid content tracker
- *
- * Copyright (c) Junio C Hamano, 2006, 2009
- */
-#include "builtin.h"
-#include "quote.h"
-#include "tree.h"
-#include "parse-options.h"
-#include "object-store.h"
-
-static struct treeent {
-	unsigned mode;
-	struct object_id oid;
-	int len;
-	char name[FLEX_ARRAY];
-} **entries;
-static int alloc, used;
-
-static void append_to_tree(unsigned mode, struct object_id *oid, char *path)
-{
-	struct treeent *ent;
-	size_t len = strlen(path);
-	if (strchr(path, '/'))
-		die("path %s contains slash", path);
-
-	FLEX_ALLOC_MEM(ent, name, path, len);
-	ent->mode = mode;
-	ent->len = len;
-	oidcpy(&ent->oid, oid);
-
-	ALLOC_GROW(entries, used + 1, alloc);
-	entries[used++] = ent;
-}
-
-static int ent_compare(const void *a_, const void *b_)
-{
-	struct treeent *a = *(struct treeent **)a_;
-	struct treeent *b = *(struct treeent **)b_;
-	return base_name_compare(a->name, a->len, a->mode,
-				 b->name, b->len, b->mode);
-}
-
-static void write_tree(struct object_id *oid)
-{
-	struct strbuf buf;
-	size_t size;
-	int i;
-
-	QSORT(entries, used, ent_compare);
-	for (size = i = 0; i < used; i++)
-		size += 32 + entries[i]->len;
-
-	strbuf_init(&buf, size);
-	for (i = 0; i < used; i++) {
-		struct treeent *ent = entries[i];
-		strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0');
-		strbuf_add(&buf, ent->oid.hash, the_hash_algo->rawsz);
-	}
-
-	write_object_file(buf.buf, buf.len, tree_type, oid);
-	strbuf_release(&buf);
-}
-
-static const char *mktree_usage[] = {
-	N_("git mktree [-z] [--missing] [--batch]"),
-	NULL
-};
-
-static void mktree_line(char *buf, int nul_term_line, int allow_missing)
-{
-	char *ptr, *ntr;
-	const char *p;
-	unsigned mode;
-	enum object_type mode_type; /* object type derived from mode */
-	enum object_type obj_type; /* object type derived from sha */
-	char *path, *to_free = NULL;
-	struct object_id oid;
-
-	ptr = buf;
-	/*
-	 * Read non-recursive ls-tree output format:
-	 *     mode SP type SP sha1 TAB name
-	 */
-	mode = strtoul(ptr, &ntr, 8);
-	if (ptr == ntr || !ntr || *ntr != ' ')
-		die("input format error: %s", buf);
-	ptr = ntr + 1; /* type */
-	ntr = strchr(ptr, ' ');
-	if (!ntr || parse_oid_hex(ntr + 1, &oid, &p) ||
-	    *p != '\t')
-		die("input format error: %s", buf);
-
-	/* It is perfectly normal if we do not have a commit from a submodule */
-	if (S_ISGITLINK(mode))
-		allow_missing = 1;
-
-
-	*ntr++ = 0; /* now at the beginning of SHA1 */
-
-	path = (char *)p + 1;  /* at the beginning of name */
-	if (!nul_term_line && path[0] == '"') {
-		struct strbuf p_uq = STRBUF_INIT;
-		if (unquote_c_style(&p_uq, path, NULL))
-			die("invalid quoting");
-		path = to_free = strbuf_detach(&p_uq, NULL);
-	}
-
-	/*
-	 * Object type is redundantly derivable three ways.
-	 * These should all agree.
-	 */
-	mode_type = object_type(mode);
-	if (mode_type != type_from_string(ptr)) {
-		die("entry '%s' object type (%s) doesn't match mode type (%s)",
-			path, ptr, type_name(mode_type));
-	}
-
-	/* Check the type of object identified by sha1 */
-	obj_type = oid_object_info(the_repository, &oid, NULL);
-	if (obj_type < 0) {
-		if (allow_missing) {
-			; /* no problem - missing objects are presumed to be of the right type */
-		} else {
-			die("entry '%s' object %s is unavailable", path, oid_to_hex(&oid));
-		}
-	} else {
-		if (obj_type != mode_type) {
-			/*
-			 * The object exists but is of the wrong type.
-			 * This is a problem regardless of allow_missing
-			 * because the new tree entry will never be correct.
-			 */
-			die("entry '%s' object %s is a %s but specified type was (%s)",
-				path, oid_to_hex(&oid), type_name(obj_type), type_name(mode_type));
-		}
-	}
-
-	append_to_tree(mode, &oid, path);
-	free(to_free);
-}
-
-int cmd_mktree(int ac, const char **av, const char *prefix)
-{
-	struct strbuf sb = STRBUF_INIT;
-	struct object_id oid;
-	int nul_term_line = 0;
-	int allow_missing = 0;
-	int is_batch_mode = 0;
-	int got_eof = 0;
-	strbuf_getline_fn getline_fn;
-
-	const struct option option[] = {
-		OPT_BOOL('z', NULL, &nul_term_line, N_("input is NUL terminated")),
-		OPT_SET_INT( 0 , "missing", &allow_missing, N_("allow missing objects"), 1),
-		OPT_SET_INT( 0 , "batch", &is_batch_mode, N_("allow creation of more than one tree"), 1),
-		OPT_END()
-	};
-
-	ac = parse_options(ac, av, prefix, option, mktree_usage, 0);
-	getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
-
-	while (!got_eof) {
-		while (1) {
-			if (getline_fn(&sb, stdin) == EOF) {
-				got_eof = 1;
-				break;
-			}
-			if (sb.buf[0] == '\0') {
-				/* empty lines denote tree boundaries in batch mode */
-				if (is_batch_mode)
-					break;
-				die("input format error: (blank line only valid in batch mode)");
-			}
-			mktree_line(sb.buf, nul_term_line, allow_missing);
-		}
-		if (is_batch_mode && got_eof && used < 1) {
-			/*
-			 * Execution gets here if the last tree entry is terminated with a
-			 * new-line.  The final new-line has been made optional to be
-			 * consistent with the original non-batch behaviour of mktree.
-			 */
-			; /* skip creating an empty tree */
-		} else {
-			write_tree(&oid);
-			puts(oid_to_hex(&oid));
-			fflush(stdout);
-		}
-		used=0; /* reset tree entry buffer for re-use in batch mode */
-	}
-	strbuf_release(&sb);
-	exit(0);
-}
diff --git a/third_party/git/builtin/multi-pack-index.c b/third_party/git/builtin/multi-pack-index.c
deleted file mode 100644
index 5bf88cd2a8e2..000000000000
--- a/third_party/git/builtin/multi-pack-index.c
+++ /dev/null
@@ -1,70 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "parse-options.h"
-#include "midx.h"
-#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>)"),
-	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(),
-	};
-
-	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,
-				   builtin_multi_pack_index_options);
-
-	if (argc > 1) {
-		die(_("too many arguments"));
-		return 1;
-	}
-
-	trace2_cmd_mode(argv[0]);
-
-	if (!strcmp(argv[0], "repack"))
-		return midx_repack(the_repository, opts.object_dir,
-			(size_t)opts.batch_size, flags);
-	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);
-	if (!strcmp(argv[0], "verify"))
-		return verify_midx_file(the_repository, opts.object_dir, flags);
-	if (!strcmp(argv[0], "expire"))
-		return expire_midx_packs(the_repository, opts.object_dir, flags);
-
-	die(_("unrecognized subcommand: %s"), argv[0]);
-}
diff --git a/third_party/git/builtin/mv.c b/third_party/git/builtin/mv.c
deleted file mode 100644
index 7dac714af908..000000000000
--- a/third_party/git/builtin/mv.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * "git mv" builtin command
- *
- * Copyright (C) 2006 Johannes Schindelin
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "config.h"
-#include "pathspec.h"
-#include "lockfile.h"
-#include "dir.h"
-#include "cache-tree.h"
-#include "string-list.h"
-#include "parse-options.h"
-#include "submodule.h"
-
-static const char * const builtin_mv_usage[] = {
-	N_("git mv [<options>] <source>... <destination>"),
-	NULL
-};
-
-#define DUP_BASENAME 1
-#define KEEP_TRAILING_SLASH 2
-
-static const char **internal_prefix_pathspec(const char *prefix,
-					     const char **pathspec,
-					     int count, unsigned flags)
-{
-	int i;
-	const char **result;
-	int prefixlen = prefix ? strlen(prefix) : 0;
-	ALLOC_ARRAY(result, count + 1);
-
-	/* Create an intermediate copy of the pathspec based on the flags */
-	for (i = 0; i < count; i++) {
-		int length = strlen(pathspec[i]);
-		int to_copy = length;
-		char *it;
-		while (!(flags & KEEP_TRAILING_SLASH) &&
-		       to_copy > 0 && is_dir_sep(pathspec[i][to_copy - 1]))
-			to_copy--;
-
-		it = xmemdupz(pathspec[i], to_copy);
-		if (flags & DUP_BASENAME) {
-			result[i] = xstrdup(basename(it));
-			free(it);
-		} else {
-			result[i] = it;
-		}
-	}
-	result[count] = NULL;
-
-	/* Prefix the pathspec and free the old intermediate strings */
-	for (i = 0; i < count; i++) {
-		const char *match = prefix_path(prefix, prefixlen, result[i]);
-		free((char *) result[i]);
-		result[i] = match;
-	}
-
-	return result;
-}
-
-static const char *add_slash(const char *path)
-{
-	size_t len = strlen(path);
-	if (path[len - 1] != '/') {
-		char *with_slash = xmalloc(st_add(len, 2));
-		memcpy(with_slash, path, len);
-		with_slash[len++] = '/';
-		with_slash[len] = 0;
-		return with_slash;
-	}
-	return path;
-}
-
-#define SUBMODULE_WITH_GITDIR ((const char *)1)
-
-static void prepare_move_submodule(const char *src, int first,
-				   const char **submodule_gitfile)
-{
-	struct strbuf submodule_dotgit = STRBUF_INIT;
-	if (!S_ISGITLINK(active_cache[first]->ce_mode))
-		die(_("Directory %s is in index and no submodule?"), src);
-	if (!is_staging_gitmodules_ok(&the_index))
-		die(_("Please stage your changes to .gitmodules or stash them to proceed"));
-	strbuf_addf(&submodule_dotgit, "%s/.git", src);
-	*submodule_gitfile = read_gitfile(submodule_dotgit.buf);
-	if (*submodule_gitfile)
-		*submodule_gitfile = xstrdup(*submodule_gitfile);
-	else
-		*submodule_gitfile = SUBMODULE_WITH_GITDIR;
-	strbuf_release(&submodule_dotgit);
-}
-
-static int index_range_of_same_dir(const char *src, int length,
-				   int *first_p, int *last_p)
-{
-	const char *src_w_slash = add_slash(src);
-	int first, last, len_w_slash = length + 1;
-
-	first = cache_name_pos(src_w_slash, len_w_slash);
-	if (first >= 0)
-		die(_("%.*s is in index"), len_w_slash, src_w_slash);
-
-	first = -1 - first;
-	for (last = first; last < active_nr; last++) {
-		const char *path = active_cache[last]->name;
-		if (strncmp(path, src_w_slash, len_w_slash))
-			break;
-	}
-	if (src_w_slash != src)
-		free((char *)src_w_slash);
-	*first_p = first;
-	*last_p = last;
-	return last - first;
-}
-
-int cmd_mv(int argc, const char **argv, const char *prefix)
-{
-	int i, flags, gitmodules_modified = 0;
-	int verbose = 0, show_only = 0, force = 0, ignore_errors = 0;
-	struct option builtin_mv_options[] = {
-		OPT__VERBOSE(&verbose, N_("be verbose")),
-		OPT__DRY_RUN(&show_only, N_("dry run")),
-		OPT__FORCE(&force, N_("force move/rename even if target exists"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT_BOOL('k', NULL, &ignore_errors, N_("skip move/rename errors")),
-		OPT_END(),
-	};
-	const char **source, **destination, **dest_path, **submodule_gitfile;
-	enum update_mode { BOTH = 0, WORKING_DIRECTORY, INDEX } *modes;
-	struct stat st;
-	struct string_list src_for_dst = STRING_LIST_INIT_NODUP;
-	struct lock_file lock_file = LOCK_INIT;
-	struct cache_entry *ce;
-
-	git_config(git_default_config, NULL);
-
-	argc = parse_options(argc, argv, prefix, builtin_mv_options,
-			     builtin_mv_usage, 0);
-	if (--argc < 1)
-		usage_with_options(builtin_mv_usage, builtin_mv_options);
-
-	hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
-	if (read_cache() < 0)
-		die(_("index file corrupt"));
-
-	source = internal_prefix_pathspec(prefix, argv, argc, 0);
-	modes = xcalloc(argc, sizeof(enum update_mode));
-	/*
-	 * Keep trailing slash, needed to let
-	 * "git mv file no-such-dir/" error out, except in the case
-	 * "git mv directory no-such-dir/".
-	 */
-	flags = KEEP_TRAILING_SLASH;
-	if (argc == 1 && is_directory(argv[0]) && !is_directory(argv[1]))
-		flags = 0;
-	dest_path = internal_prefix_pathspec(prefix, argv + argc, 1, flags);
-	submodule_gitfile = xcalloc(argc, sizeof(char *));
-
-	if (dest_path[0][0] == '\0')
-		/* special case: "." was normalized to "" */
-		destination = internal_prefix_pathspec(dest_path[0], argv, argc, DUP_BASENAME);
-	else if (!lstat(dest_path[0], &st) &&
-			S_ISDIR(st.st_mode)) {
-		dest_path[0] = add_slash(dest_path[0]);
-		destination = internal_prefix_pathspec(dest_path[0], argv, argc, DUP_BASENAME);
-	} else {
-		if (argc != 1)
-			die(_("destination '%s' is not a directory"), dest_path[0]);
-		destination = dest_path;
-	}
-
-	/* Checking */
-	for (i = 0; i < argc; i++) {
-		const char *src = source[i], *dst = destination[i];
-		int length, src_is_dir;
-		const char *bad = NULL;
-
-		if (show_only)
-			printf(_("Checking rename of '%s' to '%s'\n"), src, dst);
-
-		length = strlen(src);
-		if (lstat(src, &st) < 0)
-			bad = _("bad source");
-		else if (!strncmp(src, dst, length) &&
-				(dst[length] == 0 || dst[length] == '/')) {
-			bad = _("can not move directory into itself");
-		} else if ((src_is_dir = S_ISDIR(st.st_mode))
-				&& lstat(dst, &st) == 0)
-			bad = _("cannot move directory over file");
-		else if (src_is_dir) {
-			int first = cache_name_pos(src, length), last;
-
-			if (first >= 0)
-				prepare_move_submodule(src, first,
-						       submodule_gitfile + i);
-			else if (index_range_of_same_dir(src, length,
-							 &first, &last) < 1)
-				bad = _("source directory is empty");
-			else { /* last - first >= 1 */
-				int j, dst_len, n;
-
-				modes[i] = WORKING_DIRECTORY;
-				n = argc + last - first;
-				REALLOC_ARRAY(source, n);
-				REALLOC_ARRAY(destination, n);
-				REALLOC_ARRAY(modes, n);
-				REALLOC_ARRAY(submodule_gitfile, n);
-
-				dst = add_slash(dst);
-				dst_len = strlen(dst);
-
-				for (j = 0; j < last - first; j++) {
-					const char *path = active_cache[first + j]->name;
-					source[argc + j] = path;
-					destination[argc + j] =
-						prefix_path(dst, dst_len, path + length + 1);
-					modes[argc + j] = INDEX;
-					submodule_gitfile[argc + j] = NULL;
-				}
-				argc += last - first;
-			}
-		} else if (!(ce = cache_file_exists(src, length, ignore_case))) {
-			bad = _("not under version control");
-		} else if (ce_stage(ce)) {
-			bad = _("conflicted");
-		} else if (lstat(dst, &st) == 0 &&
-			 (!ignore_case || strcasecmp(src, dst))) {
-			bad = _("destination exists");
-			if (force) {
-				/*
-				 * only files can overwrite each other:
-				 * check both source and destination
-				 */
-				if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
-					if (verbose)
-						warning(_("overwriting '%s'"), dst);
-					bad = NULL;
-				} else
-					bad = _("Cannot overwrite");
-			}
-		} else if (string_list_has_string(&src_for_dst, dst))
-			bad = _("multiple sources for the same target");
-		else if (is_dir_sep(dst[strlen(dst) - 1]))
-			bad = _("destination directory does not exist");
-		else
-			string_list_insert(&src_for_dst, dst);
-
-		if (!bad)
-			continue;
-		if (!ignore_errors)
-			die(_("%s, source=%s, destination=%s"),
-			     bad, src, dst);
-		if (--argc > 0) {
-			int n = argc - i;
-			memmove(source + i, source + i + 1,
-				n * sizeof(char *));
-			memmove(destination + i, destination + i + 1,
-				n * sizeof(char *));
-			memmove(modes + i, modes + i + 1,
-				n * sizeof(enum update_mode));
-			memmove(submodule_gitfile + i, submodule_gitfile + i + 1,
-				n * sizeof(char *));
-			i--;
-		}
-	}
-
-	for (i = 0; i < argc; i++) {
-		const char *src = source[i], *dst = destination[i];
-		enum update_mode mode = modes[i];
-		int pos;
-		if (show_only || verbose)
-			printf(_("Renaming %s to %s\n"), src, dst);
-		if (show_only)
-			continue;
-		if (mode != INDEX && rename(src, dst) < 0) {
-			if (ignore_errors)
-				continue;
-			die_errno(_("renaming '%s' failed"), src);
-		}
-		if (submodule_gitfile[i]) {
-			if (!update_path_in_gitmodules(src, dst))
-				gitmodules_modified = 1;
-			if (submodule_gitfile[i] != SUBMODULE_WITH_GITDIR)
-				connect_work_tree_and_git_dir(dst,
-							      submodule_gitfile[i],
-							      1);
-		}
-
-		if (mode == WORKING_DIRECTORY)
-			continue;
-
-		pos = cache_name_pos(src, strlen(src));
-		assert(pos >= 0);
-		rename_cache_entry_at(pos, dst);
-	}
-
-	if (gitmodules_modified)
-		stage_updated_gitmodules(&the_index);
-
-	if (write_locked_index(&the_index, &lock_file,
-			       COMMIT_LOCK | SKIP_IF_UNCHANGED))
-		die(_("Unable to write new index file"));
-
-	return 0;
-}
diff --git a/third_party/git/builtin/name-rev.c b/third_party/git/builtin/name-rev.c
deleted file mode 100644
index 725dd0451913..000000000000
--- a/third_party/git/builtin/name-rev.c
+++ /dev/null
@@ -1,636 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "repository.h"
-#include "config.h"
-#include "commit.h"
-#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
-
-struct rev_name {
-	char *tip_name;
-	timestamp_t taggerdate;
-	int generation;
-	int distance;
-	int from_tag;
-};
-
-define_commit_slab(commit_rev_name, struct rev_name);
-
-static timestamp_t cutoff = TIME_MAX;
-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)
-{
-	return name && (name->generation || name->tip_name);
-}
-
-static struct rev_name *get_commit_rev_name(const struct commit *commit)
-{
-	struct rev_name *name = commit_rev_name_peek(&rev_names, commit);
-
-	return is_valid_rev_name(name) ? name : NULL;
-}
-
-static int is_better_name(struct rev_name *name,
-			  timestamp_t taggerdate,
-			  int distance,
-			  int from_tag)
-{
-	/*
-	 * When comparing names based on tags, prefer names
-	 * based on the older tag, even if it is farther away.
-	 */
-	if (from_tag && name->from_tag)
-		return (name->taggerdate > taggerdate ||
-			(name->taggerdate == taggerdate &&
-			 name->distance > distance));
-
-	/*
-	 * We know that at least one of them is a non-tag at this point.
-	 * favor a tag over a non-tag.
-	 */
-	if (name->from_tag != from_tag)
-		return from_tag;
-
-	/*
-	 * We are now looking at two non-tags.  Tiebreak to favor
-	 * shorter hops.
-	 */
-	if (name->distance != distance)
-		return name->distance > distance;
-
-	/* ... or tiebreak to favor older date */
-	if (name->taggerdate != taggerdate)
-		return name->taggerdate > taggerdate;
-
-	/* keep the current one if we cannot decide */
-	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,
-		const char *tip_name, timestamp_t taggerdate,
-		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;
-
-	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);
-
-	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;
-
-		for (parents = commit->parents;
-				parents;
-				parents = parents->next, parent_number++) {
-			struct commit *parent = parents->item;
-			struct rev_name *parent_name;
-			int generation, distance;
-
-			parse_commit(parent);
-			if (parent->date < cutoff)
-				continue;
-
-			if (parent_number > 1) {
-				generation = 0;
-				distance = name->distance + MERGE_TRAVERSAL_WEIGHT;
-			} else {
-				generation = name->generation + 1;
-				distance = name->distance + 1;
-			}
-
-			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++;
-			}
-		}
-
-		/* 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)
-{
-	const char *subpath = path;
-
-	while (subpath) {
-		if (!wildmatch(filter, subpath, 0))
-			return subpath - path;
-		subpath = strchr(subpath, '/');
-		if (subpath)
-			subpath++;
-	}
-	return -1;
-}
-
-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);
-	return refname;
-}
-
-struct name_ref_data {
-	int tags_only;
-	int name_only;
-	struct string_list ref_filters;
-	struct string_list exclude_filters;
-};
-
-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;
-	int sorted;
-} 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)
-{
-	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;
-}
-
-static int tipcmp(const void *a_, const void *b_)
-{
-	const struct tip_table_entry *a = a_, *b = 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/"))
-		return 0;
-
-	if (data->exclude_filters.nr) {
-		struct string_list_item *item;
-
-		for_each_string_list_item(item, &data->exclude_filters) {
-			if (subpath_matches(path, item->string) >= 0)
-				return 0;
-		}
-	}
-
-	if (data->ref_filters.nr) {
-		struct string_list_item *item;
-		int matched = 0;
-
-		/* See if any of the patterns match. */
-		for_each_string_list_item(item, &data->ref_filters) {
-			/*
-			 * Check all patterns even after finding a match, so
-			 * that we can see if a match with a subpath exists.
-			 * When a user asked for 'refs/tags/v*' and 'v1.*',
-			 * both of which match, the user is showing her
-			 * willingness to accept a shortened output by having
-			 * the 'v1.*' in the acceptable refnames, so we
-			 * shouldn't stop when seeing 'refs/tags/v1.4' matches
-			 * 'refs/tags/v*'.  We should show it as 'v1.4'.
-			 */
-			switch (subpath_matches(path, item->string)) {
-			case -1: /* did not match */
-				break;
-			case 0: /* matched fully */
-				matched = 1;
-				break;
-			default: /* matched subpath */
-				matched = 1;
-				can_abbreviate_output = 1;
-				break;
-			}
-		}
-
-		/* If none of the patterns matched, stop now */
-		if (!matched)
-			return 0;
-	}
-
-	while (o && o->type == OBJ_TAG) {
-		struct tag *t = (struct tag *) o;
-		if (!t->tagged)
-			break; /* broken repository */
-		o = parse_object(the_repository, &t->tagged->oid);
-		deref = 1;
-		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;
-	}
-
-	add_to_tip_table(oid, path, can_abbreviate_output, commit, taggerdate,
-			 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);
-		}
-	}
-}
-
-static const unsigned char *nth_tip_table_ent(size_t ix, void *table_)
-{
-	struct tip_table_entry *table = table_;
-	return table[ix].oid.hash;
-}
-
-static const char *get_exact_ref_match(const struct object *o)
-{
-	int found;
-
-	if (!tip_table.table || !tip_table.nr)
-		return NULL;
-
-	if (!tip_table.sorted) {
-		QSORT(tip_table.table, tip_table.nr, tipcmp);
-		tip_table.sorted = 1;
-	}
-
-	found = sha1_pos(o->oid.hash, tip_table.table, tip_table.nr,
-			 nth_tip_table_ent);
-	if (0 <= found)
-		return tip_table.table[found].refname;
-	return NULL;
-}
-
-/* may return a constant string or use "buf" as scratch space */
-static const char *get_rev_name(const struct object *o, struct strbuf *buf)
-{
-	struct rev_name *n;
-	const struct commit *c;
-
-	if (o->type != OBJ_COMMIT)
-		return get_exact_ref_match(o);
-	c = (const struct commit *) o;
-	n = get_commit_rev_name(c);
-	if (!n)
-		return NULL;
-
-	if (!n->generation)
-		return n->tip_name;
-	else {
-		strbuf_reset(buf);
-		strbuf_addstr(buf, n->tip_name);
-		strbuf_strip_suffix(buf, "^0");
-		strbuf_addf(buf, "~%d", n->generation);
-		return buf->buf;
-	}
-}
-
-static void show_name(const struct object *obj,
-		      const char *caller_name,
-		      int always, int allow_undefined, int name_only)
-{
-	const char *name;
-	const struct object_id *oid = &obj->oid;
-	struct strbuf buf = STRBUF_INIT;
-
-	if (!name_only)
-		printf("%s ", caller_name ? caller_name : oid_to_hex(oid));
-	name = get_rev_name(obj, &buf);
-	if (name)
-		printf("%s\n", name);
-	else if (allow_undefined)
-		printf("undefined\n");
-	else if (always)
-		printf("%s\n", find_unique_abbrev(oid, DEFAULT_ABBREV));
-	else
-		die("cannot describe '%s'", oid_to_hex(oid));
-	strbuf_release(&buf);
-}
-
-static char const * const name_rev_usage[] = {
-	N_("git name-rev [<options>] <commit>..."),
-	N_("git name-rev [<options>] --all"),
-	N_("git name-rev [<options>] --stdin"),
-	NULL
-};
-
-static void name_rev_line(char *p, struct name_ref_data *data)
-{
-	struct strbuf buf = STRBUF_INIT;
-	int counter = 0;
-	char *p_start;
-	const unsigned hexsz = the_hash_algo->hexsz;
-
-	for (p_start = p; *p; p++) {
-#define ishex(x) (isdigit((x)) || ((x) >= 'a' && (x) <= 'f'))
-		if (!ishex(*p))
-			counter = 0;
-		else if (++counter == hexsz &&
-			 !ishex(*(p+1))) {
-			struct object_id oid;
-			const char *name = NULL;
-			char c = *(p+1);
-			int p_len = p - p_start + 1;
-
-			counter = 0;
-
-			*(p+1) = 0;
-			if (!get_oid(p - (hexsz - 1), &oid)) {
-				struct object *o =
-					lookup_object(the_repository, &oid);
-				if (o)
-					name = get_rev_name(o, &buf);
-			}
-			*(p+1) = c;
-
-			if (!name)
-				continue;
-
-			if (data->name_only)
-				printf("%.*s%s", p_len - hexsz, p_start, name);
-			else
-				printf("%.*s (%s)", p_len, p_start, name);
-			p_start = p + 1;
-		}
-	}
-
-	/* flush */
-	if (p_start != p)
-		fwrite(p_start, p - p_start, 1, stdout);
-
-	strbuf_release(&buf);
-}
-
-int cmd_name_rev(int argc, const char **argv, const char *prefix)
-{
-	struct object_array revs = OBJECT_ARRAY_INIT;
-	int all = 0, transform_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0;
-	struct name_ref_data data = { 0, 0, STRING_LIST_INIT_NODUP, STRING_LIST_INIT_NODUP };
-	struct option opts[] = {
-		OPT_BOOL(0, "name-only", &data.name_only, N_("print only ref-based names (no object names)")),
-		OPT_BOOL(0, "tags", &data.tags_only, N_("only use tags to name the commits")),
-		OPT_STRING_LIST(0, "refs", &data.ref_filters, N_("pattern"),
-				   N_("only use refs matching <pattern>")),
-		OPT_STRING_LIST(0, "exclude", &data.exclude_filters, N_("pattern"),
-				   N_("ignore refs matching <pattern>")),
-		OPT_GROUP(""),
-		OPT_BOOL(0, "all", &all, N_("list all commits reachable from all refs")),
-		OPT_BOOL(0, "stdin", &transform_stdin, N_("read from stdin")),
-		OPT_BOOL(0, "undefined", &allow_undefined, N_("allow to print `undefined` names (default)")),
-		OPT_BOOL(0, "always",     &always,
-			   N_("show abbreviated commit object as fallback")),
-		{
-			/* A Hidden OPT_BOOL */
-			OPTION_SET_INT, 0, "peel-tag", &peel_tag, NULL,
-			N_("dereference tags in the input (internal use)"),
-			PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1,
-		},
-		OPT_END(),
-	};
-
-	init_commit_rev_name(&rev_names);
-	git_config(git_default_config, NULL);
-	argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0);
-	if (all + transform_stdin + !!argc > 1) {
-		error("Specify either a list, or --all, not both!");
-		usage_with_options(name_rev_usage, opts);
-	}
-	if (all || transform_stdin)
-		cutoff = 0;
-
-	for (; argc; argc--, argv++) {
-		struct object_id oid;
-		struct object *object;
-		struct commit *commit;
-
-		if (get_oid(*argv, &oid)) {
-			fprintf(stderr, "Could not get sha1 for %s. Skipping.\n",
-					*argv);
-			continue;
-		}
-
-		commit = NULL;
-		object = parse_object(the_repository, &oid);
-		if (object) {
-			struct object *peeled = deref_tag(the_repository,
-							  object, *argv, 0);
-			if (peeled && peeled->type == OBJ_COMMIT)
-				commit = (struct commit *)peeled;
-		}
-
-		if (!object) {
-			fprintf(stderr, "Could not get object for %s. Skipping.\n",
-					*argv);
-			continue;
-		}
-
-		if (commit) {
-			if (cutoff > commit->date)
-				cutoff = commit->date;
-		}
-
-		if (peel_tag) {
-			if (!commit) {
-				fprintf(stderr, "Could not get commit for %s. Skipping.\n",
-					*argv);
-				continue;
-			}
-			object = (struct object *)commit;
-		}
-		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;
-	}
-	for_each_ref(name_ref, &data);
-	name_tips();
-
-	if (transform_stdin) {
-		char buffer[2048];
-
-		while (!feof(stdin)) {
-			char *p = fgets(buffer, sizeof(buffer), stdin);
-			if (!p)
-				break;
-			name_rev_line(p, &data);
-		}
-	} else if (all) {
-		int i, max;
-
-		max = get_max_object_index();
-		for (i = 0; i < max; i++) {
-			struct object *obj = get_indexed_object(i);
-			if (!obj || obj->type != OBJ_COMMIT)
-				continue;
-			show_name(obj, NULL,
-				  always, allow_undefined, data.name_only);
-		}
-	} else {
-		int i;
-		for (i = 0; i < revs.nr; i++)
-			show_name(revs.objects[i].item, revs.objects[i].name,
-				  always, allow_undefined, data.name_only);
-	}
-
-	UNLEAK(revs);
-	return 0;
-}
diff --git a/third_party/git/builtin/notes.c b/third_party/git/builtin/notes.c
deleted file mode 100644
index 2987c08a2e92..000000000000
--- a/third_party/git/builtin/notes.c
+++ /dev/null
@@ -1,1039 +0,0 @@
-/*
- * Builtin "git notes"
- *
- * Copyright (c) 2010 Johan Herland <johan@herland.net>
- *
- * Based on git-notes.sh by Johannes Schindelin,
- * and builtin/tag.c by Kristian Hรธgsberg and Carlos Rica.
- */
-
-#include "cache.h"
-#include "config.h"
-#include "builtin.h"
-#include "notes.h"
-#include "object-store.h"
-#include "repository.h"
-#include "blob.h"
-#include "pretty.h"
-#include "refs.h"
-#include "exec-cmd.h"
-#include "run-command.h"
-#include "parse-options.h"
-#include "string-list.h"
-#include "notes-merge.h"
-#include "notes-utils.h"
-#include "worktree.h"
-
-static const char * const git_notes_usage[] = {
-	N_("git notes [--ref <notes-ref>] [list [<object>]]"),
-	N_("git notes [--ref <notes-ref>] add [-f] [--allow-empty] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]"),
-	N_("git notes [--ref <notes-ref>] copy [-f] <from-object> <to-object>"),
-	N_("git notes [--ref <notes-ref>] append [--allow-empty] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]"),
-	N_("git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]"),
-	N_("git notes [--ref <notes-ref>] show [<object>]"),
-	N_("git notes [--ref <notes-ref>] merge [-v | -q] [-s <strategy>] <notes-ref>"),
-	N_("git notes merge --commit [-v | -q]"),
-	N_("git notes merge --abort [-v | -q]"),
-	N_("git notes [--ref <notes-ref>] remove [<object>...]"),
-	N_("git notes [--ref <notes-ref>] prune [-n] [-v]"),
-	N_("git notes [--ref <notes-ref>] get-ref"),
-	NULL
-};
-
-static const char * const git_notes_list_usage[] = {
-	N_("git notes [list [<object>]]"),
-	NULL
-};
-
-static const char * const git_notes_add_usage[] = {
-	N_("git notes add [<options>] [<object>]"),
-	NULL
-};
-
-static const char * const git_notes_copy_usage[] = {
-	N_("git notes copy [<options>] <from-object> <to-object>"),
-	N_("git notes copy --stdin [<from-object> <to-object>]..."),
-	NULL
-};
-
-static const char * const git_notes_append_usage[] = {
-	N_("git notes append [<options>] [<object>]"),
-	NULL
-};
-
-static const char * const git_notes_edit_usage[] = {
-	N_("git notes edit [<object>]"),
-	NULL
-};
-
-static const char * const git_notes_show_usage[] = {
-	N_("git notes show [<object>]"),
-	NULL
-};
-
-static const char * const git_notes_merge_usage[] = {
-	N_("git notes merge [<options>] <notes-ref>"),
-	N_("git notes merge --commit [<options>]"),
-	N_("git notes merge --abort [<options>]"),
-	NULL
-};
-
-static const char * const git_notes_remove_usage[] = {
-	N_("git notes remove [<object>]"),
-	NULL
-};
-
-static const char * const git_notes_prune_usage[] = {
-	N_("git notes prune [<options>]"),
-	NULL
-};
-
-static const char * const git_notes_get_ref_usage[] = {
-	N_("git notes get-ref"),
-	NULL
-};
-
-static const char note_template[] =
-	N_("Write/edit the notes for the following object:");
-
-struct note_data {
-	int given;
-	int use_editor;
-	char *edit_path;
-	struct strbuf buf;
-};
-
-static void free_note_data(struct note_data *d)
-{
-	if (d->edit_path) {
-		unlink_or_warn(d->edit_path);
-		free(d->edit_path);
-	}
-	strbuf_release(&d->buf);
-}
-
-static int list_each_note(const struct object_id *object_oid,
-		const struct object_id *note_oid, char *note_path,
-		void *cb_data)
-{
-	printf("%s %s\n", oid_to_hex(note_oid), oid_to_hex(object_oid));
-	return 0;
-}
-
-static void copy_obj_to_fd(int fd, const struct object_id *oid)
-{
-	unsigned long size;
-	enum object_type type;
-	char *buf = read_object_file(oid, &type, &size);
-	if (buf) {
-		if (size)
-			write_or_die(fd, buf, size);
-		free(buf);
-	}
-}
-
-static void write_commented_object(int fd, const struct object_id *object)
-{
-	const char *show_args[5] =
-		{"show", "--stat", "--no-notes", oid_to_hex(object), NULL};
-	struct child_process show = CHILD_PROCESS_INIT;
-	struct strbuf buf = STRBUF_INIT;
-	struct strbuf cbuf = STRBUF_INIT;
-
-	/* Invoke "git show --stat --no-notes $object" */
-	show.argv = show_args;
-	show.no_stdin = 1;
-	show.out = -1;
-	show.err = 0;
-	show.git_cmd = 1;
-	if (start_command(&show))
-		die(_("unable to start 'show' for object '%s'"),
-		    oid_to_hex(object));
-
-	if (strbuf_read(&buf, show.out, 0) < 0)
-		die_errno(_("could not read 'show' output"));
-	strbuf_add_commented_lines(&cbuf, buf.buf, buf.len);
-	write_or_die(fd, cbuf.buf, cbuf.len);
-
-	strbuf_release(&cbuf);
-	strbuf_release(&buf);
-
-	if (finish_command(&show))
-		die(_("failed to finish 'show' for object '%s'"),
-		    oid_to_hex(object));
-}
-
-static void prepare_note_data(const struct object_id *object, struct note_data *d,
-		const struct object_id *old_note)
-{
-	if (d->use_editor || !d->given) {
-		int fd;
-		struct strbuf buf = STRBUF_INIT;
-
-		/* write the template message before editing: */
-		d->edit_path = git_pathdup("NOTES_EDITMSG");
-		fd = open(d->edit_path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
-		if (fd < 0)
-			die_errno(_("could not create file '%s'"), d->edit_path);
-
-		if (d->given)
-			write_or_die(fd, d->buf.buf, d->buf.len);
-		else if (old_note)
-			copy_obj_to_fd(fd, old_note);
-
-		strbuf_addch(&buf, '\n');
-		strbuf_add_commented_lines(&buf, "\n", strlen("\n"));
-		strbuf_add_commented_lines(&buf, _(note_template), strlen(_(note_template)));
-		strbuf_addch(&buf, '\n');
-		write_or_die(fd, buf.buf, buf.len);
-
-		write_commented_object(fd, object);
-
-		close(fd);
-		strbuf_release(&buf);
-		strbuf_reset(&d->buf);
-
-		if (launch_editor(d->edit_path, &d->buf, NULL)) {
-			die(_("please supply the note contents using either -m or -F option"));
-		}
-		strbuf_stripspace(&d->buf, 1);
-	}
-}
-
-static void write_note_data(struct note_data *d, struct object_id *oid)
-{
-	if (write_object_file(d->buf.buf, d->buf.len, blob_type, oid)) {
-		error(_("unable to write note object"));
-		if (d->edit_path)
-			error(_("the note contents have been left in %s"),
-				d->edit_path);
-		exit(128);
-	}
-}
-
-static int parse_msg_arg(const struct option *opt, const char *arg, int unset)
-{
-	struct note_data *d = opt->value;
-
-	BUG_ON_OPT_NEG(unset);
-
-	strbuf_grow(&d->buf, strlen(arg) + 2);
-	if (d->buf.len)
-		strbuf_addch(&d->buf, '\n');
-	strbuf_addstr(&d->buf, arg);
-	strbuf_stripspace(&d->buf, 0);
-
-	d->given = 1;
-	return 0;
-}
-
-static int parse_file_arg(const struct option *opt, const char *arg, int unset)
-{
-	struct note_data *d = opt->value;
-
-	BUG_ON_OPT_NEG(unset);
-
-	if (d->buf.len)
-		strbuf_addch(&d->buf, '\n');
-	if (!strcmp(arg, "-")) {
-		if (strbuf_read(&d->buf, 0, 1024) < 0)
-			die_errno(_("cannot read '%s'"), arg);
-	} else if (strbuf_read_file(&d->buf, arg, 1024) < 0)
-		die_errno(_("could not open or read '%s'"), arg);
-	strbuf_stripspace(&d->buf, 0);
-
-	d->given = 1;
-	return 0;
-}
-
-static int parse_reuse_arg(const struct option *opt, const char *arg, int unset)
-{
-	struct note_data *d = opt->value;
-	char *buf;
-	struct object_id object;
-	enum object_type type;
-	unsigned long len;
-
-	BUG_ON_OPT_NEG(unset);
-
-	if (d->buf.len)
-		strbuf_addch(&d->buf, '\n');
-
-	if (get_oid(arg, &object))
-		die(_("failed to resolve '%s' as a valid ref."), arg);
-	if (!(buf = read_object_file(&object, &type, &len)))
-		die(_("failed to read object '%s'."), arg);
-	if (type != OBJ_BLOB) {
-		free(buf);
-		die(_("cannot read note data from non-blob object '%s'."), arg);
-	}
-	strbuf_add(&d->buf, buf, len);
-	free(buf);
-
-	d->given = 1;
-	return 0;
-}
-
-static int parse_reedit_arg(const struct option *opt, const char *arg, int unset)
-{
-	struct note_data *d = opt->value;
-	BUG_ON_OPT_NEG(unset);
-	d->use_editor = 1;
-	return parse_reuse_arg(opt, arg, unset);
-}
-
-static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
-{
-	struct strbuf buf = STRBUF_INIT;
-	struct notes_rewrite_cfg *c = NULL;
-	struct notes_tree *t = NULL;
-	int ret = 0;
-	const char *msg = "Notes added by 'git notes copy'";
-
-	if (rewrite_cmd) {
-		c = init_copy_notes_for_rewrite(rewrite_cmd);
-		if (!c)
-			return 0;
-	} else {
-		init_notes(NULL, NULL, NULL, NOTES_INIT_WRITABLE);
-		t = &default_notes_tree;
-	}
-
-	while (strbuf_getline_lf(&buf, stdin) != EOF) {
-		struct object_id from_obj, to_obj;
-		struct strbuf **split;
-		int err;
-
-		split = strbuf_split(&buf, ' ');
-		if (!split[0] || !split[1])
-			die(_("malformed input line: '%s'."), buf.buf);
-		strbuf_rtrim(split[0]);
-		strbuf_rtrim(split[1]);
-		if (get_oid(split[0]->buf, &from_obj))
-			die(_("failed to resolve '%s' as a valid ref."), split[0]->buf);
-		if (get_oid(split[1]->buf, &to_obj))
-			die(_("failed to resolve '%s' as a valid ref."), split[1]->buf);
-
-		if (rewrite_cmd)
-			err = copy_note_for_rewrite(c, &from_obj, &to_obj);
-		else
-			err = copy_note(t, &from_obj, &to_obj, force,
-					combine_notes_overwrite);
-
-		if (err) {
-			error(_("failed to copy notes from '%s' to '%s'"),
-			      split[0]->buf, split[1]->buf);
-			ret = 1;
-		}
-
-		strbuf_list_free(split);
-	}
-
-	if (!rewrite_cmd) {
-		commit_notes(the_repository, t, msg);
-		free_notes(t);
-	} else {
-		finish_copy_notes_for_rewrite(the_repository, c, msg);
-	}
-	strbuf_release(&buf);
-	return ret;
-}
-
-static struct notes_tree *init_notes_check(const char *subcommand,
-					   int flags)
-{
-	struct notes_tree *t;
-	const char *ref;
-	init_notes(NULL, NULL, NULL, flags);
-	t = &default_notes_tree;
-
-	ref = (flags & NOTES_INIT_WRITABLE) ? t->update_ref : t->ref;
-	if (!starts_with(ref, "refs/notes/"))
-		/*
-		 * TRANSLATORS: the first %s will be replaced by a git
-		 * notes command: 'add', 'merge', 'remove', etc.
-		 */
-		die(_("refusing to %s notes in %s (outside of refs/notes/)"),
-		    subcommand, ref);
-	return t;
-}
-
-static int list(int argc, const char **argv, const char *prefix)
-{
-	struct notes_tree *t;
-	struct object_id object;
-	const struct object_id *note;
-	int retval = -1;
-	struct option options[] = {
-		OPT_END()
-	};
-
-	if (argc)
-		argc = parse_options(argc, argv, prefix, options,
-				     git_notes_list_usage, 0);
-
-	if (1 < argc) {
-		error(_("too many parameters"));
-		usage_with_options(git_notes_list_usage, options);
-	}
-
-	t = init_notes_check("list", 0);
-	if (argc) {
-		if (get_oid(argv[0], &object))
-			die(_("failed to resolve '%s' as a valid ref."), argv[0]);
-		note = get_note(t, &object);
-		if (note) {
-			puts(oid_to_hex(note));
-			retval = 0;
-		} else
-			retval = error(_("no note found for object %s."),
-				       oid_to_hex(&object));
-	} else
-		retval = for_each_note(t, 0, list_each_note, NULL);
-
-	free_notes(t);
-	return retval;
-}
-
-static int append_edit(int argc, const char **argv, const char *prefix);
-
-static int add(int argc, const char **argv, const char *prefix)
-{
-	int force = 0, allow_empty = 0;
-	const char *object_ref;
-	struct notes_tree *t;
-	struct object_id object, new_note;
-	const struct object_id *note;
-	struct note_data d = { 0, 0, NULL, STRBUF_INIT };
-	struct option options[] = {
-		OPT_CALLBACK_F('m', "message", &d, N_("message"),
-			N_("note contents as a string"), PARSE_OPT_NONEG,
-			parse_msg_arg),
-		OPT_CALLBACK_F('F', "file", &d, N_("file"),
-			N_("note contents in a file"), PARSE_OPT_NONEG,
-			parse_file_arg),
-		OPT_CALLBACK_F('c', "reedit-message", &d, N_("object"),
-			N_("reuse and edit specified note object"), PARSE_OPT_NONEG,
-			parse_reedit_arg),
-		OPT_CALLBACK_F('C', "reuse-message", &d, N_("object"),
-			N_("reuse specified note object"), PARSE_OPT_NONEG,
-			parse_reuse_arg),
-		OPT_BOOL(0, "allow-empty", &allow_empty,
-			N_("allow storing empty note")),
-		OPT__FORCE(&force, N_("replace existing notes"), PARSE_OPT_NOCOMPLETE),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, options, git_notes_add_usage,
-			     PARSE_OPT_KEEP_ARGV0);
-
-	if (2 < argc) {
-		error(_("too many parameters"));
-		usage_with_options(git_notes_add_usage, options);
-	}
-
-	object_ref = argc > 1 ? argv[1] : "HEAD";
-
-	if (get_oid(object_ref, &object))
-		die(_("failed to resolve '%s' as a valid ref."), object_ref);
-
-	t = init_notes_check("add", NOTES_INIT_WRITABLE);
-	note = get_note(t, &object);
-
-	if (note) {
-		if (!force) {
-			free_notes(t);
-			if (d.given) {
-				free_note_data(&d);
-				return error(_("Cannot add notes. "
-					"Found existing notes for object %s. "
-					"Use '-f' to overwrite existing notes"),
-					oid_to_hex(&object));
-			}
-			/*
-			 * Redirect to "edit" subcommand.
-			 *
-			 * We only end up here if none of -m/-F/-c/-C or -f are
-			 * given. The original args are therefore still in
-			 * argv[0-1].
-			 */
-			argv[0] = "edit";
-			return append_edit(argc, argv, prefix);
-		}
-		fprintf(stderr, _("Overwriting existing notes for object %s\n"),
-			oid_to_hex(&object));
-	}
-
-	prepare_note_data(&object, &d, note);
-	if (d.buf.len || allow_empty) {
-		write_note_data(&d, &new_note);
-		if (add_note(t, &object, &new_note, combine_notes_overwrite))
-			BUG("combine_notes_overwrite failed");
-		commit_notes(the_repository, t,
-			     "Notes added by 'git notes add'");
-	} else {
-		fprintf(stderr, _("Removing note for object %s\n"),
-			oid_to_hex(&object));
-		remove_note(t, object.hash);
-		commit_notes(the_repository, t,
-			     "Notes removed by 'git notes add'");
-	}
-
-	free_note_data(&d);
-	free_notes(t);
-	return 0;
-}
-
-static int copy(int argc, const char **argv, const char *prefix)
-{
-	int retval = 0, force = 0, from_stdin = 0;
-	const struct object_id *from_note, *note;
-	const char *object_ref;
-	struct object_id object, from_obj;
-	struct notes_tree *t;
-	const char *rewrite_cmd = NULL;
-	struct option options[] = {
-		OPT__FORCE(&force, N_("replace existing notes"), PARSE_OPT_NOCOMPLETE),
-		OPT_BOOL(0, "stdin", &from_stdin, N_("read objects from stdin")),
-		OPT_STRING(0, "for-rewrite", &rewrite_cmd, N_("command"),
-			   N_("load rewriting config for <command> (implies "
-			      "--stdin)")),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, options, git_notes_copy_usage,
-			     0);
-
-	if (from_stdin || rewrite_cmd) {
-		if (argc) {
-			error(_("too many parameters"));
-			usage_with_options(git_notes_copy_usage, options);
-		} else {
-			return notes_copy_from_stdin(force, rewrite_cmd);
-		}
-	}
-
-	if (argc < 1) {
-		error(_("too few parameters"));
-		usage_with_options(git_notes_copy_usage, options);
-	}
-	if (2 < argc) {
-		error(_("too many parameters"));
-		usage_with_options(git_notes_copy_usage, options);
-	}
-
-	if (get_oid(argv[0], &from_obj))
-		die(_("failed to resolve '%s' as a valid ref."), argv[0]);
-
-	object_ref = 1 < argc ? argv[1] : "HEAD";
-
-	if (get_oid(object_ref, &object))
-		die(_("failed to resolve '%s' as a valid ref."), object_ref);
-
-	t = init_notes_check("copy", NOTES_INIT_WRITABLE);
-	note = get_note(t, &object);
-
-	if (note) {
-		if (!force) {
-			retval = error(_("Cannot copy notes. Found existing "
-				       "notes for object %s. Use '-f' to "
-				       "overwrite existing notes"),
-				       oid_to_hex(&object));
-			goto out;
-		}
-		fprintf(stderr, _("Overwriting existing notes for object %s\n"),
-			oid_to_hex(&object));
-	}
-
-	from_note = get_note(t, &from_obj);
-	if (!from_note) {
-		retval = error(_("missing notes on source object %s. Cannot "
-			       "copy."), oid_to_hex(&from_obj));
-		goto out;
-	}
-
-	if (add_note(t, &object, from_note, combine_notes_overwrite))
-		BUG("combine_notes_overwrite failed");
-	commit_notes(the_repository, t,
-		     "Notes added by 'git notes copy'");
-out:
-	free_notes(t);
-	return retval;
-}
-
-static int append_edit(int argc, const char **argv, const char *prefix)
-{
-	int allow_empty = 0;
-	const char *object_ref;
-	struct notes_tree *t;
-	struct object_id object, new_note;
-	const struct object_id *note;
-	char *logmsg;
-	const char * const *usage;
-	struct note_data d = { 0, 0, NULL, STRBUF_INIT };
-	struct option options[] = {
-		OPT_CALLBACK_F('m', "message", &d, N_("message"),
-			N_("note contents as a string"), PARSE_OPT_NONEG,
-			parse_msg_arg),
-		OPT_CALLBACK_F('F', "file", &d, N_("file"),
-			N_("note contents in a file"), PARSE_OPT_NONEG,
-			parse_file_arg),
-		OPT_CALLBACK_F('c', "reedit-message", &d, N_("object"),
-			N_("reuse and edit specified note object"), PARSE_OPT_NONEG,
-			parse_reedit_arg),
-		OPT_CALLBACK_F('C', "reuse-message", &d, N_("object"),
-			N_("reuse specified note object"), PARSE_OPT_NONEG,
-			parse_reuse_arg),
-		OPT_BOOL(0, "allow-empty", &allow_empty,
-			N_("allow storing empty note")),
-		OPT_END()
-	};
-	int edit = !strcmp(argv[0], "edit");
-
-	usage = edit ? git_notes_edit_usage : git_notes_append_usage;
-	argc = parse_options(argc, argv, prefix, options, usage,
-			     PARSE_OPT_KEEP_ARGV0);
-
-	if (2 < argc) {
-		error(_("too many parameters"));
-		usage_with_options(usage, options);
-	}
-
-	if (d.given && edit)
-		fprintf(stderr, _("The -m/-F/-c/-C options have been deprecated "
-			"for the 'edit' subcommand.\n"
-			"Please use 'git notes add -f -m/-F/-c/-C' instead.\n"));
-
-	object_ref = 1 < argc ? argv[1] : "HEAD";
-
-	if (get_oid(object_ref, &object))
-		die(_("failed to resolve '%s' as a valid ref."), object_ref);
-
-	t = init_notes_check(argv[0], NOTES_INIT_WRITABLE);
-	note = get_note(t, &object);
-
-	prepare_note_data(&object, &d, edit && note ? note : NULL);
-
-	if (note && !edit) {
-		/* Append buf to previous note contents */
-		unsigned long size;
-		enum object_type type;
-		char *prev_buf = read_object_file(note, &type, &size);
-
-		strbuf_grow(&d.buf, size + 1);
-		if (d.buf.len && prev_buf && size)
-			strbuf_insertstr(&d.buf, 0, "\n");
-		if (prev_buf && size)
-			strbuf_insert(&d.buf, 0, prev_buf, size);
-		free(prev_buf);
-	}
-
-	if (d.buf.len || allow_empty) {
-		write_note_data(&d, &new_note);
-		if (add_note(t, &object, &new_note, combine_notes_overwrite))
-			BUG("combine_notes_overwrite failed");
-		logmsg = xstrfmt("Notes added by 'git notes %s'", argv[0]);
-	} else {
-		fprintf(stderr, _("Removing note for object %s\n"),
-			oid_to_hex(&object));
-		remove_note(t, object.hash);
-		logmsg = xstrfmt("Notes removed by 'git notes %s'", argv[0]);
-	}
-	commit_notes(the_repository, t, logmsg);
-
-	free(logmsg);
-	free_note_data(&d);
-	free_notes(t);
-	return 0;
-}
-
-static int show(int argc, const char **argv, const char *prefix)
-{
-	const char *object_ref;
-	struct notes_tree *t;
-	struct object_id object;
-	const struct object_id *note;
-	int retval;
-	struct option options[] = {
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, options, git_notes_show_usage,
-			     0);
-
-	if (1 < argc) {
-		error(_("too many parameters"));
-		usage_with_options(git_notes_show_usage, options);
-	}
-
-	object_ref = argc ? argv[0] : "HEAD";
-
-	if (get_oid(object_ref, &object))
-		die(_("failed to resolve '%s' as a valid ref."), object_ref);
-
-	t = init_notes_check("show", 0);
-	note = get_note(t, &object);
-
-	if (!note)
-		retval = error(_("no note found for object %s."),
-			       oid_to_hex(&object));
-	else {
-		const char *show_args[3] = {"show", oid_to_hex(note), NULL};
-		retval = execv_git_cmd(show_args);
-	}
-	free_notes(t);
-	return retval;
-}
-
-static int merge_abort(struct notes_merge_options *o)
-{
-	int ret = 0;
-
-	/*
-	 * Remove .git/NOTES_MERGE_PARTIAL and .git/NOTES_MERGE_REF, and call
-	 * notes_merge_abort() to remove .git/NOTES_MERGE_WORKTREE.
-	 */
-
-	if (delete_ref(NULL, "NOTES_MERGE_PARTIAL", NULL, 0))
-		ret += error(_("failed to delete ref NOTES_MERGE_PARTIAL"));
-	if (delete_ref(NULL, "NOTES_MERGE_REF", NULL, REF_NO_DEREF))
-		ret += error(_("failed to delete ref NOTES_MERGE_REF"));
-	if (notes_merge_abort(o))
-		ret += error(_("failed to remove 'git notes merge' worktree"));
-	return ret;
-}
-
-static int merge_commit(struct notes_merge_options *o)
-{
-	struct strbuf msg = STRBUF_INIT;
-	struct object_id oid, parent_oid;
-	struct notes_tree *t;
-	struct commit *partial;
-	struct pretty_print_context pretty_ctx;
-	void *local_ref_to_free;
-	int ret;
-
-	/*
-	 * Read partial merge result from .git/NOTES_MERGE_PARTIAL,
-	 * and target notes ref from .git/NOTES_MERGE_REF.
-	 */
-
-	if (get_oid("NOTES_MERGE_PARTIAL", &oid))
-		die(_("failed to read ref NOTES_MERGE_PARTIAL"));
-	else if (!(partial = lookup_commit_reference(the_repository, &oid)))
-		die(_("could not find commit from NOTES_MERGE_PARTIAL."));
-	else if (parse_commit(partial))
-		die(_("could not parse commit from NOTES_MERGE_PARTIAL."));
-
-	if (partial->parents)
-		oidcpy(&parent_oid, &partial->parents->item->object.oid);
-	else
-		oidclr(&parent_oid);
-
-	t = xcalloc(1, sizeof(struct notes_tree));
-	init_notes(t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0);
-
-	o->local_ref = local_ref_to_free =
-		resolve_refdup("NOTES_MERGE_REF", 0, &oid, NULL);
-	if (!o->local_ref)
-		die(_("failed to resolve NOTES_MERGE_REF"));
-
-	if (notes_merge_commit(o, t, partial, &oid))
-		die(_("failed to finalize notes merge"));
-
-	/* Reuse existing commit message in reflog message */
-	memset(&pretty_ctx, 0, sizeof(pretty_ctx));
-	format_commit_message(partial, "%s", &msg, &pretty_ctx);
-	strbuf_trim(&msg);
-	strbuf_insertstr(&msg, 0, "notes: ");
-	update_ref(msg.buf, o->local_ref, &oid,
-		   is_null_oid(&parent_oid) ? NULL : &parent_oid,
-		   0, UPDATE_REFS_DIE_ON_ERR);
-
-	free_notes(t);
-	strbuf_release(&msg);
-	ret = merge_abort(o);
-	free(local_ref_to_free);
-	return ret;
-}
-
-static int git_config_get_notes_strategy(const char *key,
-					 enum notes_merge_strategy *strategy)
-{
-	char *value;
-
-	if (git_config_get_string(key, &value))
-		return 1;
-	if (parse_notes_merge_strategy(value, strategy))
-		git_die_config(key, _("unknown notes merge strategy %s"), value);
-
-	free(value);
-	return 0;
-}
-
-static int merge(int argc, const char **argv, const char *prefix)
-{
-	struct strbuf remote_ref = STRBUF_INIT, msg = STRBUF_INIT;
-	struct object_id result_oid;
-	struct notes_tree *t;
-	struct notes_merge_options o;
-	int do_merge = 0, do_commit = 0, do_abort = 0;
-	int verbosity = 0, result;
-	const char *strategy = NULL;
-	struct option options[] = {
-		OPT_GROUP(N_("General options")),
-		OPT__VERBOSITY(&verbosity),
-		OPT_GROUP(N_("Merge options")),
-		OPT_STRING('s', "strategy", &strategy, N_("strategy"),
-			   N_("resolve notes conflicts using the given strategy "
-			      "(manual/ours/theirs/union/cat_sort_uniq)")),
-		OPT_GROUP(N_("Committing unmerged notes")),
-		OPT_SET_INT_F(0, "commit", &do_commit,
-			      N_("finalize notes merge by committing unmerged notes"),
-			      1, PARSE_OPT_NONEG),
-		OPT_GROUP(N_("Aborting notes merge resolution")),
-		OPT_SET_INT_F(0, "abort", &do_abort,
-			      N_("abort notes merge"),
-			      1, PARSE_OPT_NONEG),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, options,
-			     git_notes_merge_usage, 0);
-
-	if (strategy || do_commit + do_abort == 0)
-		do_merge = 1;
-	if (do_merge + do_commit + do_abort != 1) {
-		error(_("cannot mix --commit, --abort or -s/--strategy"));
-		usage_with_options(git_notes_merge_usage, options);
-	}
-
-	if (do_merge && argc != 1) {
-		error(_("must specify a notes ref to merge"));
-		usage_with_options(git_notes_merge_usage, options);
-	} else if (!do_merge && argc) {
-		error(_("too many parameters"));
-		usage_with_options(git_notes_merge_usage, options);
-	}
-
-	init_notes_merge_options(the_repository, &o);
-	o.verbosity = verbosity + NOTES_MERGE_VERBOSITY_DEFAULT;
-
-	if (do_abort)
-		return merge_abort(&o);
-	if (do_commit)
-		return merge_commit(&o);
-
-	o.local_ref = default_notes_ref();
-	strbuf_addstr(&remote_ref, argv[0]);
-	expand_loose_notes_ref(&remote_ref);
-	o.remote_ref = remote_ref.buf;
-
-	t = init_notes_check("merge", NOTES_INIT_WRITABLE);
-
-	if (strategy) {
-		if (parse_notes_merge_strategy(strategy, &o.strategy)) {
-			error(_("unknown -s/--strategy: %s"), strategy);
-			usage_with_options(git_notes_merge_usage, options);
-		}
-	} else {
-		struct strbuf merge_key = STRBUF_INIT;
-		const char *short_ref = NULL;
-
-		if (!skip_prefix(o.local_ref, "refs/notes/", &short_ref))
-			BUG("local ref %s is outside of refs/notes/",
-			    o.local_ref);
-
-		strbuf_addf(&merge_key, "notes.%s.mergeStrategy", short_ref);
-
-		if (git_config_get_notes_strategy(merge_key.buf, &o.strategy))
-			git_config_get_notes_strategy("notes.mergeStrategy", &o.strategy);
-
-		strbuf_release(&merge_key);
-	}
-
-	strbuf_addf(&msg, "notes: Merged notes from %s into %s",
-		    remote_ref.buf, default_notes_ref());
-	strbuf_add(&(o.commit_msg), msg.buf + 7, msg.len - 7); /* skip "notes: " */
-
-	result = notes_merge(&o, t, &result_oid);
-
-	if (result >= 0) /* Merge resulted (trivially) in result_oid */
-		/* Update default notes ref with new commit */
-		update_ref(msg.buf, default_notes_ref(), &result_oid, NULL, 0,
-			   UPDATE_REFS_DIE_ON_ERR);
-	else { /* Merge has unresolved conflicts */
-		const struct worktree *wt;
-		/* Update .git/NOTES_MERGE_PARTIAL with partial merge result */
-		update_ref(msg.buf, "NOTES_MERGE_PARTIAL", &result_oid, NULL,
-			   0, UPDATE_REFS_DIE_ON_ERR);
-		/* Store ref-to-be-updated into .git/NOTES_MERGE_REF */
-		wt = find_shared_symref("NOTES_MERGE_REF", default_notes_ref());
-		if (wt)
-			die(_("a notes merge into %s is already in-progress at %s"),
-			    default_notes_ref(), wt->path);
-		if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL))
-			die(_("failed to store link to current notes ref (%s)"),
-			    default_notes_ref());
-		fprintf(stderr, _("Automatic notes merge failed. Fix conflicts in %s "
-				  "and commit the result with 'git notes merge --commit', "
-				  "or abort the merge with 'git notes merge --abort'.\n"),
-			git_path(NOTES_MERGE_WORKTREE));
-	}
-
-	free_notes(t);
-	strbuf_release(&remote_ref);
-	strbuf_release(&msg);
-	return result < 0; /* return non-zero on conflicts */
-}
-
-#define IGNORE_MISSING 1
-
-static int remove_one_note(struct notes_tree *t, const char *name, unsigned flag)
-{
-	int status;
-	struct object_id oid;
-	if (get_oid(name, &oid))
-		return error(_("Failed to resolve '%s' as a valid ref."), name);
-	status = remove_note(t, oid.hash);
-	if (status)
-		fprintf(stderr, _("Object %s has no note\n"), name);
-	else
-		fprintf(stderr, _("Removing note for object %s\n"), name);
-	return (flag & IGNORE_MISSING) ? 0 : status;
-}
-
-static int remove_cmd(int argc, const char **argv, const char *prefix)
-{
-	unsigned flag = 0;
-	int from_stdin = 0;
-	struct option options[] = {
-		OPT_BIT(0, "ignore-missing", &flag,
-			N_("attempt to remove non-existent note is not an error"),
-			IGNORE_MISSING),
-		OPT_BOOL(0, "stdin", &from_stdin,
-			    N_("read object names from the standard input")),
-		OPT_END()
-	};
-	struct notes_tree *t;
-	int retval = 0;
-
-	argc = parse_options(argc, argv, prefix, options,
-			     git_notes_remove_usage, 0);
-
-	t = init_notes_check("remove", NOTES_INIT_WRITABLE);
-
-	if (!argc && !from_stdin) {
-		retval = remove_one_note(t, "HEAD", flag);
-	} else {
-		while (*argv) {
-			retval |= remove_one_note(t, *argv, flag);
-			argv++;
-		}
-	}
-	if (from_stdin) {
-		struct strbuf sb = STRBUF_INIT;
-		while (strbuf_getwholeline(&sb, stdin, '\n') != EOF) {
-			strbuf_rtrim(&sb);
-			retval |= remove_one_note(t, sb.buf, flag);
-		}
-		strbuf_release(&sb);
-	}
-	if (!retval)
-		commit_notes(the_repository, t,
-			     "Notes removed by 'git notes remove'");
-	free_notes(t);
-	return retval;
-}
-
-static int prune(int argc, const char **argv, const char *prefix)
-{
-	struct notes_tree *t;
-	int show_only = 0, verbose = 0;
-	struct option options[] = {
-		OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
-		OPT__VERBOSE(&verbose, N_("report pruned notes")),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, options, git_notes_prune_usage,
-			     0);
-
-	if (argc) {
-		error(_("too many parameters"));
-		usage_with_options(git_notes_prune_usage, options);
-	}
-
-	t = init_notes_check("prune", NOTES_INIT_WRITABLE);
-
-	prune_notes(t, (verbose ? NOTES_PRUNE_VERBOSE : 0) |
-		(show_only ? NOTES_PRUNE_VERBOSE|NOTES_PRUNE_DRYRUN : 0) );
-	if (!show_only)
-		commit_notes(the_repository, t,
-			     "Notes removed by 'git notes prune'");
-	free_notes(t);
-	return 0;
-}
-
-static int get_ref(int argc, const char **argv, const char *prefix)
-{
-	struct option options[] = { OPT_END() };
-	argc = parse_options(argc, argv, prefix, options,
-			     git_notes_get_ref_usage, 0);
-
-	if (argc) {
-		error(_("too many parameters"));
-		usage_with_options(git_notes_get_ref_usage, options);
-	}
-
-	puts(default_notes_ref());
-	return 0;
-}
-
-int cmd_notes(int argc, const char **argv, const char *prefix)
-{
-	int result;
-	const char *override_notes_ref = NULL;
-	struct option options[] = {
-		OPT_STRING(0, "ref", &override_notes_ref, N_("notes-ref"),
-			   N_("use notes from <notes-ref>")),
-		OPT_END()
-	};
-
-	git_config(git_default_config, NULL);
-	argc = parse_options(argc, argv, prefix, options, git_notes_usage,
-			     PARSE_OPT_STOP_AT_NON_OPTION);
-
-	if (override_notes_ref) {
-		struct strbuf sb = STRBUF_INIT;
-		strbuf_addstr(&sb, override_notes_ref);
-		expand_notes_ref(&sb);
-		setenv("GIT_NOTES_REF", sb.buf, 1);
-		strbuf_release(&sb);
-	}
-
-	if (argc < 1 || !strcmp(argv[0], "list"))
-		result = list(argc, argv, prefix);
-	else if (!strcmp(argv[0], "add"))
-		result = add(argc, argv, prefix);
-	else if (!strcmp(argv[0], "copy"))
-		result = copy(argc, argv, prefix);
-	else if (!strcmp(argv[0], "append") || !strcmp(argv[0], "edit"))
-		result = append_edit(argc, argv, prefix);
-	else if (!strcmp(argv[0], "show"))
-		result = show(argc, argv, prefix);
-	else if (!strcmp(argv[0], "merge"))
-		result = merge(argc, argv, prefix);
-	else if (!strcmp(argv[0], "remove"))
-		result = remove_cmd(argc, argv, prefix);
-	else if (!strcmp(argv[0], "prune"))
-		result = prune(argc, argv, prefix);
-	else if (!strcmp(argv[0], "get-ref"))
-		result = get_ref(argc, argv, prefix);
-	else {
-		result = error(_("unknown subcommand: %s"), argv[0]);
-		usage_with_options(git_notes_usage, options);
-	}
-
-	return result ? 1 : 0;
-}
diff --git a/third_party/git/builtin/pack-objects.c b/third_party/git/builtin/pack-objects.c
deleted file mode 100644
index 5617c01b5aae..000000000000
--- a/third_party/git/builtin/pack-objects.c
+++ /dev/null
@@ -1,3772 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "repository.h"
-#include "config.h"
-#include "attr.h"
-#include "object.h"
-#include "blob.h"
-#include "commit.h"
-#include "tag.h"
-#include "tree.h"
-#include "delta.h"
-#include "pack.h"
-#include "pack-revindex.h"
-#include "csum-file.h"
-#include "tree-walk.h"
-#include "diff.h"
-#include "revision.h"
-#include "list-objects.h"
-#include "list-objects-filter.h"
-#include "list-objects-filter-options.h"
-#include "pack-objects.h"
-#include "progress.h"
-#include "refs.h"
-#include "streaming.h"
-#include "thread-utils.h"
-#include "pack-bitmap.h"
-#include "delta-islands.h"
-#include "reachable.h"
-#include "oid-array.h"
-#include "strvec.h"
-#include "list.h"
-#include "packfile.h"
-#include "object-store.h"
-#include "dir.h"
-#include "midx.h"
-#include "trace2.h"
-#include "shallow.h"
-#include "promisor-remote.h"
-
-#define IN_PACK(obj) oe_in_pack(&to_pack, obj)
-#define SIZE(obj) oe_size(&to_pack, obj)
-#define SET_SIZE(obj,size) oe_set_size(&to_pack, obj, size)
-#define DELTA_SIZE(obj) oe_delta_size(&to_pack, obj)
-#define DELTA(obj) oe_delta(&to_pack, obj)
-#define DELTA_CHILD(obj) oe_delta_child(&to_pack, obj)
-#define DELTA_SIBLING(obj) oe_delta_sibling(&to_pack, obj)
-#define SET_DELTA(obj, val) oe_set_delta(&to_pack, obj, val)
-#define SET_DELTA_EXT(obj, oid) oe_set_delta_ext(&to_pack, obj, oid)
-#define SET_DELTA_SIZE(obj, val) oe_set_delta_size(&to_pack, obj, val)
-#define SET_DELTA_CHILD(obj, val) oe_set_delta_child(&to_pack, obj, val)
-#define SET_DELTA_SIBLING(obj, val) oe_set_delta_sibling(&to_pack, obj, val)
-
-static const char *pack_usage[] = {
-	N_("git pack-objects --stdout [<options>...] [< <ref-list> | < <object-list>]"),
-	N_("git pack-objects [<options>...] <base-name> [< <ref-list> | < <object-list>]"),
-	NULL
-};
-
-/*
- * Objects we are going to pack are collected in the `to_pack` structure.
- * It contains an array (dynamically expanded) of the object data, and a map
- * that can resolve SHA1s to their position in the array.
- */
-static struct packing_data to_pack;
-
-static struct pack_idx_entry **written_list;
-static uint32_t nr_result, nr_written, nr_seen;
-static struct bitmap_index *bitmap_git;
-static uint32_t write_layer;
-
-static int non_empty;
-static int reuse_delta = 1, reuse_object = 1;
-static int keep_unreachable, unpack_unreachable, include_tag;
-static timestamp_t unpack_unreachable_expiration;
-static int pack_loose_unreachable;
-static int local;
-static int have_non_local_packs;
-static int incremental;
-static int ignore_packed_keep_on_disk;
-static int ignore_packed_keep_in_core;
-static int allow_ofs_delta;
-static struct pack_idx_option pack_idx_opts;
-static const char *base_name;
-static int progress = 1;
-static int window = 10;
-static unsigned long pack_size_limit;
-static int depth = 50;
-static int delta_search_threads;
-static int pack_to_stdout;
-static int sparse;
-static int thin;
-static int num_preferred_base;
-static struct progress *progress_state;
-
-static struct packed_git *reuse_packfile;
-static uint32_t reuse_packfile_objects;
-static struct bitmap *reuse_packfile_bitmap;
-
-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,
-	WRITE_BITMAP_TRUE,
-} write_bitmap_index;
-static uint16_t write_bitmap_options = BITMAP_OPT_HASH_CACHE;
-
-static int exclude_promisor_objects;
-
-static int use_delta_islands;
-
-static unsigned long delta_cache_size = 0;
-static unsigned long max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE;
-static unsigned long cache_max_small_delta_size = 1000;
-
-static unsigned long window_memory_limit = 0;
-
-static struct list_objects_filter_options filter_options;
-
-static struct string_list uri_protocols = STRING_LIST_INIT_NODUP;
-
-enum missing_action {
-	MA_ERROR = 0,      /* fail if any missing objects are encountered */
-	MA_ALLOW_ANY,      /* silently allow ALL missing objects */
-	MA_ALLOW_PROMISOR, /* silently allow all missing PROMISOR objects */
-};
-static enum missing_action arg_missing_action;
-static show_object_fn fn_show_object;
-
-struct configured_exclusion {
-	struct oidmap_entry e;
-	char *pack_hash_hex;
-	char *uri;
-};
-static struct oidmap configured_exclusions;
-
-static struct oidset excluded_by_config;
-
-/*
- * stats
- */
-static uint32_t written, written_delta;
-static uint32_t reused, reused_delta;
-
-/*
- * Indexed commits
- */
-static struct commit **indexed_commits;
-static unsigned int indexed_commits_nr;
-static unsigned int indexed_commits_alloc;
-
-static void index_commit_for_bitmap(struct commit *commit)
-{
-	if (indexed_commits_nr >= indexed_commits_alloc) {
-		indexed_commits_alloc = (indexed_commits_alloc + 32) * 2;
-		REALLOC_ARRAY(indexed_commits, indexed_commits_alloc);
-	}
-
-	indexed_commits[indexed_commits_nr++] = commit;
-}
-
-static void *get_delta(struct object_entry *entry)
-{
-	unsigned long size, base_size, delta_size;
-	void *buf, *base_buf, *delta_buf;
-	enum object_type type;
-
-	buf = read_object_file(&entry->idx.oid, &type, &size);
-	if (!buf)
-		die(_("unable to read %s"), oid_to_hex(&entry->idx.oid));
-	base_buf = read_object_file(&DELTA(entry)->idx.oid, &type,
-				    &base_size);
-	if (!base_buf)
-		die("unable to read %s",
-		    oid_to_hex(&DELTA(entry)->idx.oid));
-	delta_buf = diff_delta(base_buf, base_size,
-			       buf, size, &delta_size, 0);
-	/*
-	 * We successfully computed this delta once but dropped it for
-	 * memory reasons. Something is very wrong if this time we
-	 * recompute and create a different delta.
-	 */
-	if (!delta_buf || delta_size != DELTA_SIZE(entry))
-		BUG("delta size changed");
-	free(buf);
-	free(base_buf);
-	return delta_buf;
-}
-
-static unsigned long do_compress(void **pptr, unsigned long size)
-{
-	git_zstream stream;
-	void *in, *out;
-	unsigned long maxsize;
-
-	git_deflate_init(&stream, pack_compression_level);
-	maxsize = git_deflate_bound(&stream, size);
-
-	in = *pptr;
-	out = xmalloc(maxsize);
-	*pptr = out;
-
-	stream.next_in = in;
-	stream.avail_in = size;
-	stream.next_out = out;
-	stream.avail_out = maxsize;
-	while (git_deflate(&stream, Z_FINISH) == Z_OK)
-		; /* nothing */
-	git_deflate_end(&stream);
-
-	free(in);
-	return stream.total_out;
-}
-
-static unsigned long write_large_blob_data(struct git_istream *st, struct hashfile *f,
-					   const struct object_id *oid)
-{
-	git_zstream stream;
-	unsigned char ibuf[1024 * 16];
-	unsigned char obuf[1024 * 16];
-	unsigned long olen = 0;
-
-	git_deflate_init(&stream, pack_compression_level);
-
-	for (;;) {
-		ssize_t readlen;
-		int zret = Z_OK;
-		readlen = read_istream(st, ibuf, sizeof(ibuf));
-		if (readlen == -1)
-			die(_("unable to read %s"), oid_to_hex(oid));
-
-		stream.next_in = ibuf;
-		stream.avail_in = readlen;
-		while ((stream.avail_in || readlen == 0) &&
-		       (zret == Z_OK || zret == Z_BUF_ERROR)) {
-			stream.next_out = obuf;
-			stream.avail_out = sizeof(obuf);
-			zret = git_deflate(&stream, readlen ? 0 : Z_FINISH);
-			hashwrite(f, obuf, stream.next_out - obuf);
-			olen += stream.next_out - obuf;
-		}
-		if (stream.avail_in)
-			die(_("deflate error (%d)"), zret);
-		if (readlen == 0) {
-			if (zret != Z_STREAM_END)
-				die(_("deflate error (%d)"), zret);
-			break;
-		}
-	}
-	git_deflate_end(&stream);
-	return olen;
-}
-
-/*
- * we are going to reuse the existing object data as is.  make
- * sure it is not corrupt.
- */
-static int check_pack_inflate(struct packed_git *p,
-		struct pack_window **w_curs,
-		off_t offset,
-		off_t len,
-		unsigned long expect)
-{
-	git_zstream stream;
-	unsigned char fakebuf[4096], *in;
-	int st;
-
-	memset(&stream, 0, sizeof(stream));
-	git_inflate_init(&stream);
-	do {
-		in = use_pack(p, w_curs, offset, &stream.avail_in);
-		stream.next_in = in;
-		stream.next_out = fakebuf;
-		stream.avail_out = sizeof(fakebuf);
-		st = git_inflate(&stream, Z_FINISH);
-		offset += stream.next_in - in;
-	} while (st == Z_OK || st == Z_BUF_ERROR);
-	git_inflate_end(&stream);
-	return (st == Z_STREAM_END &&
-		stream.total_out == expect &&
-		stream.total_in == len) ? 0 : -1;
-}
-
-static void copy_pack_data(struct hashfile *f,
-		struct packed_git *p,
-		struct pack_window **w_curs,
-		off_t offset,
-		off_t len)
-{
-	unsigned char *in;
-	unsigned long avail;
-
-	while (len) {
-		in = use_pack(p, w_curs, offset, &avail);
-		if (avail > len)
-			avail = (unsigned long)len;
-		hashwrite(f, in, avail);
-		offset += avail;
-		len -= avail;
-	}
-}
-
-/* Return 0 if we will bust the pack-size limit */
-static unsigned long write_no_reuse_object(struct hashfile *f, struct object_entry *entry,
-					   unsigned long limit, int usable_delta)
-{
-	unsigned long size, datalen;
-	unsigned char header[MAX_PACK_OBJECT_HEADER],
-		      dheader[MAX_PACK_OBJECT_HEADER];
-	unsigned hdrlen;
-	enum object_type type;
-	void *buf;
-	struct git_istream *st = NULL;
-	const unsigned hashsz = the_hash_algo->rawsz;
-
-	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)
-			buf = NULL;
-		else {
-			buf = read_object_file(&entry->idx.oid, &type, &size);
-			if (!buf)
-				die(_("unable to read %s"),
-				    oid_to_hex(&entry->idx.oid));
-		}
-		/*
-		 * make sure no cached delta data remains from a
-		 * previous attempt before a pack split occurred.
-		 */
-		FREE_AND_NULL(entry->delta_data);
-		entry->z_delta_size = 0;
-	} else if (entry->delta_data) {
-		size = DELTA_SIZE(entry);
-		buf = entry->delta_data;
-		entry->delta_data = NULL;
-		type = (allow_ofs_delta && DELTA(entry)->idx.offset) ?
-			OBJ_OFS_DELTA : OBJ_REF_DELTA;
-	} else {
-		buf = get_delta(entry);
-		size = DELTA_SIZE(entry);
-		type = (allow_ofs_delta && DELTA(entry)->idx.offset) ?
-			OBJ_OFS_DELTA : OBJ_REF_DELTA;
-	}
-
-	if (st)	/* large blob case, just assume we don't compress well */
-		datalen = size;
-	else if (entry->z_delta_size)
-		datalen = entry->z_delta_size;
-	else
-		datalen = do_compress(&buf, size);
-
-	/*
-	 * The object header is a byte of 'type' followed by zero or
-	 * more bytes of length.
-	 */
-	hdrlen = encode_in_pack_object_header(header, sizeof(header),
-					      type, size);
-
-	if (type == OBJ_OFS_DELTA) {
-		/*
-		 * Deltas with relative base contain an additional
-		 * encoding of the relative offset for the delta
-		 * base from this object's position in the pack.
-		 */
-		off_t ofs = entry->idx.offset - DELTA(entry)->idx.offset;
-		unsigned pos = sizeof(dheader) - 1;
-		dheader[pos] = ofs & 127;
-		while (ofs >>= 7)
-			dheader[--pos] = 128 | (--ofs & 127);
-		if (limit && hdrlen + sizeof(dheader) - pos + datalen + hashsz >= limit) {
-			if (st)
-				close_istream(st);
-			free(buf);
-			return 0;
-		}
-		hashwrite(f, header, hdrlen);
-		hashwrite(f, dheader + pos, sizeof(dheader) - pos);
-		hdrlen += sizeof(dheader) - pos;
-	} else if (type == OBJ_REF_DELTA) {
-		/*
-		 * Deltas with a base reference contain
-		 * additional bytes for the base object ID.
-		 */
-		if (limit && hdrlen + hashsz + datalen + hashsz >= limit) {
-			if (st)
-				close_istream(st);
-			free(buf);
-			return 0;
-		}
-		hashwrite(f, header, hdrlen);
-		hashwrite(f, DELTA(entry)->idx.oid.hash, hashsz);
-		hdrlen += hashsz;
-	} else {
-		if (limit && hdrlen + datalen + hashsz >= limit) {
-			if (st)
-				close_istream(st);
-			free(buf);
-			return 0;
-		}
-		hashwrite(f, header, hdrlen);
-	}
-	if (st) {
-		datalen = write_large_blob_data(st, f, &entry->idx.oid);
-		close_istream(st);
-	} else {
-		hashwrite(f, buf, datalen);
-		free(buf);
-	}
-
-	return hdrlen + datalen;
-}
-
-/* Return 0 if we will bust the pack-size limit */
-static off_t write_reuse_object(struct hashfile *f, struct object_entry *entry,
-				unsigned long limit, int usable_delta)
-{
-	struct packed_git *p = IN_PACK(entry);
-	struct pack_window *w_curs = NULL;
-	struct revindex_entry *revidx;
-	off_t offset;
-	enum object_type type = oe_type(entry);
-	off_t datalen;
-	unsigned char header[MAX_PACK_OBJECT_HEADER],
-		      dheader[MAX_PACK_OBJECT_HEADER];
-	unsigned hdrlen;
-	const unsigned hashsz = the_hash_algo->rawsz;
-	unsigned long entry_size = SIZE(entry);
-
-	if (DELTA(entry))
-		type = (allow_ofs_delta && DELTA(entry)->idx.offset) ?
-			OBJ_OFS_DELTA : OBJ_REF_DELTA;
-	hdrlen = encode_in_pack_object_header(header, sizeof(header),
-					      type, entry_size);
-
-	offset = entry->in_pack_offset;
-	revidx = find_pack_revindex(p, offset);
-	datalen = revidx[1].offset - offset;
-	if (!pack_to_stdout && p->index_version > 1 &&
-	    check_pack_crc(p, &w_curs, offset, datalen, revidx->nr)) {
-		error(_("bad packed object CRC for %s"),
-		      oid_to_hex(&entry->idx.oid));
-		unuse_pack(&w_curs);
-		return write_no_reuse_object(f, entry, limit, usable_delta);
-	}
-
-	offset += entry->in_pack_header_size;
-	datalen -= entry->in_pack_header_size;
-
-	if (!pack_to_stdout && p->index_version == 1 &&
-	    check_pack_inflate(p, &w_curs, offset, datalen, entry_size)) {
-		error(_("corrupt packed object for %s"),
-		      oid_to_hex(&entry->idx.oid));
-		unuse_pack(&w_curs);
-		return write_no_reuse_object(f, entry, limit, usable_delta);
-	}
-
-	if (type == OBJ_OFS_DELTA) {
-		off_t ofs = entry->idx.offset - DELTA(entry)->idx.offset;
-		unsigned pos = sizeof(dheader) - 1;
-		dheader[pos] = ofs & 127;
-		while (ofs >>= 7)
-			dheader[--pos] = 128 | (--ofs & 127);
-		if (limit && hdrlen + sizeof(dheader) - pos + datalen + hashsz >= limit) {
-			unuse_pack(&w_curs);
-			return 0;
-		}
-		hashwrite(f, header, hdrlen);
-		hashwrite(f, dheader + pos, sizeof(dheader) - pos);
-		hdrlen += sizeof(dheader) - pos;
-		reused_delta++;
-	} else if (type == OBJ_REF_DELTA) {
-		if (limit && hdrlen + hashsz + datalen + hashsz >= limit) {
-			unuse_pack(&w_curs);
-			return 0;
-		}
-		hashwrite(f, header, hdrlen);
-		hashwrite(f, DELTA(entry)->idx.oid.hash, hashsz);
-		hdrlen += hashsz;
-		reused_delta++;
-	} else {
-		if (limit && hdrlen + datalen + hashsz >= limit) {
-			unuse_pack(&w_curs);
-			return 0;
-		}
-		hashwrite(f, header, hdrlen);
-	}
-	copy_pack_data(f, p, &w_curs, offset, datalen);
-	unuse_pack(&w_curs);
-	reused++;
-	return hdrlen + datalen;
-}
-
-/* Return 0 if we will bust the pack-size limit */
-static off_t write_object(struct hashfile *f,
-			  struct object_entry *entry,
-			  off_t write_offset)
-{
-	unsigned long limit;
-	off_t len;
-	int usable_delta, to_reuse;
-
-	if (!pack_to_stdout)
-		crc32_begin(f);
-
-	/* apply size limit if limited packsize and not first object */
-	if (!pack_size_limit || !nr_written)
-		limit = 0;
-	else if (pack_size_limit <= write_offset)
-		/*
-		 * the earlier object did not fit the limit; avoid
-		 * mistaking this with unlimited (i.e. limit = 0).
-		 */
-		limit = 1;
-	else
-		limit = pack_size_limit - write_offset;
-
-	if (!DELTA(entry))
-		usable_delta = 0;	/* no delta */
-	else if (!pack_size_limit)
-	       usable_delta = 1;	/* unlimited packfile */
-	else if (DELTA(entry)->idx.offset == (off_t)-1)
-		usable_delta = 0;	/* base was written to another pack */
-	else if (DELTA(entry)->idx.offset)
-		usable_delta = 1;	/* base already exists in this pack */
-	else
-		usable_delta = 0;	/* base could end up in another pack */
-
-	if (!reuse_object)
-		to_reuse = 0;	/* explicit */
-	else if (!IN_PACK(entry))
-		to_reuse = 0;	/* can't reuse what we don't have */
-	else if (oe_type(entry) == OBJ_REF_DELTA ||
-		 oe_type(entry) == OBJ_OFS_DELTA)
-				/* check_object() decided it for us ... */
-		to_reuse = usable_delta;
-				/* ... but pack split may override that */
-	else if (oe_type(entry) != entry->in_pack_type)
-		to_reuse = 0;	/* pack has delta which is unusable */
-	else if (DELTA(entry))
-		to_reuse = 0;	/* we want to pack afresh */
-	else
-		to_reuse = 1;	/* we have it in-pack undeltified,
-				 * and we do not need to deltify it.
-				 */
-
-	if (!to_reuse)
-		len = write_no_reuse_object(f, entry, limit, usable_delta);
-	else
-		len = write_reuse_object(f, entry, limit, usable_delta);
-	if (!len)
-		return 0;
-
-	if (usable_delta)
-		written_delta++;
-	written++;
-	if (!pack_to_stdout)
-		entry->idx.crc32 = crc32_end(f);
-	return len;
-}
-
-enum write_one_status {
-	WRITE_ONE_SKIP = -1, /* already written */
-	WRITE_ONE_BREAK = 0, /* writing this will bust the limit; not written */
-	WRITE_ONE_WRITTEN = 1, /* normal */
-	WRITE_ONE_RECURSIVE = 2 /* already scheduled to be written */
-};
-
-static enum write_one_status write_one(struct hashfile *f,
-				       struct object_entry *e,
-				       off_t *offset)
-{
-	off_t size;
-	int recursing;
-
-	/*
-	 * we set offset to 1 (which is an impossible value) to mark
-	 * the fact that this object is involved in "write its base
-	 * first before writing a deltified object" recursion.
-	 */
-	recursing = (e->idx.offset == 1);
-	if (recursing) {
-		warning(_("recursive delta detected for object %s"),
-			oid_to_hex(&e->idx.oid));
-		return WRITE_ONE_RECURSIVE;
-	} else if (e->idx.offset || e->preferred_base) {
-		/* offset is non zero if object is written already. */
-		return WRITE_ONE_SKIP;
-	}
-
-	/* if we are deltified, write out base object first. */
-	if (DELTA(e)) {
-		e->idx.offset = 1; /* now recurse */
-		switch (write_one(f, DELTA(e), offset)) {
-		case WRITE_ONE_RECURSIVE:
-			/* we cannot depend on this one */
-			SET_DELTA(e, NULL);
-			break;
-		default:
-			break;
-		case WRITE_ONE_BREAK:
-			e->idx.offset = recursing;
-			return WRITE_ONE_BREAK;
-		}
-	}
-
-	e->idx.offset = *offset;
-	size = write_object(f, e, *offset);
-	if (!size) {
-		e->idx.offset = recursing;
-		return WRITE_ONE_BREAK;
-	}
-	written_list[nr_written++] = &e->idx;
-
-	/* make sure off_t is sufficiently large not to wrap */
-	if (signed_add_overflows(*offset, size))
-		die(_("pack too large for current definition of off_t"));
-	*offset += size;
-	return WRITE_ONE_WRITTEN;
-}
-
-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);
-
-	if (entry)
-		entry->tagged = 1;
-	if (!peel_ref(path, &peeled)) {
-		entry = packlist_find(&to_pack, &peeled);
-		if (entry)
-			entry->tagged = 1;
-	}
-	return 0;
-}
-
-static inline void add_to_write_order(struct object_entry **wo,
-			       unsigned int *endp,
-			       struct object_entry *e)
-{
-	if (e->filled || oe_layer(&to_pack, e) != write_layer)
-		return;
-	wo[(*endp)++] = e;
-	e->filled = 1;
-}
-
-static void add_descendants_to_write_order(struct object_entry **wo,
-					   unsigned int *endp,
-					   struct object_entry *e)
-{
-	int add_to_order = 1;
-	while (e) {
-		if (add_to_order) {
-			struct object_entry *s;
-			/* add this node... */
-			add_to_write_order(wo, endp, e);
-			/* all its siblings... */
-			for (s = DELTA_SIBLING(e); s; s = DELTA_SIBLING(s)) {
-				add_to_write_order(wo, endp, s);
-			}
-		}
-		/* drop down a level to add left subtree nodes if possible */
-		if (DELTA_CHILD(e)) {
-			add_to_order = 1;
-			e = DELTA_CHILD(e);
-		} else {
-			add_to_order = 0;
-			/* our sibling might have some children, it is next */
-			if (DELTA_SIBLING(e)) {
-				e = DELTA_SIBLING(e);
-				continue;
-			}
-			/* go back to our parent node */
-			e = DELTA(e);
-			while (e && !DELTA_SIBLING(e)) {
-				/* we're on the right side of a subtree, keep
-				 * going up until we can go right again */
-				e = DELTA(e);
-			}
-			if (!e) {
-				/* done- we hit our original root node */
-				return;
-			}
-			/* pass it off to sibling at this level */
-			e = DELTA_SIBLING(e);
-		}
-	};
-}
-
-static void add_family_to_write_order(struct object_entry **wo,
-				      unsigned int *endp,
-				      struct object_entry *e)
-{
-	struct object_entry *root;
-
-	for (root = e; DELTA(root); root = DELTA(root))
-		; /* nothing */
-	add_descendants_to_write_order(wo, endp, root);
-}
-
-static void compute_layer_order(struct object_entry **wo, unsigned int *wo_end)
-{
-	unsigned int i, last_untagged;
-	struct object_entry *objects = to_pack.objects;
-
-	for (i = 0; i < to_pack.nr_objects; i++) {
-		if (objects[i].tagged)
-			break;
-		add_to_write_order(wo, wo_end, &objects[i]);
-	}
-	last_untagged = i;
-
-	/*
-	 * Then fill all the tagged tips.
-	 */
-	for (; i < to_pack.nr_objects; i++) {
-		if (objects[i].tagged)
-			add_to_write_order(wo, wo_end, &objects[i]);
-	}
-
-	/*
-	 * And then all remaining commits and tags.
-	 */
-	for (i = last_untagged; i < to_pack.nr_objects; i++) {
-		if (oe_type(&objects[i]) != OBJ_COMMIT &&
-		    oe_type(&objects[i]) != OBJ_TAG)
-			continue;
-		add_to_write_order(wo, wo_end, &objects[i]);
-	}
-
-	/*
-	 * And then all the trees.
-	 */
-	for (i = last_untagged; i < to_pack.nr_objects; i++) {
-		if (oe_type(&objects[i]) != OBJ_TREE)
-			continue;
-		add_to_write_order(wo, wo_end, &objects[i]);
-	}
-
-	/*
-	 * Finally all the rest in really tight order
-	 */
-	for (i = last_untagged; i < to_pack.nr_objects; i++) {
-		if (!objects[i].filled && oe_layer(&to_pack, &objects[i]) == write_layer)
-			add_family_to_write_order(wo, wo_end, &objects[i]);
-	}
-}
-
-static struct object_entry **compute_write_order(void)
-{
-	uint32_t max_layers = 1;
-	unsigned int i, wo_end;
-
-	struct object_entry **wo;
-	struct object_entry *objects = to_pack.objects;
-
-	for (i = 0; i < to_pack.nr_objects; i++) {
-		objects[i].tagged = 0;
-		objects[i].filled = 0;
-		SET_DELTA_CHILD(&objects[i], NULL);
-		SET_DELTA_SIBLING(&objects[i], NULL);
-	}
-
-	/*
-	 * Fully connect delta_child/delta_sibling network.
-	 * Make sure delta_sibling is sorted in the original
-	 * recency order.
-	 */
-	for (i = to_pack.nr_objects; i > 0;) {
-		struct object_entry *e = &objects[--i];
-		if (!DELTA(e))
-			continue;
-		/* Mark me as the first child */
-		e->delta_sibling_idx = DELTA(e)->delta_child_idx;
-		SET_DELTA_CHILD(DELTA(e), e);
-	}
-
-	/*
-	 * Mark objects that are at the tip of tags.
-	 */
-	for_each_tag_ref(mark_tagged, NULL);
-
-	if (use_delta_islands)
-		max_layers = compute_pack_layers(&to_pack);
-
-	ALLOC_ARRAY(wo, to_pack.nr_objects);
-	wo_end = 0;
-
-	for (; write_layer < max_layers; ++write_layer)
-		compute_layer_order(wo, &wo_end);
-
-	if (wo_end != to_pack.nr_objects)
-		die(_("ordered %u objects, expected %"PRIu32),
-		    wo_end, to_pack.nr_objects);
-
-	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)
-{
-	if (reused_chunks_nr && reused_chunks[reused_chunks_nr-1].difference == offset)
-		return;
-
-	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++;
-}
-
-/*
- * 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;
-	}
-
-	/*
-	 * The first chunk starts at zero, so we can't have gone below
-	 * there.
-	 */
-	assert(lo);
-	return reused_chunks[lo-1].difference;
-}
-
-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;
-
-	offset = reuse_packfile->revindex[pos].offset;
-	next = reuse_packfile->revindex[pos + 1].offset;
-
-	record_reused_object(offset, offset - hashfile_total(out));
-
-	cur = offset;
-	type = unpack_object_header(reuse_packfile, w_curs, &cur, &size);
-	assert(type >= 0);
-
-	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, the_hash_algo->rawsz);
-			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);
-
-			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);
-
-		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);
-}
-
-static void write_excluded_by_configs(void)
-{
-	struct oidset_iter iter;
-	const struct object_id *oid;
-
-	oidset_iter_init(&excluded_by_config, &iter);
-	while ((oid = oidset_iter_next(&iter))) {
-		struct configured_exclusion *ex =
-			oidmap_get(&configured_exclusions, oid);
-
-		if (!ex)
-			BUG("configured exclusion wasn't configured");
-		write_in_full(1, ex->pack_hash_hex, strlen(ex->pack_hash_hex));
-		write_in_full(1, " ", 1);
-		write_in_full(1, ex->uri, strlen(ex->uri));
-		write_in_full(1, "\n", 1);
-	}
-}
-
-static const char no_split_warning[] = N_(
-"disabling bitmap writing, packs are split due to pack.packSizeLimit"
-);
-
-static void write_pack_file(void)
-{
-	uint32_t i = 0, j;
-	struct hashfile *f;
-	off_t offset;
-	uint32_t nr_remaining = nr_result;
-	time_t last_mtime = 0;
-	struct object_entry **write_order;
-
-	if (progress > pack_to_stdout)
-		progress_state = start_progress(_("Writing objects"), nr_result);
-	ALLOC_ARRAY(written_list, to_pack.nr_objects);
-	write_order = compute_write_order();
-
-	do {
-		struct object_id oid;
-		char *pack_tmp_name = NULL;
-
-		if (pack_to_stdout)
-			f = hashfd_throughput(1, "<stdout>", progress_state);
-		else
-			f = create_tmp_packfile(&pack_tmp_name);
-
-		offset = write_pack_header(f, nr_remaining);
-
-		if (reuse_packfile) {
-			assert(pack_to_stdout);
-			write_reused_pack(f);
-			offset = hashfile_total(f);
-		}
-
-		nr_written = 0;
-		for (; i < to_pack.nr_objects; i++) {
-			struct object_entry *e = write_order[i];
-			if (write_one(f, e, &offset) == WRITE_ONE_BREAK)
-				break;
-			display_progress(progress_state, written);
-		}
-
-		/*
-		 * Did we write the wrong # entries in the header?
-		 * If so, rewrite it like in fast-import
-		 */
-		if (pack_to_stdout) {
-			finalize_hashfile(f, oid.hash, CSUM_HASH_IN_STREAM | CSUM_CLOSE);
-		} else if (nr_written == nr_remaining) {
-			finalize_hashfile(f, oid.hash, CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE);
-		} else {
-			int fd = finalize_hashfile(f, oid.hash, 0);
-			fixup_pack_header_footer(fd, oid.hash, pack_tmp_name,
-						 nr_written, oid.hash, offset);
-			close(fd);
-			if (write_bitmap_index) {
-				if (write_bitmap_index != WRITE_BITMAP_QUIET)
-					warning(_(no_split_warning));
-				write_bitmap_index = 0;
-			}
-		}
-
-		if (!pack_to_stdout) {
-			struct stat st;
-			struct strbuf tmpname = STRBUF_INIT;
-
-			/*
-			 * Packs are runtime accessed in their mtime
-			 * order since newer packs are more likely to contain
-			 * younger objects.  So if we are creating multiple
-			 * packs then we should modify the mtime of later ones
-			 * to preserve this property.
-			 */
-			if (stat(pack_tmp_name, &st) < 0) {
-				warning_errno(_("failed to stat %s"), pack_tmp_name);
-			} else if (!last_mtime) {
-				last_mtime = st.st_mtime;
-			} else {
-				struct utimbuf utb;
-				utb.actime = st.st_atime;
-				utb.modtime = --last_mtime;
-				if (utime(pack_tmp_name, &utb) < 0)
-					warning_errno(_("failed utime() on %s"), pack_tmp_name);
-			}
-
-			strbuf_addf(&tmpname, "%s-", base_name);
-
-			if (write_bitmap_index) {
-				bitmap_writer_set_checksum(oid.hash);
-				bitmap_writer_build_type_index(
-					&to_pack, written_list, nr_written);
-			}
-
-			finish_tmp_packfile(&tmpname, pack_tmp_name,
-					    written_list, nr_written,
-					    &pack_idx_opts, oid.hash);
-
-			if (write_bitmap_index) {
-				strbuf_addf(&tmpname, "%s.bitmap", oid_to_hex(&oid));
-
-				stop_progress(&progress_state);
-
-				bitmap_writer_show_progress(progress);
-				bitmap_writer_reuse_bitmaps(&to_pack);
-				bitmap_writer_select_commits(indexed_commits, indexed_commits_nr, -1);
-				bitmap_writer_build(&to_pack);
-				bitmap_writer_finish(written_list, nr_written,
-						     tmpname.buf, write_bitmap_options);
-				write_bitmap_index = 0;
-			}
-
-			strbuf_release(&tmpname);
-			free(pack_tmp_name);
-			puts(oid_to_hex(&oid));
-		}
-
-		/* mark written objects as written to previous pack */
-		for (j = 0; j < nr_written; j++) {
-			written_list[j]->offset = (off_t)-1;
-		}
-		nr_remaining -= nr_written;
-	} while (nr_remaining && i < to_pack.nr_objects);
-
-	free(written_list);
-	free(write_order);
-	stop_progress(&progress_state);
-	if (written != nr_result)
-		die(_("wrote %"PRIu32" objects while expecting %"PRIu32),
-		    written, nr_result);
-	trace2_data_intmax("pack-objects", the_repository,
-			   "write_pack_file/wrote", nr_result);
-}
-
-static int no_try_delta(const char *path)
-{
-	static struct attr_check *check;
-
-	if (!check)
-		check = attr_check_initl("delta", NULL);
-	git_check_attr(the_repository->index, path, check);
-	if (ATTR_FALSE(check->items[0].value))
-		return 1;
-	return 0;
-}
-
-/*
- * When adding an object, check whether we have already added it
- * to our packing list. If so, we can skip. However, if we are
- * being asked to excludei t, but the previous mention was to include
- * it, make sure to adjust its flags and tweak our numbers accordingly.
- *
- * As an optimization, we pass out the index position where we would have
- * found the item, since that saves us from having to look it up again a
- * few lines later when we want to add the new entry.
- */
-static int have_duplicate_entry(const struct object_id *oid,
-				int exclude)
-{
-	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);
-	if (!entry)
-		return 0;
-
-	if (exclude) {
-		if (!entry->preferred_base)
-			nr_result--;
-		entry->preferred_base = 1;
-	}
-
-	return 1;
-}
-
-static int want_found_object(int exclude, struct packed_git *p)
-{
-	if (exclude)
-		return 1;
-	if (incremental)
-		return 0;
-
-	/*
-	 * When asked to do --local (do not include an object that appears in a
-	 * pack we borrow from elsewhere) or --honor-pack-keep (do not include
-	 * an object that appears in a pack marked with .keep), finding a pack
-	 * that matches the criteria is sufficient for us to decide to omit it.
-	 * However, even if this pack does not satisfy the criteria, we need to
-	 * make sure no copy of this object appears in _any_ pack that makes us
-	 * to omit the object, so we need to check all the packs.
-	 *
-	 * We can however first check whether these options can possible matter;
-	 * if they do not matter we know we want the object in generated pack.
-	 * Otherwise, we signal "-1" at the end to tell the caller that we do
-	 * not know either way, and it needs to check more packs.
-	 */
-	if (!ignore_packed_keep_on_disk &&
-	    !ignore_packed_keep_in_core &&
-	    (!local || !have_non_local_packs))
-		return 1;
-
-	if (local && !p->pack_local)
-		return 0;
-	if (p->pack_local &&
-	    ((ignore_packed_keep_on_disk && p->pack_keep) ||
-	     (ignore_packed_keep_in_core && p->pack_keep_in_core)))
-		return 0;
-
-	/* we don't know yet; keep looking for more packs */
-	return -1;
-}
-
-/*
- * Check whether we want the object in the pack (e.g., we do not want
- * objects found in non-local stores if the "--local" option was used).
- *
- * If the caller already knows an existing pack it wants to take the object
- * from, that is passed in *found_pack and *found_offset; otherwise this
- * function finds if there is any pack that has the object and returns the pack
- * and its offset in these variables.
- */
-static int want_object_in_pack(const struct object_id *oid,
-			       int exclude,
-			       struct packed_git **found_pack,
-			       off_t *found_offset)
-{
-	int want;
-	struct list_head *pos;
-	struct multi_pack_index *m;
-
-	if (!exclude && local && has_loose_object_nonlocal(oid))
-		return 0;
-
-	/*
-	 * If we already know the pack object lives in, start checks from that
-	 * pack - in the usual case when neither --local was given nor .keep files
-	 * are present we will determine the answer right now.
-	 */
-	if (*found_pack) {
-		want = want_found_object(exclude, *found_pack);
-		if (want != -1)
-			return want;
-	}
-
-	for (m = get_multi_pack_index(the_repository); m; m = m->next) {
-		struct pack_entry e;
-		if (fill_midx_entry(the_repository, oid, &e, m)) {
-			struct packed_git *p = e.p;
-			off_t offset;
-
-			if (p == *found_pack)
-				offset = *found_offset;
-			else
-				offset = find_pack_entry_one(oid->hash, p);
-
-			if (offset) {
-				if (!*found_pack) {
-					if (!is_pack_valid(p))
-						continue;
-					*found_offset = offset;
-					*found_pack = p;
-				}
-				want = want_found_object(exclude, p);
-				if (want != -1)
-					return want;
-			}
-		}
-	}
-
-	list_for_each(pos, get_packed_git_mru(the_repository)) {
-		struct packed_git *p = list_entry(pos, struct packed_git, mru);
-		off_t offset;
-
-		if (p == *found_pack)
-			offset = *found_offset;
-		else
-			offset = find_pack_entry_one(oid->hash, p);
-
-		if (offset) {
-			if (!*found_pack) {
-				if (!is_pack_valid(p))
-					continue;
-				*found_offset = offset;
-				*found_pack = p;
-			}
-			want = want_found_object(exclude, p);
-			if (!exclude && want > 0)
-				list_move(&p->mru,
-					  get_packed_git_mru(the_repository));
-			if (want != -1)
-				return want;
-		}
-	}
-
-	if (uri_protocols.nr) {
-		struct configured_exclusion *ex =
-			oidmap_get(&configured_exclusions, oid);
-		int i;
-		const char *p;
-
-		if (ex) {
-			for (i = 0; i < uri_protocols.nr; i++) {
-				if (skip_prefix(ex->uri,
-						uri_protocols.items[i].string,
-						&p) &&
-				    *p == ':') {
-					oidset_insert(&excluded_by_config, oid);
-					return 0;
-				}
-			}
-		}
-	}
-
-	return 1;
-}
-
-static void create_object_entry(const struct object_id *oid,
-				enum object_type type,
-				uint32_t hash,
-				int exclude,
-				int no_try_delta,
-				struct packed_git *found_pack,
-				off_t found_offset)
-{
-	struct object_entry *entry;
-
-	entry = packlist_alloc(&to_pack, oid);
-	entry->hash = hash;
-	oe_set_type(entry, type);
-	if (exclude)
-		entry->preferred_base = 1;
-	else
-		nr_result++;
-	if (found_pack) {
-		oe_set_in_pack(&to_pack, entry, found_pack);
-		entry->in_pack_offset = found_offset;
-	}
-
-	entry->no_try_delta = no_try_delta;
-}
-
-static const char no_closure_warning[] = N_(
-"disabling bitmap writing, as some objects are not being packed"
-);
-
-static int add_object_entry(const struct object_id *oid, enum object_type type,
-			    const char *name, int exclude)
-{
-	struct packed_git *found_pack = NULL;
-	off_t found_offset = 0;
-
-	display_progress(progress_state, ++nr_seen);
-
-	if (have_duplicate_entry(oid, exclude))
-		return 0;
-
-	if (!want_object_in_pack(oid, exclude, &found_pack, &found_offset)) {
-		/* The pack is missing an object, so it will not have closure */
-		if (write_bitmap_index) {
-			if (write_bitmap_index != WRITE_BITMAP_QUIET)
-				warning(_(no_closure_warning));
-			write_bitmap_index = 0;
-		}
-		return 0;
-	}
-
-	create_object_entry(oid, type, pack_name_hash(name),
-			    exclude, name && no_try_delta(name),
-			    found_pack, found_offset);
-	return 1;
-}
-
-static int add_object_entry_from_bitmap(const struct object_id *oid,
-					enum object_type type,
-					int flags, uint32_t name_hash,
-					struct packed_git *pack, off_t offset)
-{
-	display_progress(progress_state, ++nr_seen);
-
-	if (have_duplicate_entry(oid, 0))
-		return 0;
-
-	if (!want_object_in_pack(oid, 0, &pack, &offset))
-		return 0;
-
-	create_object_entry(oid, type, name_hash, 0, 0, pack, offset);
-	return 1;
-}
-
-struct pbase_tree_cache {
-	struct object_id oid;
-	int ref;
-	int temporary;
-	void *tree_data;
-	unsigned long tree_size;
-};
-
-static struct pbase_tree_cache *(pbase_tree_cache[256]);
-static int pbase_tree_cache_ix(const struct object_id *oid)
-{
-	return oid->hash[0] % ARRAY_SIZE(pbase_tree_cache);
-}
-static int pbase_tree_cache_ix_incr(int ix)
-{
-	return (ix+1) % ARRAY_SIZE(pbase_tree_cache);
-}
-
-static struct pbase_tree {
-	struct pbase_tree *next;
-	/* This is a phony "cache" entry; we are not
-	 * going to evict it or find it through _get()
-	 * mechanism -- this is for the toplevel node that
-	 * would almost always change with any commit.
-	 */
-	struct pbase_tree_cache pcache;
-} *pbase_tree;
-
-static struct pbase_tree_cache *pbase_tree_get(const struct object_id *oid)
-{
-	struct pbase_tree_cache *ent, *nent;
-	void *data;
-	unsigned long size;
-	enum object_type type;
-	int neigh;
-	int my_ix = pbase_tree_cache_ix(oid);
-	int available_ix = -1;
-
-	/* pbase-tree-cache acts as a limited hashtable.
-	 * your object will be found at your index or within a few
-	 * slots after that slot if it is cached.
-	 */
-	for (neigh = 0; neigh < 8; neigh++) {
-		ent = pbase_tree_cache[my_ix];
-		if (ent && oideq(&ent->oid, oid)) {
-			ent->ref++;
-			return ent;
-		}
-		else if (((available_ix < 0) && (!ent || !ent->ref)) ||
-			 ((0 <= available_ix) &&
-			  (!ent && pbase_tree_cache[available_ix])))
-			available_ix = my_ix;
-		if (!ent)
-			break;
-		my_ix = pbase_tree_cache_ix_incr(my_ix);
-	}
-
-	/* Did not find one.  Either we got a bogus request or
-	 * we need to read and perhaps cache.
-	 */
-	data = read_object_file(oid, &type, &size);
-	if (!data)
-		return NULL;
-	if (type != OBJ_TREE) {
-		free(data);
-		return NULL;
-	}
-
-	/* We need to either cache or return a throwaway copy */
-
-	if (available_ix < 0)
-		ent = NULL;
-	else {
-		ent = pbase_tree_cache[available_ix];
-		my_ix = available_ix;
-	}
-
-	if (!ent) {
-		nent = xmalloc(sizeof(*nent));
-		nent->temporary = (available_ix < 0);
-	}
-	else {
-		/* evict and reuse */
-		free(ent->tree_data);
-		nent = ent;
-	}
-	oidcpy(&nent->oid, oid);
-	nent->tree_data = data;
-	nent->tree_size = size;
-	nent->ref = 1;
-	if (!nent->temporary)
-		pbase_tree_cache[my_ix] = nent;
-	return nent;
-}
-
-static void pbase_tree_put(struct pbase_tree_cache *cache)
-{
-	if (!cache->temporary) {
-		cache->ref--;
-		return;
-	}
-	free(cache->tree_data);
-	free(cache);
-}
-
-static int name_cmp_len(const char *name)
-{
-	int i;
-	for (i = 0; name[i] && name[i] != '\n' && name[i] != '/'; i++)
-		;
-	return i;
-}
-
-static void add_pbase_object(struct tree_desc *tree,
-			     const char *name,
-			     int cmplen,
-			     const char *fullname)
-{
-	struct name_entry entry;
-	int cmp;
-
-	while (tree_entry(tree,&entry)) {
-		if (S_ISGITLINK(entry.mode))
-			continue;
-		cmp = tree_entry_len(&entry) != cmplen ? 1 :
-		      memcmp(name, entry.path, cmplen);
-		if (cmp > 0)
-			continue;
-		if (cmp < 0)
-			return;
-		if (name[cmplen] != '/') {
-			add_object_entry(&entry.oid,
-					 object_type(entry.mode),
-					 fullname, 1);
-			return;
-		}
-		if (S_ISDIR(entry.mode)) {
-			struct tree_desc sub;
-			struct pbase_tree_cache *tree;
-			const char *down = name+cmplen+1;
-			int downlen = name_cmp_len(down);
-
-			tree = pbase_tree_get(&entry.oid);
-			if (!tree)
-				return;
-			init_tree_desc(&sub, tree->tree_data, tree->tree_size);
-
-			add_pbase_object(&sub, down, downlen, fullname);
-			pbase_tree_put(tree);
-		}
-	}
-}
-
-static unsigned *done_pbase_paths;
-static int done_pbase_paths_num;
-static int done_pbase_paths_alloc;
-static int done_pbase_path_pos(unsigned hash)
-{
-	int lo = 0;
-	int hi = done_pbase_paths_num;
-	while (lo < hi) {
-		int mi = lo + (hi - lo) / 2;
-		if (done_pbase_paths[mi] == hash)
-			return mi;
-		if (done_pbase_paths[mi] < hash)
-			hi = mi;
-		else
-			lo = mi + 1;
-	}
-	return -lo-1;
-}
-
-static int check_pbase_path(unsigned hash)
-{
-	int pos = done_pbase_path_pos(hash);
-	if (0 <= pos)
-		return 1;
-	pos = -pos - 1;
-	ALLOC_GROW(done_pbase_paths,
-		   done_pbase_paths_num + 1,
-		   done_pbase_paths_alloc);
-	done_pbase_paths_num++;
-	if (pos < done_pbase_paths_num)
-		MOVE_ARRAY(done_pbase_paths + pos + 1, done_pbase_paths + pos,
-			   done_pbase_paths_num - pos - 1);
-	done_pbase_paths[pos] = hash;
-	return 0;
-}
-
-static void add_preferred_base_object(const char *name)
-{
-	struct pbase_tree *it;
-	int cmplen;
-	unsigned hash = pack_name_hash(name);
-
-	if (!num_preferred_base || check_pbase_path(hash))
-		return;
-
-	cmplen = name_cmp_len(name);
-	for (it = pbase_tree; it; it = it->next) {
-		if (cmplen == 0) {
-			add_object_entry(&it->pcache.oid, OBJ_TREE, NULL, 1);
-		}
-		else {
-			struct tree_desc tree;
-			init_tree_desc(&tree, it->pcache.tree_data, it->pcache.tree_size);
-			add_pbase_object(&tree, name, cmplen, name);
-		}
-	}
-}
-
-static void add_preferred_base(struct object_id *oid)
-{
-	struct pbase_tree *it;
-	void *data;
-	unsigned long size;
-	struct object_id tree_oid;
-
-	if (window <= num_preferred_base++)
-		return;
-
-	data = read_object_with_reference(the_repository, oid,
-					  tree_type, &size, &tree_oid);
-	if (!data)
-		return;
-
-	for (it = pbase_tree; it; it = it->next) {
-		if (oideq(&it->pcache.oid, &tree_oid)) {
-			free(data);
-			return;
-		}
-	}
-
-	it = xcalloc(1, sizeof(*it));
-	it->next = pbase_tree;
-	pbase_tree = it;
-
-	oidcpy(&it->pcache.oid, &tree_oid);
-	it->pcache.tree_data = data;
-	it->pcache.tree_size = size;
-}
-
-static void cleanup_preferred_base(void)
-{
-	struct pbase_tree *it;
-	unsigned i;
-
-	it = pbase_tree;
-	pbase_tree = NULL;
-	while (it) {
-		struct pbase_tree *tmp = it;
-		it = tmp->next;
-		free(tmp->pcache.tree_data);
-		free(tmp);
-	}
-
-	for (i = 0; i < ARRAY_SIZE(pbase_tree_cache); i++) {
-		if (!pbase_tree_cache[i])
-			continue;
-		free(pbase_tree_cache[i]->tree_data);
-		FREE_AND_NULL(pbase_tree_cache[i]);
-	}
-
-	FREE_AND_NULL(done_pbase_paths);
-	done_pbase_paths_num = done_pbase_paths_alloc = 0;
-}
-
-/*
- * Return 1 iff the object specified by "delta" can be sent
- * literally as a delta against the base in "base_sha1". If
- * so, then *base_out will point to the entry in our packing
- * list, or NULL if we must use the external-base list.
- *
- * Depth value does not matter - find_deltas() will
- * never consider reused delta as the base object to
- * deltify other objects against, in order to avoid
- * circular deltas.
- */
-static int can_reuse_delta(const struct object_id *base_oid,
-			   struct object_entry *delta,
-			   struct object_entry **base_out)
-{
-	struct object_entry *base;
-
-	/*
-	 * First see if we're already sending the base (or it's explicitly in
-	 * our "excluded" list).
-	 */
-	base = packlist_find(&to_pack, base_oid);
-	if (base) {
-		if (!in_same_island(&delta->idx.oid, &base->idx.oid))
-			return 0;
-		*base_out = base;
-		return 1;
-	}
-
-	/*
-	 * Otherwise, reachability bitmaps may tell us if the receiver has it,
-	 * 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 (use_delta_islands) {
-			if (!in_same_island(&delta->idx.oid, base_oid))
-				return 0;
-		}
-		*base_out = NULL;
-		return 1;
-	}
-
-	return 0;
-}
-
-static void prefetch_to_pack(uint32_t object_index_start) {
-	struct oid_array to_fetch = OID_ARRAY_INIT;
-	uint32_t i;
-
-	for (i = object_index_start; i < to_pack.nr_objects; i++) {
-		struct object_entry *entry = to_pack.objects + i;
-
-		if (!oid_object_info_extended(the_repository,
-					      &entry->idx.oid,
-					      NULL,
-					      OBJECT_INFO_FOR_PREFETCH))
-			continue;
-		oid_array_append(&to_fetch, &entry->idx.oid);
-	}
-	promisor_remote_get_direct(the_repository,
-				   to_fetch.oid, to_fetch.nr);
-	oid_array_clear(&to_fetch);
-}
-
-static void check_object(struct object_entry *entry, uint32_t object_index)
-{
-	unsigned long canonical_size;
-	enum object_type type;
-	struct object_info oi = {.typep = &type, .sizep = &canonical_size};
-
-	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;
-		struct object_entry *base_entry;
-		unsigned long used, used_0;
-		unsigned long avail;
-		off_t ofs;
-		unsigned char *buf, c;
-		enum object_type type;
-		unsigned long in_pack_size;
-
-		buf = use_pack(p, &w_curs, entry->in_pack_offset, &avail);
-
-		/*
-		 * We want in_pack_type even if we do not reuse delta
-		 * since non-delta representations could still be reused.
-		 */
-		used = unpack_object_header_buffer(buf, avail,
-						   &type,
-						   &in_pack_size);
-		if (used == 0)
-			goto give_up;
-
-		if (type < 0)
-			BUG("invalid type %d", type);
-		entry->in_pack_type = type;
-
-		/*
-		 * Determine if this is a delta and if so whether we can
-		 * reuse it or not.  Otherwise let's find out as cheaply as
-		 * possible what the actual type and size for this object is.
-		 */
-		switch (entry->in_pack_type) {
-		default:
-			/* Not a delta hence we've already got all we need. */
-			oe_set_type(entry, entry->in_pack_type);
-			SET_SIZE(entry, in_pack_size);
-			entry->in_pack_header_size = used;
-			if (oe_type(entry) < OBJ_COMMIT || oe_type(entry) > OBJ_BLOB)
-				goto give_up;
-			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;
-			}
-			entry->in_pack_header_size = used + the_hash_algo->rawsz;
-			break;
-		case OBJ_OFS_DELTA:
-			buf = use_pack(p, &w_curs,
-				       entry->in_pack_offset + used, NULL);
-			used_0 = 0;
-			c = buf[used_0++];
-			ofs = c & 127;
-			while (c & 128) {
-				ofs += 1;
-				if (!ofs || MSB(ofs, 7)) {
-					error(_("delta base offset overflow in pack for %s"),
-					      oid_to_hex(&entry->idx.oid));
-					goto give_up;
-				}
-				c = buf[used_0++];
-				ofs = (ofs << 7) + (c & 127);
-			}
-			ofs = entry->in_pack_offset - ofs;
-			if (ofs <= 0 || ofs >= entry->in_pack_offset) {
-				error(_("delta base offset out of bound for %s"),
-				      oid_to_hex(&entry->idx.oid));
-				goto give_up;
-			}
-			if (reuse_delta && !entry->preferred_base) {
-				struct revindex_entry *revidx;
-				revidx = find_pack_revindex(p, ofs);
-				if (!revidx)
-					goto give_up;
-				if (!nth_packed_object_id(&base_ref, p, revidx->nr))
-					have_base = 1;
-			}
-			entry->in_pack_header_size = used + used_0;
-			break;
-		}
-
-		if (have_base &&
-		    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);
-
-			if (base_entry) {
-				SET_DELTA(entry, base_entry);
-				entry->delta_sibling_idx = base_entry->delta_child_idx;
-				SET_DELTA_CHILD(base_entry, entry);
-			} else {
-				SET_DELTA_EXT(entry, &base_ref);
-			}
-
-			unuse_pack(&w_curs);
-			return;
-		}
-
-		if (oe_type(entry)) {
-			off_t delta_pos;
-
-			/*
-			 * This must be a delta and we already know what the
-			 * final object type is.  Let's extract the actual
-			 * object size from the delta header.
-			 */
-			delta_pos = entry->in_pack_offset + entry->in_pack_header_size;
-			canonical_size = get_size_from_delta(p, &w_curs, delta_pos);
-			if (canonical_size == 0)
-				goto give_up;
-			SET_SIZE(entry, canonical_size);
-			unuse_pack(&w_curs);
-			return;
-		}
-
-		/*
-		 * No choice but to fall back to the recursive delta walk
-		 * with oid_object_info() to find about the object type
-		 * at this point...
-		 */
-		give_up:
-		unuse_pack(&w_curs);
-	}
-
-	if (oid_object_info_extended(the_repository, &entry->idx.oid, &oi,
-				     OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_LOOKUP_REPLACE) < 0) {
-		if (has_promisor_remote()) {
-			prefetch_to_pack(object_index);
-			if (oid_object_info_extended(the_repository, &entry->idx.oid, &oi,
-						     OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_LOOKUP_REPLACE) < 0)
-				type = -1;
-		} else {
-			type = -1;
-		}
-	}
-	oe_set_type(entry, type);
-	if (entry->type_valid) {
-		SET_SIZE(entry, canonical_size);
-	} else {
-		/*
-		 * Bad object type is checked in prepare_pack().  This is
-		 * to permit a missing preferred base object to be ignored
-		 * as a preferred base.  Doing so can result in a larger
-		 * pack file, but the transfer will still take place.
-		 */
-	}
-}
-
-static int pack_offset_sort(const void *_a, const void *_b)
-{
-	const struct object_entry *a = *(struct object_entry **)_a;
-	const struct object_entry *b = *(struct object_entry **)_b;
-	const struct packed_git *a_in_pack = IN_PACK(a);
-	const struct packed_git *b_in_pack = IN_PACK(b);
-
-	/* avoid filesystem trashing with loose objects */
-	if (!a_in_pack && !b_in_pack)
-		return oidcmp(&a->idx.oid, &b->idx.oid);
-
-	if (a_in_pack < b_in_pack)
-		return -1;
-	if (a_in_pack > b_in_pack)
-		return 1;
-	return a->in_pack_offset < b->in_pack_offset ? -1 :
-			(a->in_pack_offset > b->in_pack_offset);
-}
-
-/*
- * Drop an on-disk delta we were planning to reuse. Naively, this would
- * just involve blanking out the "delta" field, but we have to deal
- * with some extra book-keeping:
- *
- *   1. Removing ourselves from the delta_sibling linked list.
- *
- *   2. Updating our size/type to the non-delta representation. These were
- *      either not recorded initially (size) or overwritten with the delta type
- *      (type) when check_object() decided to reuse the delta.
- *
- *   3. Resetting our delta depth, as we are now a base object.
- */
-static void drop_reused_delta(struct object_entry *entry)
-{
-	unsigned *idx = &to_pack.objects[entry->delta_idx - 1].delta_child_idx;
-	struct object_info oi = OBJECT_INFO_INIT;
-	enum object_type type;
-	unsigned long size;
-
-	while (*idx) {
-		struct object_entry *oe = &to_pack.objects[*idx - 1];
-
-		if (oe == entry)
-			*idx = oe->delta_sibling_idx;
-		else
-			idx = &oe->delta_sibling_idx;
-	}
-	SET_DELTA(entry, NULL);
-	entry->depth = 0;
-
-	oi.sizep = &size;
-	oi.typep = &type;
-	if (packed_object_info(the_repository, IN_PACK(entry), entry->in_pack_offset, &oi) < 0) {
-		/*
-		 * We failed to get the info from this pack for some reason;
-		 * fall back to oid_object_info, which may find another copy.
-		 * And if that fails, the error will be recorded in oe_type(entry)
-		 * and dealt with in prepare_pack().
-		 */
-		oe_set_type(entry,
-			    oid_object_info(the_repository, &entry->idx.oid, &size));
-	} else {
-		oe_set_type(entry, type);
-	}
-	SET_SIZE(entry, size);
-}
-
-/*
- * Follow the chain of deltas from this entry onward, throwing away any links
- * that cause us to hit a cycle (as determined by the DFS state flags in
- * the entries).
- *
- * We also detect too-long reused chains that would violate our --depth
- * limit.
- */
-static void break_delta_chains(struct object_entry *entry)
-{
-	/*
-	 * The actual depth of each object we will write is stored as an int,
-	 * as it cannot exceed our int "depth" limit. But before we break
-	 * changes based no that limit, we may potentially go as deep as the
-	 * number of objects, which is elsewhere bounded to a uint32_t.
-	 */
-	uint32_t total_depth;
-	struct object_entry *cur, *next;
-
-	for (cur = entry, total_depth = 0;
-	     cur;
-	     cur = DELTA(cur), total_depth++) {
-		if (cur->dfs_state == DFS_DONE) {
-			/*
-			 * We've already seen this object and know it isn't
-			 * part of a cycle. We do need to append its depth
-			 * to our count.
-			 */
-			total_depth += cur->depth;
-			break;
-		}
-
-		/*
-		 * We break cycles before looping, so an ACTIVE state (or any
-		 * other cruft which made its way into the state variable)
-		 * is a bug.
-		 */
-		if (cur->dfs_state != DFS_NONE)
-			BUG("confusing delta dfs state in first pass: %d",
-			    cur->dfs_state);
-
-		/*
-		 * Now we know this is the first time we've seen the object. If
-		 * it's not a delta, we're done traversing, but we'll mark it
-		 * done to save time on future traversals.
-		 */
-		if (!DELTA(cur)) {
-			cur->dfs_state = DFS_DONE;
-			break;
-		}
-
-		/*
-		 * Mark ourselves as active and see if the next step causes
-		 * us to cycle to another active object. It's important to do
-		 * this _before_ we loop, because it impacts where we make the
-		 * cut, and thus how our total_depth counter works.
-		 * E.g., We may see a partial loop like:
-		 *
-		 *   A -> B -> C -> D -> B
-		 *
-		 * Cutting B->C breaks the cycle. But now the depth of A is
-		 * only 1, and our total_depth counter is at 3. The size of the
-		 * error is always one less than the size of the cycle we
-		 * broke. Commits C and D were "lost" from A's chain.
-		 *
-		 * If we instead cut D->B, then the depth of A is correct at 3.
-		 * We keep all commits in the chain that we examined.
-		 */
-		cur->dfs_state = DFS_ACTIVE;
-		if (DELTA(cur)->dfs_state == DFS_ACTIVE) {
-			drop_reused_delta(cur);
-			cur->dfs_state = DFS_DONE;
-			break;
-		}
-	}
-
-	/*
-	 * And now that we've gone all the way to the bottom of the chain, we
-	 * need to clear the active flags and set the depth fields as
-	 * appropriate. Unlike the loop above, which can quit when it drops a
-	 * delta, we need to keep going to look for more depth cuts. So we need
-	 * an extra "next" pointer to keep going after we reset cur->delta.
-	 */
-	for (cur = entry; cur; cur = next) {
-		next = DELTA(cur);
-
-		/*
-		 * We should have a chain of zero or more ACTIVE states down to
-		 * a final DONE. We can quit after the DONE, because either it
-		 * has no bases, or we've already handled them in a previous
-		 * call.
-		 */
-		if (cur->dfs_state == DFS_DONE)
-			break;
-		else if (cur->dfs_state != DFS_ACTIVE)
-			BUG("confusing delta dfs state in second pass: %d",
-			    cur->dfs_state);
-
-		/*
-		 * If the total_depth is more than depth, then we need to snip
-		 * the chain into two or more smaller chains that don't exceed
-		 * the maximum depth. Most of the resulting chains will contain
-		 * (depth + 1) entries (i.e., depth deltas plus one base), and
-		 * the last chain (i.e., the one containing entry) will contain
-		 * whatever entries are left over, namely
-		 * (total_depth % (depth + 1)) of them.
-		 *
-		 * Since we are iterating towards decreasing depth, we need to
-		 * decrement total_depth as we go, and we need to write to the
-		 * entry what its final depth will be after all of the
-		 * snipping. Since we're snipping into chains of length (depth
-		 * + 1) entries, the final depth of an entry will be its
-		 * original depth modulo (depth + 1). Any time we encounter an
-		 * entry whose final depth is supposed to be zero, we snip it
-		 * from its delta base, thereby making it so.
-		 */
-		cur->depth = (total_depth--) % (depth + 1);
-		if (!cur->depth)
-			drop_reused_delta(cur);
-
-		cur->dfs_state = DFS_DONE;
-	}
-}
-
-static void get_object_details(void)
-{
-	uint32_t i;
-	struct object_entry **sorted_by_offset;
-
-	if (progress)
-		progress_state = start_progress(_("Counting objects"),
-						to_pack.nr_objects);
-
-	sorted_by_offset = xcalloc(to_pack.nr_objects, sizeof(struct object_entry *));
-	for (i = 0; i < to_pack.nr_objects; i++)
-		sorted_by_offset[i] = to_pack.objects + i;
-	QSORT(sorted_by_offset, to_pack.nr_objects, pack_offset_sort);
-
-	for (i = 0; i < to_pack.nr_objects; i++) {
-		struct object_entry *entry = sorted_by_offset[i];
-		check_object(entry, i);
-		if (entry->type_valid &&
-		    oe_size_greater_than(&to_pack, entry, big_file_threshold))
-			entry->no_try_delta = 1;
-		display_progress(progress_state, i + 1);
-	}
-	stop_progress(&progress_state);
-
-	/*
-	 * This must happen in a second pass, since we rely on the delta
-	 * information for the whole list being completed.
-	 */
-	for (i = 0; i < to_pack.nr_objects; i++)
-		break_delta_chains(&to_pack.objects[i]);
-
-	free(sorted_by_offset);
-}
-
-/*
- * We search for deltas in a list sorted by type, by filename hash, and then
- * by size, so that we see progressively smaller and smaller files.
- * That's because we prefer deltas to be from the bigger file
- * to the smaller -- deletes are potentially cheaper, but perhaps
- * more importantly, the bigger file is likely the more recent
- * one.  The deepest deltas are therefore the oldest objects which are
- * less susceptible to be accessed often.
- */
-static int type_size_sort(const void *_a, const void *_b)
-{
-	const struct object_entry *a = *(struct object_entry **)_a;
-	const struct object_entry *b = *(struct object_entry **)_b;
-	const enum object_type a_type = oe_type(a);
-	const enum object_type b_type = oe_type(b);
-	const unsigned long a_size = SIZE(a);
-	const unsigned long b_size = SIZE(b);
-
-	if (a_type > b_type)
-		return -1;
-	if (a_type < b_type)
-		return 1;
-	if (a->hash > b->hash)
-		return -1;
-	if (a->hash < b->hash)
-		return 1;
-	if (a->preferred_base > b->preferred_base)
-		return -1;
-	if (a->preferred_base < b->preferred_base)
-		return 1;
-	if (use_delta_islands) {
-		const int island_cmp = island_delta_cmp(&a->idx.oid, &b->idx.oid);
-		if (island_cmp)
-			return island_cmp;
-	}
-	if (a_size > b_size)
-		return -1;
-	if (a_size < b_size)
-		return 1;
-	return a < b ? -1 : (a > b);  /* newest first */
-}
-
-struct unpacked {
-	struct object_entry *entry;
-	void *data;
-	struct delta_index *index;
-	unsigned depth;
-};
-
-static int delta_cacheable(unsigned long src_size, unsigned long trg_size,
-			   unsigned long delta_size)
-{
-	if (max_delta_cache_size && delta_cache_size + delta_size > max_delta_cache_size)
-		return 0;
-
-	if (delta_size < cache_max_small_delta_size)
-		return 1;
-
-	/* cache delta, if objects are large enough compared to delta size */
-	if ((src_size >> 20) + (trg_size >> 21) > (delta_size >> 10))
-		return 1;
-
-	return 0;
-}
-
-/* Protect delta_cache_size */
-static pthread_mutex_t cache_mutex;
-#define cache_lock()		pthread_mutex_lock(&cache_mutex)
-#define cache_unlock()		pthread_mutex_unlock(&cache_mutex)
-
-/*
- * Protect object list partitioning (e.g. struct thread_param) and
- * progress_state
- */
-static pthread_mutex_t progress_mutex;
-#define progress_lock()		pthread_mutex_lock(&progress_mutex)
-#define progress_unlock()	pthread_mutex_unlock(&progress_mutex)
-
-/*
- * Access to struct object_entry is unprotected since each thread owns
- * a portion of the main object list. Just don't access object entries
- * ahead in the list because they can be stolen and would need
- * progress_mutex for protection.
- */
-
-/*
- * Return the size of the object without doing any delta
- * reconstruction (so non-deltas are true object sizes, but deltas
- * return the size of the delta data).
- */
-unsigned long oe_get_size_slow(struct packing_data *pack,
-			       const struct object_entry *e)
-{
-	struct packed_git *p;
-	struct pack_window *w_curs;
-	unsigned char *buf;
-	enum object_type type;
-	unsigned long used, avail, size;
-
-	if (e->type_ != OBJ_OFS_DELTA && e->type_ != OBJ_REF_DELTA) {
-		packing_data_lock(&to_pack);
-		if (oid_object_info(the_repository, &e->idx.oid, &size) < 0)
-			die(_("unable to get size of %s"),
-			    oid_to_hex(&e->idx.oid));
-		packing_data_unlock(&to_pack);
-		return size;
-	}
-
-	p = oe_in_pack(pack, e);
-	if (!p)
-		BUG("when e->type is a delta, it must belong to a pack");
-
-	packing_data_lock(&to_pack);
-	w_curs = NULL;
-	buf = use_pack(p, &w_curs, e->in_pack_offset, &avail);
-	used = unpack_object_header_buffer(buf, avail, &type, &size);
-	if (used == 0)
-		die(_("unable to parse object header of %s"),
-		    oid_to_hex(&e->idx.oid));
-
-	unuse_pack(&w_curs);
-	packing_data_unlock(&to_pack);
-	return size;
-}
-
-static int try_delta(struct unpacked *trg, struct unpacked *src,
-		     unsigned max_depth, unsigned long *mem_usage)
-{
-	struct object_entry *trg_entry = trg->entry;
-	struct object_entry *src_entry = src->entry;
-	unsigned long trg_size, src_size, delta_size, sizediff, max_size, sz;
-	unsigned ref_depth;
-	enum object_type type;
-	void *delta_buf;
-
-	/* Don't bother doing diffs between different types */
-	if (oe_type(trg_entry) != oe_type(src_entry))
-		return -1;
-
-	/*
-	 * We do not bother to try a delta that we discarded on an
-	 * earlier try, but only when reusing delta data.  Note that
-	 * src_entry that is marked as the preferred_base should always
-	 * be considered, as even if we produce a suboptimal delta against
-	 * it, we will still save the transfer cost, as we already know
-	 * the other side has it and we won't send src_entry at all.
-	 */
-	if (reuse_delta && IN_PACK(trg_entry) &&
-	    IN_PACK(trg_entry) == IN_PACK(src_entry) &&
-	    !src_entry->preferred_base &&
-	    trg_entry->in_pack_type != OBJ_REF_DELTA &&
-	    trg_entry->in_pack_type != OBJ_OFS_DELTA)
-		return 0;
-
-	/* Let's not bust the allowed depth. */
-	if (src->depth >= max_depth)
-		return 0;
-
-	/* Now some size filtering heuristics. */
-	trg_size = SIZE(trg_entry);
-	if (!DELTA(trg_entry)) {
-		max_size = trg_size/2 - the_hash_algo->rawsz;
-		ref_depth = 1;
-	} else {
-		max_size = DELTA_SIZE(trg_entry);
-		ref_depth = trg->depth;
-	}
-	max_size = (uint64_t)max_size * (max_depth - src->depth) /
-						(max_depth - ref_depth + 1);
-	if (max_size == 0)
-		return 0;
-	src_size = SIZE(src_entry);
-	sizediff = src_size < trg_size ? trg_size - src_size : 0;
-	if (sizediff >= max_size)
-		return 0;
-	if (trg_size < src_size / 32)
-		return 0;
-
-	if (!in_same_island(&trg->entry->idx.oid, &src->entry->idx.oid))
-		return 0;
-
-	/* Load data if not already done */
-	if (!trg->data) {
-		packing_data_lock(&to_pack);
-		trg->data = read_object_file(&trg_entry->idx.oid, &type, &sz);
-		packing_data_unlock(&to_pack);
-		if (!trg->data)
-			die(_("object %s cannot be read"),
-			    oid_to_hex(&trg_entry->idx.oid));
-		if (sz != trg_size)
-			die(_("object %s inconsistent object length (%"PRIuMAX" vs %"PRIuMAX")"),
-			    oid_to_hex(&trg_entry->idx.oid), (uintmax_t)sz,
-			    (uintmax_t)trg_size);
-		*mem_usage += sz;
-	}
-	if (!src->data) {
-		packing_data_lock(&to_pack);
-		src->data = read_object_file(&src_entry->idx.oid, &type, &sz);
-		packing_data_unlock(&to_pack);
-		if (!src->data) {
-			if (src_entry->preferred_base) {
-				static int warned = 0;
-				if (!warned++)
-					warning(_("object %s cannot be read"),
-						oid_to_hex(&src_entry->idx.oid));
-				/*
-				 * Those objects are not included in the
-				 * resulting pack.  Be resilient and ignore
-				 * them if they can't be read, in case the
-				 * pack could be created nevertheless.
-				 */
-				return 0;
-			}
-			die(_("object %s cannot be read"),
-			    oid_to_hex(&src_entry->idx.oid));
-		}
-		if (sz != src_size)
-			die(_("object %s inconsistent object length (%"PRIuMAX" vs %"PRIuMAX")"),
-			    oid_to_hex(&src_entry->idx.oid), (uintmax_t)sz,
-			    (uintmax_t)src_size);
-		*mem_usage += sz;
-	}
-	if (!src->index) {
-		src->index = create_delta_index(src->data, src_size);
-		if (!src->index) {
-			static int warned = 0;
-			if (!warned++)
-				warning(_("suboptimal pack - out of memory"));
-			return 0;
-		}
-		*mem_usage += sizeof_delta_index(src->index);
-	}
-
-	delta_buf = create_delta(src->index, trg->data, trg_size, &delta_size, max_size);
-	if (!delta_buf)
-		return 0;
-
-	if (DELTA(trg_entry)) {
-		/* Prefer only shallower same-sized deltas. */
-		if (delta_size == DELTA_SIZE(trg_entry) &&
-		    src->depth + 1 >= trg->depth) {
-			free(delta_buf);
-			return 0;
-		}
-	}
-
-	/*
-	 * Handle memory allocation outside of the cache
-	 * accounting lock.  Compiler will optimize the strangeness
-	 * away when NO_PTHREADS is defined.
-	 */
-	free(trg_entry->delta_data);
-	cache_lock();
-	if (trg_entry->delta_data) {
-		delta_cache_size -= DELTA_SIZE(trg_entry);
-		trg_entry->delta_data = NULL;
-	}
-	if (delta_cacheable(src_size, trg_size, delta_size)) {
-		delta_cache_size += delta_size;
-		cache_unlock();
-		trg_entry->delta_data = xrealloc(delta_buf, delta_size);
-	} else {
-		cache_unlock();
-		free(delta_buf);
-	}
-
-	SET_DELTA(trg_entry, src_entry);
-	SET_DELTA_SIZE(trg_entry, delta_size);
-	trg->depth = src->depth + 1;
-
-	return 1;
-}
-
-static unsigned int check_delta_limit(struct object_entry *me, unsigned int n)
-{
-	struct object_entry *child = DELTA_CHILD(me);
-	unsigned int m = n;
-	while (child) {
-		const unsigned int c = check_delta_limit(child, n + 1);
-		if (m < c)
-			m = c;
-		child = DELTA_SIBLING(child);
-	}
-	return m;
-}
-
-static unsigned long free_unpacked(struct unpacked *n)
-{
-	unsigned long freed_mem = sizeof_delta_index(n->index);
-	free_delta_index(n->index);
-	n->index = NULL;
-	if (n->data) {
-		freed_mem += SIZE(n->entry);
-		FREE_AND_NULL(n->data);
-	}
-	n->entry = NULL;
-	n->depth = 0;
-	return freed_mem;
-}
-
-static void find_deltas(struct object_entry **list, unsigned *list_size,
-			int window, int depth, unsigned *processed)
-{
-	uint32_t i, idx = 0, count = 0;
-	struct unpacked *array;
-	unsigned long mem_usage = 0;
-
-	array = xcalloc(window, sizeof(struct unpacked));
-
-	for (;;) {
-		struct object_entry *entry;
-		struct unpacked *n = array + idx;
-		int j, max_depth, best_base = -1;
-
-		progress_lock();
-		if (!*list_size) {
-			progress_unlock();
-			break;
-		}
-		entry = *list++;
-		(*list_size)--;
-		if (!entry->preferred_base) {
-			(*processed)++;
-			display_progress(progress_state, *processed);
-		}
-		progress_unlock();
-
-		mem_usage -= free_unpacked(n);
-		n->entry = entry;
-
-		while (window_memory_limit &&
-		       mem_usage > window_memory_limit &&
-		       count > 1) {
-			const uint32_t tail = (idx + window - count) % window;
-			mem_usage -= free_unpacked(array + tail);
-			count--;
-		}
-
-		/* We do not compute delta to *create* objects we are not
-		 * going to pack.
-		 */
-		if (entry->preferred_base)
-			goto next;
-
-		/*
-		 * If the current object is at pack edge, take the depth the
-		 * objects that depend on the current object into account
-		 * otherwise they would become too deep.
-		 */
-		max_depth = depth;
-		if (DELTA_CHILD(entry)) {
-			max_depth -= check_delta_limit(entry, 0);
-			if (max_depth <= 0)
-				goto next;
-		}
-
-		j = window;
-		while (--j > 0) {
-			int ret;
-			uint32_t other_idx = idx + j;
-			struct unpacked *m;
-			if (other_idx >= window)
-				other_idx -= window;
-			m = array + other_idx;
-			if (!m->entry)
-				break;
-			ret = try_delta(n, m, max_depth, &mem_usage);
-			if (ret < 0)
-				break;
-			else if (ret > 0)
-				best_base = other_idx;
-		}
-
-		/*
-		 * If we decided to cache the delta data, then it is best
-		 * to compress it right away.  First because we have to do
-		 * it anyway, and doing it here while we're threaded will
-		 * save a lot of time in the non threaded write phase,
-		 * as well as allow for caching more deltas within
-		 * the same cache size limit.
-		 * ...
-		 * But only if not writing to stdout, since in that case
-		 * the network is most likely throttling writes anyway,
-		 * and therefore it is best to go to the write phase ASAP
-		 * instead, as we can afford spending more time compressing
-		 * between writes at that moment.
-		 */
-		if (entry->delta_data && !pack_to_stdout) {
-			unsigned long size;
-
-			size = do_compress(&entry->delta_data, DELTA_SIZE(entry));
-			if (size < (1U << OE_Z_DELTA_BITS)) {
-				entry->z_delta_size = size;
-				cache_lock();
-				delta_cache_size -= DELTA_SIZE(entry);
-				delta_cache_size += entry->z_delta_size;
-				cache_unlock();
-			} else {
-				FREE_AND_NULL(entry->delta_data);
-				entry->z_delta_size = 0;
-			}
-		}
-
-		/* if we made n a delta, and if n is already at max
-		 * depth, leaving it in the window is pointless.  we
-		 * should evict it first.
-		 */
-		if (DELTA(entry) && max_depth <= n->depth)
-			continue;
-
-		/*
-		 * Move the best delta base up in the window, after the
-		 * currently deltified object, to keep it longer.  It will
-		 * be the first base object to be attempted next.
-		 */
-		if (DELTA(entry)) {
-			struct unpacked swap = array[best_base];
-			int dist = (window + idx - best_base) % window;
-			int dst = best_base;
-			while (dist--) {
-				int src = (dst + 1) % window;
-				array[dst] = array[src];
-				dst = src;
-			}
-			array[dst] = swap;
-		}
-
-		next:
-		idx++;
-		if (count + 1 < window)
-			count++;
-		if (idx >= window)
-			idx = 0;
-	}
-
-	for (i = 0; i < window; ++i) {
-		free_delta_index(array[i].index);
-		free(array[i].data);
-	}
-	free(array);
-}
-
-/*
- * The main object list is split into smaller lists, each is handed to
- * one worker.
- *
- * The main thread waits on the condition that (at least) one of the workers
- * has stopped working (which is indicated in the .working member of
- * struct thread_params).
- *
- * When a work thread has completed its work, it sets .working to 0 and
- * signals the main thread and waits on the condition that .data_ready
- * becomes 1.
- *
- * The main thread steals half of the work from the worker that has
- * most work left to hand it to the idle worker.
- */
-
-struct thread_params {
-	pthread_t thread;
-	struct object_entry **list;
-	unsigned list_size;
-	unsigned remaining;
-	int window;
-	int depth;
-	int working;
-	int data_ready;
-	pthread_mutex_t mutex;
-	pthread_cond_t cond;
-	unsigned *processed;
-};
-
-static pthread_cond_t progress_cond;
-
-/*
- * Mutex and conditional variable can't be statically-initialized on Windows.
- */
-static void init_threaded_search(void)
-{
-	pthread_mutex_init(&cache_mutex, NULL);
-	pthread_mutex_init(&progress_mutex, NULL);
-	pthread_cond_init(&progress_cond, NULL);
-}
-
-static void cleanup_threaded_search(void)
-{
-	pthread_cond_destroy(&progress_cond);
-	pthread_mutex_destroy(&cache_mutex);
-	pthread_mutex_destroy(&progress_mutex);
-}
-
-static void *threaded_find_deltas(void *arg)
-{
-	struct thread_params *me = arg;
-
-	progress_lock();
-	while (me->remaining) {
-		progress_unlock();
-
-		find_deltas(me->list, &me->remaining,
-			    me->window, me->depth, me->processed);
-
-		progress_lock();
-		me->working = 0;
-		pthread_cond_signal(&progress_cond);
-		progress_unlock();
-
-		/*
-		 * We must not set ->data_ready before we wait on the
-		 * condition because the main thread may have set it to 1
-		 * before we get here. In order to be sure that new
-		 * work is available if we see 1 in ->data_ready, it
-		 * was initialized to 0 before this thread was spawned
-		 * and we reset it to 0 right away.
-		 */
-		pthread_mutex_lock(&me->mutex);
-		while (!me->data_ready)
-			pthread_cond_wait(&me->cond, &me->mutex);
-		me->data_ready = 0;
-		pthread_mutex_unlock(&me->mutex);
-
-		progress_lock();
-	}
-	progress_unlock();
-	/* leave ->working 1 so that this doesn't get more work assigned */
-	return NULL;
-}
-
-static void ll_find_deltas(struct object_entry **list, unsigned list_size,
-			   int window, int depth, unsigned *processed)
-{
-	struct thread_params *p;
-	int i, ret, active_threads = 0;
-
-	init_threaded_search();
-
-	if (delta_search_threads <= 1) {
-		find_deltas(list, &list_size, window, depth, processed);
-		cleanup_threaded_search();
-		return;
-	}
-	if (progress > pack_to_stdout)
-		fprintf_ln(stderr, _("Delta compression using up to %d threads"),
-			   delta_search_threads);
-	p = xcalloc(delta_search_threads, sizeof(*p));
-
-	/* Partition the work amongst work threads. */
-	for (i = 0; i < delta_search_threads; i++) {
-		unsigned sub_size = list_size / (delta_search_threads - i);
-
-		/* don't use too small segments or no deltas will be found */
-		if (sub_size < 2*window && i+1 < delta_search_threads)
-			sub_size = 0;
-
-		p[i].window = window;
-		p[i].depth = depth;
-		p[i].processed = processed;
-		p[i].working = 1;
-		p[i].data_ready = 0;
-
-		/* try to split chunks on "path" boundaries */
-		while (sub_size && sub_size < list_size &&
-		       list[sub_size]->hash &&
-		       list[sub_size]->hash == list[sub_size-1]->hash)
-			sub_size++;
-
-		p[i].list = list;
-		p[i].list_size = sub_size;
-		p[i].remaining = sub_size;
-
-		list += sub_size;
-		list_size -= sub_size;
-	}
-
-	/* Start work threads. */
-	for (i = 0; i < delta_search_threads; i++) {
-		if (!p[i].list_size)
-			continue;
-		pthread_mutex_init(&p[i].mutex, NULL);
-		pthread_cond_init(&p[i].cond, NULL);
-		ret = pthread_create(&p[i].thread, NULL,
-				     threaded_find_deltas, &p[i]);
-		if (ret)
-			die(_("unable to create thread: %s"), strerror(ret));
-		active_threads++;
-	}
-
-	/*
-	 * Now let's wait for work completion.  Each time a thread is done
-	 * with its work, we steal half of the remaining work from the
-	 * thread with the largest number of unprocessed objects and give
-	 * it to that newly idle thread.  This ensure good load balancing
-	 * until the remaining object list segments are simply too short
-	 * to be worth splitting anymore.
-	 */
-	while (active_threads) {
-		struct thread_params *target = NULL;
-		struct thread_params *victim = NULL;
-		unsigned sub_size = 0;
-
-		progress_lock();
-		for (;;) {
-			for (i = 0; !target && i < delta_search_threads; i++)
-				if (!p[i].working)
-					target = &p[i];
-			if (target)
-				break;
-			pthread_cond_wait(&progress_cond, &progress_mutex);
-		}
-
-		for (i = 0; i < delta_search_threads; i++)
-			if (p[i].remaining > 2*window &&
-			    (!victim || victim->remaining < p[i].remaining))
-				victim = &p[i];
-		if (victim) {
-			sub_size = victim->remaining / 2;
-			list = victim->list + victim->list_size - sub_size;
-			while (sub_size && list[0]->hash &&
-			       list[0]->hash == list[-1]->hash) {
-				list++;
-				sub_size--;
-			}
-			if (!sub_size) {
-				/*
-				 * It is possible for some "paths" to have
-				 * so many objects that no hash boundary
-				 * might be found.  Let's just steal the
-				 * exact half in that case.
-				 */
-				sub_size = victim->remaining / 2;
-				list -= sub_size;
-			}
-			target->list = list;
-			victim->list_size -= sub_size;
-			victim->remaining -= sub_size;
-		}
-		target->list_size = sub_size;
-		target->remaining = sub_size;
-		target->working = 1;
-		progress_unlock();
-
-		pthread_mutex_lock(&target->mutex);
-		target->data_ready = 1;
-		pthread_cond_signal(&target->cond);
-		pthread_mutex_unlock(&target->mutex);
-
-		if (!sub_size) {
-			pthread_join(target->thread, NULL);
-			pthread_cond_destroy(&target->cond);
-			pthread_mutex_destroy(&target->mutex);
-			active_threads--;
-		}
-	}
-	cleanup_threaded_search();
-	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;
-
-	/*
-	 * We catch duplicates already in add_object_entry(), but we'd
-	 * prefer to do this extra check to avoid having to parse the
-	 * tag at all if we already know that it's being packed (e.g., if
-	 * it was included via bitmaps, we would not have parsed it
-	 * previously).
-	 */
-	if (obj_is_packed(oid))
-		return;
-
-	tag = lookup_tag(the_repository, oid);
-	while (1) {
-		if (!tag || parse_tag(tag) || !tag->tagged)
-			die(_("unable to pack objects reachable from tag %s"),
-			    oid_to_hex(oid));
-
-		add_object_entry(&tag->object.oid, OBJ_TAG, NULL, 0);
-
-		if (tag->tagged->type != OBJ_TAG)
-			return;
-
-		tag = (struct tag *)tag->tagged;
-	}
-}
-
-static int add_ref_tag(const char *path, const struct object_id *oid, int flag, void *cb_data)
-{
-	struct object_id peeled;
-
-	if (starts_with(path, "refs/tags/") && /* is a tag? */
-	    !peel_ref(path, &peeled)    && /* peelable? */
-	    obj_is_packed(&peeled)) /* object packed? */
-		add_tag_chain(oid);
-	return 0;
-}
-
-static void prepare_pack(int window, int depth)
-{
-	struct object_entry **delta_list;
-	uint32_t i, nr_deltas;
-	unsigned n;
-
-	if (use_delta_islands)
-		resolve_tree_islands(the_repository, progress, &to_pack);
-
-	get_object_details();
-
-	/*
-	 * If we're locally repacking then we need to be doubly careful
-	 * from now on in order to make sure no stealth corruption gets
-	 * propagated to the new pack.  Clients receiving streamed packs
-	 * should validate everything they get anyway so no need to incur
-	 * the additional cost here in that case.
-	 */
-	if (!pack_to_stdout)
-		do_check_packed_object_crc = 1;
-
-	if (!to_pack.nr_objects || !window || !depth)
-		return;
-
-	ALLOC_ARRAY(delta_list, to_pack.nr_objects);
-	nr_deltas = n = 0;
-
-	for (i = 0; i < to_pack.nr_objects; i++) {
-		struct object_entry *entry = to_pack.objects + i;
-
-		if (DELTA(entry))
-			/* This happens if we decided to reuse existing
-			 * delta from a pack.  "reuse_delta &&" is implied.
-			 */
-			continue;
-
-		if (!entry->type_valid ||
-		    oe_size_less_than(&to_pack, entry, 50))
-			continue;
-
-		if (entry->no_try_delta)
-			continue;
-
-		if (!entry->preferred_base) {
-			nr_deltas++;
-			if (oe_type(entry) < 0)
-				die(_("unable to get type of object %s"),
-				    oid_to_hex(&entry->idx.oid));
-		} else {
-			if (oe_type(entry) < 0) {
-				/*
-				 * This object is not found, but we
-				 * don't have to include it anyway.
-				 */
-				continue;
-			}
-		}
-
-		delta_list[n++] = entry;
-	}
-
-	if (nr_deltas && n > 1) {
-		unsigned nr_done = 0;
-
-		if (progress)
-			progress_state = start_progress(_("Compressing objects"),
-							nr_deltas);
-		QSORT(delta_list, n, type_size_sort);
-		ll_find_deltas(delta_list, n, window+1, depth, &nr_done);
-		stop_progress(&progress_state);
-		if (nr_done != nr_deltas)
-			die(_("inconsistency with delta count"));
-	}
-	free(delta_list);
-}
-
-static int git_pack_config(const char *k, const char *v, void *cb)
-{
-	if (!strcmp(k, "pack.window")) {
-		window = git_config_int(k, v);
-		return 0;
-	}
-	if (!strcmp(k, "pack.windowmemory")) {
-		window_memory_limit = git_config_ulong(k, v);
-		return 0;
-	}
-	if (!strcmp(k, "pack.depth")) {
-		depth = git_config_int(k, v);
-		return 0;
-	}
-	if (!strcmp(k, "pack.deltacachesize")) {
-		max_delta_cache_size = git_config_int(k, v);
-		return 0;
-	}
-	if (!strcmp(k, "pack.deltacachelimit")) {
-		cache_max_small_delta_size = git_config_int(k, v);
-		return 0;
-	}
-	if (!strcmp(k, "pack.writebitmaphashcache")) {
-		if (git_config_bool(k, v))
-			write_bitmap_options |= BITMAP_OPT_HASH_CACHE;
-		else
-			write_bitmap_options &= ~BITMAP_OPT_HASH_CACHE;
-	}
-	if (!strcmp(k, "pack.usebitmaps")) {
-		use_bitmap_index_default = git_config_bool(k, v);
-		return 0;
-	}
-	if (!strcmp(k, "pack.allowpackreuse")) {
-		allow_pack_reuse = git_config_bool(k, v);
-		return 0;
-	}
-	if (!strcmp(k, "pack.threads")) {
-		delta_search_threads = git_config_int(k, v);
-		if (delta_search_threads < 0)
-			die(_("invalid number of threads specified (%d)"),
-			    delta_search_threads);
-		if (!HAVE_THREADS && delta_search_threads != 1) {
-			warning(_("no threads support, ignoring %s"), k);
-			delta_search_threads = 0;
-		}
-		return 0;
-	}
-	if (!strcmp(k, "pack.indexversion")) {
-		pack_idx_opts.version = git_config_int(k, v);
-		if (pack_idx_opts.version > 2)
-			die(_("bad pack.indexversion=%"PRIu32),
-			    pack_idx_opts.version);
-		return 0;
-	}
-	if (!strcmp(k, "uploadpack.blobpackfileuri")) {
-		struct configured_exclusion *ex = xmalloc(sizeof(*ex));
-		const char *oid_end, *pack_end;
-		/*
-		 * Stores the pack hash. This is not a true object ID, but is
-		 * of the same form.
-		 */
-		struct object_id pack_hash;
-
-		if (parse_oid_hex(v, &ex->e.oid, &oid_end) ||
-		    *oid_end != ' ' ||
-		    parse_oid_hex(oid_end + 1, &pack_hash, &pack_end) ||
-		    *pack_end != ' ')
-			die(_("value of uploadpack.blobpackfileuri must be "
-			      "of the form '<object-hash> <pack-hash> <uri>' (got '%s')"), v);
-		if (oidmap_get(&configured_exclusions, &ex->e.oid))
-			die(_("object already configured in another "
-			      "uploadpack.blobpackfileuri (got '%s')"), v);
-		ex->pack_hash_hex = xcalloc(1, pack_end - oid_end);
-		memcpy(ex->pack_hash_hex, oid_end + 1, pack_end - oid_end - 1);
-		ex->uri = xstrdup(pack_end + 1);
-		oidmap_put(&configured_exclusions, ex);
-	}
-	return git_default_config(k, v, cb);
-}
-
-static void read_object_list_from_stdin(void)
-{
-	char line[GIT_MAX_HEXSZ + 1 + PATH_MAX + 2];
-	struct object_id oid;
-	const char *p;
-
-	for (;;) {
-		if (!fgets(line, sizeof(line), stdin)) {
-			if (feof(stdin))
-				break;
-			if (!ferror(stdin))
-				die("BUG: fgets returned NULL, not EOF, not error!");
-			if (errno != EINTR)
-				die_errno("fgets");
-			clearerr(stdin);
-			continue;
-		}
-		if (line[0] == '-') {
-			if (get_oid_hex(line+1, &oid))
-				die(_("expected edge object ID, got garbage:\n %s"),
-				    line);
-			add_preferred_base(&oid);
-			continue;
-		}
-		if (parse_oid_hex(line, &oid, &p))
-			die(_("expected object ID, got garbage:\n %s"), line);
-
-		add_preferred_base_object(p + 1);
-		add_object_entry(&oid, OBJ_NONE, p + 1, 0);
-	}
-}
-
-/* Remember to update object flag allocation in object.h */
-#define OBJECT_ADDED (1u<<20)
-
-static void show_commit(struct commit *commit, void *data)
-{
-	add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0);
-	commit->object.flags |= OBJECT_ADDED;
-
-	if (write_bitmap_index)
-		index_commit_for_bitmap(commit);
-
-	if (use_delta_islands)
-		propagate_island_marks(commit);
-}
-
-static void show_object(struct object *obj, const char *name, void *data)
-{
-	add_preferred_base_object(name);
-	add_object_entry(&obj->oid, obj->type, name, 0);
-	obj->flags |= OBJECT_ADDED;
-
-	if (use_delta_islands) {
-		const char *p;
-		unsigned depth;
-		struct object_entry *ent;
-
-		/* the empty string is a root tree, which is depth 0 */
-		depth = *name ? 1 : 0;
-		for (p = strchr(name, '/'); p; p = strchr(p + 1, '/'))
-			depth++;
-
-		ent = packlist_find(&to_pack, &obj->oid);
-		if (ent && depth > oe_tree_depth(&to_pack, ent))
-			oe_set_tree_depth(&to_pack, ent, depth);
-	}
-}
-
-static void show_object__ma_allow_any(struct object *obj, const char *name, void *data)
-{
-	assert(arg_missing_action == MA_ALLOW_ANY);
-
-	/*
-	 * Quietly ignore ALL missing objects.  This avoids problems with
-	 * staging them now and getting an odd error later.
-	 */
-	if (!has_object(the_repository, &obj->oid, 0))
-		return;
-
-	show_object(obj, name, data);
-}
-
-static void show_object__ma_allow_promisor(struct object *obj, const char *name, void *data)
-{
-	assert(arg_missing_action == MA_ALLOW_PROMISOR);
-
-	/*
-	 * Quietly ignore EXPECTED missing objects.  This avoids problems with
-	 * staging them now and getting an odd error later.
-	 */
-	if (!has_object(the_repository, &obj->oid, 0) && is_promisor_object(&obj->oid))
-		return;
-
-	show_object(obj, name, data);
-}
-
-static int option_parse_missing_action(const struct option *opt,
-				       const char *arg, int unset)
-{
-	assert(arg);
-	assert(!unset);
-
-	if (!strcmp(arg, "error")) {
-		arg_missing_action = MA_ERROR;
-		fn_show_object = show_object;
-		return 0;
-	}
-
-	if (!strcmp(arg, "allow-any")) {
-		arg_missing_action = MA_ALLOW_ANY;
-		fetch_if_missing = 0;
-		fn_show_object = show_object__ma_allow_any;
-		return 0;
-	}
-
-	if (!strcmp(arg, "allow-promisor")) {
-		arg_missing_action = MA_ALLOW_PROMISOR;
-		fetch_if_missing = 0;
-		fn_show_object = show_object__ma_allow_promisor;
-		return 0;
-	}
-
-	die(_("invalid value for --missing"));
-	return 0;
-}
-
-static void show_edge(struct commit *commit)
-{
-	add_preferred_base(&commit->object.oid);
-}
-
-struct in_pack_object {
-	off_t offset;
-	struct object *object;
-};
-
-struct in_pack {
-	unsigned int alloc;
-	unsigned int nr;
-	struct in_pack_object *array;
-};
-
-static void mark_in_pack_object(struct object *object, struct packed_git *p, struct in_pack *in_pack)
-{
-	in_pack->array[in_pack->nr].offset = find_pack_entry_one(object->oid.hash, p);
-	in_pack->array[in_pack->nr].object = object;
-	in_pack->nr++;
-}
-
-/*
- * Compare the objects in the offset order, in order to emulate the
- * "git rev-list --objects" output that produced the pack originally.
- */
-static int ofscmp(const void *a_, const void *b_)
-{
-	struct in_pack_object *a = (struct in_pack_object *)a_;
-	struct in_pack_object *b = (struct in_pack_object *)b_;
-
-	if (a->offset < b->offset)
-		return -1;
-	else if (a->offset > b->offset)
-		return 1;
-	else
-		return oidcmp(&a->object->oid, &b->object->oid);
-}
-
-static void add_objects_in_unpacked_packs(void)
-{
-	struct packed_git *p;
-	struct in_pack in_pack;
-	uint32_t i;
-
-	memset(&in_pack, 0, sizeof(in_pack));
-
-	for (p = get_all_packs(the_repository); p; p = p->next) {
-		struct object_id oid;
-		struct object *o;
-
-		if (!p->pack_local || p->pack_keep || p->pack_keep_in_core)
-			continue;
-		if (open_pack_index(p))
-			die(_("cannot open pack index"));
-
-		ALLOC_GROW(in_pack.array,
-			   in_pack.nr + p->num_objects,
-			   in_pack.alloc);
-
-		for (i = 0; i < p->num_objects; i++) {
-			nth_packed_object_id(&oid, p, i);
-			o = lookup_unknown_object(&oid);
-			if (!(o->flags & OBJECT_ADDED))
-				mark_in_pack_object(o, p, &in_pack);
-			o->flags |= OBJECT_ADDED;
-		}
-	}
-
-	if (in_pack.nr) {
-		QSORT(in_pack.array, in_pack.nr, ofscmp);
-		for (i = 0; i < in_pack.nr; i++) {
-			struct object *o = in_pack.array[i].object;
-			add_object_entry(&o->oid, o->type, "", 0);
-		}
-	}
-	free(in_pack.array);
-}
-
-static int add_loose_object(const struct object_id *oid, const char *path,
-			    void *data)
-{
-	enum object_type type = oid_object_info(the_repository, oid, NULL);
-
-	if (type < 0) {
-		warning(_("loose object at %s could not be examined"), path);
-		return 0;
-	}
-
-	add_object_entry(oid, type, "", 0);
-	return 0;
-}
-
-/*
- * We actually don't even have to worry about reachability here.
- * add_object_entry will weed out duplicates, so we just add every
- * loose object we find.
- */
-static void add_unreachable_loose_objects(void)
-{
-	for_each_loose_file_in_objdir(get_object_directory(),
-				      add_loose_object,
-				      NULL, NULL, NULL);
-}
-
-static int has_sha1_pack_kept_or_nonlocal(const struct object_id *oid)
-{
-	static struct packed_git *last_found = (void *)1;
-	struct packed_git *p;
-
-	p = (last_found != (void *)1) ? last_found :
-					get_all_packs(the_repository);
-
-	while (p) {
-		if ((!p->pack_local || p->pack_keep ||
-				p->pack_keep_in_core) &&
-			find_pack_entry_one(oid->hash, p)) {
-			last_found = p;
-			return 1;
-		}
-		if (p == last_found)
-			p = get_all_packs(the_repository);
-		else
-			p = p->next;
-		if (p == last_found)
-			p = p->next;
-	}
-	return 0;
-}
-
-/*
- * Store a list of sha1s that are should not be discarded
- * because they are either written too recently, or are
- * reachable from another object that was.
- *
- * This is filled by get_object_list.
- */
-static struct oid_array recent_objects;
-
-static int loosened_object_can_be_discarded(const struct object_id *oid,
-					    timestamp_t mtime)
-{
-	if (!unpack_unreachable_expiration)
-		return 0;
-	if (mtime > unpack_unreachable_expiration)
-		return 0;
-	if (oid_array_lookup(&recent_objects, oid) >= 0)
-		return 0;
-	return 1;
-}
-
-static void loosen_unused_packed_objects(void)
-{
-	struct packed_git *p;
-	uint32_t i;
-	struct object_id oid;
-
-	for (p = get_all_packs(the_repository); p; p = p->next) {
-		if (!p->pack_local || p->pack_keep || p->pack_keep_in_core)
-			continue;
-
-		if (open_pack_index(p))
-			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) &&
-			    !has_sha1_pack_kept_or_nonlocal(&oid) &&
-			    !loosened_object_can_be_discarded(&oid, p->mtime))
-				if (force_object_loose(&oid, p->mtime))
-					die(_("unable to force loose object"));
-		}
-	}
-}
-
-/*
- * This tracks any options which pack-reuse code expects to be on, or which a
- * reader of the pack might not understand, and which would therefore prevent
- * blind reuse of what we have on disk.
- */
-static int pack_options_allow_reuse(void)
-{
-	return allow_pack_reuse &&
-	       pack_to_stdout &&
-	       !ignore_packed_keep_on_disk &&
-	       !ignore_packed_keep_in_core &&
-	       (!local || !have_non_local_packs) &&
-	       !incremental;
-}
-
-static int get_object_list_from_bitmap(struct rev_info *revs)
-{
-	if (!(bitmap_git = prepare_bitmap_walk(revs, &filter_options)))
-		return -1;
-
-	if (pack_options_allow_reuse() &&
-	    !reuse_partial_packfile_from_bitmap(
-			bitmap_git,
-			&reuse_packfile,
-			&reuse_packfile_objects,
-			&reuse_packfile_bitmap)) {
-		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);
-	return 0;
-}
-
-static void record_recent_object(struct object *obj,
-				 const char *name,
-				 void *data)
-{
-	oid_array_append(&recent_objects, &obj->oid);
-}
-
-static void record_recent_commit(struct commit *commit, void *data)
-{
-	oid_array_append(&recent_objects, &commit->object.oid);
-}
-
-static void get_object_list(int ac, const char **av)
-{
-	struct rev_info revs;
-	struct setup_revision_opt s_r_opt = {
-		.allow_exclude_promisor_objects = 1,
-	};
-	char line[1000];
-	int flags = 0;
-	int save_warning;
-
-	repo_init_revisions(the_repository, &revs, NULL);
-	save_commit_buffer = 0;
-	setup_revisions(ac, av, &revs, &s_r_opt);
-
-	/* make sure shallows are read */
-	is_repository_shallow(the_repository);
-
-	save_warning = warn_on_object_refname_ambiguity;
-	warn_on_object_refname_ambiguity = 0;
-
-	while (fgets(line, sizeof(line), stdin) != NULL) {
-		int len = strlen(line);
-		if (len && line[len - 1] == '\n')
-			line[--len] = 0;
-		if (!len)
-			break;
-		if (*line == '-') {
-			if (!strcmp(line, "--not")) {
-				flags ^= UNINTERESTING;
-				write_bitmap_index = 0;
-				continue;
-			}
-			if (starts_with(line, "--shallow ")) {
-				struct object_id oid;
-				if (get_oid_hex(line + 10, &oid))
-					die("not an object name '%s'", line + 10);
-				register_shallow(the_repository, &oid);
-				use_bitmap_index = 0;
-				continue;
-			}
-			die(_("not a rev '%s'"), line);
-		}
-		if (handle_revision_arg(line, &revs, flags, REVARG_CANNOT_BE_FILENAME))
-			die(_("bad revision '%s'"), line);
-	}
-
-	warn_on_object_refname_ambiguity = save_warning;
-
-	if (use_bitmap_index && !get_object_list_from_bitmap(&revs))
-		return;
-
-	if (use_delta_islands)
-		load_delta_islands(the_repository, progress);
-
-	if (prepare_revision_walk(&revs))
-		die(_("revision walk setup failed"));
-	mark_edges_uninteresting(&revs, show_edge, sparse);
-
-	if (!fn_show_object)
-		fn_show_object = show_object;
-	traverse_commit_list_filtered(&filter_options, &revs,
-				      show_commit, fn_show_object, NULL,
-				      NULL);
-
-	if (unpack_unreachable_expiration) {
-		revs.ignore_missing_links = 1;
-		if (add_unseen_recent_objects_to_traversal(&revs,
-				unpack_unreachable_expiration))
-			die(_("unable to add recent objects"));
-		if (prepare_revision_walk(&revs))
-			die(_("revision walk setup failed"));
-		traverse_commit_list(&revs, record_recent_commit,
-				     record_recent_object, NULL);
-	}
-
-	if (keep_unreachable)
-		add_objects_in_unpacked_packs();
-	if (pack_loose_unreachable)
-		add_unreachable_loose_objects();
-	if (unpack_unreachable)
-		loosen_unused_packed_objects();
-
-	oid_array_clear(&recent_objects);
-}
-
-static void add_extra_kept_packs(const struct string_list *names)
-{
-	struct packed_git *p;
-
-	if (!names->nr)
-		return;
-
-	for (p = get_all_packs(the_repository); p; p = p->next) {
-		const char *name = basename(p->pack_name);
-		int i;
-
-		if (!p->pack_local)
-			continue;
-
-		for (i = 0; i < names->nr; i++)
-			if (!fspathcmp(name, names->items[i].string))
-				break;
-
-		if (i < names->nr) {
-			p->pack_keep_in_core = 1;
-			ignore_packed_keep_in_core = 1;
-			continue;
-		}
-	}
-}
-
-static int option_parse_index_version(const struct option *opt,
-				      const char *arg, int unset)
-{
-	char *c;
-	const char *val = arg;
-
-	BUG_ON_OPT_NEG(unset);
-
-	pack_idx_opts.version = strtoul(val, &c, 10);
-	if (pack_idx_opts.version > 2)
-		die(_("unsupported index version %s"), val);
-	if (*c == ',' && c[1])
-		pack_idx_opts.off32_limit = strtoul(c+1, &c, 0);
-	if (*c || pack_idx_opts.off32_limit & 0x80000000)
-		die(_("bad index version '%s'"), val);
-	return 0;
-}
-
-static int option_parse_unpack_unreachable(const struct option *opt,
-					   const char *arg, int unset)
-{
-	if (unset) {
-		unpack_unreachable = 0;
-		unpack_unreachable_expiration = 0;
-	}
-	else {
-		unpack_unreachable = 1;
-		if (arg)
-			unpack_unreachable_expiration = approxidate(arg);
-	}
-	return 0;
-}
-
-int cmd_pack_objects(int argc, const char **argv, const char *prefix)
-{
-	int use_internal_rev_list = 0;
-	int shallow = 0;
-	int all_progress_implied = 0;
-	struct strvec rp = STRVEC_INIT;
-	int rev_list_unpacked = 0, rev_list_all = 0, rev_list_reflog = 0;
-	int rev_list_index = 0;
-	struct string_list keep_pack_list = STRING_LIST_INIT_NODUP;
-	struct option pack_objects_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_CALLBACK_F(0, "index-version", NULL, N_("<version>[,<offset>]"),
-		  N_("write the pack index file in the specified idx format version"),
-		  PARSE_OPT_NONEG, option_parse_index_version),
-		OPT_MAGNITUDE(0, "max-pack-size", &pack_size_limit,
-			      N_("maximum size of each output pack file")),
-		OPT_BOOL(0, "local", &local,
-			 N_("ignore borrowed objects from alternate object store")),
-		OPT_BOOL(0, "incremental", &incremental,
-			 N_("ignore packed objects")),
-		OPT_INTEGER(0, "window", &window,
-			    N_("limit pack window by objects")),
-		OPT_MAGNITUDE(0, "window-memory", &window_memory_limit,
-			      N_("limit pack window by memory in addition to object limit")),
-		OPT_INTEGER(0, "depth", &depth,
-			    N_("maximum length of delta chain allowed in the resulting pack")),
-		OPT_BOOL(0, "reuse-delta", &reuse_delta,
-			 N_("reuse existing deltas")),
-		OPT_BOOL(0, "reuse-object", &reuse_object,
-			 N_("reuse existing objects")),
-		OPT_BOOL(0, "delta-base-offset", &allow_ofs_delta,
-			 N_("use OFS_DELTA objects")),
-		OPT_INTEGER(0, "threads", &delta_search_threads,
-			    N_("use threads when searching for best delta matches")),
-		OPT_BOOL(0, "non-empty", &non_empty,
-			 N_("do not create an empty pack output")),
-		OPT_BOOL(0, "revs", &use_internal_rev_list,
-			 N_("read revision arguments from standard input")),
-		OPT_SET_INT_F(0, "unpacked", &rev_list_unpacked,
-			      N_("limit the objects to those that are not yet packed"),
-			      1, PARSE_OPT_NONEG),
-		OPT_SET_INT_F(0, "all", &rev_list_all,
-			      N_("include objects reachable from any reference"),
-			      1, PARSE_OPT_NONEG),
-		OPT_SET_INT_F(0, "reflog", &rev_list_reflog,
-			      N_("include objects referred by reflog entries"),
-			      1, PARSE_OPT_NONEG),
-		OPT_SET_INT_F(0, "indexed-objects", &rev_list_index,
-			      N_("include objects referred to by the index"),
-			      1, PARSE_OPT_NONEG),
-		OPT_BOOL(0, "stdout", &pack_to_stdout,
-			 N_("output pack to stdout")),
-		OPT_BOOL(0, "include-tag", &include_tag,
-			 N_("include tag objects that refer to objects to be packed")),
-		OPT_BOOL(0, "keep-unreachable", &keep_unreachable,
-			 N_("keep unreachable objects")),
-		OPT_BOOL(0, "pack-loose-unreachable", &pack_loose_unreachable,
-			 N_("pack loose unreachable objects")),
-		OPT_CALLBACK_F(0, "unpack-unreachable", NULL, N_("time"),
-		  N_("unpack unreachable objects newer than <time>"),
-		  PARSE_OPT_OPTARG, option_parse_unpack_unreachable),
-		OPT_BOOL(0, "sparse", &sparse,
-			 N_("use the sparse reachability algorithm")),
-		OPT_BOOL(0, "thin", &thin,
-			 N_("create thin packs")),
-		OPT_BOOL(0, "shallow", &shallow,
-			 N_("create packs suitable for shallow fetches")),
-		OPT_BOOL(0, "honor-pack-keep", &ignore_packed_keep_on_disk,
-			 N_("ignore packs that have companion .keep file")),
-		OPT_STRING_LIST(0, "keep-pack", &keep_pack_list, N_("name"),
-				N_("ignore this pack")),
-		OPT_INTEGER(0, "compression", &pack_compression_level,
-			    N_("pack compression level")),
-		OPT_SET_INT(0, "keep-true-parents", &grafts_replace_parents,
-			    N_("do not hide commits by grafts"), 0),
-		OPT_BOOL(0, "use-bitmap-index", &use_bitmap_index,
-			 N_("use a bitmap index if available to speed up counting objects")),
-		OPT_SET_INT(0, "write-bitmap-index", &write_bitmap_index,
-			    N_("write a bitmap index together with the pack index"),
-			    WRITE_BITMAP_TRUE),
-		OPT_SET_INT_F(0, "write-bitmap-index-quiet",
-			      &write_bitmap_index,
-			      N_("write a bitmap index if possible"),
-			      WRITE_BITMAP_QUIET, PARSE_OPT_HIDDEN),
-		OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
-		OPT_CALLBACK_F(0, "missing", NULL, N_("action"),
-		  N_("handling for missing objects"), PARSE_OPT_NONEG,
-		  option_parse_missing_action),
-		OPT_BOOL(0, "exclude-promisor-objects", &exclude_promisor_objects,
-			 N_("do not pack objects in promisor packfiles")),
-		OPT_BOOL(0, "delta-islands", &use_delta_islands,
-			 N_("respect islands during delta compression")),
-		OPT_STRING_LIST(0, "uri-protocol", &uri_protocols,
-				N_("protocol"),
-				N_("exclude any configured uploadpack.blobpackfileuri with this protocol")),
-		OPT_END(),
-	};
-
-	if (DFS_NUM_STATES > (1 << OE_DFS_STATE_BITS))
-		BUG("too many dfs states, increase OE_DFS_STATE_BITS");
-
-	read_replace_refs = 0;
-
-	sparse = git_env_bool("GIT_TEST_PACK_SPARSE", -1);
-	prepare_repo_settings(the_repository);
-	if (sparse < 0)
-		sparse = the_repository->settings.pack_use_sparse;
-
-	reset_pack_idx_option(&pack_idx_opts);
-	git_config(git_pack_config, NULL);
-
-	progress = isatty(2);
-	argc = parse_options(argc, argv, prefix, pack_objects_options,
-			     pack_usage, 0);
-
-	if (argc) {
-		base_name = argv[0];
-		argc--;
-	}
-	if (pack_to_stdout != !base_name || argc)
-		usage_with_options(pack_usage, pack_objects_options);
-
-	if (depth >= (1 << OE_DEPTH_BITS)) {
-		warning(_("delta chain depth %d is too deep, forcing %d"),
-			depth, (1 << OE_DEPTH_BITS) - 1);
-		depth = (1 << OE_DEPTH_BITS) - 1;
-	}
-	if (cache_max_small_delta_size >= (1U << OE_Z_DELTA_BITS)) {
-		warning(_("pack.deltaCacheLimit is too high, forcing %d"),
-			(1U << OE_Z_DELTA_BITS) - 1);
-		cache_max_small_delta_size = (1U << OE_Z_DELTA_BITS) - 1;
-	}
-
-	strvec_push(&rp, "pack-objects");
-	if (thin) {
-		use_internal_rev_list = 1;
-		strvec_push(&rp, shallow
-				? "--objects-edge-aggressive"
-				: "--objects-edge");
-	} else
-		strvec_push(&rp, "--objects");
-
-	if (rev_list_all) {
-		use_internal_rev_list = 1;
-		strvec_push(&rp, "--all");
-	}
-	if (rev_list_reflog) {
-		use_internal_rev_list = 1;
-		strvec_push(&rp, "--reflog");
-	}
-	if (rev_list_index) {
-		use_internal_rev_list = 1;
-		strvec_push(&rp, "--indexed-objects");
-	}
-	if (rev_list_unpacked) {
-		use_internal_rev_list = 1;
-		strvec_push(&rp, "--unpacked");
-	}
-
-	if (exclude_promisor_objects) {
-		use_internal_rev_list = 1;
-		fetch_if_missing = 0;
-		strvec_push(&rp, "--exclude-promisor-objects");
-	}
-	if (unpack_unreachable || keep_unreachable || pack_loose_unreachable)
-		use_internal_rev_list = 1;
-
-	if (!reuse_object)
-		reuse_delta = 0;
-	if (pack_compression_level == -1)
-		pack_compression_level = Z_DEFAULT_COMPRESSION;
-	else if (pack_compression_level < 0 || pack_compression_level > Z_BEST_COMPRESSION)
-		die(_("bad pack compression level %d"), pack_compression_level);
-
-	if (!delta_search_threads)	/* --threads=0 means autodetect */
-		delta_search_threads = online_cpus();
-
-	if (!HAVE_THREADS && delta_search_threads != 1)
-		warning(_("no threads support, ignoring --threads"));
-	if (!pack_to_stdout && !pack_size_limit)
-		pack_size_limit = pack_size_limit_cfg;
-	if (pack_to_stdout && pack_size_limit)
-		die(_("--max-pack-size cannot be used to build a pack for transfer"));
-	if (pack_size_limit && pack_size_limit < 1024*1024) {
-		warning(_("minimum pack size limit is 1 MiB"));
-		pack_size_limit = 1024*1024;
-	}
-
-	if (!pack_to_stdout && thin)
-		die(_("--thin cannot be used to build an indexable pack"));
-
-	if (keep_unreachable && unpack_unreachable)
-		die(_("--keep-unreachable and --unpack-unreachable are incompatible"));
-	if (!rev_list_all || !rev_list_reflog || !rev_list_index)
-		unpack_unreachable_expiration = 0;
-
-	if (filter_options.choice) {
-		if (!pack_to_stdout)
-			die(_("cannot use --filter without --stdout"));
-	}
-
-	/*
-	 * "soft" reasons not to use bitmaps - for on-disk repack by default we want
-	 *
-	 * - to produce good pack (with bitmap index not-yet-packed objects are
-	 *   packed in suboptimal order).
-	 *
-	 * - to use more robust pack-generation codepath (avoiding possible
-	 *   bugs in bitmap code and possible bitmap index corruption).
-	 */
-	if (!pack_to_stdout)
-		use_bitmap_index_default = 0;
-
-	if (use_bitmap_index < 0)
-		use_bitmap_index = use_bitmap_index_default;
-
-	/* "hard" reasons not to use bitmaps; these just won't work at all */
-	if (!use_internal_rev_list || (!pack_to_stdout && write_bitmap_index) || is_repository_shallow(the_repository))
-		use_bitmap_index = 0;
-
-	if (pack_to_stdout || !rev_list_all)
-		write_bitmap_index = 0;
-
-	if (use_delta_islands)
-		strvec_push(&rp, "--topo-order");
-
-	if (progress && all_progress_implied)
-		progress = 2;
-
-	add_extra_kept_packs(&keep_pack_list);
-	if (ignore_packed_keep_on_disk) {
-		struct packed_git *p;
-		for (p = get_all_packs(the_repository); p; p = p->next)
-			if (p->pack_local && p->pack_keep)
-				break;
-		if (!p) /* no keep-able packs found */
-			ignore_packed_keep_on_disk = 0;
-	}
-	if (local) {
-		/*
-		 * unlike ignore_packed_keep_on_disk above, we do not
-		 * want to unset "local" based on looking at packs, as
-		 * it also covers non-local objects
-		 */
-		struct packed_git *p;
-		for (p = get_all_packs(the_repository); p; p = p->next) {
-			if (!p->pack_local) {
-				have_non_local_packs = 1;
-				break;
-			}
-		}
-	}
-
-	trace2_region_enter("pack-objects", "enumerate-objects",
-			    the_repository);
-	prepare_packing_data(the_repository, &to_pack);
-
-	if (progress)
-		progress_state = start_progress(_("Enumerating objects"), 0);
-	if (!use_internal_rev_list)
-		read_object_list_from_stdin();
-	else {
-		get_object_list(rp.nr, rp.v);
-		strvec_clear(&rp);
-	}
-	cleanup_preferred_base();
-	if (include_tag && nr_result)
-		for_each_ref(add_ref_tag, NULL);
-	stop_progress(&progress_state);
-	trace2_region_leave("pack-objects", "enumerate-objects",
-			    the_repository);
-
-	if (non_empty && !nr_result)
-		return 0;
-	if (nr_result) {
-		trace2_region_enter("pack-objects", "prepare-pack",
-				    the_repository);
-		prepare_pack(window, depth);
-		trace2_region_leave("pack-objects", "prepare-pack",
-				    the_repository);
-	}
-
-	trace2_region_enter("pack-objects", "write-pack-file", the_repository);
-	write_excluded_by_configs();
-	write_pack_file();
-	trace2_region_leave("pack-objects", "write-pack-file", the_repository);
-
-	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);
-	return 0;
-}
diff --git a/third_party/git/builtin/pack-redundant.c b/third_party/git/builtin/pack-redundant.c
deleted file mode 100644
index 178e3409b7f8..000000000000
--- a/third_party/git/builtin/pack-redundant.c
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
-*
-* Copyright 2005, Lukas Sandstrom <lukass@etek.chalmers.se>
-*
-* This file is licensed under the GPL v2.
-*
-*/
-
-#include "builtin.h"
-#include "repository.h"
-#include "packfile.h"
-#include "object-store.h"
-
-#define BLKSIZE 512
-
-static const char pack_redundant_usage[] =
-"git pack-redundant [--verbose] [--alt-odb] (--all | <filename.pack>...)";
-
-static int load_all_packs, verbose, alt_odb;
-
-struct llist_item {
-	struct llist_item *next;
-	const struct object_id *oid;
-};
-static struct llist {
-	struct llist_item *front;
-	struct llist_item *back;
-	size_t size;
-} *all_objects; /* all objects which must be present in local packfiles */
-
-static struct pack_list {
-	struct pack_list *next;
-	struct packed_git *pack;
-	struct llist *unique_objects;
-	struct llist *remaining_objects;
-	size_t all_objects_size;
-} *local_packs = NULL, *altodb_packs = NULL;
-
-static struct llist_item *free_nodes;
-
-static inline void llist_item_put(struct llist_item *item)
-{
-	item->next = free_nodes;
-	free_nodes = item;
-}
-
-static inline struct llist_item *llist_item_get(void)
-{
-	struct llist_item *new_item;
-	if ( free_nodes ) {
-		new_item = free_nodes;
-		free_nodes = free_nodes->next;
-	} else {
-		int i = 1;
-		ALLOC_ARRAY(new_item, BLKSIZE);
-		for (; i < BLKSIZE; i++)
-			llist_item_put(&new_item[i]);
-	}
-	return new_item;
-}
-
-static inline void llist_init(struct llist **list)
-{
-	*list = xmalloc(sizeof(struct llist));
-	(*list)->front = (*list)->back = NULL;
-	(*list)->size = 0;
-}
-
-static struct llist * llist_copy(struct llist *list)
-{
-	struct llist *ret;
-	struct llist_item *new_item, *old_item, *prev;
-
-	llist_init(&ret);
-
-	if ((ret->size = list->size) == 0)
-		return ret;
-
-	new_item = ret->front = llist_item_get();
-	new_item->oid = list->front->oid;
-
-	old_item = list->front->next;
-	while (old_item) {
-		prev = new_item;
-		new_item = llist_item_get();
-		prev->next = new_item;
-		new_item->oid = old_item->oid;
-		old_item = old_item->next;
-	}
-	new_item->next = NULL;
-	ret->back = new_item;
-
-	return ret;
-}
-
-static inline struct llist_item *llist_insert(struct llist *list,
-					      struct llist_item *after,
-					      const struct object_id *oid)
-{
-	struct llist_item *new_item = llist_item_get();
-	new_item->oid = oid;
-	new_item->next = NULL;
-
-	if (after != NULL) {
-		new_item->next = after->next;
-		after->next = new_item;
-		if (after == list->back)
-			list->back = new_item;
-	} else {/* insert in front */
-		if (list->size == 0)
-			list->back = new_item;
-		else
-			new_item->next = list->front;
-		list->front = new_item;
-	}
-	list->size++;
-	return new_item;
-}
-
-static inline struct llist_item *llist_insert_back(struct llist *list,
-						   const struct object_id *oid)
-{
-	return llist_insert(list, list->back, oid);
-}
-
-static inline struct llist_item *llist_insert_sorted_unique(struct llist *list,
-			const struct object_id *oid, struct llist_item *hint)
-{
-	struct llist_item *prev = NULL, *l;
-
-	l = (hint == NULL) ? list->front : hint;
-	while (l) {
-		int cmp = oidcmp(l->oid, oid);
-		if (cmp > 0) { /* we insert before this entry */
-			return llist_insert(list, prev, oid);
-		}
-		if (!cmp) { /* already exists */
-			return l;
-		}
-		prev = l;
-		l = l->next;
-	}
-	/* insert at the end */
-	return llist_insert_back(list, oid);
-}
-
-/* returns a pointer to an item in front of sha1 */
-static inline struct llist_item * llist_sorted_remove(struct llist *list, const struct object_id *oid, struct llist_item *hint)
-{
-	struct llist_item *prev, *l;
-
-redo_from_start:
-	l = (hint == NULL) ? list->front : hint;
-	prev = NULL;
-	while (l) {
-		const int cmp = oidcmp(l->oid, oid);
-		if (cmp > 0) /* not in list, since sorted */
-			return prev;
-		if (!cmp) { /* found */
-			if (prev == NULL) {
-				if (hint != NULL && hint != list->front) {
-					/* we don't know the previous element */
-					hint = NULL;
-					goto redo_from_start;
-				}
-				list->front = l->next;
-			} else
-				prev->next = l->next;
-			if (l == list->back)
-				list->back = prev;
-			llist_item_put(l);
-			list->size--;
-			return prev;
-		}
-		prev = l;
-		l = l->next;
-	}
-	return prev;
-}
-
-/* computes A\B */
-static void llist_sorted_difference_inplace(struct llist *A,
-				     struct llist *B)
-{
-	struct llist_item *hint, *b;
-
-	hint = NULL;
-	b = B->front;
-
-	while (b) {
-		hint = llist_sorted_remove(A, b->oid, hint);
-		b = b->next;
-	}
-}
-
-static inline struct pack_list * pack_list_insert(struct pack_list **pl,
-					   struct pack_list *entry)
-{
-	struct pack_list *p = xmalloc(sizeof(struct pack_list));
-	memcpy(p, entry, sizeof(struct pack_list));
-	p->next = *pl;
-	*pl = p;
-	return p;
-}
-
-static inline size_t pack_list_size(struct pack_list *pl)
-{
-	size_t ret = 0;
-	while (pl) {
-		ret++;
-		pl = pl->next;
-	}
-	return ret;
-}
-
-static struct pack_list * pack_list_difference(const struct pack_list *A,
-					       const struct pack_list *B)
-{
-	struct pack_list *ret;
-	const struct pack_list *pl;
-
-	if (A == NULL)
-		return NULL;
-
-	pl = B;
-	while (pl != NULL) {
-		if (A->pack == pl->pack)
-			return pack_list_difference(A->next, B);
-		pl = pl->next;
-	}
-	ret = xmalloc(sizeof(struct pack_list));
-	memcpy(ret, A, sizeof(struct pack_list));
-	ret->next = pack_list_difference(A->next, B);
-	return ret;
-}
-
-static void cmp_two_packs(struct pack_list *p1, struct pack_list *p2)
-{
-	unsigned long p1_off = 0, p2_off = 0, p1_step, p2_step;
-	const unsigned char *p1_base, *p2_base;
-	struct llist_item *p1_hint = NULL, *p2_hint = NULL;
-	const unsigned int hashsz = the_hash_algo->rawsz;
-
-	if (!p1->unique_objects)
-		p1->unique_objects = llist_copy(p1->remaining_objects);
-	if (!p2->unique_objects)
-		p2->unique_objects = llist_copy(p2->remaining_objects);
-
-	p1_base = p1->pack->index_data;
-	p2_base = p2->pack->index_data;
-	p1_base += 256 * 4 + ((p1->pack->index_version < 2) ? 4 : 8);
-	p2_base += 256 * 4 + ((p2->pack->index_version < 2) ? 4 : 8);
-	p1_step = hashsz + ((p1->pack->index_version < 2) ? 4 : 0);
-	p2_step = hashsz + ((p2->pack->index_version < 2) ? 4 : 0);
-
-	while (p1_off < p1->pack->num_objects * p1_step &&
-	       p2_off < p2->pack->num_objects * p2_step)
-	{
-		const int cmp = hashcmp(p1_base + p1_off, p2_base + p2_off);
-		/* cmp ~ p1 - p2 */
-		if (cmp == 0) {
-			p1_hint = llist_sorted_remove(p1->unique_objects,
-					(const struct object_id *)(p1_base + p1_off),
-					p1_hint);
-			p2_hint = llist_sorted_remove(p2->unique_objects,
-					(const struct object_id *)(p1_base + p1_off),
-					p2_hint);
-			p1_off += p1_step;
-			p2_off += p2_step;
-			continue;
-		}
-		if (cmp < 0) { /* p1 has the object, p2 doesn't */
-			p1_off += p1_step;
-		} else { /* p2 has the object, p1 doesn't */
-			p2_off += p2_step;
-		}
-	}
-}
-
-static size_t sizeof_union(struct packed_git *p1, struct packed_git *p2)
-{
-	size_t ret = 0;
-	unsigned long p1_off = 0, p2_off = 0, p1_step, p2_step;
-	const unsigned char *p1_base, *p2_base;
-	const unsigned int hashsz = the_hash_algo->rawsz;
-
-	p1_base = p1->index_data;
-	p2_base = p2->index_data;
-	p1_base += 256 * 4 + ((p1->index_version < 2) ? 4 : 8);
-	p2_base += 256 * 4 + ((p2->index_version < 2) ? 4 : 8);
-	p1_step = hashsz + ((p1->index_version < 2) ? 4 : 0);
-	p2_step = hashsz + ((p2->index_version < 2) ? 4 : 0);
-
-	while (p1_off < p1->num_objects * p1_step &&
-	       p2_off < p2->num_objects * p2_step)
-	{
-		int cmp = hashcmp(p1_base + p1_off, p2_base + p2_off);
-		/* cmp ~ p1 - p2 */
-		if (cmp == 0) {
-			ret++;
-			p1_off += p1_step;
-			p2_off += p2_step;
-			continue;
-		}
-		if (cmp < 0) { /* p1 has the object, p2 doesn't */
-			p1_off += p1_step;
-		} else { /* p2 has the object, p1 doesn't */
-			p2_off += p2_step;
-		}
-	}
-	return ret;
-}
-
-/* another O(n^2) function ... */
-static size_t get_pack_redundancy(struct pack_list *pl)
-{
-	struct pack_list *subset;
-	size_t ret = 0;
-
-	if (pl == NULL)
-		return 0;
-
-	while ((subset = pl->next)) {
-		while (subset) {
-			ret += sizeof_union(pl->pack, subset->pack);
-			subset = subset->next;
-		}
-		pl = pl->next;
-	}
-	return ret;
-}
-
-static inline off_t pack_set_bytecount(struct pack_list *pl)
-{
-	off_t ret = 0;
-	while (pl) {
-		ret += pl->pack->pack_size;
-		ret += pl->pack->index_size;
-		pl = pl->next;
-	}
-	return ret;
-}
-
-static int cmp_remaining_objects(const void *a, const void *b)
-{
-	struct pack_list *pl_a = *((struct pack_list **)a);
-	struct pack_list *pl_b = *((struct pack_list **)b);
-
-	if (pl_a->remaining_objects->size == pl_b->remaining_objects->size) {
-		/* have the same remaining_objects, big pack first */
-		if (pl_a->all_objects_size == pl_b->all_objects_size)
-			return 0;
-		else if (pl_a->all_objects_size < pl_b->all_objects_size)
-			return 1;
-		else
-			return -1;
-	} else if (pl_a->remaining_objects->size < pl_b->remaining_objects->size) {
-		/* sort by remaining objects, more objects first */
-		return 1;
-	} else {
-		return -1;
-	}
-}
-
-/* Sort pack_list, greater size of remaining_objects first */
-static void sort_pack_list(struct pack_list **pl)
-{
-	struct pack_list **ary, *p;
-	int i;
-	size_t n = pack_list_size(*pl);
-
-	if (n < 2)
-		return;
-
-	/* prepare an array of packed_list for easier sorting */
-	ary = xcalloc(n, sizeof(struct pack_list *));
-	for (n = 0, p = *pl; p; p = p->next)
-		ary[n++] = p;
-
-	QSORT(ary, n, cmp_remaining_objects);
-
-	/* link them back again */
-	for (i = 0; i < n - 1; i++)
-		ary[i]->next = ary[i + 1];
-	ary[n - 1]->next = NULL;
-	*pl = ary[0];
-
-	free(ary);
-}
-
-
-static void minimize(struct pack_list **min)
-{
-	struct pack_list *pl, *unique = NULL, *non_unique = NULL;
-	struct llist *missing, *unique_pack_objects;
-
-	pl = local_packs;
-	while (pl) {
-		if (pl->unique_objects->size)
-			pack_list_insert(&unique, pl);
-		else
-			pack_list_insert(&non_unique, pl);
-		pl = pl->next;
-	}
-	/* find out which objects are missing from the set of unique packs */
-	missing = llist_copy(all_objects);
-	pl = unique;
-	while (pl) {
-		llist_sorted_difference_inplace(missing, pl->remaining_objects);
-		pl = pl->next;
-	}
-
-	*min = unique;
-
-	/* return if there are no objects missing from the unique set */
-	if (missing->size == 0) {
-		free(missing);
-		return;
-	}
-
-	unique_pack_objects = llist_copy(all_objects);
-	llist_sorted_difference_inplace(unique_pack_objects, missing);
-
-	/* remove unique pack objects from the non_unique packs */
-	pl = non_unique;
-	while (pl) {
-		llist_sorted_difference_inplace(pl->remaining_objects, unique_pack_objects);
-		pl = pl->next;
-	}
-
-	while (non_unique) {
-		/* sort the non_unique packs, greater size of remaining_objects first */
-		sort_pack_list(&non_unique);
-		if (non_unique->remaining_objects->size == 0)
-			break;
-
-		pack_list_insert(min, non_unique);
-
-		for (pl = non_unique->next; pl && pl->remaining_objects->size > 0;  pl = pl->next)
-			llist_sorted_difference_inplace(pl->remaining_objects, non_unique->remaining_objects);
-
-		non_unique = non_unique->next;
-	}
-}
-
-static void load_all_objects(void)
-{
-	struct pack_list *pl = local_packs;
-	struct llist_item *hint, *l;
-
-	llist_init(&all_objects);
-
-	while (pl) {
-		hint = NULL;
-		l = pl->remaining_objects->front;
-		while (l) {
-			hint = llist_insert_sorted_unique(all_objects,
-							  l->oid, hint);
-			l = l->next;
-		}
-		pl = pl->next;
-	}
-	/* remove objects present in remote packs */
-	pl = altodb_packs;
-	while (pl) {
-		llist_sorted_difference_inplace(all_objects, pl->remaining_objects);
-		pl = pl->next;
-	}
-}
-
-/* this scales like O(n^2) */
-static void cmp_local_packs(void)
-{
-	struct pack_list *subset, *pl = local_packs;
-
-	while ((subset = pl)) {
-		while ((subset = subset->next))
-			cmp_two_packs(pl, subset);
-		pl = pl->next;
-	}
-}
-
-static void scan_alt_odb_packs(void)
-{
-	struct pack_list *local, *alt;
-
-	alt = altodb_packs;
-	while (alt) {
-		local = local_packs;
-		while (local) {
-			llist_sorted_difference_inplace(local->remaining_objects,
-							alt->remaining_objects);
-			local = local->next;
-		}
-		alt = alt->next;
-	}
-}
-
-static struct pack_list * add_pack(struct packed_git *p)
-{
-	struct pack_list l;
-	unsigned long off = 0, step;
-	const unsigned char *base;
-
-	if (!p->pack_local && !(alt_odb || verbose))
-		return NULL;
-
-	l.pack = p;
-	llist_init(&l.remaining_objects);
-
-	if (open_pack_index(p))
-		return NULL;
-
-	base = p->index_data;
-	base += 256 * 4 + ((p->index_version < 2) ? 4 : 8);
-	step = the_hash_algo->rawsz + ((p->index_version < 2) ? 4 : 0);
-	while (off < p->num_objects * step) {
-		llist_insert_back(l.remaining_objects, (const struct object_id *)(base + off));
-		off += step;
-	}
-	l.all_objects_size = l.remaining_objects->size;
-	l.unique_objects = NULL;
-	if (p->pack_local)
-		return pack_list_insert(&local_packs, &l);
-	else
-		return pack_list_insert(&altodb_packs, &l);
-}
-
-static struct pack_list * add_pack_file(const char *filename)
-{
-	struct packed_git *p = get_all_packs(the_repository);
-
-	if (strlen(filename) < 40)
-		die("Bad pack filename: %s", filename);
-
-	while (p) {
-		if (strstr(p->pack_name, filename))
-			return add_pack(p);
-		p = p->next;
-	}
-	die("Filename %s not found in packed_git", filename);
-}
-
-static void load_all(void)
-{
-	struct packed_git *p = get_all_packs(the_repository);
-
-	while (p) {
-		add_pack(p);
-		p = p->next;
-	}
-}
-
-int cmd_pack_redundant(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	struct pack_list *min = NULL, *red, *pl;
-	struct llist *ignore;
-	struct object_id *oid;
-	char buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \n + \0 */
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage(pack_redundant_usage);
-
-	for (i = 1; i < argc; i++) {
-		const char *arg = argv[i];
-		if (!strcmp(arg, "--")) {
-			i++;
-			break;
-		}
-		if (!strcmp(arg, "--all")) {
-			load_all_packs = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--verbose")) {
-			verbose = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--alt-odb")) {
-			alt_odb = 1;
-			continue;
-		}
-		if (*arg == '-')
-			usage(pack_redundant_usage);
-		else
-			break;
-	}
-
-	if (load_all_packs)
-		load_all();
-	else
-		while (*(argv + i) != NULL)
-			add_pack_file(*(argv + i++));
-
-	if (local_packs == NULL)
-		die("Zero packs found!");
-
-	load_all_objects();
-
-	if (alt_odb)
-		scan_alt_odb_packs();
-
-	/* ignore objects given on stdin */
-	llist_init(&ignore);
-	if (!isatty(0)) {
-		while (fgets(buf, sizeof(buf), stdin)) {
-			oid = xmalloc(sizeof(*oid));
-			if (get_oid_hex(buf, oid))
-				die("Bad object ID on stdin: %s", buf);
-			llist_insert_sorted_unique(ignore, oid, NULL);
-		}
-	}
-	llist_sorted_difference_inplace(all_objects, ignore);
-	pl = local_packs;
-	while (pl) {
-		llist_sorted_difference_inplace(pl->remaining_objects, ignore);
-		pl = pl->next;
-	}
-
-	cmp_local_packs();
-
-	minimize(&min);
-
-	if (verbose) {
-		fprintf(stderr, "There are %lu packs available in alt-odbs.\n",
-			(unsigned long)pack_list_size(altodb_packs));
-		fprintf(stderr, "The smallest (bytewise) set of packs is:\n");
-		pl = min;
-		while (pl) {
-			fprintf(stderr, "\t%s\n", pl->pack->pack_name);
-			pl = pl->next;
-		}
-		fprintf(stderr, "containing %lu duplicate objects "
-				"with a total size of %lukb.\n",
-			(unsigned long)get_pack_redundancy(min),
-			(unsigned long)pack_set_bytecount(min)/1024);
-		fprintf(stderr, "A total of %lu unique objects were considered.\n",
-			(unsigned long)all_objects->size);
-		fprintf(stderr, "Redundant packs (with indexes):\n");
-	}
-	pl = red = pack_list_difference(local_packs, min);
-	while (pl) {
-		printf("%s\n%s\n",
-		       sha1_pack_index_name(pl->pack->hash),
-		       pl->pack->pack_name);
-		pl = pl->next;
-	}
-	if (verbose)
-		fprintf(stderr, "%luMB of redundant packs in total.\n",
-			(unsigned long)pack_set_bytecount(red)/(1024*1024));
-
-	return 0;
-}
diff --git a/third_party/git/builtin/pack-refs.c b/third_party/git/builtin/pack-refs.c
deleted file mode 100644
index cfbd5c36c764..000000000000
--- a/third_party/git/builtin/pack-refs.c
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "builtin.h"
-#include "config.h"
-#include "parse-options.h"
-#include "refs.h"
-#include "repository.h"
-
-static char const * const pack_refs_usage[] = {
-	N_("git pack-refs [<options>]"),
-	NULL
-};
-
-int cmd_pack_refs(int argc, const char **argv, const char *prefix)
-{
-	unsigned int flags = PACK_REFS_PRUNE;
-	struct option opts[] = {
-		OPT_BIT(0, "all",   &flags, N_("pack everything"), PACK_REFS_ALL),
-		OPT_BIT(0, "prune", &flags, N_("prune loose refs (default)"), PACK_REFS_PRUNE),
-		OPT_END(),
-	};
-	git_config(git_default_config, NULL);
-	if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0))
-		usage_with_options(pack_refs_usage, opts);
-	return refs_pack_refs(get_main_ref_store(the_repository), flags);
-}
diff --git a/third_party/git/builtin/patch-id.c b/third_party/git/builtin/patch-id.c
deleted file mode 100644
index 822ffff51fbd..000000000000
--- a/third_party/git/builtin/patch-id.c
+++ /dev/null
@@ -1,180 +0,0 @@
-#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));
-}
-
-static int remove_space(char *line)
-{
-	char *src = line;
-	char *dst = line;
-	unsigned char c;
-
-	while ((c = *src++) != '\0') {
-		if (!isspace(c))
-			*dst++ = c;
-	}
-	return dst - line;
-}
-
-static int scan_hunk_header(const char *p, int *p_before, int *p_after)
-{
-	static const char digits[] = "0123456789";
-	const char *q, *r;
-	int n;
-
-	q = p + 4;
-	n = strspn(q, digits);
-	if (q[n] == ',') {
-		q += n + 1;
-		n = strspn(q, digits);
-	}
-	if (n == 0 || q[n] != ' ' || q[n+1] != '+')
-		return 0;
-
-	r = q + n + 2;
-	n = strspn(r, digits);
-	if (r[n] == ',') {
-		r += n + 1;
-		n = strspn(r, digits);
-	}
-	if (n == 0)
-		return 0;
-
-	*p_before = atoi(q);
-	*p_after = atoi(r);
-	return 1;
-}
-
-static int get_one_patchid(struct object_id *next_oid, struct object_id *result,
-			   struct strbuf *line_buf, int stable)
-{
-	int patchlen = 0, found_next = 0;
-	int before = -1, after = -1;
-	git_hash_ctx ctx;
-
-	the_hash_algo->init_fn(&ctx);
-	oidclr(result);
-
-	while (strbuf_getwholeline(line_buf, stdin, '\n') != EOF) {
-		char *line = line_buf->buf;
-		const char *p = line;
-		int len;
-
-		if (!skip_prefix(line, "diff-tree ", &p) &&
-		    !skip_prefix(line, "commit ", &p) &&
-		    !skip_prefix(line, "From ", &p) &&
-		    starts_with(line, "\\ ") && 12 < strlen(line))
-			continue;
-
-		if (!get_oid_hex(p, next_oid)) {
-			found_next = 1;
-			break;
-		}
-
-		/* Ignore commit comments */
-		if (!patchlen && !starts_with(line, "diff "))
-			continue;
-
-		/* Parsing diff header?  */
-		if (before == -1) {
-			if (starts_with(line, "index "))
-				continue;
-			else if (starts_with(line, "--- "))
-				before = after = 1;
-			else if (!isalpha(line[0]))
-				break;
-		}
-
-		/* Looking for a valid hunk header?  */
-		if (before == 0 && after == 0) {
-			if (starts_with(line, "@@ -")) {
-				/* Parse next hunk, but ignore line numbers.  */
-				scan_hunk_header(line, &before, &after);
-				continue;
-			}
-
-			/* Split at the end of the patch.  */
-			if (!starts_with(line, "diff "))
-				break;
-
-			/* Else we're parsing another header.  */
-			if (stable)
-				flush_one_hunk(result, &ctx);
-			before = after = -1;
-		}
-
-		/* If we get here, we're inside a hunk.  */
-		if (line[0] == '-' || line[0] == ' ')
-			before--;
-		if (line[0] == '+' || line[0] == ' ')
-			after--;
-
-		/* Compute the sha without whitespace */
-		len = remove_space(line);
-		patchlen += len;
-		the_hash_algo->update_fn(&ctx, line, len);
-	}
-
-	if (!found_next)
-		oidclr(next_oid);
-
-	flush_one_hunk(result, &ctx);
-
-	return patchlen;
-}
-
-static void generate_id_list(int stable)
-{
-	struct object_id oid, n, result;
-	int patchlen;
-	struct strbuf line_buf = STRBUF_INIT;
-
-	oidclr(&oid);
-	while (!feof(stdin)) {
-		patchlen = get_one_patchid(&n, &result, &line_buf, stable);
-		flush_current_id(patchlen, &oid, &result);
-		oidcpy(&oid, &n);
-	}
-	strbuf_release(&line_buf);
-}
-
-static const char patch_id_usage[] = "git patch-id [--stable | --unstable]";
-
-static int git_patch_id_config(const char *var, const char *value, void *cb)
-{
-	int *stable = cb;
-
-	if (!strcmp(var, "patchid.stable")) {
-		*stable = git_config_bool(var, value);
-		return 0;
-	}
-
-	return git_default_config(var, value, cb);
-}
-
-int cmd_patch_id(int argc, const char **argv, const char *prefix)
-{
-	int stable = -1;
-
-	git_config(git_patch_id_config, &stable);
-
-	/* If nothing is set, default to unstable. */
-	if (stable < 0)
-		stable = 0;
-
-	if (argc == 2 && !strcmp(argv[1], "--stable"))
-		stable = 1;
-	else if (argc == 2 && !strcmp(argv[1], "--unstable"))
-		stable = 0;
-	else if (argc != 1)
-		usage(patch_id_usage);
-
-	generate_id_list(stable);
-	return 0;
-}
diff --git a/third_party/git/builtin/prune-packed.c b/third_party/git/builtin/prune-packed.c
deleted file mode 100644
index b7b9281a8cea..000000000000
--- a/third_party/git/builtin/prune-packed.c
+++ /dev/null
@@ -1,31 +0,0 @@
-#include "builtin.h"
-#include "parse-options.h"
-#include "prune-packed.h"
-
-static const char * const prune_packed_usage[] = {
-	N_("git prune-packed [-n | --dry-run] [-q | --quiet]"),
-	NULL
-};
-
-int cmd_prune_packed(int argc, const char **argv, const char *prefix)
-{
-	int opts = isatty(2) ? PRUNE_PACKED_VERBOSE : 0;
-	const struct option prune_packed_options[] = {
-		OPT_BIT('n', "dry-run", &opts, N_("dry run"),
-			PRUNE_PACKED_DRY_RUN),
-		OPT_NEGBIT('q', "quiet", &opts, N_("be quiet"),
-			   PRUNE_PACKED_VERBOSE),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, prune_packed_options,
-			     prune_packed_usage, 0);
-
-	if (argc > 0)
-		usage_msg_opt(_("too many arguments"),
-			      prune_packed_usage,
-			      prune_packed_options);
-
-	prune_packed_objects(opts);
-	return 0;
-}
diff --git a/third_party/git/builtin/prune.c b/third_party/git/builtin/prune.c
deleted file mode 100644
index 02c6ab7cbaaf..000000000000
--- a/third_party/git/builtin/prune.c
+++ /dev/null
@@ -1,189 +0,0 @@
-#include "cache.h"
-#include "commit.h"
-#include "diff.h"
-#include "revision.h"
-#include "builtin.h"
-#include "reachable.h"
-#include "parse-options.h"
-#include "progress.h"
-#include "prune-packed.h"
-#include "object-store.h"
-#include "shallow.h"
-
-static const char * const prune_usage[] = {
-	N_("git prune [-n] [-v] [--progress] [--expire <time>] [--] [<head>...]"),
-	NULL
-};
-static int show_only;
-static int verbose;
-static timestamp_t expire;
-static int show_progress = -1;
-
-static int prune_tmp_file(const char *fullpath)
-{
-	struct stat st;
-	if (lstat(fullpath, &st))
-		return error("Could not stat '%s'", fullpath);
-	if (st.st_mtime > expire)
-		return 0;
-	if (show_only || verbose)
-		printf("Removing stale temporary file %s\n", fullpath);
-	if (!show_only)
-		unlink_or_warn(fullpath);
-	return 0;
-}
-
-static void perform_reachability_traversal(struct rev_info *revs)
-{
-	static int initialized;
-	struct progress *progress = NULL;
-
-	if (initialized)
-		return;
-
-	if (show_progress)
-		progress = start_delayed_progress(_("Checking connectivity"), 0);
-	mark_reachable_objects(revs, 1, expire, progress);
-	stop_progress(&progress);
-	initialized = 1;
-}
-
-static int is_object_reachable(const struct object_id *oid,
-			       struct rev_info *revs)
-{
-	struct object *obj;
-
-	perform_reachability_traversal(revs);
-
-	obj = lookup_object(the_repository, oid);
-	return obj && (obj->flags & SEEN);
-}
-
-static int prune_object(const struct object_id *oid, const char *fullpath,
-			void *data)
-{
-	struct rev_info *revs = data;
-	struct stat st;
-
-	if (is_object_reachable(oid, revs))
-		return 0;
-
-	if (lstat(fullpath, &st)) {
-		/* report errors, but do not stop pruning */
-		error("Could not stat '%s'", fullpath);
-		return 0;
-	}
-	if (st.st_mtime > expire)
-		return 0;
-	if (show_only || verbose) {
-		enum object_type type = oid_object_info(the_repository, oid,
-							NULL);
-		printf("%s %s\n", oid_to_hex(oid),
-		       (type > 0) ? type_name(type) : "unknown");
-	}
-	if (!show_only)
-		unlink_or_warn(fullpath);
-	return 0;
-}
-
-static int prune_cruft(const char *basename, const char *path, void *data)
-{
-	if (starts_with(basename, "tmp_obj_"))
-		prune_tmp_file(path);
-	else
-		fprintf(stderr, "bad sha1 file: %s\n", path);
-	return 0;
-}
-
-static int prune_subdir(unsigned int nr, const char *path, void *data)
-{
-	if (!show_only)
-		rmdir(path);
-	return 0;
-}
-
-/*
- * Write errors (particularly out of space) can result in
- * failed temporary packs (and more rarely indexes and other
- * files beginning with "tmp_") accumulating in the object
- * and the pack directories.
- */
-static void remove_temporary_files(const char *path)
-{
-	DIR *dir;
-	struct dirent *de;
-
-	dir = opendir(path);
-	if (!dir) {
-		fprintf(stderr, "Unable to open directory %s\n", path);
-		return;
-	}
-	while ((de = readdir(dir)) != NULL)
-		if (starts_with(de->d_name, "tmp_"))
-			prune_tmp_file(mkpath("%s/%s", path, de->d_name));
-	closedir(dir);
-}
-
-int cmd_prune(int argc, const char **argv, const char *prefix)
-{
-	struct rev_info revs;
-	int exclude_promisor_objects = 0;
-	const struct option options[] = {
-		OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
-		OPT__VERBOSE(&verbose, N_("report pruned objects")),
-		OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
-		OPT_EXPIRY_DATE(0, "expire", &expire,
-				N_("expire objects older than <time>")),
-		OPT_BOOL(0, "exclude-promisor-objects", &exclude_promisor_objects,
-			 N_("limit traversal to objects outside promisor packfiles")),
-		OPT_END()
-	};
-	char *s;
-
-	expire = TIME_MAX;
-	save_commit_buffer = 0;
-	read_replace_refs = 0;
-	ref_paranoia = 1;
-	repo_init_revisions(the_repository, &revs, prefix);
-
-	argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
-
-	if (repository_format_precious_objects)
-		die(_("cannot prune in a precious-objects repo"));
-
-	while (argc--) {
-		struct object_id oid;
-		const char *name = *argv++;
-
-		if (!get_oid(name, &oid)) {
-			struct object *object = parse_object_or_die(&oid,
-								    name);
-			add_pending_object(&revs, object, "");
-		}
-		else
-			die("unrecognized argument: %s", name);
-	}
-
-	if (show_progress == -1)
-		show_progress = isatty(2);
-	if (exclude_promisor_objects) {
-		fetch_if_missing = 0;
-		revs.exclude_promisor_objects = 1;
-	}
-
-	for_each_loose_file_in_objdir(get_object_directory(), prune_object,
-				      prune_cruft, prune_subdir, &revs);
-
-	prune_packed_objects(show_only ? PRUNE_PACKED_DRY_RUN : 0);
-	remove_temporary_files(get_object_directory());
-	s = mkpathdup("%s/pack", get_object_directory());
-	remove_temporary_files(s);
-	free(s);
-
-	if (is_repository_shallow(the_repository)) {
-		perform_reachability_traversal(&revs);
-		prune_shallow(show_only ? PRUNE_SHOW_ONLY : 0);
-	}
-
-	return 0;
-}
diff --git a/third_party/git/builtin/pull.c b/third_party/git/builtin/pull.c
deleted file mode 100644
index 425950f46973..000000000000
--- a/third_party/git/builtin/pull.c
+++ /dev/null
@@ -1,1051 +0,0 @@
-/*
- * Builtin "git pull"
- *
- * Based on git-pull.sh by Junio C Hamano
- *
- * Fetch one or more remote refs and merge it/them into the current HEAD.
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "config.h"
-#include "builtin.h"
-#include "parse-options.h"
-#include "exec-cmd.h"
-#include "run-command.h"
-#include "oid-array.h"
-#include "remote.h"
-#include "dir.h"
-#include "rebase.h"
-#include "refs.h"
-#include "refspec.h"
-#include "revision.h"
-#include "submodule.h"
-#include "submodule-config.h"
-#include "tempfile.h"
-#include "lockfile.h"
-#include "wt-status.h"
-#include "commit-reach.h"
-#include "sequencer.h"
-
-/**
- * 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
- * "merges", returns REBASE_MERGES. If value is "preserve", returns
- * REBASE_PRESERVE. If value is a invalid value, dies with a fatal error if
- * fatal is true, otherwise returns REBASE_INVALID.
- */
-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;
-
-	if (fatal)
-		die(_("Invalid value for %s: %s"), key, value);
-	else
-		error(_("Invalid value for %s: %s"), key, value);
-
-	return REBASE_INVALID;
-}
-
-/**
- * Callback for --rebase, which parses arg with parse_config_rebase().
- */
-static int parse_opt_rebase(const struct option *opt, const char *arg, int unset)
-{
-	enum rebase_type *value = opt->value;
-
-	if (arg)
-		*value = parse_config_rebase("--rebase", arg, 0);
-	else
-		*value = unset ? REBASE_FALSE : REBASE_TRUE;
-	return *value == REBASE_INVALID ? -1 : 0;
-}
-
-static const char * const pull_usage[] = {
-	N_("git pull [<options>] [<repository> [<refspec>...]]"),
-	NULL
-};
-
-/* Shared options */
-static int opt_verbosity;
-static char *opt_progress;
-static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
-
-/* Options passed to git-merge or git-rebase */
-static enum rebase_type opt_rebase = -1;
-static char *opt_diffstat;
-static char *opt_log;
-static char *opt_signoff;
-static char *opt_squash;
-static char *opt_commit;
-static char *opt_edit;
-static char *cleanup_arg;
-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 strvec opt_strategies = STRVEC_INIT;
-static struct strvec opt_strategy_opts = STRVEC_INIT;
-static char *opt_gpg_sign;
-static int opt_allow_unrelated_histories;
-
-/* Options passed to git-fetch */
-static char *opt_all;
-static char *opt_append;
-static char *opt_upload_pack;
-static int opt_force;
-static char *opt_tags;
-static char *opt_prune;
-static char *max_children;
-static int opt_dry_run;
-static char *opt_keep;
-static char *opt_depth;
-static char *opt_unshallow;
-static char *opt_update_shallow;
-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 strvec opt_fetch = STRVEC_INIT;
-
-static struct option pull_options[] = {
-	/* Shared options */
-	OPT__VERBOSITY(&opt_verbosity),
-	OPT_PASSTHRU(0, "progress", &opt_progress, NULL,
-		N_("force progress reporting"),
-		PARSE_OPT_NOARG),
-	OPT_CALLBACK_F(0, "recurse-submodules",
-		   &recurse_submodules, N_("on-demand"),
-		   N_("control for recursive fetching of submodules"),
-		   PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules),
-
-	/* Options passed to git-merge or git-rebase */
-	OPT_GROUP(N_("Options related to merging")),
-	OPT_CALLBACK_F('r', "rebase", &opt_rebase,
-	  "(false|true|merges|preserve|interactive)",
-	  N_("incorporate changes by rebasing rather than merging"),
-	  PARSE_OPT_OPTARG, parse_opt_rebase),
-	OPT_PASSTHRU('n', NULL, &opt_diffstat, NULL,
-		N_("do not show a diffstat at the end of the merge"),
-		PARSE_OPT_NOARG | PARSE_OPT_NONEG),
-	OPT_PASSTHRU(0, "stat", &opt_diffstat, NULL,
-		N_("show a diffstat at the end of the merge"),
-		PARSE_OPT_NOARG),
-	OPT_PASSTHRU(0, "summary", &opt_diffstat, NULL,
-		N_("(synonym to --stat)"),
-		PARSE_OPT_NOARG | PARSE_OPT_HIDDEN),
-	OPT_PASSTHRU(0, "log", &opt_log, N_("n"),
-		N_("add (at most <n>) entries from shortlog to merge commit message"),
-		PARSE_OPT_OPTARG),
-	OPT_PASSTHRU(0, "signoff", &opt_signoff, NULL,
-		N_("add Signed-off-by:"),
-		PARSE_OPT_OPTARG),
-	OPT_PASSTHRU(0, "squash", &opt_squash, NULL,
-		N_("create a single commit instead of doing a merge"),
-		PARSE_OPT_NOARG),
-	OPT_PASSTHRU(0, "commit", &opt_commit, NULL,
-		N_("perform a commit if the merge succeeds (default)"),
-		PARSE_OPT_NOARG),
-	OPT_PASSTHRU(0, "edit", &opt_edit, NULL,
-		N_("edit message before committing"),
-		PARSE_OPT_NOARG),
-	OPT_CLEANUP(&cleanup_arg),
-	OPT_PASSTHRU(0, "ff", &opt_ff, NULL,
-		N_("allow fast-forward"),
-		PARSE_OPT_NOARG),
-	OPT_PASSTHRU(0, "ff-only", &opt_ff, NULL,
-		N_("abort if fast-forward is not possible"),
-		PARSE_OPT_NOARG | PARSE_OPT_NONEG),
-	OPT_PASSTHRU(0, "verify-signatures", &opt_verify_signatures, NULL,
-		N_("verify that the named commit has a valid GPG signature"),
-		PARSE_OPT_NOARG),
-	OPT_BOOL(0, "autostash", &opt_autostash,
-		N_("automatically stash/stash pop before and after")),
-	OPT_PASSTHRU_ARGV('s', "strategy", &opt_strategies, N_("strategy"),
-		N_("merge strategy to use"),
-		0),
-	OPT_PASSTHRU_ARGV('X', "strategy-option", &opt_strategy_opts,
-		N_("option=value"),
-		N_("option for selected merge strategy"),
-		0),
-	OPT_PASSTHRU('S', "gpg-sign", &opt_gpg_sign, N_("key-id"),
-		N_("GPG sign commit"),
-		PARSE_OPT_OPTARG),
-	OPT_SET_INT(0, "allow-unrelated-histories",
-		    &opt_allow_unrelated_histories,
-		    N_("allow merging unrelated histories"), 1),
-
-	/* Options passed to git-fetch */
-	OPT_GROUP(N_("Options related to fetching")),
-	OPT_PASSTHRU(0, "all", &opt_all, NULL,
-		N_("fetch from all remotes"),
-		PARSE_OPT_NOARG),
-	OPT_PASSTHRU('a', "append", &opt_append, NULL,
-		N_("append to .git/FETCH_HEAD instead of overwriting"),
-		PARSE_OPT_NOARG),
-	OPT_PASSTHRU(0, "upload-pack", &opt_upload_pack, N_("path"),
-		N_("path to upload pack on remote end"),
-		0),
-	OPT__FORCE(&opt_force, N_("force overwrite of local branch"), 0),
-	OPT_PASSTHRU('t', "tags", &opt_tags, NULL,
-		N_("fetch all tags and associated objects"),
-		PARSE_OPT_NOARG),
-	OPT_PASSTHRU('p', "prune", &opt_prune, NULL,
-		N_("prune remote-tracking branches no longer on remote"),
-		PARSE_OPT_NOARG),
-	OPT_PASSTHRU('j', "jobs", &max_children, N_("n"),
-		N_("number of submodules pulled in parallel"),
-		PARSE_OPT_OPTARG),
-	OPT_BOOL(0, "dry-run", &opt_dry_run,
-		N_("dry run")),
-	OPT_PASSTHRU('k', "keep", &opt_keep, NULL,
-		N_("keep downloaded pack"),
-		PARSE_OPT_NOARG),
-	OPT_PASSTHRU(0, "depth", &opt_depth, N_("depth"),
-		N_("deepen history of shallow clone"),
-		0),
-	OPT_PASSTHRU_ARGV(0, "shallow-since", &opt_fetch, N_("time"),
-		N_("deepen history of shallow repository based on time"),
-		0),
-	OPT_PASSTHRU_ARGV(0, "shallow-exclude", &opt_fetch, N_("revision"),
-		N_("deepen history of shallow clone, excluding rev"),
-		0),
-	OPT_PASSTHRU_ARGV(0, "deepen", &opt_fetch, N_("n"),
-		N_("deepen history of shallow clone"),
-		0),
-	OPT_PASSTHRU(0, "unshallow", &opt_unshallow, NULL,
-		N_("convert to a complete repository"),
-		PARSE_OPT_NONEG | PARSE_OPT_NOARG),
-	OPT_PASSTHRU(0, "update-shallow", &opt_update_shallow, NULL,
-		N_("accept refs that update .git/shallow"),
-		PARSE_OPT_NOARG),
-	OPT_PASSTHRU(0, "refmap", &opt_refmap, N_("refmap"),
-		N_("specify fetch refmap"),
-		PARSE_OPT_NONEG),
-	OPT_PASSTHRU_ARGV('o', "server-option", &opt_fetch,
-		N_("server-specific"),
-		N_("option to transmit"),
-		0),
-	OPT_PASSTHRU('4',  "ipv4", &opt_ipv4, NULL,
-		N_("use IPv4 addresses only"),
-		PARSE_OPT_NOARG),
-	OPT_PASSTHRU('6',  "ipv6", &opt_ipv6, NULL,
-		N_("use IPv6 addresses only"),
-		PARSE_OPT_NOARG),
-	OPT_PASSTHRU_ARGV(0, "negotiation-tip", &opt_fetch, N_("revision"),
-		N_("report that we have only objects reachable from this object"),
-		0),
-	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()
-};
-
-/**
- * Pushes "-q" or "-v" switches into arr to match the opt_verbosity level.
- */
-static void argv_push_verbosity(struct strvec *arr)
-{
-	int verbosity;
-
-	for (verbosity = opt_verbosity; verbosity > 0; verbosity--)
-		strvec_push(arr, "-v");
-
-	for (verbosity = opt_verbosity; verbosity < 0; verbosity++)
-		strvec_push(arr, "-q");
-}
-
-/**
- * Pushes "-f" switches into arr to match the opt_force level.
- */
-static void argv_push_force(struct strvec *arr)
-{
-	int force = opt_force;
-	while (force-- > 0)
-		strvec_push(arr, "-f");
-}
-
-/**
- * Sets the GIT_REFLOG_ACTION environment variable to the concatenation of argv
- */
-static void set_reflog_message(int argc, const char **argv)
-{
-	int i;
-	struct strbuf msg = STRBUF_INIT;
-
-	for (i = 0; i < argc; i++) {
-		if (i)
-			strbuf_addch(&msg, ' ');
-		strbuf_addstr(&msg, argv[i]);
-	}
-
-	setenv("GIT_REFLOG_ACTION", msg.buf, 0);
-
-	strbuf_release(&msg);
-}
-
-/**
- * If pull.ff is unset, returns NULL. If pull.ff is "true", returns "--ff". If
- * pull.ff is "false", returns "--no-ff". If pull.ff is "only", returns
- * "--ff-only". Otherwise, if pull.ff is set to an invalid value, die with an
- * error.
- */
-static const char *config_get_ff(void)
-{
-	const char *value;
-
-	if (git_config_get_value("pull.ff", &value))
-		return NULL;
-
-	switch (git_parse_maybe_bool(value)) {
-	case 0:
-		return "--no-ff";
-	case 1:
-		return "--ff";
-	}
-
-	if (!strcmp(value, "only"))
-		return "--ff-only";
-
-	die(_("Invalid value for pull.ff: %s"), value);
-}
-
-/**
- * Returns the default configured value for --rebase. It first looks for the
- * value of "branch.$curr_branch.rebase", where $curr_branch is the current
- * branch, and if HEAD is detached or the configuration key does not exist,
- * looks for the value of "pull.rebase". If both configuration keys do not
- * exist, returns REBASE_FALSE.
- */
-static enum rebase_type config_get_rebase(void)
-{
-	struct branch *curr_branch = branch_get("HEAD");
-	const char *value;
-
-	if (curr_branch) {
-		char *key = xstrfmt("branch.%s.rebase", curr_branch->name);
-
-		if (!git_config_get_value(key, &value)) {
-			enum rebase_type ret = parse_config_rebase(key, value, 1);
-			free(key);
-			return ret;
-		}
-
-		free(key);
-	}
-
-	if (!git_config_get_value("pull.rebase", &value))
-		return parse_config_rebase("pull.rebase", value, 1);
-
-	if (opt_verbosity >= 0 && !opt_ff) {
-		warning(_("Pulling without specifying how to reconcile divergent branches is\n"
-			"discouraged. You can squelch this message by running one of the following\n"
-			"commands sometime before your next pull:\n"
-			"\n"
-			"  git config pull.rebase false  # merge (the default strategy)\n"
-			"  git config pull.rebase true   # rebase\n"
-			"  git config pull.ff only       # fast-forward only\n"
-			"\n"
-			"You can replace \"git config\" with \"git config --global\" to set a default\n"
-			"preference for all repositories. You can also pass --rebase, --no-rebase,\n"
-			"or --ff-only on the command line to override the configured default per\n"
-			"invocation.\n"));
-	}
-
-	return REBASE_FALSE;
-}
-
-/**
- * Read config variables.
- */
-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;
-	} else if (!strcmp(var, "submodule.recurse")) {
-		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);
-}
-
-/**
- * Appends merge candidates from FETCH_HEAD that are not marked not-for-merge
- * into merge_heads.
- */
-static void get_merge_heads(struct oid_array *merge_heads)
-{
-	const char *filename = git_path_fetch_head(the_repository);
-	FILE *fp;
-	struct strbuf sb = STRBUF_INIT;
-	struct object_id oid;
-
-	fp = xfopen(filename, "r");
-	while (strbuf_getline_lf(&sb, fp) != EOF) {
-		const char *p;
-		if (parse_oid_hex(sb.buf, &oid, &p))
-			continue;  /* invalid line: does not start with object ID */
-		if (starts_with(p, "\tnot-for-merge\t"))
-			continue;  /* ref is not-for-merge */
-		oid_array_append(merge_heads, &oid);
-	}
-	fclose(fp);
-	strbuf_release(&sb);
-}
-
-/**
- * Used by die_no_merge_candidates() as a for_each_remote() callback to
- * retrieve the name of the remote if the repository only has one remote.
- */
-static int get_only_remote(struct remote *remote, void *cb_data)
-{
-	const char **remote_name = cb_data;
-
-	if (*remote_name)
-		return -1;
-
-	*remote_name = remote->name;
-	return 0;
-}
-
-/**
- * Dies with the appropriate reason for why there are no merge candidates:
- *
- * 1. We fetched from a specific remote, and a refspec was given, but it ended
- *    up not fetching anything. This is usually because the user provided a
- *    wildcard refspec which had no matches on the remote end.
- *
- * 2. We fetched from a non-default remote, but didn't specify a branch to
- *    merge. We can't use the configured one because it applies to the default
- *    remote, thus the user must specify the branches to merge.
- *
- * 3. We fetched from the branch's or repo's default remote, but:
- *
- *    a. We are not on a branch, so there will never be a configured branch to
- *       merge with.
- *
- *    b. We are on a branch, but there is no configured branch to merge with.
- *
- * 4. We fetched from the branch's or repo's default remote, but the configured
- *    branch to merge didn't get fetched. (Either it doesn't exist, or wasn't
- *    part of the configured fetch refspec.)
- */
-static void NORETURN die_no_merge_candidates(const char *repo, const char **refspecs)
-{
-	struct branch *curr_branch = branch_get("HEAD");
-	const char *remote = curr_branch ? curr_branch->remote_name : NULL;
-
-	if (*refspecs) {
-		if (opt_rebase)
-			fprintf_ln(stderr, _("There is no candidate for rebasing against among the refs that you just fetched."));
-		else
-			fprintf_ln(stderr, _("There are no candidates for merging among the refs that you just fetched."));
-		fprintf_ln(stderr, _("Generally this means that you provided a wildcard refspec which had no\n"
-					"matches on the remote end."));
-	} else if (repo && curr_branch && (!remote || strcmp(repo, remote))) {
-		fprintf_ln(stderr, _("You asked to pull from the remote '%s', but did not specify\n"
-			"a branch. Because this is not the default configured remote\n"
-			"for your current branch, you must specify a branch on the command line."),
-			repo);
-	} else if (!curr_branch) {
-		fprintf_ln(stderr, _("You are not currently on a branch."));
-		if (opt_rebase)
-			fprintf_ln(stderr, _("Please specify which branch you want to rebase against."));
-		else
-			fprintf_ln(stderr, _("Please specify which branch you want to merge with."));
-		fprintf_ln(stderr, _("See git-pull(1) for details."));
-		fprintf(stderr, "\n");
-		fprintf_ln(stderr, "    git pull %s %s", _("<remote>"), _("<branch>"));
-		fprintf(stderr, "\n");
-	} else if (!curr_branch->merge_nr) {
-		const char *remote_name = NULL;
-
-		if (for_each_remote(get_only_remote, &remote_name) || !remote_name)
-			remote_name = _("<remote>");
-
-		fprintf_ln(stderr, _("There is no tracking information for the current branch."));
-		if (opt_rebase)
-			fprintf_ln(stderr, _("Please specify which branch you want to rebase against."));
-		else
-			fprintf_ln(stderr, _("Please specify which branch you want to merge with."));
-		fprintf_ln(stderr, _("See git-pull(1) for details."));
-		fprintf(stderr, "\n");
-		fprintf_ln(stderr, "    git pull %s %s", _("<remote>"), _("<branch>"));
-		fprintf(stderr, "\n");
-		fprintf_ln(stderr, _("If you wish to set tracking information for this branch you can do so with:"));
-		fprintf(stderr, "\n");
-		fprintf_ln(stderr, "    git branch --set-upstream-to=%s/%s %s\n",
-				remote_name, _("<branch>"), curr_branch->name);
-	} else
-		fprintf_ln(stderr, _("Your configuration specifies to merge with the ref '%s'\n"
-			"from the remote, but no such ref was fetched."),
-			*curr_branch->merge_name);
-	exit(1);
-}
-
-/**
- * Parses argv into [<repo> [<refspecs>...]], returning their values in `repo`
- * as a string and `refspecs` as a null-terminated array of strings. If `repo`
- * is not provided in argv, it is set to NULL.
- */
-static void parse_repo_refspecs(int argc, const char **argv, const char **repo,
-		const char ***refspecs)
-{
-	if (argc > 0) {
-		*repo = *argv++;
-		argc--;
-	} else
-		*repo = NULL;
-	*refspecs = argv;
-}
-
-/**
- * Runs git-fetch, returning its exit status. `repo` and `refspecs` are the
- * repository and refspecs to fetch, or NULL if they are not provided.
- */
-static int run_fetch(const char *repo, const char **refspecs)
-{
-	struct strvec args = STRVEC_INIT;
-	int ret;
-
-	strvec_pushl(&args, "fetch", "--update-head-ok", NULL);
-
-	/* Shared options */
-	argv_push_verbosity(&args);
-	if (opt_progress)
-		strvec_push(&args, opt_progress);
-
-	/* Options passed to git-fetch */
-	if (opt_all)
-		strvec_push(&args, opt_all);
-	if (opt_append)
-		strvec_push(&args, opt_append);
-	if (opt_upload_pack)
-		strvec_push(&args, opt_upload_pack);
-	argv_push_force(&args);
-	if (opt_tags)
-		strvec_push(&args, opt_tags);
-	if (opt_prune)
-		strvec_push(&args, opt_prune);
-	if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT)
-		switch (recurse_submodules) {
-		case RECURSE_SUBMODULES_ON:
-			strvec_push(&args, "--recurse-submodules=on");
-			break;
-		case RECURSE_SUBMODULES_OFF:
-			strvec_push(&args, "--recurse-submodules=no");
-			break;
-		case RECURSE_SUBMODULES_ON_DEMAND:
-			strvec_push(&args, "--recurse-submodules=on-demand");
-			break;
-		default:
-			BUG("submodule recursion option not understood");
-		}
-	if (max_children)
-		strvec_push(&args, max_children);
-	if (opt_dry_run)
-		strvec_push(&args, "--dry-run");
-	if (opt_keep)
-		strvec_push(&args, opt_keep);
-	if (opt_depth)
-		strvec_push(&args, opt_depth);
-	if (opt_unshallow)
-		strvec_push(&args, opt_unshallow);
-	if (opt_update_shallow)
-		strvec_push(&args, opt_update_shallow);
-	if (opt_refmap)
-		strvec_push(&args, opt_refmap);
-	if (opt_ipv4)
-		strvec_push(&args, opt_ipv4);
-	if (opt_ipv6)
-		strvec_push(&args, opt_ipv6);
-	if (opt_show_forced_updates > 0)
-		strvec_push(&args, "--show-forced-updates");
-	else if (opt_show_forced_updates == 0)
-		strvec_push(&args, "--no-show-forced-updates");
-	if (set_upstream)
-		strvec_push(&args, set_upstream);
-	strvec_pushv(&args, opt_fetch.v);
-
-	if (repo) {
-		strvec_push(&args, repo);
-		strvec_pushv(&args, refspecs);
-	} else if (*refspecs)
-		BUG("refspecs without repo?");
-	ret = run_command_v_opt(args.v, RUN_GIT_CMD);
-	strvec_clear(&args);
-	return ret;
-}
-
-/**
- * "Pulls into void" by branching off merge_head.
- */
-static int pull_into_void(const struct object_id *merge_head,
-		const struct object_id *curr_head)
-{
-	if (opt_verify_signatures) {
-		struct commit *commit;
-
-		commit = lookup_commit(the_repository, merge_head);
-		if (!commit)
-			die(_("unable to access commit %s"),
-			    oid_to_hex(merge_head));
-
-		verify_merge_signature(commit, opt_verbosity,
-				       check_trust_level);
-	}
-
-	/*
-	 * Two-way merge: we treat the index as based on an empty tree,
-	 * and try to fast-forward to HEAD. This ensures we will not lose
-	 * index/worktree changes that the user already made on the unborn
-	 * branch.
-	 */
-	if (checkout_fast_forward(the_repository,
-				  the_hash_algo->empty_tree,
-				  merge_head, 0))
-		return 1;
-
-	if (update_ref("initial pull", "HEAD", merge_head, curr_head, 0, UPDATE_REFS_DIE_ON_ERR))
-		return 1;
-
-	return 0;
-}
-
-static int rebase_submodules(void)
-{
-	struct child_process cp = CHILD_PROCESS_INIT;
-
-	cp.git_cmd = 1;
-	cp.no_stdin = 1;
-	strvec_pushl(&cp.args, "submodule", "update",
-		     "--recursive", "--rebase", NULL);
-	argv_push_verbosity(&cp.args);
-
-	return run_command(&cp);
-}
-
-static int update_submodules(void)
-{
-	struct child_process cp = CHILD_PROCESS_INIT;
-
-	cp.git_cmd = 1;
-	cp.no_stdin = 1;
-	strvec_pushl(&cp.args, "submodule", "update",
-		     "--recursive", "--checkout", NULL);
-	argv_push_verbosity(&cp.args);
-
-	return run_command(&cp);
-}
-
-/**
- * Runs git-merge, returning its exit status.
- */
-static int run_merge(void)
-{
-	int ret;
-	struct strvec args = STRVEC_INIT;
-
-	strvec_pushl(&args, "merge", NULL);
-
-	/* Shared options */
-	argv_push_verbosity(&args);
-	if (opt_progress)
-		strvec_push(&args, opt_progress);
-
-	/* Options passed to git-merge */
-	if (opt_diffstat)
-		strvec_push(&args, opt_diffstat);
-	if (opt_log)
-		strvec_push(&args, opt_log);
-	if (opt_signoff)
-		strvec_push(&args, opt_signoff);
-	if (opt_squash)
-		strvec_push(&args, opt_squash);
-	if (opt_commit)
-		strvec_push(&args, opt_commit);
-	if (opt_edit)
-		strvec_push(&args, opt_edit);
-	if (cleanup_arg)
-		strvec_pushf(&args, "--cleanup=%s", cleanup_arg);
-	if (opt_ff)
-		strvec_push(&args, opt_ff);
-	if (opt_verify_signatures)
-		strvec_push(&args, opt_verify_signatures);
-	strvec_pushv(&args, opt_strategies.v);
-	strvec_pushv(&args, opt_strategy_opts.v);
-	if (opt_gpg_sign)
-		strvec_push(&args, opt_gpg_sign);
-	if (opt_autostash == 0)
-		strvec_push(&args, "--no-autostash");
-	else if (opt_autostash == 1)
-		strvec_push(&args, "--autostash");
-	if (opt_allow_unrelated_histories > 0)
-		strvec_push(&args, "--allow-unrelated-histories");
-
-	strvec_push(&args, "FETCH_HEAD");
-	ret = run_command_v_opt(args.v, RUN_GIT_CMD);
-	strvec_clear(&args);
-	return ret;
-}
-
-/**
- * Returns remote's upstream branch for the current branch. If remote is NULL,
- * the current branch's configured default remote is used. Returns NULL if
- * `remote` does not name a valid remote, HEAD does not point to a branch,
- * remote is not the branch's configured remote or the branch does not have any
- * configured upstream branch.
- */
-static const char *get_upstream_branch(const char *remote)
-{
-	struct remote *rm;
-	struct branch *curr_branch;
-	const char *curr_branch_remote;
-
-	rm = remote_get(remote);
-	if (!rm)
-		return NULL;
-
-	curr_branch = branch_get("HEAD");
-	if (!curr_branch)
-		return NULL;
-
-	curr_branch_remote = remote_for_branch(curr_branch, NULL);
-	assert(curr_branch_remote);
-
-	if (strcmp(curr_branch_remote, rm->name))
-		return NULL;
-
-	return branch_get_upstream(curr_branch, NULL);
-}
-
-/**
- * Derives the remote-tracking branch from the remote and refspec.
- *
- * FIXME: The current implementation assumes the default mapping of
- * refs/heads/<branch_name> to refs/remotes/<remote_name>/<branch_name>.
- */
-static const char *get_tracking_branch(const char *remote, const char *refspec)
-{
-	struct refspec_item spec;
-	const char *spec_src;
-	const char *merge_branch;
-
-	refspec_item_init_or_die(&spec, refspec, REFSPEC_FETCH);
-	spec_src = spec.src;
-	if (!*spec_src || !strcmp(spec_src, "HEAD"))
-		spec_src = "HEAD";
-	else if (skip_prefix(spec_src, "heads/", &spec_src))
-		;
-	else if (skip_prefix(spec_src, "refs/heads/", &spec_src))
-		;
-	else if (starts_with(spec_src, "refs/") ||
-		starts_with(spec_src, "tags/") ||
-		starts_with(spec_src, "remotes/"))
-		spec_src = "";
-
-	if (*spec_src) {
-		if (!strcmp(remote, "."))
-			merge_branch = mkpath("refs/heads/%s", spec_src);
-		else
-			merge_branch = mkpath("refs/remotes/%s/%s", remote, spec_src);
-	} else
-		merge_branch = NULL;
-
-	refspec_item_clear(&spec);
-	return merge_branch;
-}
-
-/**
- * Given the repo and refspecs, sets fork_point to the point at which the
- * current branch forked from its remote-tracking branch. Returns 0 on success,
- * -1 on failure.
- */
-static int get_rebase_fork_point(struct object_id *fork_point, const char *repo,
-		const char *refspec)
-{
-	int ret;
-	struct branch *curr_branch;
-	const char *remote_branch;
-	struct child_process cp = CHILD_PROCESS_INIT;
-	struct strbuf sb = STRBUF_INIT;
-
-	curr_branch = branch_get("HEAD");
-	if (!curr_branch)
-		return -1;
-
-	if (refspec)
-		remote_branch = get_tracking_branch(repo, refspec);
-	else
-		remote_branch = get_upstream_branch(repo);
-
-	if (!remote_branch)
-		return -1;
-
-	strvec_pushl(&cp.args, "merge-base", "--fork-point",
-		     remote_branch, curr_branch->name, NULL);
-	cp.no_stdin = 1;
-	cp.no_stderr = 1;
-	cp.git_cmd = 1;
-
-	ret = capture_command(&cp, &sb, GIT_MAX_HEXSZ);
-	if (ret)
-		goto cleanup;
-
-	ret = get_oid_hex(sb.buf, fork_point);
-	if (ret)
-		goto cleanup;
-
-cleanup:
-	strbuf_release(&sb);
-	return ret ? -1 : 0;
-}
-
-/**
- * Sets merge_base to the octopus merge base of curr_head, merge_head and
- * fork_point. Returns 0 if a merge base is found, 1 otherwise.
- */
-static int get_octopus_merge_base(struct object_id *merge_base,
-		const struct object_id *curr_head,
-		const struct object_id *merge_head,
-		const struct object_id *fork_point)
-{
-	struct commit_list *revs = NULL, *result;
-
-	commit_list_insert(lookup_commit_reference(the_repository, curr_head),
-			   &revs);
-	commit_list_insert(lookup_commit_reference(the_repository, merge_head),
-			   &revs);
-	if (!is_null_oid(fork_point))
-		commit_list_insert(lookup_commit_reference(the_repository, fork_point),
-				   &revs);
-
-	result = get_octopus_merge_bases(revs);
-	free_commit_list(revs);
-	reduce_heads_replace(&result);
-
-	if (!result)
-		return 1;
-
-	oidcpy(merge_base, &result->item->object.oid);
-	free_commit_list(result);
-	return 0;
-}
-
-/**
- * Given the current HEAD oid, the merge head returned from git-fetch and the
- * fork point calculated by get_rebase_fork_point(), runs git-rebase with the
- * appropriate arguments and returns its exit status.
- */
-static int run_rebase(const struct object_id *curr_head,
-		const struct object_id *merge_head,
-		const struct object_id *fork_point)
-{
-	int ret;
-	struct object_id oct_merge_base;
-	struct strvec args = STRVEC_INIT;
-
-	if (!get_octopus_merge_base(&oct_merge_base, curr_head, merge_head, fork_point))
-		if (!is_null_oid(fork_point) && oideq(&oct_merge_base, fork_point))
-			fork_point = NULL;
-
-	strvec_push(&args, "rebase");
-
-	/* Shared options */
-	argv_push_verbosity(&args);
-
-	/* Options passed to git-rebase */
-	if (opt_rebase == REBASE_MERGES)
-		strvec_push(&args, "--rebase-merges");
-	else if (opt_rebase == REBASE_PRESERVE)
-		strvec_push(&args, "--preserve-merges");
-	else if (opt_rebase == REBASE_INTERACTIVE)
-		strvec_push(&args, "--interactive");
-	if (opt_diffstat)
-		strvec_push(&args, opt_diffstat);
-	strvec_pushv(&args, opt_strategies.v);
-	strvec_pushv(&args, opt_strategy_opts.v);
-	if (opt_gpg_sign)
-		strvec_push(&args, opt_gpg_sign);
-	if (opt_autostash == 0)
-		strvec_push(&args, "--no-autostash");
-	else if (opt_autostash == 1)
-		strvec_push(&args, "--autostash");
-	if (opt_verify_signatures &&
-	    !strcmp(opt_verify_signatures, "--verify-signatures"))
-		warning(_("ignoring --verify-signatures for rebase"));
-
-	strvec_push(&args, "--onto");
-	strvec_push(&args, oid_to_hex(merge_head));
-
-	if (fork_point && !is_null_oid(fork_point))
-		strvec_push(&args, oid_to_hex(fork_point));
-	else
-		strvec_push(&args, oid_to_hex(merge_head));
-
-	ret = run_command_v_opt(args.v, RUN_GIT_CMD);
-	strvec_clear(&args);
-	return ret;
-}
-
-int cmd_pull(int argc, const char **argv, const char *prefix)
-{
-	const char *repo, **refspecs;
-	struct oid_array merge_heads = OID_ARRAY_INIT;
-	struct object_id orig_head, curr_head;
-	struct object_id rebase_fork_point;
-	int autostash;
-
-	if (!getenv("GIT_REFLOG_ACTION"))
-		set_reflog_message(argc, argv);
-
-	git_config(git_pull_config, NULL);
-
-	argc = parse_options(argc, argv, prefix, pull_options, pull_usage, 0);
-
-	if (cleanup_arg)
-		/*
-		 * this only checks the validity of cleanup_arg; we don't need
-		 * a valid value for use_editor
-		 */
-		get_cleanup_mode(cleanup_arg, 0);
-
-	parse_repo_refspecs(argc, argv, &repo, &refspecs);
-
-	if (!opt_ff)
-		opt_ff = xstrdup_or_null(config_get_ff());
-
-	if (opt_rebase < 0)
-		opt_rebase = config_get_rebase();
-
-	if (read_cache_unmerged())
-		die_resolve_conflict("pull");
-
-	if (file_exists(git_path_merge_head(the_repository)))
-		die_conclude_merge();
-
-	if (get_oid("HEAD", &orig_head))
-		oidclr(&orig_head);
-
-	autostash = config_autostash;
-	if (opt_rebase) {
-		if (opt_autostash != -1)
-			autostash = opt_autostash;
-
-		if (is_null_oid(&orig_head) && !is_cache_unborn())
-			die(_("Updating an unborn branch with changes added to the index."));
-
-		if (!autostash)
-			require_clean_work_tree(the_repository,
-				N_("pull with rebase"),
-				_("please commit or stash them."), 1, 0);
-
-		if (get_rebase_fork_point(&rebase_fork_point, repo, *refspecs))
-			oidclr(&rebase_fork_point);
-	}
-
-	if (run_fetch(repo, refspecs))
-		return 1;
-
-	if (opt_dry_run)
-		return 0;
-
-	if (get_oid("HEAD", &curr_head))
-		oidclr(&curr_head);
-
-	if (!is_null_oid(&orig_head) && !is_null_oid(&curr_head) &&
-			!oideq(&orig_head, &curr_head)) {
-		/*
-		 * The fetch involved updating the current branch.
-		 *
-		 * The working tree and the index file are still based on
-		 * orig_head commit, but we are merging into curr_head.
-		 * Update the working tree to match curr_head.
-		 */
-
-		warning(_("fetch updated the current branch head.\n"
-			"fast-forwarding your working tree from\n"
-			"commit %s."), oid_to_hex(&orig_head));
-
-		if (checkout_fast_forward(the_repository, &orig_head,
-					  &curr_head, 0))
-			die(_("Cannot fast-forward your working tree.\n"
-				"After making sure that you saved anything precious from\n"
-				"$ git diff %s\n"
-				"output, run\n"
-				"$ git reset --hard\n"
-				"to recover."), oid_to_hex(&orig_head));
-	}
-
-	get_merge_heads(&merge_heads);
-
-	if (!merge_heads.nr)
-		die_no_merge_candidates(repo, refspecs);
-
-	if (is_null_oid(&orig_head)) {
-		if (merge_heads.nr > 1)
-			die(_("Cannot merge multiple branches into empty head."));
-		return pull_into_void(merge_heads.oid, &curr_head);
-	}
-	if (opt_rebase && merge_heads.nr > 1)
-		die(_("Cannot rebase onto multiple branches."));
-
-	if (opt_rebase) {
-		int ret = 0;
-		int ran_ff = 0;
-		if ((recurse_submodules == RECURSE_SUBMODULES_ON ||
-		     recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) &&
-		    submodule_touches_in_range(the_repository, &rebase_fork_point, &curr_head))
-			die(_("cannot rebase with locally recorded submodule modifications"));
-		if (!autostash) {
-			struct commit_list *list = NULL;
-			struct commit *merge_head, *head;
-
-			head = lookup_commit_reference(the_repository,
-						       &orig_head);
-			commit_list_insert(head, &list);
-			merge_head = lookup_commit_reference(the_repository,
-							     &merge_heads.oid[0]);
-			if (repo_is_descendant_of(the_repository,
-						  merge_head, list)) {
-				/* we can fast-forward this without invoking rebase */
-				opt_ff = "--ff-only";
-				ran_ff = 1;
-				ret = run_merge();
-			}
-			free_commit_list(list);
-		}
-		if (!ran_ff)
-			ret = run_rebase(&curr_head, merge_heads.oid, &rebase_fork_point);
-
-		if (!ret && (recurse_submodules == RECURSE_SUBMODULES_ON ||
-			     recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND))
-			ret = rebase_submodules();
-
-		return ret;
-	} else {
-		int ret = run_merge();
-		if (!ret && (recurse_submodules == RECURSE_SUBMODULES_ON ||
-			     recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND))
-			ret = update_submodules();
-		return ret;
-	}
-}
diff --git a/third_party/git/builtin/push.c b/third_party/git/builtin/push.c
deleted file mode 100644
index 6da3a8e5d30a..000000000000
--- a/third_party/git/builtin/push.c
+++ /dev/null
@@ -1,639 +0,0 @@
-/*
- * "git push"
- */
-#include "cache.h"
-#include "config.h"
-#include "refs.h"
-#include "refspec.h"
-#include "run-command.h"
-#include "builtin.h"
-#include "remote.h"
-#include "transport.h"
-#include "parse-options.h"
-#include "submodule.h"
-#include "submodule-config.h"
-#include "send-pack.h"
-#include "color.h"
-
-static const char * const push_usage[] = {
-	N_("git push [<options>] [<repository> [<refspec>...]]"),
-	NULL,
-};
-
-static int push_use_color = -1;
-static char push_colors[][COLOR_MAXLEN] = {
-	GIT_COLOR_RESET,
-	GIT_COLOR_RED,	/* ERROR */
-};
-
-enum color_push {
-	PUSH_COLOR_RESET = 0,
-	PUSH_COLOR_ERROR = 1
-};
-
-static int parse_push_color_slot(const char *slot)
-{
-	if (!strcasecmp(slot, "reset"))
-		return PUSH_COLOR_RESET;
-	if (!strcasecmp(slot, "error"))
-		return PUSH_COLOR_ERROR;
-	return -1;
-}
-
-static const char *push_get_color(enum color_push ix)
-{
-	if (want_color_stderr(push_use_color))
-		return push_colors[ix];
-	return "";
-}
-
-static int thin = 1;
-static int deleterefs;
-static const char *receivepack;
-static int verbosity;
-static int progress = -1;
-static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
-static enum transport_family family;
-
-static struct push_cas_option cas;
-
-static struct refspec rs = REFSPEC_INIT_PUSH;
-
-static struct string_list push_options_config = STRING_LIST_INIT_DUP;
-
-static void refspec_append_mapped(struct refspec *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? */
-	if (count_refspec_match(ref, local_refs, &matched) != 1) {
-		refspec_append(refspec, ref);
-		return;
-	}
-
-	if (remote->push.nr) {
-		struct refspec_item query;
-		memset(&query, 0, sizeof(struct refspec_item));
-		query.src = matched->name;
-		if (!query_refspecs(&remote->push, &query) && query.dst) {
-			refspec_appendf(refspec, "%s%s:%s",
-					query.force ? "+" : "",
-					query.src, query.dst);
-			return;
-		}
-	}
-
-	if (push_default == PUSH_DEFAULT_UPSTREAM &&
-	    skip_prefix(matched->name, "refs/heads/", &branch_name)) {
-		struct branch *branch = branch_get(branch_name);
-		if (branch->merge_nr == 1 && branch->merge[0]->src) {
-			refspec_appendf(refspec, "%s:%s",
-					ref, branch->merge[0]->src);
-			return;
-		}
-	}
-
-	refspec_append(refspec, ref);
-}
-
-static void set_refspecs(const char **refs, int nr, const char *repo)
-{
-	struct remote *remote = NULL;
-	struct ref *local_refs = NULL;
-	int i;
-
-	for (i = 0; i < nr; i++) {
-		const char *ref = refs[i];
-		if (!strcmp("tag", ref)) {
-			if (nr <= ++i)
-				die(_("tag shorthand without <tag>"));
-			ref = refs[i];
-			if (deleterefs)
-				refspec_appendf(&rs, ":refs/tags/%s", ref);
-			else
-				refspec_appendf(&rs, "refs/tags/%s", ref);
-		} else if (deleterefs) {
-			if (strchr(ref, ':'))
-				die(_("--delete only accepts plain target ref names"));
-			refspec_appendf(&rs, ":%s", ref);
-		} else if (!strchr(ref, ':')) {
-			if (!remote) {
-				/* lazily grab remote and local_refs */
-				remote = remote_get(repo);
-				local_refs = get_local_heads();
-			}
-			refspec_append_mapped(&rs, ref, remote, local_refs);
-		} else
-			refspec_append(&rs, ref);
-	}
-}
-
-static int push_url_of_remote(struct remote *remote, const char ***url_p)
-{
-	if (remote->pushurl_nr) {
-		*url_p = remote->pushurl;
-		return remote->pushurl_nr;
-	}
-	*url_p = remote->url;
-	return remote->url_nr;
-}
-
-static NORETURN void die_push_simple(struct branch *branch,
-				     struct remote *remote)
-{
-	/*
-	 * There's no point in using shorten_unambiguous_ref here,
-	 * as the ambiguity would be on the remote side, not what
-	 * we have locally. Plus, this is supposed to be the simple
-	 * mode. If the user is doing something crazy like setting
-	 * upstream to a non-branch, we should probably be showing
-	 * them the big ugly fully qualified ref.
-	 */
-	const char *advice_maybe = "";
-	const char *short_upstream = branch->merge[0]->src;
-
-	skip_prefix(short_upstream, "refs/heads/", &short_upstream);
-
-	/*
-	 * Don't show advice for people who explicitly set
-	 * push.default.
-	 */
-	if (push_default == PUSH_DEFAULT_UNSPECIFIED)
-		advice_maybe = _("\n"
-				 "To choose either option permanently, "
-				 "see push.default in 'git help config'.");
-	die(_("The upstream branch of your current branch does not match\n"
-	      "the name of your current branch.  To push to the upstream branch\n"
-	      "on the remote, use\n"
-	      "\n"
-	      "    git push %s HEAD:%s\n"
-	      "\n"
-	      "To push to the branch of the same name on the remote, use\n"
-	      "\n"
-	      "    git push %s HEAD\n"
-	      "%s"),
-	    remote->name, short_upstream,
-	    remote->name, advice_maybe);
-}
-
-static const char message_detached_head_die[] =
-	N_("You are not currently on a branch.\n"
-	   "To push the history leading to the current (detached HEAD)\n"
-	   "state now, use\n"
-	   "\n"
-	   "    git push %s HEAD:<name-of-remote-branch>\n");
-
-static void setup_push_upstream(struct remote *remote, struct branch *branch,
-				int triangular, int simple)
-{
-	if (!branch)
-		die(_(message_detached_head_die), remote->name);
-	if (!branch->merge_nr || !branch->merge || !branch->remote_name)
-		die(_("The current branch %s has no upstream branch.\n"
-		    "To push the current branch and set the remote as upstream, use\n"
-		    "\n"
-		    "    git push --set-upstream %s %s\n"),
-		    branch->name,
-		    remote->name,
-		    branch->name);
-	if (branch->merge_nr != 1)
-		die(_("The current branch %s has multiple upstream branches, "
-		    "refusing to push."), branch->name);
-	if (triangular)
-		die(_("You are pushing to remote '%s', which is not the upstream of\n"
-		      "your current branch '%s', without telling me what to push\n"
-		      "to update which remote branch."),
-		    remote->name, branch->name);
-
-	if (simple) {
-		/* Additional safety */
-		if (strcmp(branch->refname, branch->merge[0]->src))
-			die_push_simple(branch, remote);
-	}
-
-	refspec_appendf(&rs, "%s:%s", branch->refname, branch->merge[0]->src);
-}
-
-static void setup_push_current(struct remote *remote, struct branch *branch)
-{
-	if (!branch)
-		die(_(message_detached_head_die), remote->name);
-	refspec_appendf(&rs, "%s:%s", branch->refname, branch->refname);
-}
-
-static int is_workflow_triangular(struct remote *remote)
-{
-	struct remote *fetch_remote = remote_get(NULL);
-	return (fetch_remote && fetch_remote != remote);
-}
-
-static void setup_default_push_refspecs(struct remote *remote)
-{
-	struct branch *branch = branch_get(NULL);
-	int triangular = is_workflow_triangular(remote);
-
-	switch (push_default) {
-	default:
-	case PUSH_DEFAULT_MATCHING:
-		refspec_append(&rs, ":");
-		break;
-
-	case PUSH_DEFAULT_UNSPECIFIED:
-	case PUSH_DEFAULT_SIMPLE:
-		if (triangular)
-			setup_push_current(remote, branch);
-		else
-			setup_push_upstream(remote, branch, triangular, 1);
-		break;
-
-	case PUSH_DEFAULT_UPSTREAM:
-		setup_push_upstream(remote, branch, triangular, 0);
-		break;
-
-	case PUSH_DEFAULT_CURRENT:
-		setup_push_current(remote, branch);
-		break;
-
-	case PUSH_DEFAULT_NOTHING:
-		die(_("You didn't specify any refspecs to push, and "
-		    "push.default is \"nothing\"."));
-		break;
-	}
-}
-
-static const char message_advice_pull_before_push[] =
-	N_("Updates were rejected because the tip of your current branch is behind\n"
-	   "its remote counterpart. Integrate the remote changes (e.g.\n"
-	   "'git pull ...') before pushing again.\n"
-	   "See the 'Note about fast-forwards' in 'git push --help' for details.");
-
-static const char message_advice_checkout_pull_push[] =
-	N_("Updates were rejected because a pushed branch tip is behind its remote\n"
-	   "counterpart. Check out this branch and integrate the remote changes\n"
-	   "(e.g. 'git pull ...') before pushing again.\n"
-	   "See the 'Note about fast-forwards' in 'git push --help' for details.");
-
-static const char message_advice_ref_fetch_first[] =
-	N_("Updates were rejected because the remote contains work that you do\n"
-	   "not have locally. This is usually caused by another repository pushing\n"
-	   "to the same ref. You may want to first integrate the remote changes\n"
-	   "(e.g., 'git pull ...') before pushing again.\n"
-	   "See the 'Note about fast-forwards' in 'git push --help' for details.");
-
-static const char message_advice_ref_already_exists[] =
-	N_("Updates were rejected because the tag already exists in the remote.");
-
-static const char message_advice_ref_needs_force[] =
-	N_("You cannot update a remote ref that points at a non-commit object,\n"
-	   "or update a remote ref to make it point at a non-commit object,\n"
-	   "without using the '--force' option.\n");
-
-static void advise_pull_before_push(void)
-{
-	if (!advice_push_non_ff_current || !advice_push_update_rejected)
-		return;
-	advise(_(message_advice_pull_before_push));
-}
-
-static void advise_checkout_pull_push(void)
-{
-	if (!advice_push_non_ff_matching || !advice_push_update_rejected)
-		return;
-	advise(_(message_advice_checkout_pull_push));
-}
-
-static void advise_ref_already_exists(void)
-{
-	if (!advice_push_already_exists || !advice_push_update_rejected)
-		return;
-	advise(_(message_advice_ref_already_exists));
-}
-
-static void advise_ref_fetch_first(void)
-{
-	if (!advice_push_fetch_first || !advice_push_update_rejected)
-		return;
-	advise(_(message_advice_ref_fetch_first));
-}
-
-static void advise_ref_needs_force(void)
-{
-	if (!advice_push_needs_force || !advice_push_update_rejected)
-		return;
-	advise(_(message_advice_ref_needs_force));
-}
-
-static int push_with_options(struct transport *transport, struct refspec *rs,
-			     int flags)
-{
-	int err;
-	unsigned int reject_reasons;
-	char *anon_url = transport_anonymize_url(transport->url);
-
-	transport_set_verbosity(transport, verbosity, progress);
-	transport->family = family;
-
-	if (receivepack)
-		transport_set_option(transport,
-				     TRANS_OPT_RECEIVEPACK, receivepack);
-	transport_set_option(transport, TRANS_OPT_THIN, thin ? "yes" : NULL);
-
-	if (!is_empty_cas(&cas)) {
-		if (!transport->smart_options)
-			die("underlying transport does not support --%s option",
-			    CAS_OPT_NAME);
-		transport->smart_options->cas = &cas;
-	}
-
-	if (verbosity > 0)
-		fprintf(stderr, _("Pushing to %s\n"), anon_url);
-	trace2_region_enter("push", "transport_push", the_repository);
-	err = transport_push(the_repository, transport,
-			     rs, flags, &reject_reasons);
-	trace2_region_leave("push", "transport_push", the_repository);
-	if (err != 0) {
-		fprintf(stderr, "%s", push_get_color(PUSH_COLOR_ERROR));
-		error(_("failed to push some refs to '%s'"), anon_url);
-		fprintf(stderr, "%s", push_get_color(PUSH_COLOR_RESET));
-	}
-
-	err |= transport_disconnect(transport);
-	free(anon_url);
-	if (!err)
-		return 0;
-
-	if (reject_reasons & REJECT_NON_FF_HEAD) {
-		advise_pull_before_push();
-	} else if (reject_reasons & REJECT_NON_FF_OTHER) {
-		advise_checkout_pull_push();
-	} else if (reject_reasons & REJECT_ALREADY_EXISTS) {
-		advise_ref_already_exists();
-	} else if (reject_reasons & REJECT_FETCH_FIRST) {
-		advise_ref_fetch_first();
-	} else if (reject_reasons & REJECT_NEEDS_FORCE) {
-		advise_ref_needs_force();
-	}
-
-	return 1;
-}
-
-static int do_push(int flags,
-		   const struct string_list *push_options,
-		   struct remote *remote)
-{
-	int i, errs;
-	const char **url;
-	int url_nr;
-	struct refspec *push_refspec = &rs;
-
-	if (push_options->nr)
-		flags |= TRANSPORT_PUSH_OPTIONS;
-
-	if (!push_refspec->nr && !(flags & TRANSPORT_PUSH_ALL)) {
-		if (remote->push.nr) {
-			push_refspec = &remote->push;
-		} else if (!(flags & TRANSPORT_PUSH_MIRROR))
-			setup_default_push_refspecs(remote);
-	}
-	errs = 0;
-	url_nr = push_url_of_remote(remote, &url);
-	if (url_nr) {
-		for (i = 0; i < url_nr; i++) {
-			struct transport *transport =
-				transport_get(remote, url[i]);
-			if (flags & TRANSPORT_PUSH_OPTIONS)
-				transport->push_options = push_options;
-			if (push_with_options(transport, push_refspec, flags))
-				errs++;
-		}
-	} else {
-		struct transport *transport =
-			transport_get(remote, NULL);
-		if (flags & TRANSPORT_PUSH_OPTIONS)
-			transport->push_options = push_options;
-		if (push_with_options(transport, push_refspec, flags))
-			errs++;
-	}
-	return !!errs;
-}
-
-static int option_parse_recurse_submodules(const struct option *opt,
-				   const char *arg, int unset)
-{
-	int *recurse_submodules = opt->value;
-
-	if (unset)
-		*recurse_submodules = RECURSE_SUBMODULES_OFF;
-	else
-		*recurse_submodules = parse_push_recurse_submodules_arg(opt->long_name, arg);
-
-	return 0;
-}
-
-static void set_push_cert_flags(int *flags, int v)
-{
-	switch (v) {
-	case SEND_PACK_PUSH_CERT_NEVER:
-		*flags &= ~(TRANSPORT_PUSH_CERT_ALWAYS | TRANSPORT_PUSH_CERT_IF_ASKED);
-		break;
-	case SEND_PACK_PUSH_CERT_ALWAYS:
-		*flags |= TRANSPORT_PUSH_CERT_ALWAYS;
-		*flags &= ~TRANSPORT_PUSH_CERT_IF_ASKED;
-		break;
-	case SEND_PACK_PUSH_CERT_IF_ASKED:
-		*flags |= TRANSPORT_PUSH_CERT_IF_ASKED;
-		*flags &= ~TRANSPORT_PUSH_CERT_ALWAYS;
-		break;
-	}
-}
-
-
-static int git_push_config(const char *k, const char *v, void *cb)
-{
-	const char *slot_name;
-	int *flags = cb;
-	int status;
-
-	status = git_gpg_config(k, v, NULL);
-	if (status)
-		return status;
-
-	if (!strcmp(k, "push.followtags")) {
-		if (git_config_bool(k, v))
-			*flags |= TRANSPORT_PUSH_FOLLOW_TAGS;
-		else
-			*flags &= ~TRANSPORT_PUSH_FOLLOW_TAGS;
-		return 0;
-	} else if (!strcmp(k, "push.gpgsign")) {
-		const char *value;
-		if (!git_config_get_value("push.gpgsign", &value)) {
-			switch (git_parse_maybe_bool(value)) {
-			case 0:
-				set_push_cert_flags(flags, SEND_PACK_PUSH_CERT_NEVER);
-				break;
-			case 1:
-				set_push_cert_flags(flags, SEND_PACK_PUSH_CERT_ALWAYS);
-				break;
-			default:
-				if (value && !strcasecmp(value, "if-asked"))
-					set_push_cert_flags(flags, SEND_PACK_PUSH_CERT_IF_ASKED);
-				else
-					return error("Invalid value for '%s'", k);
-			}
-		}
-	} else if (!strcmp(k, "push.recursesubmodules")) {
-		const char *value;
-		if (!git_config_get_value("push.recursesubmodules", &value))
-			recurse_submodules = parse_push_recurse_submodules_arg(k, value);
-	} else if (!strcmp(k, "submodule.recurse")) {
-		int val = git_config_bool(k, v) ?
-			RECURSE_SUBMODULES_ON_DEMAND : RECURSE_SUBMODULES_OFF;
-		recurse_submodules = val;
-	} else if (!strcmp(k, "push.pushoption")) {
-		if (!v)
-			return config_error_nonbool(k);
-		else
-			if (!*v)
-				string_list_clear(&push_options_config, 0);
-			else
-				string_list_append(&push_options_config, v);
-		return 0;
-	} else if (!strcmp(k, "color.push")) {
-		push_use_color = git_config_colorbool(k, v);
-		return 0;
-	} else if (skip_prefix(k, "color.push.", &slot_name)) {
-		int slot = parse_push_color_slot(slot_name);
-		if (slot < 0)
-			return 0;
-		if (!v)
-			return config_error_nonbool(k);
-		return color_parse(v, push_colors[slot]);
-	}
-
-	return git_default_config(k, v, NULL);
-}
-
-int cmd_push(int argc, const char **argv, const char *prefix)
-{
-	int flags = 0;
-	int tags = 0;
-	int push_cert = -1;
-	int rc;
-	const char *repo = NULL;	/* default repository */
-	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),
-		OPT_STRING( 0 , "repo", &repo, N_("repository"), N_("repository")),
-		OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL),
-		OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"),
-			    (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
-		OPT_BOOL('d', "delete", &deleterefs, N_("delete refs")),
-		OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")),
-		OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN),
-		OPT_BIT( 0,  "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN),
-		OPT_BIT('f', "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE),
-		OPT_CALLBACK_F(0, CAS_OPT_NAME, &cas, N_("<refname>:<expect>"),
-			       N_("require old value of ref to be at this value"),
-			       PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP, parseopt_push_cas_option),
-		OPT_CALLBACK(0, "recurse-submodules", &recurse_submodules, "(check|on-demand|no)",
-			     N_("control recursive pushing of submodules"), option_parse_recurse_submodules),
-		OPT_BOOL_F( 0 , "thin", &thin, N_("use thin pack"), PARSE_OPT_NOCOMPLETE),
-		OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", N_("receive pack program")),
-		OPT_STRING( 0 , "exec", &receivepack, "receive-pack", N_("receive pack program")),
-		OPT_BIT('u', "set-upstream", &flags, N_("set upstream for git pull/status"),
-			TRANSPORT_PUSH_SET_UPSTREAM),
-		OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
-		OPT_BIT(0, "prune", &flags, N_("prune locally removed refs"),
-			TRANSPORT_PUSH_PRUNE),
-		OPT_BIT(0, "no-verify", &flags, N_("bypass pre-push hook"), TRANSPORT_PUSH_NO_HOOK),
-		OPT_BIT(0, "follow-tags", &flags, N_("push missing but relevant tags"),
-			TRANSPORT_PUSH_FOLLOW_TAGS),
-		OPT_CALLBACK_F(0, "signed", &push_cert, "(yes|no|if-asked)", N_("GPG sign the push"),
-				PARSE_OPT_OPTARG, option_parse_push_signed),
-		OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC),
-		OPT_STRING_LIST('o', "push-option", &push_options_cmdline, N_("server-specific"), N_("option to transmit")),
-		OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
-				TRANSPORT_FAMILY_IPV4),
-		OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
-				TRANSPORT_FAMILY_IPV6),
-		OPT_END()
-	};
-
-	packet_trace_identity("push");
-	git_config(git_push_config, &flags);
-	argc = parse_options(argc, argv, prefix, options, push_usage, 0);
-	push_options = (push_options_cmdline.nr
-		? &push_options_cmdline
-		: &push_options_config);
-	set_push_cert_flags(&flags, push_cert);
-
-	if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
-		die(_("--delete is incompatible with --all, --mirror and --tags"));
-	if (deleterefs && argc < 2)
-		die(_("--delete doesn't make sense without any refs"));
-
-	if (recurse_submodules == RECURSE_SUBMODULES_CHECK)
-		flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK;
-	else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)
-		flags |= TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND;
-	else if (recurse_submodules == RECURSE_SUBMODULES_ONLY)
-		flags |= TRANSPORT_RECURSE_SUBMODULES_ONLY;
-
-	if (tags)
-		refspec_append(&rs, "refs/tags/*");
-
-	if (argc > 0) {
-		repo = argv[0];
-		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(flags, push_options, remote);
-	string_list_clear(&push_options_cmdline, 0);
-	string_list_clear(&push_options_config, 0);
-	if (rc == -1)
-		usage_with_options(push_usage, options);
-	else
-		return rc;
-}
diff --git a/third_party/git/builtin/range-diff.c b/third_party/git/builtin/range-diff.c
deleted file mode 100644
index 24c4162f7446..000000000000
--- a/third_party/git/builtin/range-diff.c
+++ /dev/null
@@ -1,92 +0,0 @@
-#include "cache.h"
-#include "builtin.h"
-#include "parse-options.h"
-#include "range-diff.h"
-#include "config.h"
-
-static const char * const builtin_range_diff_usage[] = {
-N_("git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>"),
-N_("git range-diff [<options>] <old-tip>...<new-tip>"),
-N_("git range-diff [<options>] <base> <old-tip> <new-tip>"),
-NULL
-};
-
-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 strvec other_arg = STRVEC_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;
-	int res = 0;
-	struct strbuf range1 = STRBUF_INIT, range2 = STRBUF_INIT;
-
-	git_config(git_diff_ui_config, NULL);
-
-	repo_diff_setup(the_repository, &diffopt);
-
-	options = parse_options_concat(range_diff_options, diffopt.parseopts);
-	argc = parse_options(argc, argv, prefix, options,
-			     builtin_range_diff_usage, 0);
-
-	diff_setup_done(&diffopt);
-
-	/* force color when --dual-color was used */
-	if (!simple_color)
-		diffopt.use_color = 1;
-
-	if (argc == 2) {
-		if (!strstr(argv[0], ".."))
-			die(_("no .. in range: '%s'"), argv[0]);
-		strbuf_addstr(&range1, argv[0]);
-
-		if (!strstr(argv[1], ".."))
-			die(_("no .. in range: '%s'"), argv[1]);
-		strbuf_addstr(&range2, argv[1]);
-	} else if (argc == 3) {
-		strbuf_addf(&range1, "%s..%s", argv[0], argv[1]);
-		strbuf_addf(&range2, "%s..%s", argv[0], argv[2]);
-	} else if (argc == 1) {
-		const char *b = strstr(argv[0], "..."), *a = argv[0];
-		int a_len;
-
-		if (!b) {
-			error(_("single arg format must be symmetric range"));
-			usage_with_options(builtin_range_diff_usage, options);
-		}
-
-		a_len = (int)(b - a);
-		if (!a_len) {
-			a = "HEAD";
-			a_len = strlen(a);
-		}
-		b += 3;
-		if (!*b)
-			b = "HEAD";
-		strbuf_addf(&range1, "%s..%.*s", b, a_len, a);
-		strbuf_addf(&range2, "%.*s..%s", a_len, a, b);
-	} else {
-		error(_("need two commit ranges"));
-		usage_with_options(builtin_range_diff_usage, options);
-	}
-	FREE_AND_NULL(options);
-
-	res = show_range_diff(range1.buf, range2.buf, creation_factor,
-			      simple_color < 1, &diffopt, &other_arg);
-
-	strvec_clear(&other_arg);
-	strbuf_release(&range1);
-	strbuf_release(&range2);
-
-	return res;
-}
diff --git a/third_party/git/builtin/read-tree.c b/third_party/git/builtin/read-tree.c
deleted file mode 100644
index 485e7b047948..000000000000
--- a/third_party/git/builtin/read-tree.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * GIT - The information manager from hell
- *
- * Copyright (C) Linus Torvalds, 2005
- */
-
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "config.h"
-#include "lockfile.h"
-#include "object.h"
-#include "tree.h"
-#include "tree-walk.h"
-#include "cache-tree.h"
-#include "unpack-trees.h"
-#include "dir.h"
-#include "builtin.h"
-#include "parse-options.h"
-#include "resolve-undo.h"
-#include "submodule.h"
-#include "submodule-config.h"
-
-static int nr_trees;
-static int read_empty;
-static struct tree *trees[MAX_UNPACK_TREES];
-
-static int list_tree(struct object_id *oid)
-{
-	struct tree *tree;
-
-	if (nr_trees >= MAX_UNPACK_TREES)
-		die("I cannot read more than %d trees", MAX_UNPACK_TREES);
-	tree = parse_tree_indirect(oid);
-	if (!tree)
-		return -1;
-	trees[nr_trees++] = tree;
-	return 0;
-}
-
-static const char * const read_tree_usage[] = {
-	N_("git read-tree [(-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>) [-u [--exclude-per-directory=<gitignore>] | -i]] [--no-sparse-checkout] [--index-output=<file>] (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])"),
-	NULL
-};
-
-static int index_output_cb(const struct option *opt, const char *arg,
-				 int unset)
-{
-	BUG_ON_OPT_NEG(unset);
-	set_alternate_index_output(arg);
-	return 0;
-}
-
-static int exclude_per_directory_cb(const struct option *opt, const char *arg,
-				    int unset)
-{
-	struct dir_struct *dir;
-	struct unpack_trees_options *opts;
-
-	BUG_ON_OPT_NEG(unset);
-
-	opts = (struct unpack_trees_options *)opt->value;
-
-	if (opts->dir)
-		die("more than one --exclude-per-directory given.");
-
-	dir = xcalloc(1, sizeof(*opts->dir));
-	dir->flags |= DIR_SHOW_IGNORED;
-	dir->exclude_per_dir = arg;
-	opts->dir = dir;
-	/* We do not need to nor want to do read-directory
-	 * here; we are merely interested in reusing the
-	 * per directory ignore stack mechanism.
-	 */
-	return 0;
-}
-
-static void debug_stage(const char *label, const struct cache_entry *ce,
-			struct unpack_trees_options *o)
-{
-	printf("%s ", label);
-	if (!ce)
-		printf("(missing)\n");
-	else if (ce == o->df_conflict_entry)
-		printf("(conflict)\n");
-	else
-		printf("%06o #%d %s %.8s\n",
-		       ce->ce_mode, ce_stage(ce), ce->name,
-		       oid_to_hex(&ce->oid));
-}
-
-static int debug_merge(const struct cache_entry * const *stages,
-		       struct unpack_trees_options *o)
-{
-	int i;
-
-	printf("* %d-way merge\n", o->merge_size);
-	debug_stage("index", stages[0], o);
-	for (i = 1; i <= o->merge_size; i++) {
-		char buf[24];
-		xsnprintf(buf, sizeof(buf), "ent#%d", i);
-		debug_stage(buf, stages[i], o);
-	}
-	return 0;
-}
-
-static int git_read_tree_config(const char *var, const char *value, void *cb)
-{
-	if (!strcmp(var, "submodule.recurse"))
-		return git_default_submodule_config(var, value, cb);
-
-	return git_default_config(var, value, cb);
-}
-
-int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
-{
-	int i, stage = 0;
-	struct object_id oid;
-	struct tree_desc t[MAX_UNPACK_TREES];
-	struct unpack_trees_options opts;
-	int prefix_set = 0;
-	struct lock_file lock_file = LOCK_INIT;
-	const struct option read_tree_options[] = {
-		OPT_CALLBACK_F(0, "index-output", NULL, N_("file"),
-		  N_("write resulting index to <file>"),
-		  PARSE_OPT_NONEG, index_output_cb),
-		OPT_BOOL(0, "empty", &read_empty,
-			    N_("only empty the index")),
-		OPT__VERBOSE(&opts.verbose_update, N_("be verbose")),
-		OPT_GROUP(N_("Merging")),
-		OPT_BOOL('m', NULL, &opts.merge,
-			 N_("perform a merge in addition to a read")),
-		OPT_BOOL(0, "trivial", &opts.trivial_merges_only,
-			 N_("3-way merge if no file level merging required")),
-		OPT_BOOL(0, "aggressive", &opts.aggressive,
-			 N_("3-way merge in presence of adds and removes")),
-		OPT_BOOL(0, "reset", &opts.reset,
-			 N_("same as -m, but discard unmerged entries")),
-		{ OPTION_STRING, 0, "prefix", &opts.prefix, N_("<subdirectory>/"),
-		  N_("read the tree into the index under <subdirectory>/"),
-		  PARSE_OPT_NONEG },
-		OPT_BOOL('u', NULL, &opts.update,
-			 N_("update working tree with merge result")),
-		OPT_CALLBACK_F(0, "exclude-per-directory", &opts,
-		  N_("gitignore"),
-		  N_("allow explicitly ignored files to be overwritten"),
-		  PARSE_OPT_NONEG, exclude_per_directory_cb),
-		OPT_BOOL('i', NULL, &opts.index_only,
-			 N_("don't check the working tree after merging")),
-		OPT__DRY_RUN(&opts.dry_run, N_("don't update the index or the work tree")),
-		OPT_BOOL(0, "no-sparse-checkout", &opts.skip_sparse_checkout,
-			 N_("skip applying sparse checkout filter")),
-		OPT_BOOL(0, "debug-unpack", &opts.debug_unpack,
-			 N_("debug unpack-trees")),
-		OPT_CALLBACK_F(0, "recurse-submodules", NULL,
-			    "checkout", "control recursive updating of submodules",
-			    PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater),
-		OPT__QUIET(&opts.quiet, N_("suppress feedback messages")),
-		OPT_END()
-	};
-
-	memset(&opts, 0, sizeof(opts));
-	opts.head_idx = -1;
-	opts.src_index = &the_index;
-	opts.dst_index = &the_index;
-
-	git_config(git_read_tree_config, NULL);
-
-	argc = parse_options(argc, argv, cmd_prefix, read_tree_options,
-			     read_tree_usage, 0);
-
-	hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
-
-	prefix_set = opts.prefix ? 1 : 0;
-	if (1 < opts.merge + opts.reset + prefix_set)
-		die("Which one? -m, --reset, or --prefix?");
-
-	/*
-	 * NEEDSWORK
-	 *
-	 * The old index should be read anyway even if we're going to
-	 * destroy all index entries because we still need to preserve
-	 * certain information such as index version or split-index
-	 * mode.
-	 */
-
-	if (opts.reset || opts.merge || opts.prefix) {
-		if (read_cache_unmerged() && (opts.prefix || opts.merge))
-			die(_("You need to resolve your current index first"));
-		stage = opts.merge = 1;
-	}
-	resolve_undo_clear();
-
-	for (i = 0; i < argc; i++) {
-		const char *arg = argv[i];
-
-		if (get_oid(arg, &oid))
-			die("Not a valid object name %s", arg);
-		if (list_tree(&oid) < 0)
-			die("failed to unpack tree object %s", arg);
-		stage++;
-	}
-	if (!nr_trees && !read_empty && !opts.merge)
-		warning("read-tree: emptying the index with no arguments is deprecated; use --empty");
-	else if (nr_trees > 0 && read_empty)
-		die("passing trees as arguments contradicts --empty");
-
-	if (1 < opts.index_only + opts.update)
-		die("-u and -i at the same time makes no sense");
-	if ((opts.update || opts.index_only) && !opts.merge)
-		die("%s is meaningless without -m, --reset, or --prefix",
-		    opts.update ? "-u" : "-i");
-	if ((opts.dir && !opts.update))
-		die("--exclude-per-directory is meaningless unless -u");
-	if (opts.merge && !opts.index_only)
-		setup_work_tree();
-
-	if (opts.merge) {
-		switch (stage - 1) {
-		case 0:
-			die("you must specify at least one tree to merge");
-			break;
-		case 1:
-			opts.fn = opts.prefix ? bind_merge : oneway_merge;
-			break;
-		case 2:
-			opts.fn = twoway_merge;
-			opts.initial_checkout = is_cache_unborn();
-			break;
-		case 3:
-		default:
-			opts.fn = threeway_merge;
-			break;
-		}
-
-		if (stage - 1 >= 3)
-			opts.head_idx = stage - 2;
-		else
-			opts.head_idx = 1;
-	}
-
-	if (opts.debug_unpack)
-		opts.fn = debug_merge;
-
-	cache_tree_free(&active_cache_tree);
-	for (i = 0; i < nr_trees; i++) {
-		struct tree *tree = trees[i];
-		parse_tree(tree);
-		init_tree_desc(t+i, tree->buffer, tree->size);
-	}
-	if (unpack_trees(nr_trees, t, &opts))
-		return 128;
-
-	if (opts.debug_unpack || opts.dry_run)
-		return 0; /* do not write the index out */
-
-	/*
-	 * When reading only one tree (either the most basic form,
-	 * "-m ent" or "--reset ent" form), we can obtain a fully
-	 * valid cache-tree because the index must match exactly
-	 * what came from the tree.
-	 */
-	if (nr_trees == 1 && !opts.prefix)
-		prime_cache_tree(the_repository,
-				 the_repository->index,
-				 trees[0]);
-
-	if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
-		die("unable to write new index file");
-	return 0;
-}
diff --git a/third_party/git/builtin/rebase.c b/third_party/git/builtin/rebase.c
deleted file mode 100644
index eeca53382f79..000000000000
--- a/third_party/git/builtin/rebase.c
+++ /dev/null
@@ -1,2105 +0,0 @@
-/*
- * "git rebase" builtin command
- *
- * Copyright (c) 2018 Pratik Karki
- */
-
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "run-command.h"
-#include "exec-cmd.h"
-#include "strvec.h"
-#include "dir.h"
-#include "packfile.h"
-#include "refs.h"
-#include "quote.h"
-#include "config.h"
-#include "cache-tree.h"
-#include "unpack-trees.h"
-#include "lockfile.h"
-#include "parse-options.h"
-#include "commit.h"
-#include "diff.h"
-#include "wt-status.h"
-#include "revision.h"
-#include "commit-reach.h"
-#include "rerere.h"
-#include "branch.h"
-#include "sequencer.h"
-#include "rebase-interactive.h"
-#include "reset.h"
-
-#define DEFAULT_REFLOG_ACTION "rebase"
-
-static char const * const builtin_rebase_usage[] = {
-	N_("git rebase [-i] [options] [--exec <cmd>] "
-		"[--onto <newbase> | --keep-base] [<upstream> [<branch>]]"),
-	N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
-		"--root [<branch>]"),
-	N_("git rebase --continue | --abort | --skip | --edit-todo"),
-	NULL
-};
-
-static GIT_PATH_FUNC(path_squash_onto, "rebase-merge/squash-onto")
-static GIT_PATH_FUNC(path_interactive, "rebase-merge/interactive")
-static GIT_PATH_FUNC(apply_dir, "rebase-apply")
-static GIT_PATH_FUNC(merge_dir, "rebase-merge")
-
-enum rebase_type {
-	REBASE_UNSPECIFIED = -1,
-	REBASE_APPLY,
-	REBASE_MERGE,
-	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;
-	const char *upstream_arg;
-	char *head_name;
-	struct object_id orig_head;
-	struct commit *onto;
-	const char *onto_name;
-	const char *revisions;
-	const char *switch_to;
-	int root, root_with_onto;
-	struct object_id *squash_onto;
-	struct commit *restrict_revision;
-	int dont_finish_rebase;
-	enum {
-		REBASE_NO_QUIET = 1<<0,
-		REBASE_VERBOSE = 1<<1,
-		REBASE_DIFFSTAT = 1<<2,
-		REBASE_FORCE = 1<<3,
-		REBASE_INTERACTIVE_EXPLICIT = 1<<4,
-	} flags;
-	struct strvec git_am_opts;
-	const char *action;
-	int signoff;
-	int allow_rerere_autoupdate;
-	int keep_empty;
-	int autosquash;
-	char *gpg_sign_opt;
-	int autostash;
-	int committer_date_is_author_date;
-	int ignore_date;
-	char *cmd;
-	int allow_empty_message;
-	int rebase_merges, rebase_cousins;
-	char *strategy, *strategy_opts;
-	struct strbuf git_format_patch_opt;
-	int reschedule_failed_exec;
-	int use_legacy_rebase;
-	int reapply_cherry_picks;
-};
-
-#define REBASE_OPTIONS_INIT {			  	\
-		.type = REBASE_UNSPECIFIED,	  	\
-		.empty = EMPTY_UNSPECIFIED,	  	\
-		.keep_empty = 1,			\
-		.default_backend = "merge",	  	\
-		.flags = REBASE_NO_QUIET, 		\
-		.git_am_opts = STRVEC_INIT,		\
-		.git_format_patch_opt = STRBUF_INIT	\
-	}
-
-static struct replay_opts get_replay_opts(const struct rebase_options *opts)
-{
-	struct replay_opts replay = REPLAY_OPTS_INIT;
-
-	replay.action = REPLAY_INTERACTIVE_REBASE;
-	sequencer_init_config(&replay);
-
-	replay.signoff = opts->signoff;
-	replay.allow_ff = !(opts->flags & REBASE_FORCE);
-	if (opts->allow_rerere_autoupdate)
-		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.committer_date_is_author_date =
-					opts->committer_date_is_author_date;
-	replay.ignore_date = opts->ignore_date;
-	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
-	replay.strategy = opts->strategy;
-
-	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;
-}
-
-enum action {
-	ACTION_NONE = 0,
-	ACTION_CONTINUE,
-	ACTION_SKIP,
-	ACTION_ABORT,
-	ACTION_QUIT,
-	ACTION_EDIT_TODO,
-	ACTION_SHOW_CURRENT_PATCH,
-	ACTION_SHORTEN_OIDS,
-	ACTION_EXPAND_OIDS,
-	ACTION_CHECK_TODO_LIST,
-	ACTION_REARRANGE_SQUASH,
-	ACTION_ADD_EXEC
-};
-
-static const char *action_names[] = { "undefined",
-				      "continue",
-				      "skip",
-				      "abort",
-				      "quit",
-				      "edit_todo",
-				      "show_current_patch" };
-
-static int add_exec_commands(struct string_list *commands)
-{
-	const char *todo_file = rebase_path_todo();
-	struct todo_list todo_list = TODO_LIST_INIT;
-	int res;
-
-	if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
-		return error_errno(_("could not read '%s'."), todo_file);
-
-	if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
-					&todo_list)) {
-		todo_list_release(&todo_list);
-		return error(_("unusable todo list: '%s'"), todo_file);
-	}
-
-	todo_list_add_exec_commands(&todo_list, commands);
-	res = todo_list_write_to_file(the_repository, &todo_list,
-				      todo_file, NULL, NULL, -1, 0);
-	todo_list_release(&todo_list);
-
-	if (res)
-		return error_errno(_("could not write '%s'."), todo_file);
-	return 0;
-}
-
-static int rearrange_squash_in_todo_file(void)
-{
-	const char *todo_file = rebase_path_todo();
-	struct todo_list todo_list = TODO_LIST_INIT;
-	int res = 0;
-
-	if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
-		return error_errno(_("could not read '%s'."), todo_file);
-	if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
-					&todo_list)) {
-		todo_list_release(&todo_list);
-		return error(_("unusable todo list: '%s'"), todo_file);
-	}
-
-	res = todo_list_rearrange_squash(&todo_list);
-	if (!res)
-		res = todo_list_write_to_file(the_repository, &todo_list,
-					      todo_file, NULL, NULL, -1, 0);
-
-	todo_list_release(&todo_list);
-
-	if (res)
-		return error_errno(_("could not write '%s'."), todo_file);
-	return 0;
-}
-
-static int transform_todo_file(unsigned flags)
-{
-	const char *todo_file = rebase_path_todo();
-	struct todo_list todo_list = TODO_LIST_INIT;
-	int res;
-
-	if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
-		return error_errno(_("could not read '%s'."), todo_file);
-
-	if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
-					&todo_list)) {
-		todo_list_release(&todo_list);
-		return error(_("unusable todo list: '%s'"), todo_file);
-	}
-
-	res = todo_list_write_to_file(the_repository, &todo_list, todo_file,
-				      NULL, NULL, -1, flags);
-	todo_list_release(&todo_list);
-
-	if (res)
-		return error_errno(_("could not write '%s'."), todo_file);
-	return 0;
-}
-
-static int edit_todo_file(unsigned flags)
-{
-	const char *todo_file = rebase_path_todo();
-	struct todo_list todo_list = TODO_LIST_INIT,
-		new_todo = TODO_LIST_INIT;
-	int res = 0;
-
-	if (strbuf_read_file(&todo_list.buf, todo_file, 0) < 0)
-		return error_errno(_("could not read '%s'."), todo_file);
-
-	strbuf_stripspace(&todo_list.buf, 1);
-	res = edit_todo_list(the_repository, &todo_list, &new_todo, NULL, NULL, flags);
-	if (!res && todo_list_write_to_file(the_repository, &new_todo, todo_file,
-					    NULL, NULL, -1, flags & ~(TODO_LIST_SHORTEN_IDS)))
-		res = error_errno(_("could not write '%s'"), todo_file);
-
-	todo_list_release(&todo_list);
-	todo_list_release(&new_todo);
-
-	return res;
-}
-
-static int get_revision_ranges(struct commit *upstream, struct commit *onto,
-			       struct object_id *orig_head, const char **head_hash,
-			       char **revisions, char **shortrevisions)
-{
-	struct commit *base_rev = upstream ? upstream : onto;
-	const char *shorthead;
-
-	*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);
-
-	if (upstream) {
-		const char *shortrev;
-
-		shortrev = find_unique_abbrev(&base_rev->object.oid,
-					      DEFAULT_ABBREV);
-
-		*shortrevisions = xstrfmt("%s..%s", shortrev, shorthead);
-	} else
-		*shortrevisions = xstrdup(shorthead);
-
-	return 0;
-}
-
-static int init_basic_state(struct replay_opts *opts, const char *head_name,
-			    struct commit *onto, const char *orig_head)
-{
-	FILE *interactive;
-
-	if (!is_directory(merge_dir()) && mkdir_in_gitdir(merge_dir()))
-		return error_errno(_("could not create temporary %s"), merge_dir());
-
-	delete_reflog("REBASE_HEAD");
-
-	interactive = fopen(path_interactive(), "w");
-	if (!interactive)
-		return error_errno(_("could not mark as interactive"));
-	fclose(interactive);
-
-	return write_basic_state(opts, head_name, onto, orig_head);
-}
-
-static void split_exec_commands(const char *cmd, struct string_list *commands)
-{
-	if (cmd && *cmd) {
-		string_list_split(commands, cmd, '\n', -1);
-
-		/* rebase.c adds a new line to cmd after every command,
-		 * so here the last command is always empty */
-		string_list_remove_empty_items(commands, 0);
-	}
-}
-
-static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
-{
-	int ret;
-	const char *head_hash = NULL;
-	char *revisions = NULL, *shortrevisions = NULL;
-	struct strvec make_script_args = STRVEC_INIT;
-	struct todo_list todo_list = TODO_LIST_INIT;
-	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))
-		return -1;
-
-	if (init_basic_state(&replay,
-			     opts->head_name ? opts->head_name : "detached HEAD",
-			     opts->onto, head_hash)) {
-		free(revisions);
-		free(shortrevisions);
-
-		return -1;
-	}
-
-	if (!opts->upstream && opts->squash_onto)
-		write_file(path_squash_onto(), "%s\n",
-			   oid_to_hex(opts->squash_onto));
-
-	strvec_pushl(&make_script_args, "", revisions, NULL);
-	if (opts->restrict_revision)
-		strvec_pushf(&make_script_args, "^%s",
-			     oid_to_hex(&opts->restrict_revision->object.oid));
-
-	ret = sequencer_make_script(the_repository, &todo_list.buf,
-				    make_script_args.nr, make_script_args.v,
-				    flags);
-
-	if (ret)
-		error(_("could not generate todo list"));
-	else {
-		discard_cache();
-		if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
-						&todo_list))
-			BUG("unusable todo list");
-
-		split_exec_commands(opts->cmd, &commands);
-		ret = complete_action(the_repository, &replay, flags,
-			shortrevisions, opts->onto_name, opts->onto, head_hash,
-			&commands, opts->autosquash, &todo_list);
-	}
-
-	string_list_clear(&commands, 0);
-	free(revisions);
-	free(shortrevisions);
-	todo_list_release(&todo_list);
-	strvec_clear(&make_script_args);
-
-	return ret;
-}
-
-static int run_sequencer_rebase(struct rebase_options *opts,
-				  enum action command)
-{
-	unsigned flags = 0;
-	int abbreviate_commands = 0, ret = 0;
-
-	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;
-	flags |= opts->reapply_cherry_picks ? TODO_LIST_REAPPLY_CHERRY_PICKS : 0;
-
-	switch (command) {
-	case ACTION_NONE: {
-		if (!opts->onto && !opts->upstream)
-			die(_("a base commit must be provided with --upstream or --onto"));
-
-		ret = do_interactive_rebase(opts, flags);
-		break;
-	}
-	case ACTION_SKIP: {
-		struct string_list merge_rr = STRING_LIST_INIT_DUP;
-
-		rerere_clear(the_repository, &merge_rr);
-	}
-		/* fallthrough */
-	case ACTION_CONTINUE: {
-		struct replay_opts replay_opts = get_replay_opts(opts);
-
-		ret = sequencer_continue(the_repository, &replay_opts);
-		break;
-	}
-	case ACTION_EDIT_TODO:
-		ret = edit_todo_file(flags);
-		break;
-	case ACTION_SHOW_CURRENT_PATCH: {
-		struct child_process cmd = CHILD_PROCESS_INIT;
-
-		cmd.git_cmd = 1;
-		strvec_pushl(&cmd.args, "show", "REBASE_HEAD", "--", NULL);
-		ret = run_command(&cmd);
-
-		break;
-	}
-	case ACTION_SHORTEN_OIDS:
-	case ACTION_EXPAND_OIDS:
-		ret = transform_todo_file(flags);
-		break;
-	case ACTION_CHECK_TODO_LIST:
-		ret = check_todo_list_from_file(the_repository);
-		break;
-	case ACTION_REARRANGE_SQUASH:
-		ret = rearrange_squash_in_todo_file();
-		break;
-	case ACTION_ADD_EXEC: {
-		struct string_list commands = STRING_LIST_INIT_DUP;
-
-		split_exec_commands(opts->cmd, &commands);
-		ret = add_exec_commands(&commands);
-		string_list_clear(&commands, 0);
-		break;
-	}
-	default:
-		BUG("invalid command '%d'", command);
-	}
-
-	return ret;
-}
-
-static void imply_merge(struct rebase_options *opts, const char *option);
-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);
-
-	imply_merge(opts, unset ? "--no-keep-empty" : "--keep-empty");
-	opts->keep_empty = !unset;
-	opts->type = REBASE_MERGE;
-	return 0;
-}
-
-static const char * const builtin_rebase_interactive_usage[] = {
-	N_("git rebase--interactive [<options>]"),
-	NULL
-};
-
-int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
-{
-	struct rebase_options opts = REBASE_OPTIONS_INIT;
-	struct object_id squash_onto = null_oid;
-	enum action command = ACTION_NONE;
-	struct option options[] = {
-		OPT_NEGBIT(0, "ff", &opts.flags, N_("allow fast-forward"),
-			   REBASE_FORCE),
-		OPT_CALLBACK_F('k', "keep-empty", &options, NULL,
-			N_("keep commits which start empty"),
-			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, "rebase-merges", &opts.rebase_merges, N_("rebase merge commits")),
-		OPT_BOOL(0, "rebase-cousins", &opts.rebase_cousins,
-			 N_("keep original branch points of cousins")),
-		OPT_BOOL(0, "autosquash", &opts.autosquash,
-			 N_("move commits that begin with squash!/fixup!")),
-		OPT_BOOL(0, "signoff", &opts.signoff, N_("sign commits")),
-		OPT_BIT('v', "verbose", &opts.flags,
-			N_("display a diffstat of what changed upstream"),
-			REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT),
-		OPT_CMDMODE(0, "continue", &command, N_("continue rebase"),
-			    ACTION_CONTINUE),
-		OPT_CMDMODE(0, "skip", &command, N_("skip commit"), ACTION_SKIP),
-		OPT_CMDMODE(0, "edit-todo", &command, N_("edit the todo list"),
-			    ACTION_EDIT_TODO),
-		OPT_CMDMODE(0, "show-current-patch", &command, N_("show the current patch"),
-			    ACTION_SHOW_CURRENT_PATCH),
-		OPT_CMDMODE(0, "shorten-ids", &command,
-			N_("shorten commit ids in the todo list"), ACTION_SHORTEN_OIDS),
-		OPT_CMDMODE(0, "expand-ids", &command,
-			N_("expand commit ids in the todo list"), ACTION_EXPAND_OIDS),
-		OPT_CMDMODE(0, "check-todo-list", &command,
-			N_("check the todo list"), ACTION_CHECK_TODO_LIST),
-		OPT_CMDMODE(0, "rearrange-squash", &command,
-			N_("rearrange fixup/squash lines"), ACTION_REARRANGE_SQUASH),
-		OPT_CMDMODE(0, "add-exec-commands", &command,
-			N_("insert exec commands in todo list"), ACTION_ADD_EXEC),
-		{ OPTION_CALLBACK, 0, "onto", &opts.onto, N_("onto"), N_("onto"),
-		  PARSE_OPT_NONEG, parse_opt_commit, 0 },
-		{ OPTION_CALLBACK, 0, "restrict-revision", &opts.restrict_revision,
-		  N_("restrict-revision"), N_("restrict revision"),
-		  PARSE_OPT_NONEG, parse_opt_commit, 0 },
-		{ OPTION_CALLBACK, 0, "squash-onto", &squash_onto, N_("squash-onto"),
-		  N_("squash onto"), PARSE_OPT_NONEG, parse_opt_object_id, 0 },
-		{ OPTION_CALLBACK, 0, "upstream", &opts.upstream, N_("upstream"),
-		  N_("the upstream commit"), PARSE_OPT_NONEG, parse_opt_commit,
-		  0 },
-		OPT_STRING(0, "head-name", &opts.head_name, N_("head-name"), N_("head name")),
-		{ OPTION_STRING, 'S', "gpg-sign", &opts.gpg_sign_opt, N_("key-id"),
-			N_("GPG-sign commits"),
-			PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
-		OPT_STRING(0, "strategy", &opts.strategy, N_("strategy"),
-			   N_("rebase strategy")),
-		OPT_STRING(0, "strategy-opts", &opts.strategy_opts, N_("strategy-opts"),
-			   N_("strategy options")),
-		OPT_STRING(0, "switch-to", &opts.switch_to, N_("switch-to"),
-			   N_("the branch or commit to checkout")),
-		OPT_STRING(0, "onto-name", &opts.onto_name, N_("onto-name"), N_("onto name")),
-		OPT_STRING(0, "cmd", &opts.cmd, N_("cmd"), N_("the command to run")),
-		OPT_RERERE_AUTOUPDATE(&opts.allow_rerere_autoupdate),
-		OPT_BOOL(0, "reschedule-failed-exec", &opts.reschedule_failed_exec,
-			 N_("automatically re-schedule any `exec` that fails")),
-		OPT_END()
-	};
-
-	opts.rebase_cousins = -1;
-
-	if (argc == 1)
-		usage_with_options(builtin_rebase_interactive_usage, options);
-
-	argc = parse_options(argc, argv, prefix, options,
-			builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
-
-	if (!is_null_oid(&squash_onto))
-		opts.squash_onto = &squash_onto;
-
-	if (opts.rebase_cousins >= 0 && !opts.rebase_merges)
-		warning(_("--[no-]rebase-cousins has no effect without "
-			  "--rebase-merges"));
-
-	return !!run_sequencer_rebase(&opts, command);
-}
-
-static int is_merge(struct rebase_options *opts)
-{
-	return opts->type == REBASE_MERGE ||
-		opts->type == REBASE_PRESERVE_MERGES;
-}
-
-static void imply_merge(struct rebase_options *opts, const char *option)
-{
-	switch (opts->type) {
-	case REBASE_APPLY:
-		die(_("%s requires the merge backend"), option);
-		break;
-	case REBASE_MERGE:
-	case REBASE_PRESERVE_MERGES:
-		break;
-	default:
-		opts->type = REBASE_MERGE; /* implied */
-		break;
-	}
-}
-
-/* Returns the filename prefixed by the state_dir */
-static const char *state_dir_path(const char *filename, struct rebase_options *opts)
-{
-	static struct strbuf path = STRBUF_INIT;
-	static size_t prefix_len;
-
-	if (!prefix_len) {
-		strbuf_addf(&path, "%s/", opts->state_dir);
-		prefix_len = path.len;
-	}
-
-	strbuf_setlen(&path, prefix_len);
-	strbuf_addstr(&path, filename);
-	return path.buf;
-}
-
-/* Initialize the rebase options from the state directory. */
-static int read_basic_state(struct rebase_options *opts)
-{
-	struct strbuf head_name = STRBUF_INIT;
-	struct strbuf buf = STRBUF_INIT;
-	struct object_id oid;
-
-	if (!read_oneliner(&head_name, state_dir_path("head-name", opts),
-			   READ_ONELINER_WARN_MISSING) ||
-	    !read_oneliner(&buf, state_dir_path("onto", opts),
-			   READ_ONELINER_WARN_MISSING))
-		return -1;
-	opts->head_name = starts_with(head_name.buf, "refs/") ?
-		xstrdup(head_name.buf) : NULL;
-	strbuf_release(&head_name);
-	if (get_oid(buf.buf, &oid))
-		return error(_("could not get 'onto': '%s'"), buf.buf);
-	opts->onto = lookup_commit_or_die(&oid, buf.buf);
-
-	/*
-	 * We always write to orig-head, but interactive rebase used to write to
-	 * head. Fall back to reading from head to cover for the case that the
-	 * user upgraded git with an ongoing interactive rebase.
-	 */
-	strbuf_reset(&buf);
-	if (file_exists(state_dir_path("orig-head", opts))) {
-		if (!read_oneliner(&buf, state_dir_path("orig-head", opts),
-				   READ_ONELINER_WARN_MISSING))
-			return -1;
-	} else if (!read_oneliner(&buf, state_dir_path("head", opts),
-				  READ_ONELINER_WARN_MISSING))
-		return -1;
-	if (get_oid(buf.buf, &opts->orig_head))
-		return error(_("invalid orig-head: '%s'"), buf.buf);
-
-	if (file_exists(state_dir_path("quiet", opts)))
-		opts->flags &= ~REBASE_NO_QUIET;
-	else
-		opts->flags |= REBASE_NO_QUIET;
-
-	if (file_exists(state_dir_path("verbose", opts)))
-		opts->flags |= REBASE_VERBOSE;
-
-	if (file_exists(state_dir_path("signoff", opts))) {
-		opts->signoff = 1;
-		opts->flags |= REBASE_FORCE;
-	}
-
-	if (file_exists(state_dir_path("allow_rerere_autoupdate", opts))) {
-		strbuf_reset(&buf);
-		if (!read_oneliner(&buf, state_dir_path("allow_rerere_autoupdate", opts),
-				   READ_ONELINER_WARN_MISSING))
-			return -1;
-		if (!strcmp(buf.buf, "--rerere-autoupdate"))
-			opts->allow_rerere_autoupdate = RERERE_AUTOUPDATE;
-		else if (!strcmp(buf.buf, "--no-rerere-autoupdate"))
-			opts->allow_rerere_autoupdate = RERERE_NOAUTOUPDATE;
-		else
-			warning(_("ignoring invalid allow_rerere_autoupdate: "
-				  "'%s'"), buf.buf);
-	}
-
-	if (file_exists(state_dir_path("gpg_sign_opt", opts))) {
-		strbuf_reset(&buf);
-		if (!read_oneliner(&buf, state_dir_path("gpg_sign_opt", opts),
-				   READ_ONELINER_WARN_MISSING))
-			return -1;
-		free(opts->gpg_sign_opt);
-		opts->gpg_sign_opt = xstrdup(buf.buf);
-	}
-
-	if (file_exists(state_dir_path("strategy", opts))) {
-		strbuf_reset(&buf);
-		if (!read_oneliner(&buf, state_dir_path("strategy", opts),
-				   READ_ONELINER_WARN_MISSING))
-			return -1;
-		free(opts->strategy);
-		opts->strategy = xstrdup(buf.buf);
-	}
-
-	if (file_exists(state_dir_path("strategy_opts", opts))) {
-		strbuf_reset(&buf);
-		if (!read_oneliner(&buf, state_dir_path("strategy_opts", opts),
-				   READ_ONELINER_WARN_MISSING))
-			return -1;
-		free(opts->strategy_opts);
-		opts->strategy_opts = xstrdup(buf.buf);
-	}
-
-	strbuf_release(&buf);
-
-	return 0;
-}
-
-static int rebase_write_basic_state(struct rebase_options *opts)
-{
-	write_file(state_dir_path("head-name", opts), "%s",
-		   opts->head_name ? opts->head_name : "detached HEAD");
-	write_file(state_dir_path("onto", opts), "%s",
-		   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", "");
-	if (opts->flags & REBASE_VERBOSE)
-		write_file(state_dir_path("verbose", opts), "%s", "");
-	if (opts->strategy)
-		write_file(state_dir_path("strategy", opts), "%s",
-			   opts->strategy);
-	if (opts->strategy_opts)
-		write_file(state_dir_path("strategy_opts", opts), "%s",
-			   opts->strategy_opts);
-	if (opts->allow_rerere_autoupdate > 0)
-		write_file(state_dir_path("allow_rerere_autoupdate", opts),
-			   "-%s-rerere-autoupdate",
-			   opts->allow_rerere_autoupdate == RERERE_AUTOUPDATE ?
-				"" : "-no");
-	if (opts->gpg_sign_opt)
-		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");
-
-	return 0;
-}
-
-static int finish_rebase(struct rebase_options *opts)
-{
-	struct strbuf dir = STRBUF_INIT;
-	int ret = 0;
-
-	delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
-	apply_autostash(state_dir_path("autostash", opts));
-	close_object_store(the_repository->objects);
-	/*
-	 * We ignore errors in 'git maintenance run --auto', since the
-	 * user should see them.
-	 */
-	run_auto_maintenance(!(opts->flags & (REBASE_NO_QUIET|REBASE_VERBOSE)));
-	if (opts->type == REBASE_MERGE) {
-		struct replay_opts replay = REPLAY_OPTS_INIT;
-
-		replay.action = REPLAY_INTERACTIVE_REBASE;
-		ret = sequencer_remove_state(&replay);
-	} else {
-		strbuf_addstr(&dir, opts->state_dir);
-		if (remove_dir_recursively(&dir, 0))
-			ret = error(_("could not remove '%s'"),
-				    opts->state_dir);
-		strbuf_release(&dir);
-	}
-
-	return ret;
-}
-
-static struct commit *peel_committish(const char *name)
-{
-	struct object *obj;
-	struct object_id oid;
-
-	if (get_oid(name, &oid))
-		return NULL;
-	obj = parse_object(the_repository, &oid);
-	return (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT);
-}
-
-static void add_var(struct strbuf *buf, const char *name, const char *value)
-{
-	if (!value)
-		strbuf_addf(buf, "unset %s; ", name);
-	else {
-		strbuf_addf(buf, "%s=", name);
-		sq_quote_buf(buf, value);
-		strbuf_addstr(buf, "; ");
-	}
-}
-
-static int move_to_original_branch(struct rebase_options *opts)
-{
-	struct strbuf orig_head_reflog = STRBUF_INIT, head_reflog = STRBUF_INIT;
-	int ret;
-
-	if (!opts->head_name)
-		return 0; /* nothing to move back to */
-
-	if (!opts->onto)
-		BUG("move_to_original_branch without onto");
-
-	strbuf_addf(&orig_head_reflog, "rebase finished: %s onto %s",
-		    opts->head_name, oid_to_hex(&opts->onto->object.oid));
-	strbuf_addf(&head_reflog, "rebase finished: returning to %s",
-		    opts->head_name);
-	ret = reset_head(the_repository, NULL, "", opts->head_name,
-			 RESET_HEAD_REFS_ONLY,
-			 orig_head_reflog.buf, head_reflog.buf,
-			 DEFAULT_REFLOG_ACTION);
-
-	strbuf_release(&orig_head_reflog);
-	strbuf_release(&head_reflog);
-	return ret;
-}
-
-static const char *resolvemsg =
-N_("Resolve all conflicts manually, mark them as resolved with\n"
-"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
-"You can instead skip this commit: run \"git rebase --skip\".\n"
-"To abort and get back to the state before \"git rebase\", run "
-"\"git rebase --abort\".");
-
-static int run_am(struct rebase_options *opts)
-{
-	struct child_process am = CHILD_PROCESS_INIT;
-	struct child_process format_patch = CHILD_PROCESS_INIT;
-	struct strbuf revisions = STRBUF_INIT;
-	int status;
-	char *rebased_patches;
-
-	am.git_cmd = 1;
-	strvec_push(&am.args, "am");
-
-	if (opts->action && !strcmp("continue", opts->action)) {
-		strvec_push(&am.args, "--resolved");
-		strvec_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
-		if (opts->gpg_sign_opt)
-			strvec_push(&am.args, opts->gpg_sign_opt);
-		status = run_command(&am);
-		if (status)
-			return status;
-
-		return move_to_original_branch(opts);
-	}
-	if (opts->action && !strcmp("skip", opts->action)) {
-		strvec_push(&am.args, "--skip");
-		strvec_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
-		status = run_command(&am);
-		if (status)
-			return status;
-
-		return move_to_original_branch(opts);
-	}
-	if (opts->action && !strcmp("show-current-patch", opts->action)) {
-		strvec_push(&am.args, "--show-current-patch");
-		return run_command(&am);
-	}
-
-	strbuf_addf(&revisions, "%s...%s",
-		    oid_to_hex(opts->root ?
-			       /* this is now equivalent to !opts->upstream */
-			       &opts->onto->object.oid :
-			       &opts->upstream->object.oid),
-		    oid_to_hex(&opts->orig_head));
-
-	rebased_patches = xstrdup(git_path("rebased-patches"));
-	format_patch.out = open(rebased_patches,
-				O_WRONLY | O_CREAT | O_TRUNC, 0666);
-	if (format_patch.out < 0) {
-		status = error_errno(_("could not open '%s' for writing"),
-				     rebased_patches);
-		free(rebased_patches);
-		strvec_clear(&am.args);
-		return status;
-	}
-
-	format_patch.git_cmd = 1;
-	strvec_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);
-	if (opts->git_format_patch_opt.len)
-		strvec_split(&format_patch.args,
-			     opts->git_format_patch_opt.buf);
-	strvec_push(&format_patch.args, revisions.buf);
-	if (opts->restrict_revision)
-		strvec_pushf(&format_patch.args, "^%s",
-			     oid_to_hex(&opts->restrict_revision->object.oid));
-
-	status = run_command(&format_patch);
-	if (status) {
-		unlink(rebased_patches);
-		free(rebased_patches);
-		strvec_clear(&am.args);
-
-		reset_head(the_repository, &opts->orig_head, "checkout",
-			   opts->head_name, 0,
-			   "HEAD", NULL, DEFAULT_REFLOG_ACTION);
-		error(_("\ngit encountered an error while preparing the "
-			"patches to replay\n"
-			"these revisions:\n"
-			"\n    %s\n\n"
-			"As a result, git cannot rebase them."),
-		      opts->revisions);
-
-		strbuf_release(&revisions);
-		return status;
-	}
-	strbuf_release(&revisions);
-
-	am.in = open(rebased_patches, O_RDONLY);
-	if (am.in < 0) {
-		status = error_errno(_("could not open '%s' for reading"),
-				     rebased_patches);
-		free(rebased_patches);
-		strvec_clear(&am.args);
-		return status;
-	}
-
-	strvec_pushv(&am.args, opts->git_am_opts.v);
-	strvec_push(&am.args, "--rebasing");
-	strvec_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
-	strvec_push(&am.args, "--patch-format=mboxrd");
-	if (opts->allow_rerere_autoupdate == RERERE_AUTOUPDATE)
-		strvec_push(&am.args, "--rerere-autoupdate");
-	else if (opts->allow_rerere_autoupdate == RERERE_NOAUTOUPDATE)
-		strvec_push(&am.args, "--no-rerere-autoupdate");
-	if (opts->gpg_sign_opt)
-		strvec_push(&am.args, opts->gpg_sign_opt);
-	status = run_command(&am);
-	unlink(rebased_patches);
-	free(rebased_patches);
-
-	if (!status) {
-		return move_to_original_branch(opts);
-	}
-
-	if (is_directory(opts->state_dir))
-		rebase_write_basic_state(opts);
-
-	return status;
-}
-
-static int run_specific_rebase(struct rebase_options *opts, enum action action)
-{
-	const char *argv[] = { NULL, NULL };
-	struct strbuf script_snippet = STRBUF_INIT, buf = STRBUF_INIT;
-	int status;
-	const char *backend, *backend_func;
-
-	if (opts->type == REBASE_MERGE) {
-		/* Run sequencer-based rebase */
-		setenv("GIT_CHERRY_PICK_HELP", resolvemsg, 1);
-		if (!(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) {
-			setenv("GIT_SEQUENCE_EDITOR", ":", 1);
-			opts->autosquash = 0;
-		}
-		if (opts->gpg_sign_opt) {
-			/* remove the leading "-S" */
-			char *tmp = xstrdup(opts->gpg_sign_opt + 2);
-			free(opts->gpg_sign_opt);
-			opts->gpg_sign_opt = tmp;
-		}
-
-		status = run_sequencer_rebase(opts, action);
-		goto finished_rebase;
-	}
-
-	if (opts->type == REBASE_APPLY) {
-		status = run_am(opts);
-		goto finished_rebase;
-	}
-
-	add_var(&script_snippet, "GIT_DIR", absolute_path(get_git_dir()));
-	add_var(&script_snippet, "state_dir", opts->state_dir);
-
-	add_var(&script_snippet, "upstream_name", opts->upstream_name);
-	add_var(&script_snippet, "upstream", opts->upstream ?
-		oid_to_hex(&opts->upstream->object.oid) : NULL);
-	add_var(&script_snippet, "head_name",
-		opts->head_name ? opts->head_name : "detached HEAD");
-	add_var(&script_snippet, "orig_head", oid_to_hex(&opts->orig_head));
-	add_var(&script_snippet, "onto", opts->onto ?
-		oid_to_hex(&opts->onto->object.oid) : NULL);
-	add_var(&script_snippet, "onto_name", opts->onto_name);
-	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);
-	sq_quote_argv_pretty(&buf, opts->git_am_opts.v);
-	add_var(&script_snippet, "git_am_opt", buf.buf);
-	strbuf_release(&buf);
-	add_var(&script_snippet, "verbose",
-		opts->flags & REBASE_VERBOSE ? "t" : "");
-	add_var(&script_snippet, "diffstat",
-		opts->flags & REBASE_DIFFSTAT ? "t" : "");
-	add_var(&script_snippet, "force_rebase",
-		opts->flags & REBASE_FORCE ? "t" : "");
-	if (opts->switch_to)
-		add_var(&script_snippet, "switch_to", opts->switch_to);
-	add_var(&script_snippet, "action", opts->action ? opts->action : "");
-	add_var(&script_snippet, "signoff", opts->signoff ? "--signoff" : "");
-	add_var(&script_snippet, "allow_rerere_autoupdate",
-		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);
-	add_var(&script_snippet, "allow_empty_message",
-		opts->allow_empty_message ?  "--allow-empty-message" : "");
-	add_var(&script_snippet, "rebase_merges",
-		opts->rebase_merges ? "t" : "");
-	add_var(&script_snippet, "rebase_cousins",
-		opts->rebase_cousins ? "t" : "");
-	add_var(&script_snippet, "strategy", opts->strategy);
-	add_var(&script_snippet, "strategy_opts", opts->strategy_opts);
-	add_var(&script_snippet, "rebase_root", opts->root ? "t" : "");
-	add_var(&script_snippet, "squash_onto",
-		opts->squash_onto ? oid_to_hex(opts->squash_onto) : "");
-	add_var(&script_snippet, "git_format_patch_opt",
-		opts->git_format_patch_opt.buf);
-
-	if (is_merge(opts) &&
-	    !(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) {
-		strbuf_addstr(&script_snippet,
-			      "GIT_SEQUENCE_EDITOR=:; export GIT_SEQUENCE_EDITOR; ");
-		opts->autosquash = 0;
-	}
-
-	switch (opts->type) {
-	case REBASE_PRESERVE_MERGES:
-		backend = "git-rebase--preserve-merges";
-		backend_func = "git_rebase__preserve_merges";
-		break;
-	default:
-		BUG("Unhandled rebase type %d", opts->type);
-		break;
-	}
-
-	strbuf_addf(&script_snippet,
-		    ". git-sh-setup && . %s && %s", backend, backend_func);
-	argv[0] = script_snippet.buf;
-
-	status = run_command_v_opt(argv, RUN_USING_SHELL);
-finished_rebase:
-	if (opts->dont_finish_rebase)
-		; /* do nothing */
-	else if (opts->type == REBASE_MERGE)
-		; /* merge backend cleans up after itself */
-	else if (status == 0) {
-		if (!file_exists(state_dir_path("stopped-sha", opts)))
-			finish_rebase(opts);
-	} else if (status == 2) {
-		struct strbuf dir = STRBUF_INIT;
-
-		apply_autostash(state_dir_path("autostash", opts));
-		strbuf_addstr(&dir, opts->state_dir);
-		remove_dir_recursively(&dir, 0);
-		strbuf_release(&dir);
-		die("Nothing to do");
-	}
-
-	strbuf_release(&script_snippet);
-
-	return status ? -1 : 0;
-}
-
-static int rebase_config(const char *var, const char *value, void *data)
-{
-	struct rebase_options *opts = data;
-
-	if (!strcmp(var, "rebase.stat")) {
-		if (git_config_bool(var, value))
-			opts->flags |= REBASE_DIFFSTAT;
-		else
-			opts->flags &= ~REBASE_DIFFSTAT;
-		return 0;
-	}
-
-	if (!strcmp(var, "rebase.autosquash")) {
-		opts->autosquash = git_config_bool(var, value);
-		return 0;
-	}
-
-	if (!strcmp(var, "commit.gpgsign")) {
-		free(opts->gpg_sign_opt);
-		opts->gpg_sign_opt = git_config_bool(var, value) ?
-			xstrdup("-S") : NULL;
-		return 0;
-	}
-
-	if (!strcmp(var, "rebase.autostash")) {
-		opts->autostash = git_config_bool(var, value);
-		return 0;
-	}
-
-	if (!strcmp(var, "rebase.reschedulefailedexec")) {
-		opts->reschedule_failed_exec = git_config_bool(var, value);
-		return 0;
-	}
-
-	if (!strcmp(var, "rebase.usebuiltin")) {
-		opts->use_legacy_rebase = !git_config_bool(var, value);
-		return 0;
-	}
-
-	if (!strcmp(var, "rebase.backend")) {
-		return git_config_string(&opts->default_backend, var, value);
-	}
-
-	return git_default_config(var, value, data);
-}
-
-/*
- * Determines whether the commits in from..to are linear, i.e. contain
- * no merge commits. This function *expects* `from` to be an ancestor of
- * `to`.
- */
-static int is_linear_history(struct commit *from, struct commit *to)
-{
-	while (to && to != from) {
-		parse_commit(to);
-		if (!to->parents)
-			return 1;
-		if (to->parents->next)
-			return 0;
-		to = to->parents->item;
-	}
-	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)
-{
-	struct commit *head = lookup_commit(the_repository, head_oid);
-	struct commit_list *merge_bases = NULL;
-	int res = 0;
-
-	if (!head)
-		goto done;
-
-	merge_bases = get_merge_bases(onto, head);
-	if (!merge_bases || merge_bases->next) {
-		oidcpy(merge_base, &null_oid);
-		goto done;
-	}
-
-	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)
-{
-	struct rebase_options *opts = opt->value;
-
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-
-	if (!is_merge(opts))
-		opts->type = REBASE_MERGE;
-
-	return 0;
-}
-
-/* -i followed by -p is still explicitly interactive, but -p alone is not */
-static int parse_opt_interactive(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_MERGE;
-	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);
-
-	printf(_("%s\n"
-		 "Please specify which branch you want to rebase against.\n"
-		 "See git-rebase(1) for details.\n"
-		 "\n"
-		 "    git rebase '<branch>'\n"
-		 "\n"),
-		current_branch ? _("There is no tracking information for "
-			"the current branch.") :
-			_("You are not currently on a branch."));
-
-	if (current_branch) {
-		const char *remote = current_branch->remote_name;
-
-		if (!remote)
-			remote = _("<remote>");
-
-		printf(_("If you wish to set tracking information for this "
-			 "branch you can do so with:\n"
-			 "\n"
-			 "    git branch --set-upstream-to=%s/<branch> %s\n"
-			 "\n"),
-		       remote, current_branch->name);
-	}
-	exit(1);
-}
-
-static void set_reflog_action(struct rebase_options *options)
-{
-	const char *env;
-	struct strbuf buf = STRBUF_INIT;
-
-	if (!is_merge(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);
-	setenv(GIT_REFLOG_ACTION_ENVIRONMENT, buf.buf, 1);
-	strbuf_release(&buf);
-}
-
-static int check_exec_cmd(const char *cmd)
-{
-	if (strchr(cmd, '\n'))
-		return error(_("exec commands cannot contain newlines"));
-
-	/* Does the command consist purely of whitespace? */
-	if (!cmd[strspn(cmd, " \t\r\f\v")])
-		return error(_("empty exec command"));
-
-	return 0;
-}
-
-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;
-	struct strbuf buf = STRBUF_INIT;
-	struct object_id merge_base;
-	int ignore_whitespace = 0;
-	enum action action = ACTION_NONE;
-	const char *gpg_sign = NULL;
-	struct string_list exec = STRING_LIST_INIT_NODUP;
-	const char *rebase_merges = NULL;
-	int fork_point = -1;
-	struct string_list strategy_options = STRING_LIST_INIT_NODUP;
-	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),
-		OPT_BIT('v', "verbose", &options.flags,
-			N_("display a diffstat of what changed upstream"),
-			REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT),
-		{OPTION_NEGBIT, 'n', "no-stat", &options.flags, NULL,
-			N_("do not show diffstat of what changed upstream"),
-			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
-		OPT_BOOL(0, "signoff", &options.signoff,
-			 N_("add a Signed-off-by: line to each commit")),
-		OPT_BOOL(0, "committer-date-is-author-date",
-			 &options.committer_date_is_author_date,
-			 N_("make committer date match author date")),
-		OPT_BOOL(0, "reset-author-date", &options.ignore_date,
-			 N_("ignore author date and use current date")),
-		OPT_HIDDEN_BOOL(0, "ignore-date", &options.ignore_date,
-				N_("synonym of --reset-author-date")),
-		OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
-				  N_("passed to 'git apply'"), 0),
-		OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
-			 N_("ignore changes in whitespace")),
-		OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
-				  N_("action"), N_("passed to 'git apply'"), 0),
-		OPT_BIT('f', "force-rebase", &options.flags,
-			N_("cherry-pick all commits, even if unchanged"),
-			REBASE_FORCE),
-		OPT_BIT(0, "no-ff", &options.flags,
-			N_("cherry-pick all commits, even if unchanged"),
-			REBASE_FORCE),
-		OPT_CMDMODE(0, "continue", &action, N_("continue"),
-			    ACTION_CONTINUE),
-		OPT_CMDMODE(0, "skip", &action,
-			    N_("skip current patch and continue"), ACTION_SKIP),
-		OPT_CMDMODE(0, "abort", &action,
-			    N_("abort and check out the original branch"),
-			    ACTION_ABORT),
-		OPT_CMDMODE(0, "quit", &action,
-			    N_("abort but keep HEAD where it is"), ACTION_QUIT),
-		OPT_CMDMODE(0, "edit-todo", &action, N_("edit the todo list "
-			    "during an interactive rebase"), ACTION_EDIT_TODO),
-		OPT_CMDMODE(0, "show-current-patch", &action,
-			    N_("show the patch file being applied or merged"),
-			    ACTION_SHOW_CURRENT_PATCH),
-		OPT_CALLBACK_F(0, "apply", &options, NULL,
-			N_("use apply strategies to rebase"),
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG,
-			parse_opt_am),
-		OPT_CALLBACK_F('m', "merge", &options, NULL,
-			N_("use merging strategies to rebase"),
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG,
-			parse_opt_merge),
-		OPT_CALLBACK_F('i', "interactive", &options, NULL,
-			N_("let the user edit the list of commits to rebase"),
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG,
-			parse_opt_interactive),
-		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_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),
-		OPT_CALLBACK_F('k', "keep-empty", &options, NULL,
-			N_("keep commits which start empty"),
-			PARSE_OPT_NOARG | PARSE_OPT_HIDDEN,
-			parse_opt_keep_empty),
-		OPT_BOOL(0, "autosquash", &options.autosquash,
-			 N_("move commits that begin with "
-			    "squash!/fixup! under -i")),
-		{ OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"),
-			N_("GPG-sign commits"),
-			PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
-		OPT_AUTOSTASH(&options.autostash),
-		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),
-		{OPTION_STRING, 'r', "rebase-merges", &rebase_merges,
-			N_("mode"),
-			N_("try to rebase merges instead of skipping them"),
-			PARSE_OPT_OPTARG, NULL, (intptr_t)""},
-		OPT_BOOL(0, "fork-point", &fork_point,
-			 N_("use 'merge-base --fork-point' to refine upstream")),
-		OPT_STRING('s', "strategy", &options.strategy,
-			   N_("strategy"), N_("use the given merge strategy")),
-		OPT_STRING_LIST('X', "strategy-option", &strategy_options,
-				N_("option"),
-				N_("pass the argument through to the merge "
-				   "strategy")),
-		OPT_BOOL(0, "root", &options.root,
-			 N_("rebase all reachable commits up to the root(s)")),
-		OPT_BOOL(0, "reschedule-failed-exec",
-			 &reschedule_failed_exec,
-			 N_("automatically re-schedule any `exec` that fails")),
-		OPT_BOOL(0, "reapply-cherry-picks", &options.reapply_cherry_picks,
-			 N_("apply all changes, even those already present upstream")),
-		OPT_END(),
-	};
-	int i;
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage_with_options(builtin_rebase_usage,
-				   builtin_rebase_options);
-
-	options.allow_empty_message = 1;
-	git_config(rebase_config, &options);
-	/* options.gpg_sign_opt will be either "-S" or NULL */
-	gpg_sign = options.gpg_sign_opt ? "" : NULL;
-	FREE_AND_NULL(options.gpg_sign_opt);
-
-	if (options.use_legacy_rebase ||
-	    !git_env_bool("GIT_TEST_REBASE_USE_BUILTIN", -1))
-		warning(_("the rebase.useBuiltin support has been removed!\n"
-			  "See its entry in 'git help config' for details."));
-
-	strbuf_reset(&buf);
-	strbuf_addf(&buf, "%s/applying", apply_dir());
-	if(file_exists(buf.buf))
-		die(_("It looks like 'git am' is in progress. Cannot rebase."));
-
-	if (is_directory(apply_dir())) {
-		options.type = REBASE_APPLY;
-		options.state_dir = apply_dir();
-	} else if (is_directory(merge_dir())) {
-		strbuf_reset(&buf);
-		strbuf_addf(&buf, "%s/rewritten", merge_dir());
-		if (is_directory(buf.buf)) {
-			options.type = REBASE_PRESERVE_MERGES;
-			options.flags |= REBASE_INTERACTIVE_EXPLICIT;
-		} else {
-			strbuf_reset(&buf);
-			strbuf_addf(&buf, "%s/interactive", merge_dir());
-			if(file_exists(buf.buf)) {
-				options.type = REBASE_MERGE;
-				options.flags |= REBASE_INTERACTIVE_EXPLICIT;
-			} else
-				options.type = REBASE_MERGE;
-		}
-		options.state_dir = merge_dir();
-	}
-
-	if (options.type != REBASE_UNSPECIFIED)
-		in_progress = 1;
-
-	total_argc = argc;
-	argc = parse_options(argc, argv, prefix,
-			     builtin_rebase_options,
-			     builtin_rebase_usage, 0);
-
-	if (action != ACTION_NONE && total_argc != 2) {
-		usage_with_options(builtin_rebase_usage,
-				   builtin_rebase_options);
-	}
-
-	if (argc > 2)
-		usage_with_options(builtin_rebase_usage,
-				   builtin_rebase_options);
-
-	if (options.type == REBASE_PRESERVE_MERGES)
-		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 (options.root && fork_point > 0)
-		die(_("cannot combine '--root' with '--fork-point'"));
-
-	if (action != ACTION_NONE && !in_progress)
-		die(_("No rebase in progress?"));
-	setenv(GIT_REFLOG_ACTION_ENVIRONMENT, "rebase", 0);
-
-	if (action == ACTION_EDIT_TODO && !is_merge(&options))
-		die(_("The --edit-todo action can only be used during "
-		      "interactive rebase."));
-
-	if (trace2_is_enabled()) {
-		if (is_merge(&options))
-			trace2_cmd_mode("interactive");
-		else if (exec.nr)
-			trace2_cmd_mode("interactive-exec");
-		else
-			trace2_cmd_mode(action_names[action]);
-	}
-
-	switch (action) {
-	case ACTION_CONTINUE: {
-		struct object_id head;
-		struct lock_file lock_file = LOCK_INIT;
-		int fd;
-
-		options.action = "continue";
-		set_reflog_action(&options);
-
-		/* Sanity check */
-		if (get_oid("HEAD", &head))
-			die(_("Cannot read HEAD"));
-
-		fd = hold_locked_index(&lock_file, 0);
-		if (repo_read_index(the_repository) < 0)
-			die(_("could not read index"));
-		refresh_index(the_repository->index, REFRESH_QUIET, NULL, NULL,
-			      NULL);
-		if (0 <= fd)
-			repo_update_index_if_able(the_repository, &lock_file);
-		rollback_lock_file(&lock_file);
-
-		if (has_unstaged_changes(the_repository, 1)) {
-			puts(_("You must edit all merge conflicts and then\n"
-			       "mark them as resolved using git add"));
-			exit(1);
-		}
-		if (read_basic_state(&options))
-			exit(1);
-		goto run_rebase;
-	}
-	case ACTION_SKIP: {
-		struct string_list merge_rr = STRING_LIST_INIT_DUP;
-
-		options.action = "skip";
-		set_reflog_action(&options);
-
-		rerere_clear(the_repository, &merge_rr);
-		string_list_clear(&merge_rr, 1);
-
-		if (reset_head(the_repository, NULL, "reset", NULL, RESET_HEAD_HARD,
-			       NULL, NULL, DEFAULT_REFLOG_ACTION) < 0)
-			die(_("could not discard worktree changes"));
-		remove_branch_state(the_repository, 0);
-		if (read_basic_state(&options))
-			exit(1);
-		goto run_rebase;
-	}
-	case ACTION_ABORT: {
-		struct string_list merge_rr = STRING_LIST_INIT_DUP;
-		options.action = "abort";
-		set_reflog_action(&options);
-
-		rerere_clear(the_repository, &merge_rr);
-		string_list_clear(&merge_rr, 1);
-
-		if (read_basic_state(&options))
-			exit(1);
-		if (reset_head(the_repository, &options.orig_head, "reset",
-			       options.head_name, RESET_HEAD_HARD,
-			       NULL, NULL, DEFAULT_REFLOG_ACTION) < 0)
-			die(_("could not move back to %s"),
-			    oid_to_hex(&options.orig_head));
-		remove_branch_state(the_repository, 0);
-		ret = !!finish_rebase(&options);
-		goto cleanup;
-	}
-	case ACTION_QUIT: {
-		save_autostash(state_dir_path("autostash", &options));
-		if (options.type == REBASE_MERGE) {
-			struct replay_opts replay = REPLAY_OPTS_INIT;
-
-			replay.action = REPLAY_INTERACTIVE_REBASE;
-			ret = !!sequencer_remove_state(&replay);
-		} else {
-			strbuf_reset(&buf);
-			strbuf_addstr(&buf, options.state_dir);
-			ret = !!remove_dir_recursively(&buf, 0);
-			if (ret)
-				error(_("could not remove '%s'"),
-				       options.state_dir);
-		}
-		goto cleanup;
-	}
-	case ACTION_EDIT_TODO:
-		options.action = "edit-todo";
-		options.dont_finish_rebase = 1;
-		goto run_rebase;
-	case ACTION_SHOW_CURRENT_PATCH:
-		options.action = "show-current-patch";
-		options.dont_finish_rebase = 1;
-		goto run_rebase;
-	case ACTION_NONE:
-		break;
-	default:
-		BUG("action: %d", action);
-	}
-
-	/* Make sure no rebase is in progress */
-	if (in_progress) {
-		const char *last_slash = strrchr(options.state_dir, '/');
-		const char *state_dir_base =
-			last_slash ? last_slash + 1 : options.state_dir;
-		const char *cmd_live_rebase =
-			"git rebase (--continue | --abort | --skip)";
-		strbuf_reset(&buf);
-		strbuf_addf(&buf, "rm -fr \"%s\"", options.state_dir);
-		die(_("It seems that there is already a %s directory, and\n"
-		      "I wonder if you are in the middle of another rebase.  "
-		      "If that is the\n"
-		      "case, please try\n\t%s\n"
-		      "If that is not the case, please\n\t%s\n"
-		      "and run me again.  I am stopping in case you still "
-		      "have something\n"
-		      "valuable there.\n"),
-		    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;
-	}
-	if (options.committer_date_is_author_date || options.ignore_date)
-		options.flags |= REBASE_FORCE;
-
-	for (i = 0; i < options.git_am_opts.nr; i++) {
-		const char *option = options.git_am_opts.v[i], *p;
-		if (!strcmp(option, "--whitespace=fix") ||
-		    !strcmp(option, "--whitespace=strip"))
-			allow_preemptive_ff = 0;
-		else if (skip_prefix(option, "-C", &p)) {
-			while (*p)
-				if (!isdigit(*(p++)))
-					die(_("switch `C' expects a "
-					      "numerical value"));
-		} else if (skip_prefix(option, "--whitespace=", &p)) {
-			if (*p && strcmp(p, "warn") && strcmp(p, "nowarn") &&
-			    strcmp(p, "error") && strcmp(p, "error-all"))
-				die("Invalid whitespace option: '%s'", p);
-		}
-	}
-
-	for (i = 0; i < exec.nr; i++)
-		if (check_exec_cmd(exec.items[i].string))
-			exit(1);
-
-	if (!(options.flags & REBASE_NO_QUIET))
-		strvec_push(&options.git_am_opts, "-q");
-
-	if (options.empty != EMPTY_UNSPECIFIED)
-		imply_merge(&options, "--empty");
-
-	if (options.reapply_cherry_picks)
-		imply_merge(&options, "--reapply-cherry-picks");
-
-	if (gpg_sign)
-		options.gpg_sign_opt = xstrfmt("-S%s", gpg_sign);
-
-	if (exec.nr) {
-		int i;
-
-		imply_merge(&options, "--exec");
-
-		strbuf_reset(&buf);
-		for (i = 0; i < exec.nr; i++)
-			strbuf_addf(&buf, "exec %s\n", exec.items[i].string);
-		options.cmd = xstrdup(buf.buf);
-	}
-
-	if (rebase_merges) {
-		if (!*rebase_merges)
-			; /* default mode; do nothing */
-		else if (!strcmp("rebase-cousins", rebase_merges))
-			options.rebase_cousins = 1;
-		else if (strcmp("no-rebase-cousins", rebase_merges))
-			die(_("Unknown mode: %s"), rebase_merges);
-		options.rebase_merges = 1;
-		imply_merge(&options, "--rebase-merges");
-	}
-
-	if (options.type == REBASE_APPLY) {
-		if (ignore_whitespace)
-			strvec_push(&options.git_am_opts,
-				    "--ignore-whitespace");
-		if (options.committer_date_is_author_date)
-			strvec_push(&options.git_am_opts,
-				    "--committer-date-is-author-date");
-		if (options.ignore_date)
-			strvec_push(&options.git_am_opts, "--ignore-date");
-	} else {
-		/* REBASE_MERGE and PRESERVE_MERGES */
-		if (ignore_whitespace) {
-			string_list_append(&strategy_options,
-					   "ignore-space-change");
-		}
-	}
-
-	if (strategy_options.nr) {
-		int i;
-
-		if (!options.strategy)
-			options.strategy = "recursive";
-
-		strbuf_reset(&buf);
-		for (i = 0; i < strategy_options.nr; i++)
-			strbuf_addf(&buf, " --%s",
-				    strategy_options.items[i].string);
-		options.strategy_opts = xstrdup(buf.buf);
-	}
-
-	if (options.strategy) {
-		options.strategy = xstrdup(options.strategy);
-		switch (options.type) {
-		case REBASE_APPLY:
-			die(_("--strategy requires --merge or --interactive"));
-		case REBASE_MERGE:
-		case REBASE_PRESERVE_MERGES:
-			/* compatible */
-			break;
-		case REBASE_UNSPECIFIED:
-			options.type = REBASE_MERGE;
-			break;
-		default:
-			BUG("unhandled rebase type (%d)", options.type);
-		}
-	}
-
-	if (options.type == REBASE_MERGE)
-		imply_merge(&options, "--merge");
-
-	if (options.root && !options.onto_name)
-		imply_merge(&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.nr || options.type == REBASE_APPLY) {
-		/* all am options except -q are compatible only with --apply */
-		for (i = options.git_am_opts.nr - 1; i >= 0; i--)
-			if (strcmp(options.git_am_opts.v[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_PRESERVE_MERGES:
-		options.state_dir = merge_dir();
-		break;
-	case REBASE_APPLY:
-		options.state_dir = apply_dir();
-		break;
-	default:
-		BUG("options.type was just set above; should be unreachable.");
-	}
-
-	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))
-		die(_("--reschedule-failed-exec requires "
-		      "--exec or --interactive"));
-	if (reschedule_failed_exec >= 0)
-		options.reschedule_failed_exec = reschedule_failed_exec;
-
-	if (options.signoff) {
-		if (options.type == REBASE_PRESERVE_MERGES)
-			die("cannot combine '--signoff' with "
-			    "'--preserve-merges'");
-		strvec_push(&options.git_am_opts, "--signoff");
-		options.flags |= REBASE_FORCE;
-	}
-
-	if (options.type == REBASE_PRESERVE_MERGES) {
-		/*
-		 * Note: incompatibility with --signoff handled in signoff block above
-		 * Note: incompatibility with --interactive is just a strong warning;
-		 *       git-rebase.txt caveats with "unless you know what you are doing"
-		 */
-		if (options.rebase_merges)
-			die(_("cannot combine '--preserve-merges' with "
-			      "'--rebase-merges'"));
-
-		if (options.reschedule_failed_exec)
-			die(_("error: cannot combine '--preserve-merges' with "
-			      "'--reschedule-failed-exec'"));
-	}
-
-	if (!options.root) {
-		if (argc < 1) {
-			struct branch *branch;
-
-			branch = branch_get(NULL);
-			options.upstream_name = branch_get_upstream(branch,
-								    NULL);
-			if (!options.upstream_name)
-				error_on_missing_default_upstream();
-			if (fork_point < 0)
-				fork_point = 1;
-		} else {
-			options.upstream_name = argv[0];
-			argc--;
-			argv++;
-			if (!strcmp(options.upstream_name, "-"))
-				options.upstream_name = "@{-1}";
-		}
-		options.upstream = peel_committish(options.upstream_name);
-		if (!options.upstream)
-			die(_("invalid upstream '%s'"), options.upstream_name);
-		options.upstream_arg = options.upstream_name;
-	} else {
-		if (!options.onto_name) {
-			if (commit_tree("", 0, the_hash_algo->empty_tree, NULL,
-					&squash_onto, NULL, NULL) < 0)
-				die(_("Could not create new root commit"));
-			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)
-			usage_with_options(builtin_rebase_usage,
-					   builtin_rebase_options);
-		options.upstream_arg = "--root";
-	}
-
-	/* 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)
-		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);
-		}
-		options.onto = lookup_commit_or_die(&merge_base,
-						    options.onto_name);
-	} else {
-		options.onto = peel_committish(options.onto_name);
-		if (!options.onto)
-			die(_("Does not point to a valid commit '%s'"),
-				options.onto_name);
-	}
-
-	/*
-	 * If the branch to rebase is given, that is the branch we will rebase
-	 * branch_name -- branch/commit being rebased, or
-	 * 		  HEAD (already detached)
-	 * orig_head -- commit object name of tip of the branch before rebasing
-	 * head_name -- refs/heads/<that-branch> or NULL (detached HEAD)
-	 */
-	if (argc == 1) {
-		/* Is it "rebase other branchname" or "rebase other commit"? */
-		branch_name = argv[0];
-		options.switch_to = argv[0];
-
-		/* 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);
-			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))
-			options.head_name = NULL;
-		else
-			die(_("fatal: no such branch/commit '%s'"),
-			    branch_name);
-	} else if (argc == 0) {
-		/* Do not need to switch branches, we are already on it. */
-		options.head_name =
-			xstrdup_or_null(resolve_ref_unsafe("HEAD", 0, NULL,
-					 &flags));
-		if (!options.head_name)
-			die(_("No such ref: %s"), "HEAD");
-		if (flags & REF_ISSYMREF) {
-			if (!skip_prefix(options.head_name,
-					 "refs/heads/", &branch_name))
-				branch_name = options.head_name;
-
-		} else {
-			FREE_AND_NULL(options.head_name);
-			branch_name = "HEAD";
-		}
-		if (get_oid("HEAD", &options.orig_head))
-			die(_("Could not resolve HEAD to a revision"));
-	} else
-		BUG("unexpected number of arguments left to parse");
-
-	if (fork_point > 0) {
-		struct commit *head =
-			lookup_commit_reference(the_repository,
-						&options.orig_head);
-		options.restrict_revision =
-			get_fork_point(options.upstream_name, head);
-	}
-
-	if (repo_read_index(the_repository) < 0)
-		die(_("could not read index"));
-
-	if (options.autostash) {
-		create_autostash(the_repository, state_dir_path("autostash", &options),
-				 DEFAULT_REFLOG_ACTION);
-	}
-
-	if (require_clean_work_tree(the_repository, "rebase",
-				    _("Please commit or stash them."), 1, 1)) {
-		ret = 1;
-		goto cleanup;
-	}
-
-	/*
-	 * Now we are rebasing commits upstream..orig_head (or with --root,
-	 * everything leading up to orig_head) on top of onto.
-	 */
-
-	/*
-	 * 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.
-	 */
-	if (can_fast_forward(options.onto, options.upstream, options.restrict_revision,
-		    &options.orig_head, &merge_base) &&
-	    allow_preemptive_ff) {
-		int flag;
-
-		if (!(options.flags & REBASE_FORCE)) {
-			/* Lazily switch to the target branch if needed... */
-			if (options.switch_to) {
-				strbuf_reset(&buf);
-				strbuf_addf(&buf, "%s: checkout %s",
-					    getenv(GIT_REFLOG_ACTION_ENVIRONMENT),
-					    options.switch_to);
-				if (reset_head(the_repository,
-					       &options.orig_head, "checkout",
-					       options.head_name,
-					       RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
-					       NULL, buf.buf,
-					       DEFAULT_REFLOG_ACTION) < 0) {
-					ret = !!error(_("could not switch to "
-							"%s"),
-						      options.switch_to);
-					goto cleanup;
-				}
-			}
-
-			if (!(options.flags & REBASE_NO_QUIET))
-				; /* be quiet */
-			else if (!strcmp(branch_name, "HEAD") &&
-				 resolve_ref_unsafe("HEAD", 0, NULL, &flag))
-				puts(_("HEAD is up to date."));
-			else
-				printf(_("Current branch %s is up to date.\n"),
-				       branch_name);
-			ret = !!finish_rebase(&options);
-			goto cleanup;
-		} else if (!(options.flags & REBASE_NO_QUIET))
-			; /* be quiet */
-		else if (!strcmp(branch_name, "HEAD") &&
-			 resolve_ref_unsafe("HEAD", 0, NULL, &flag))
-			puts(_("HEAD is up to date, rebase forced."));
-		else
-			printf(_("Current branch %s is up to date, rebase "
-				 "forced.\n"), branch_name);
-	}
-
-	/* If a hook exists, give it a chance to interrupt*/
-	if (!ok_to_skip_pre_rebase &&
-	    run_hook_le(NULL, "pre-rebase", options.upstream_arg,
-			argc ? argv[0] : NULL, NULL))
-		die(_("The pre-rebase hook refused to rebase."));
-
-	if (options.flags & REBASE_DIFFSTAT) {
-		struct diff_options opts;
-
-		if (options.flags & REBASE_VERBOSE) {
-			if (is_null_oid(&merge_base))
-				printf(_("Changes to %s:\n"),
-				       oid_to_hex(&options.onto->object.oid));
-			else
-				printf(_("Changes from %s to %s:\n"),
-				       oid_to_hex(&merge_base),
-				       oid_to_hex(&options.onto->object.oid));
-		}
-
-		/* We want color (if set), but no pager */
-		diff_setup(&opts);
-		opts.stat_width = -1; /* use full terminal width */
-		opts.stat_graph_width = -1; /* respect statGraphWidth config */
-		opts.output_format |=
-			DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
-		opts.detect_rename = DIFF_DETECT_RENAME;
-		diff_setup_done(&opts);
-		diff_tree_oid(is_null_oid(&merge_base) ?
-			      the_hash_algo->empty_tree : &merge_base,
-			      &options.onto->object.oid, "", &opts);
-		diffcore_std(&opts);
-		diff_flush(&opts);
-	}
-
-	if (is_merge(&options))
-		goto run_rebase;
-
-	/* Detach HEAD and reset the tree */
-	if (options.flags & REBASE_NO_QUIET)
-		printf(_("First, rewinding head to replay your work on top of "
-			 "it...\n"));
-
-	strbuf_addf(&msg, "%s: checkout %s",
-		    getenv(GIT_REFLOG_ACTION_ENVIRONMENT), options.onto_name);
-	if (reset_head(the_repository, &options.onto->object.oid, "checkout", NULL,
-		       RESET_HEAD_DETACH | RESET_ORIG_HEAD |
-		       RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
-		       NULL, msg.buf, DEFAULT_REFLOG_ACTION))
-		die(_("Could not detach HEAD"));
-	strbuf_release(&msg);
-
-	/*
-	 * If the onto is a proper descendant of the tip of the branch, then
-	 * we just fast-forwarded.
-	 */
-	strbuf_reset(&msg);
-	if (oideq(&merge_base, &options.orig_head)) {
-		printf(_("Fast-forwarded %s to %s.\n"),
-			branch_name, options.onto_name);
-		strbuf_addf(&msg, "rebase finished: %s onto %s",
-			options.head_name ? options.head_name : "detached HEAD",
-			oid_to_hex(&options.onto->object.oid));
-		reset_head(the_repository, NULL, "Fast-forwarded", options.head_name,
-			   RESET_HEAD_REFS_ONLY, "HEAD", msg.buf,
-			   DEFAULT_REFLOG_ACTION);
-		strbuf_release(&msg);
-		ret = !!finish_rebase(&options);
-		goto cleanup;
-	}
-
-	strbuf_addf(&revisions, "%s..%s",
-		    options.root ? oid_to_hex(&options.onto->object.oid) :
-		    (options.restrict_revision ?
-		     oid_to_hex(&options.restrict_revision->object.oid) :
-		     oid_to_hex(&options.upstream->object.oid)),
-		    oid_to_hex(&options.orig_head));
-
-	options.revisions = revisions.buf;
-
-run_rebase:
-	ret = !!run_specific_rebase(&options, action);
-
-cleanup:
-	strbuf_release(&buf);
-	strbuf_release(&revisions);
-	free(options.head_name);
-	free(options.gpg_sign_opt);
-	free(options.cmd);
-	free(squash_onto_name);
-	return ret;
-}
diff --git a/third_party/git/builtin/receive-pack.c b/third_party/git/builtin/receive-pack.c
deleted file mode 100644
index bb9909c52e4e..000000000000
--- a/third_party/git/builtin/receive-pack.c
+++ /dev/null
@@ -1,2547 +0,0 @@
-#include "builtin.h"
-#include "repository.h"
-#include "config.h"
-#include "lockfile.h"
-#include "pack.h"
-#include "refs.h"
-#include "pkt-line.h"
-#include "sideband.h"
-#include "run-command.h"
-#include "exec-cmd.h"
-#include "commit.h"
-#include "object.h"
-#include "remote.h"
-#include "connect.h"
-#include "string-list.h"
-#include "oid-array.h"
-#include "connected.h"
-#include "strvec.h"
-#include "version.h"
-#include "tag.h"
-#include "gpg-interface.h"
-#include "sigchain.h"
-#include "fsck.h"
-#include "tmp-objdir.h"
-#include "oidset.h"
-#include "packfile.h"
-#include "object-store.h"
-#include "protocol.h"
-#include "commit-reach.h"
-#include "worktree.h"
-#include "shallow.h"
-
-static const char * const receive_pack_usage[] = {
-	N_("git receive-pack <git-dir>"),
-	NULL
-};
-
-enum deny_action {
-	DENY_UNCONFIGURED,
-	DENY_IGNORE,
-	DENY_WARN,
-	DENY_REFUSE,
-	DENY_UPDATE_INSTEAD
-};
-
-static int deny_deletes;
-static int deny_non_fast_forwards;
-static enum deny_action deny_current_branch = DENY_UNCONFIGURED;
-static enum deny_action deny_delete_current = DENY_UNCONFIGURED;
-static int receive_fsck_objects = -1;
-static int transfer_fsck_objects = -1;
-static struct strbuf fsck_msg_types = STRBUF_INIT;
-static int receive_unpack_limit = -1;
-static int transfer_unpack_limit = -1;
-static int advertise_atomic_push = 1;
-static int advertise_push_options;
-static int unpack_limit = 100;
-static off_t max_input_size;
-static int report_status;
-static int report_status_v2;
-static int use_sideband;
-static int use_atomic;
-static int use_push_options;
-static int quiet;
-static int prefer_ofs_delta = 1;
-static int auto_update_server_info;
-static int auto_gc = 1;
-static int reject_thin;
-static int stateless_rpc;
-static const char *service_dir;
-static const char *head_name;
-static void *head_name_to_free;
-static int sent_capabilities;
-static int shallow_update;
-static const char *alt_shallow_file;
-static struct strbuf push_cert = STRBUF_INIT;
-static struct object_id push_cert_oid;
-static struct signature_check sigcheck;
-static const char *push_cert_nonce;
-static const char *cert_nonce_seed;
-
-static const char *NONCE_UNSOLICITED = "UNSOLICITED";
-static const char *NONCE_BAD = "BAD";
-static const char *NONCE_MISSING = "MISSING";
-static const char *NONCE_OK = "OK";
-static const char *NONCE_SLOP = "SLOP";
-static const char *nonce_status;
-static long nonce_stamp_slop;
-static timestamp_t nonce_stamp_slop_limit;
-static struct ref_transaction *transaction;
-
-static enum {
-	KEEPALIVE_NEVER = 0,
-	KEEPALIVE_AFTER_NUL,
-	KEEPALIVE_ALWAYS
-} use_keepalive;
-static int keepalive_in_sec = 5;
-
-static struct tmp_objdir *tmp_objdir;
-
-static struct proc_receive_ref {
-	unsigned int want_add:1,
-		     want_delete:1,
-		     want_modify:1,
-		     negative_ref:1;
-	char *ref_prefix;
-	struct proc_receive_ref *next;
-} *proc_receive_ref;
-
-static void proc_receive_ref_append(const char *prefix);
-
-static enum deny_action parse_deny_action(const char *var, const char *value)
-{
-	if (value) {
-		if (!strcasecmp(value, "ignore"))
-			return DENY_IGNORE;
-		if (!strcasecmp(value, "warn"))
-			return DENY_WARN;
-		if (!strcasecmp(value, "refuse"))
-			return DENY_REFUSE;
-		if (!strcasecmp(value, "updateinstead"))
-			return DENY_UPDATE_INSTEAD;
-	}
-	if (git_config_bool(var, value))
-		return DENY_REFUSE;
-	return DENY_IGNORE;
-}
-
-static int receive_pack_config(const char *var, const char *value, void *cb)
-{
-	int status = parse_hide_refs_config(var, value, "receive");
-
-	if (status)
-		return status;
-
-	if (strcmp(var, "receive.denydeletes") == 0) {
-		deny_deletes = git_config_bool(var, value);
-		return 0;
-	}
-
-	if (strcmp(var, "receive.denynonfastforwards") == 0) {
-		deny_non_fast_forwards = git_config_bool(var, value);
-		return 0;
-	}
-
-	if (strcmp(var, "receive.unpacklimit") == 0) {
-		receive_unpack_limit = git_config_int(var, value);
-		return 0;
-	}
-
-	if (strcmp(var, "transfer.unpacklimit") == 0) {
-		transfer_unpack_limit = git_config_int(var, value);
-		return 0;
-	}
-
-	if (strcmp(var, "receive.fsck.skiplist") == 0) {
-		const char *path;
-
-		if (git_config_pathname(&path, var, value))
-			return 1;
-		strbuf_addf(&fsck_msg_types, "%cskiplist=%s",
-			fsck_msg_types.len ? ',' : '=', path);
-		free((char *)path);
-		return 0;
-	}
-
-	if (skip_prefix(var, "receive.fsck.", &var)) {
-		if (is_valid_msg_type(var, value))
-			strbuf_addf(&fsck_msg_types, "%c%s=%s",
-				fsck_msg_types.len ? ',' : '=', var, value);
-		else
-			warning("Skipping unknown msg id '%s'", var);
-		return 0;
-	}
-
-	if (strcmp(var, "receive.fsckobjects") == 0) {
-		receive_fsck_objects = git_config_bool(var, value);
-		return 0;
-	}
-
-	if (strcmp(var, "transfer.fsckobjects") == 0) {
-		transfer_fsck_objects = git_config_bool(var, value);
-		return 0;
-	}
-
-	if (!strcmp(var, "receive.denycurrentbranch")) {
-		deny_current_branch = parse_deny_action(var, value);
-		return 0;
-	}
-
-	if (strcmp(var, "receive.denydeletecurrent") == 0) {
-		deny_delete_current = parse_deny_action(var, value);
-		return 0;
-	}
-
-	if (strcmp(var, "repack.usedeltabaseoffset") == 0) {
-		prefer_ofs_delta = git_config_bool(var, value);
-		return 0;
-	}
-
-	if (strcmp(var, "receive.updateserverinfo") == 0) {
-		auto_update_server_info = git_config_bool(var, value);
-		return 0;
-	}
-
-	if (strcmp(var, "receive.autogc") == 0) {
-		auto_gc = git_config_bool(var, value);
-		return 0;
-	}
-
-	if (strcmp(var, "receive.shallowupdate") == 0) {
-		shallow_update = git_config_bool(var, value);
-		return 0;
-	}
-
-	if (strcmp(var, "receive.certnonceseed") == 0)
-		return git_config_string(&cert_nonce_seed, var, value);
-
-	if (strcmp(var, "receive.certnonceslop") == 0) {
-		nonce_stamp_slop_limit = git_config_ulong(var, value);
-		return 0;
-	}
-
-	if (strcmp(var, "receive.advertiseatomic") == 0) {
-		advertise_atomic_push = git_config_bool(var, value);
-		return 0;
-	}
-
-	if (strcmp(var, "receive.advertisepushoptions") == 0) {
-		advertise_push_options = git_config_bool(var, value);
-		return 0;
-	}
-
-	if (strcmp(var, "receive.keepalive") == 0) {
-		keepalive_in_sec = git_config_int(var, value);
-		return 0;
-	}
-
-	if (strcmp(var, "receive.maxinputsize") == 0) {
-		max_input_size = git_config_int64(var, value);
-		return 0;
-	}
-
-	if (strcmp(var, "receive.procreceiverefs") == 0) {
-		if (!value)
-			return config_error_nonbool(var);
-		proc_receive_ref_append(value);
-		return 0;
-	}
-
-	return git_default_config(var, value, cb);
-}
-
-static void show_ref(const char *path, const struct object_id *oid)
-{
-	if (sent_capabilities) {
-		packet_write_fmt(1, "%s %s\n", oid_to_hex(oid), path);
-	} else {
-		struct strbuf cap = STRBUF_INIT;
-
-		strbuf_addstr(&cap,
-			      "report-status report-status-v2 delete-refs side-band-64k quiet");
-		if (advertise_atomic_push)
-			strbuf_addstr(&cap, " atomic");
-		if (prefer_ofs_delta)
-			strbuf_addstr(&cap, " ofs-delta");
-		if (push_cert_nonce)
-			strbuf_addf(&cap, " push-cert=%s", push_cert_nonce);
-		if (advertise_push_options)
-			strbuf_addstr(&cap, " push-options");
-		strbuf_addf(&cap, " object-format=%s", the_hash_algo->name);
-		strbuf_addf(&cap, " agent=%s", git_user_agent_sanitized());
-		packet_write_fmt(1, "%s %s%c%s\n",
-			     oid_to_hex(oid), path, 0, cap.buf);
-		strbuf_release(&cap);
-		sent_capabilities = 1;
-	}
-}
-
-static int show_ref_cb(const char *path_full, const struct object_id *oid,
-		       int flag, void *data)
-{
-	struct oidset *seen = data;
-	const char *path = strip_namespace(path_full);
-
-	if (ref_is_hidden(path, path_full))
-		return 0;
-
-	/*
-	 * Advertise refs outside our current namespace as ".have"
-	 * refs, so that the client can use them to minimize data
-	 * transfer but will otherwise ignore them.
-	 */
-	if (!path) {
-		if (oidset_insert(seen, oid))
-			return 0;
-		path = ".have";
-	} else {
-		oidset_insert(seen, oid);
-	}
-	show_ref(path, oid);
-	return 0;
-}
-
-static void show_one_alternate_ref(const struct object_id *oid,
-				   void *data)
-{
-	struct oidset *seen = data;
-
-	if (oidset_insert(seen, oid))
-		return;
-
-	show_ref(".have", oid);
-}
-
-static void write_head_info(void)
-{
-	static struct oidset seen = OIDSET_INIT;
-
-	for_each_ref(show_ref_cb, &seen);
-	for_each_alternate_ref(show_one_alternate_ref, &seen);
-	oidset_clear(&seen);
-	if (!sent_capabilities)
-		show_ref("capabilities^{}", &null_oid);
-
-	advertise_shallow_grafts(1);
-
-	/* EOF */
-	packet_flush(1);
-}
-
-#define RUN_PROC_RECEIVE_SCHEDULED	1
-#define RUN_PROC_RECEIVE_RETURNED	2
-struct command {
-	struct command *next;
-	const char *error_string;
-	struct ref_push_report *report;
-	unsigned int skip_update:1,
-		     did_not_exist:1,
-		     run_proc_receive:2;
-	int index;
-	struct object_id old_oid;
-	struct object_id new_oid;
-	char ref_name[FLEX_ARRAY]; /* more */
-};
-
-static void proc_receive_ref_append(const char *prefix)
-{
-	struct proc_receive_ref *ref_pattern;
-	char *p;
-	int len;
-
-	ref_pattern = xcalloc(1, sizeof(struct proc_receive_ref));
-	p = strchr(prefix, ':');
-	if (p) {
-		while (prefix < p) {
-			if (*prefix == 'a')
-				ref_pattern->want_add = 1;
-			else if (*prefix == 'd')
-				ref_pattern->want_delete = 1;
-			else if (*prefix == 'm')
-				ref_pattern->want_modify = 1;
-			else if (*prefix == '!')
-				ref_pattern->negative_ref = 1;
-			prefix++;
-		}
-		prefix++;
-	} else {
-		ref_pattern->want_add = 1;
-		ref_pattern->want_delete = 1;
-		ref_pattern->want_modify = 1;
-	}
-	len = strlen(prefix);
-	while (len && prefix[len - 1] == '/')
-		len--;
-	ref_pattern->ref_prefix = xmemdupz(prefix, len);
-	if (!proc_receive_ref) {
-		proc_receive_ref = ref_pattern;
-	} else {
-		struct proc_receive_ref *end;
-
-		end = proc_receive_ref;
-		while (end->next)
-			end = end->next;
-		end->next = ref_pattern;
-	}
-}
-
-static int proc_receive_ref_matches(struct command *cmd)
-{
-	struct proc_receive_ref *p;
-
-	if (!proc_receive_ref)
-		return 0;
-
-	for (p = proc_receive_ref; p; p = p->next) {
-		const char *match = p->ref_prefix;
-		const char *remains;
-
-		if (!p->want_add && is_null_oid(&cmd->old_oid))
-			continue;
-		else if (!p->want_delete && is_null_oid(&cmd->new_oid))
-			continue;
-		else if (!p->want_modify &&
-			 !is_null_oid(&cmd->old_oid) &&
-			 !is_null_oid(&cmd->new_oid))
-			continue;
-
-		if (skip_prefix(cmd->ref_name, match, &remains) &&
-		    (!*remains || *remains == '/')) {
-			if (!p->negative_ref)
-				return 1;
-		} else if (p->negative_ref) {
-			return 1;
-		}
-	}
-	return 0;
-}
-
-static void rp_error(const char *err, ...) __attribute__((format (printf, 1, 2)));
-static void rp_warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
-
-static void report_message(const char *prefix, const char *err, va_list params)
-{
-	int sz;
-	char msg[4096];
-
-	sz = xsnprintf(msg, sizeof(msg), "%s", prefix);
-	sz += vsnprintf(msg + sz, sizeof(msg) - sz, err, params);
-	if (sz > (sizeof(msg) - 1))
-		sz = sizeof(msg) - 1;
-	msg[sz++] = '\n';
-
-	if (use_sideband)
-		send_sideband(1, 2, msg, sz, use_sideband);
-	else
-		xwrite(2, msg, sz);
-}
-
-static void rp_warning(const char *err, ...)
-{
-	va_list params;
-	va_start(params, err);
-	report_message("warning: ", err, params);
-	va_end(params);
-}
-
-static void rp_error(const char *err, ...)
-{
-	va_list params;
-	va_start(params, err);
-	report_message("error: ", err, params);
-	va_end(params);
-}
-
-static int copy_to_sideband(int in, int out, void *arg)
-{
-	char data[128];
-	int keepalive_active = 0;
-
-	if (keepalive_in_sec <= 0)
-		use_keepalive = KEEPALIVE_NEVER;
-	if (use_keepalive == KEEPALIVE_ALWAYS)
-		keepalive_active = 1;
-
-	while (1) {
-		ssize_t sz;
-
-		if (keepalive_active) {
-			struct pollfd pfd;
-			int ret;
-
-			pfd.fd = in;
-			pfd.events = POLLIN;
-			ret = poll(&pfd, 1, 1000 * keepalive_in_sec);
-
-			if (ret < 0) {
-				if (errno == EINTR)
-					continue;
-				else
-					break;
-			} else if (ret == 0) {
-				/* no data; send a keepalive packet */
-				static const char buf[] = "0005\1";
-				write_or_die(1, buf, sizeof(buf) - 1);
-				continue;
-			} /* else there is actual data to read */
-		}
-
-		sz = xread(in, data, sizeof(data));
-		if (sz <= 0)
-			break;
-
-		if (use_keepalive == KEEPALIVE_AFTER_NUL && !keepalive_active) {
-			const char *p = memchr(data, '\0', sz);
-			if (p) {
-				/*
-				 * The NUL tells us to start sending keepalives. Make
-				 * sure we send any other data we read along
-				 * with it.
-				 */
-				keepalive_active = 1;
-				send_sideband(1, 2, data, p - data, use_sideband);
-				send_sideband(1, 2, p + 1, sz - (p - data + 1), use_sideband);
-				continue;
-			}
-		}
-
-		/*
-		 * Either we're not looking for a NUL signal, or we didn't see
-		 * it yet; just pass along the data.
-		 */
-		send_sideband(1, 2, data, sz, use_sideband);
-	}
-	close(in);
-	return 0;
-}
-
-static void hmac_hash(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];
-	int i;
-	git_hash_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);
-	} else {
-		memcpy(key, key_in, key_len);
-	}
-
-	/* RFC 2104 2. (2) & (5) */
-	for (i = 0; i < sizeof(key); i++) {
-		k_ipad[i] = key[i] ^ 0x36;
-		k_opad[i] = key[i] ^ 0x5c;
-	}
-
-	/* 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);
-
-	/* 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);
-}
-
-static char *prepare_push_cert_nonce(const char *path, timestamp_t stamp)
-{
-	struct strbuf buf = STRBUF_INIT;
-	unsigned char hash[GIT_MAX_RAWSZ];
-
-	strbuf_addf(&buf, "%s:%"PRItime, path, stamp);
-	hmac_hash(hash, buf.buf, buf.len, cert_nonce_seed, strlen(cert_nonce_seed));
-	strbuf_release(&buf);
-
-	/* RFC 2104 5. HMAC-SHA1 or HMAC-SHA256 */
-	strbuf_addf(&buf, "%"PRItime"-%.*s", stamp, (int)the_hash_algo->hexsz, hash_to_hex(hash));
-	return strbuf_detach(&buf, NULL);
-}
-
-/*
- * NEEDSWORK: reuse find_commit_header() from jk/commit-author-parsing
- * after dropping "_commit" from its name and possibly moving it out
- * of commit.c
- */
-static char *find_header(const char *msg, size_t len, const char *key,
-			 const char **next_line)
-{
-	int key_len = strlen(key);
-	const char *line = msg;
-
-	while (line && line < msg + len) {
-		const char *eol = strchrnul(line, '\n');
-
-		if ((msg + len <= eol) || line == eol)
-			return NULL;
-		if (line + key_len < eol &&
-		    !memcmp(line, key, key_len) && line[key_len] == ' ') {
-			int offset = key_len + 1;
-			if (next_line)
-				*next_line = *eol ? eol + 1 : eol;
-			return xmemdupz(line + offset, (eol - line) - offset);
-		}
-		line = *eol ? eol + 1 : NULL;
-	}
-	return NULL;
-}
-
-/*
- * Return zero if a and b are equal up to n bytes and nonzero if they are not.
- * This operation is guaranteed to run in constant time to avoid leaking data.
- */
-static int constant_memequal(const char *a, const char *b, size_t n)
-{
-	int res = 0;
-	size_t i;
-
-	for (i = 0; i < n; i++)
-		res |= a[i] ^ b[i];
-	return res;
-}
-
-static const char *check_nonce(const char *buf, size_t len)
-{
-	char *nonce = find_header(buf, len, "nonce", NULL);
-	timestamp_t stamp, ostamp;
-	char *bohmac, *expect = NULL;
-	const char *retval = NONCE_BAD;
-	size_t noncelen;
-
-	if (!nonce) {
-		retval = NONCE_MISSING;
-		goto leave;
-	} else if (!push_cert_nonce) {
-		retval = NONCE_UNSOLICITED;
-		goto leave;
-	} else if (!strcmp(push_cert_nonce, nonce)) {
-		retval = NONCE_OK;
-		goto leave;
-	}
-
-	if (!stateless_rpc) {
-		/* returned nonce MUST match what we gave out earlier */
-		retval = NONCE_BAD;
-		goto leave;
-	}
-
-	/*
-	 * In stateless mode, we may be receiving a nonce issued by
-	 * another instance of the server that serving the same
-	 * repository, and the timestamps may not match, but the
-	 * nonce-seed and dir should match, so we can recompute and
-	 * report the time slop.
-	 *
-	 * In addition, when a nonce issued by another instance has
-	 * timestamp within receive.certnonceslop seconds, we pretend
-	 * as if we issued that nonce when reporting to the hook.
-	 */
-
-	/* nonce is concat(<seconds-since-epoch>, "-", <hmac>) */
-	if (*nonce <= '0' || '9' < *nonce) {
-		retval = NONCE_BAD;
-		goto leave;
-	}
-	stamp = parse_timestamp(nonce, &bohmac, 10);
-	if (bohmac == nonce || bohmac[0] != '-') {
-		retval = NONCE_BAD;
-		goto leave;
-	}
-
-	noncelen = strlen(nonce);
-	expect = prepare_push_cert_nonce(service_dir, stamp);
-	if (noncelen != strlen(expect)) {
-		/* This is not even the right size. */
-		retval = NONCE_BAD;
-		goto leave;
-	}
-	if (constant_memequal(expect, nonce, noncelen)) {
-		/* Not what we would have signed earlier */
-		retval = NONCE_BAD;
-		goto leave;
-	}
-
-	/*
-	 * By how many seconds is this nonce stale?  Negative value
-	 * would mean it was issued by another server with its clock
-	 * skewed in the future.
-	 */
-	ostamp = parse_timestamp(push_cert_nonce, NULL, 10);
-	nonce_stamp_slop = (long)ostamp - (long)stamp;
-
-	if (nonce_stamp_slop_limit &&
-	    labs(nonce_stamp_slop) <= nonce_stamp_slop_limit) {
-		/*
-		 * Pretend as if the received nonce (which passes the
-		 * HMAC check, so it is not a forged by third-party)
-		 * is what we issued.
-		 */
-		free((void *)push_cert_nonce);
-		push_cert_nonce = xstrdup(nonce);
-		retval = NONCE_OK;
-	} else {
-		retval = NONCE_SLOP;
-	}
-
-leave:
-	free(nonce);
-	free(expect);
-	return retval;
-}
-
-/*
- * Return 1 if there is no push_cert or if the push options in push_cert are
- * the same as those in the argument; 0 otherwise.
- */
-static int check_cert_push_options(const struct string_list *push_options)
-{
-	const char *buf = push_cert.buf;
-	int len = push_cert.len;
-
-	char *option;
-	const char *next_line;
-	int options_seen = 0;
-
-	int retval = 1;
-
-	if (!len)
-		return 1;
-
-	while ((option = find_header(buf, len, "push-option", &next_line))) {
-		len -= (next_line - buf);
-		buf = next_line;
-		options_seen++;
-		if (options_seen > push_options->nr
-		    || strcmp(option,
-			      push_options->items[options_seen - 1].string)) {
-			retval = 0;
-			goto leave;
-		}
-		free(option);
-	}
-
-	if (options_seen != push_options->nr)
-		retval = 0;
-
-leave:
-	free(option);
-	return retval;
-}
-
-static void prepare_push_cert_sha1(struct child_process *proc)
-{
-	static int already_done;
-
-	if (!push_cert.len)
-		return;
-
-	if (!already_done) {
-		int bogs /* beginning_of_gpg_sig */;
-
-		already_done = 1;
-		if (write_object_file(push_cert.buf, push_cert.len, "blob",
-				      &push_cert_oid))
-			oidclr(&push_cert_oid);
-
-		memset(&sigcheck, '\0', sizeof(sigcheck));
-
-		bogs = parse_signature(push_cert.buf, push_cert.len);
-		check_signature(push_cert.buf, bogs, push_cert.buf + bogs,
-				push_cert.len - bogs, &sigcheck);
-
-		nonce_status = check_nonce(push_cert.buf, bogs);
-	}
-	if (!is_null_oid(&push_cert_oid)) {
-		strvec_pushf(&proc->env_array, "GIT_PUSH_CERT=%s",
-			     oid_to_hex(&push_cert_oid));
-		strvec_pushf(&proc->env_array, "GIT_PUSH_CERT_SIGNER=%s",
-			     sigcheck.signer ? sigcheck.signer : "");
-		strvec_pushf(&proc->env_array, "GIT_PUSH_CERT_KEY=%s",
-			     sigcheck.key ? sigcheck.key : "");
-		strvec_pushf(&proc->env_array, "GIT_PUSH_CERT_STATUS=%c",
-			     sigcheck.result);
-		if (push_cert_nonce) {
-			strvec_pushf(&proc->env_array,
-				     "GIT_PUSH_CERT_NONCE=%s",
-				     push_cert_nonce);
-			strvec_pushf(&proc->env_array,
-				     "GIT_PUSH_CERT_NONCE_STATUS=%s",
-				     nonce_status);
-			if (nonce_status == NONCE_SLOP)
-				strvec_pushf(&proc->env_array,
-					     "GIT_PUSH_CERT_NONCE_SLOP=%ld",
-					     nonce_stamp_slop);
-		}
-	}
-}
-
-struct receive_hook_feed_state {
-	struct command *cmd;
-	struct ref_push_report *report;
-	int skip_broken;
-	struct strbuf buf;
-	const struct string_list *push_options;
-};
-
-typedef int (*feed_fn)(void *, const char **, size_t *);
-static int run_and_feed_hook(const char *hook_name, feed_fn feed,
-			     struct receive_hook_feed_state *feed_state)
-{
-	struct child_process proc = CHILD_PROCESS_INIT;
-	struct async muxer;
-	const char *argv[2];
-	int code;
-
-	argv[0] = find_hook(hook_name);
-	if (!argv[0])
-		return 0;
-
-	argv[1] = NULL;
-
-	proc.argv = argv;
-	proc.in = -1;
-	proc.stdout_to_stderr = 1;
-	proc.trace2_hook_name = hook_name;
-
-	if (feed_state->push_options) {
-		int i;
-		for (i = 0; i < feed_state->push_options->nr; i++)
-			strvec_pushf(&proc.env_array,
-				     "GIT_PUSH_OPTION_%d=%s", i,
-				     feed_state->push_options->items[i].string);
-		strvec_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT=%d",
-			     feed_state->push_options->nr);
-	} else
-		strvec_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT");
-
-	if (tmp_objdir)
-		strvec_pushv(&proc.env_array, tmp_objdir_env(tmp_objdir));
-
-	if (use_sideband) {
-		memset(&muxer, 0, sizeof(muxer));
-		muxer.proc = copy_to_sideband;
-		muxer.in = -1;
-		code = start_async(&muxer);
-		if (code)
-			return code;
-		proc.err = muxer.in;
-	}
-
-	prepare_push_cert_sha1(&proc);
-
-	code = start_command(&proc);
-	if (code) {
-		if (use_sideband)
-			finish_async(&muxer);
-		return code;
-	}
-
-	sigchain_push(SIGPIPE, SIG_IGN);
-
-	while (1) {
-		const char *buf;
-		size_t n;
-		if (feed(feed_state, &buf, &n))
-			break;
-		if (write_in_full(proc.in, buf, n) < 0)
-			break;
-	}
-	close(proc.in);
-	if (use_sideband)
-		finish_async(&muxer);
-
-	sigchain_pop(SIGPIPE);
-
-	return finish_command(&proc);
-}
-
-static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
-{
-	struct receive_hook_feed_state *state = state_;
-	struct command *cmd = state->cmd;
-
-	while (cmd &&
-	       state->skip_broken && (cmd->error_string || cmd->did_not_exist))
-		cmd = cmd->next;
-	if (!cmd)
-		return -1; /* EOF */
-	if (!bufp)
-		return 0; /* OK, can feed something. */
-	strbuf_reset(&state->buf);
-	if (!state->report)
-		state->report = cmd->report;
-	if (state->report) {
-		struct object_id *old_oid;
-		struct object_id *new_oid;
-		const char *ref_name;
-
-		old_oid = state->report->old_oid ? state->report->old_oid : &cmd->old_oid;
-		new_oid = state->report->new_oid ? state->report->new_oid : &cmd->new_oid;
-		ref_name = state->report->ref_name ? state->report->ref_name : cmd->ref_name;
-		strbuf_addf(&state->buf, "%s %s %s\n",
-			    oid_to_hex(old_oid), oid_to_hex(new_oid),
-			    ref_name);
-		state->report = state->report->next;
-		if (!state->report)
-			state->cmd = cmd->next;
-	} else {
-		strbuf_addf(&state->buf, "%s %s %s\n",
-			    oid_to_hex(&cmd->old_oid), oid_to_hex(&cmd->new_oid),
-			    cmd->ref_name);
-		state->cmd = cmd->next;
-	}
-	if (bufp) {
-		*bufp = state->buf.buf;
-		*sizep = state->buf.len;
-	}
-	return 0;
-}
-
-static int run_receive_hook(struct command *commands,
-			    const char *hook_name,
-			    int skip_broken,
-			    const struct string_list *push_options)
-{
-	struct receive_hook_feed_state state;
-	int status;
-
-	strbuf_init(&state.buf, 0);
-	state.cmd = commands;
-	state.skip_broken = skip_broken;
-	state.report = NULL;
-	if (feed_receive_hook(&state, NULL, NULL))
-		return 0;
-	state.cmd = commands;
-	state.push_options = push_options;
-	status = run_and_feed_hook(hook_name, feed_receive_hook, &state);
-	strbuf_release(&state.buf);
-	return status;
-}
-
-static int run_update_hook(struct command *cmd)
-{
-	const char *argv[5];
-	struct child_process proc = CHILD_PROCESS_INIT;
-	int code;
-
-	argv[0] = find_hook("update");
-	if (!argv[0])
-		return 0;
-
-	argv[1] = cmd->ref_name;
-	argv[2] = oid_to_hex(&cmd->old_oid);
-	argv[3] = oid_to_hex(&cmd->new_oid);
-	argv[4] = NULL;
-
-	proc.no_stdin = 1;
-	proc.stdout_to_stderr = 1;
-	proc.err = use_sideband ? -1 : 0;
-	proc.argv = argv;
-	proc.trace2_hook_name = "update";
-
-	code = start_command(&proc);
-	if (code)
-		return code;
-	if (use_sideband)
-		copy_to_sideband(proc.err, -1, NULL);
-	return finish_command(&proc);
-}
-
-static struct command *find_command_by_refname(struct command *list,
-					       const char *refname)
-{
-	for (; list; list = list->next)
-		if (!strcmp(list->ref_name, refname))
-			return list;
-	return NULL;
-}
-
-static int read_proc_receive_report(struct packet_reader *reader,
-				    struct command *commands,
-				    struct strbuf *errmsg)
-{
-	struct command *cmd;
-	struct command *hint = NULL;
-	struct ref_push_report *report = NULL;
-	int new_report = 0;
-	int code = 0;
-	int once = 0;
-
-	for (;;) {
-		struct object_id old_oid, new_oid;
-		const char *head;
-		const char *refname;
-		char *p;
-
-		if (packet_reader_read(reader) != PACKET_READ_NORMAL)
-			break;
-
-		head = reader->line;
-		p = strchr(head, ' ');
-		if (!p) {
-			strbuf_addf(errmsg, "proc-receive reported incomplete status line: '%s'\n", head);
-			code = -1;
-			continue;
-		}
-		*p++ = '\0';
-		if (!strcmp(head, "option")) {
-			const char *key, *val;
-
-			if (!hint || !(report || new_report)) {
-				if (!once++)
-					strbuf_addstr(errmsg, "proc-receive reported 'option' without a matching 'ok/ng' directive\n");
-				code = -1;
-				continue;
-			}
-			if (new_report) {
-				if (!hint->report) {
-					hint->report = xcalloc(1, sizeof(struct ref_push_report));
-					report = hint->report;
-				} else {
-					report = hint->report;
-					while (report->next)
-						report = report->next;
-					report->next = xcalloc(1, sizeof(struct ref_push_report));
-					report = report->next;
-				}
-				new_report = 0;
-			}
-			key = p;
-			p = strchr(key, ' ');
-			if (p)
-				*p++ = '\0';
-			val = p;
-			if (!strcmp(key, "refname"))
-				report->ref_name = xstrdup_or_null(val);
-			else if (!strcmp(key, "old-oid") && val &&
-				 !parse_oid_hex(val, &old_oid, &val))
-				report->old_oid = oiddup(&old_oid);
-			else if (!strcmp(key, "new-oid") && val &&
-				 !parse_oid_hex(val, &new_oid, &val))
-				report->new_oid = oiddup(&new_oid);
-			else if (!strcmp(key, "forced-update"))
-				report->forced_update = 1;
-			else if (!strcmp(key, "fall-through"))
-				/* Fall through, let 'receive-pack' to execute it. */
-				hint->run_proc_receive = 0;
-			continue;
-		}
-
-		report = NULL;
-		new_report = 0;
-		refname = p;
-		p = strchr(refname, ' ');
-		if (p)
-			*p++ = '\0';
-		if (strcmp(head, "ok") && strcmp(head, "ng")) {
-			strbuf_addf(errmsg, "proc-receive reported bad status '%s' on ref '%s'\n",
-				    head, refname);
-			code = -1;
-			continue;
-		}
-
-		/* first try searching at our hint, falling back to all refs */
-		if (hint)
-			hint = find_command_by_refname(hint, refname);
-		if (!hint)
-			hint = find_command_by_refname(commands, refname);
-		if (!hint) {
-			strbuf_addf(errmsg, "proc-receive reported status on unknown ref: %s\n",
-				    refname);
-			code = -1;
-			continue;
-		}
-		if (!hint->run_proc_receive) {
-			strbuf_addf(errmsg, "proc-receive reported status on unexpected ref: %s\n",
-				    refname);
-			code = -1;
-			continue;
-		}
-		hint->run_proc_receive |= RUN_PROC_RECEIVE_RETURNED;
-		if (!strcmp(head, "ng")) {
-			if (p)
-				hint->error_string = xstrdup(p);
-			else
-				hint->error_string = "failed";
-			code = -1;
-			continue;
-		}
-		new_report = 1;
-	}
-
-	for (cmd = commands; cmd; cmd = cmd->next)
-		if (cmd->run_proc_receive && !cmd->error_string &&
-		    !(cmd->run_proc_receive & RUN_PROC_RECEIVE_RETURNED)) {
-		    cmd->error_string = "proc-receive failed to report status";
-		    code = -1;
-		}
-	return code;
-}
-
-static int run_proc_receive_hook(struct command *commands,
-				 const struct string_list *push_options)
-{
-	struct child_process proc = CHILD_PROCESS_INIT;
-	struct async muxer;
-	struct command *cmd;
-	const char *argv[2];
-	struct packet_reader reader;
-	struct strbuf cap = STRBUF_INIT;
-	struct strbuf errmsg = STRBUF_INIT;
-	int hook_use_push_options = 0;
-	int version = 0;
-	int code;
-
-	argv[0] = find_hook("proc-receive");
-	if (!argv[0]) {
-		rp_error("cannot find hook 'proc-receive'");
-		return -1;
-	}
-	argv[1] = NULL;
-
-	proc.argv = argv;
-	proc.in = -1;
-	proc.out = -1;
-	proc.trace2_hook_name = "proc-receive";
-
-	if (use_sideband) {
-		memset(&muxer, 0, sizeof(muxer));
-		muxer.proc = copy_to_sideband;
-		muxer.in = -1;
-		code = start_async(&muxer);
-		if (code)
-			return code;
-		proc.err = muxer.in;
-	} else {
-		proc.err = 0;
-	}
-
-	code = start_command(&proc);
-	if (code) {
-		if (use_sideband)
-			finish_async(&muxer);
-		return code;
-	}
-
-	sigchain_push(SIGPIPE, SIG_IGN);
-
-	/* Version negotiaton */
-	packet_reader_init(&reader, proc.out, NULL, 0,
-			   PACKET_READ_CHOMP_NEWLINE |
-			   PACKET_READ_GENTLE_ON_EOF);
-	if (use_atomic)
-		strbuf_addstr(&cap, " atomic");
-	if (use_push_options)
-		strbuf_addstr(&cap, " push-options");
-	if (cap.len) {
-		packet_write_fmt(proc.in, "version=1%c%s\n", '\0', cap.buf + 1);
-		strbuf_release(&cap);
-	} else {
-		packet_write_fmt(proc.in, "version=1\n");
-	}
-	packet_flush(proc.in);
-
-	for (;;) {
-		int linelen;
-
-		if (packet_reader_read(&reader) != PACKET_READ_NORMAL)
-			break;
-
-		if (reader.pktlen > 8 && starts_with(reader.line, "version=")) {
-			version = atoi(reader.line + 8);
-			linelen = strlen(reader.line);
-			if (linelen < reader.pktlen) {
-				const char *feature_list = reader.line + linelen + 1;
-				if (parse_feature_request(feature_list, "push-options"))
-					hook_use_push_options = 1;
-			}
-		}
-	}
-
-	if (version != 1) {
-		strbuf_addf(&errmsg, "proc-receive version '%d' is not supported",
-			    version);
-		code = -1;
-		goto cleanup;
-	}
-
-	/* Send commands */
-	for (cmd = commands; cmd; cmd = cmd->next) {
-		if (!cmd->run_proc_receive || cmd->skip_update || cmd->error_string)
-			continue;
-		packet_write_fmt(proc.in, "%s %s %s",
-				 oid_to_hex(&cmd->old_oid),
-				 oid_to_hex(&cmd->new_oid),
-				 cmd->ref_name);
-	}
-	packet_flush(proc.in);
-
-	/* Send push options */
-	if (hook_use_push_options) {
-		struct string_list_item *item;
-
-		for_each_string_list_item(item, push_options)
-			packet_write_fmt(proc.in, "%s", item->string);
-		packet_flush(proc.in);
-	}
-
-	/* Read result from proc-receive */
-	code = read_proc_receive_report(&reader, commands, &errmsg);
-
-cleanup:
-	close(proc.in);
-	close(proc.out);
-	if (use_sideband)
-		finish_async(&muxer);
-	if (finish_command(&proc))
-		code = -1;
-	if (errmsg.len >0) {
-		char *p = errmsg.buf;
-
-		p += errmsg.len - 1;
-		if (*p == '\n')
-			*p = '\0';
-		rp_error("%s", errmsg.buf);
-		strbuf_release(&errmsg);
-	}
-	sigchain_pop(SIGPIPE);
-
-	return code;
-}
-
-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"
-	   "with what you pushed, and will require 'git reset --hard' to match\n"
-	   "the work tree to HEAD.\n"
-	   "\n"
-	   "You can set the 'receive.denyCurrentBranch' configuration variable\n"
-	   "to 'ignore' or 'warn' in the remote repository to allow pushing into\n"
-	   "its current branch; however, this is not recommended unless you\n"
-	   "arranged to update its work tree to match what you pushed in some\n"
-	   "other way.\n"
-	   "\n"
-	   "To squelch this message and still keep the default behaviour, set\n"
-	   "'receive.denyCurrentBranch' configuration variable to 'refuse'.");
-
-static void refuse_unconfigured_deny(void)
-{
-	rp_error("%s", _(refuse_unconfigured_deny_msg));
-}
-
-static char *refuse_unconfigured_deny_delete_current_msg =
-	N_("By default, deleting the current branch is denied, because the next\n"
-	   "'git clone' won't result in any file checked out, causing confusion.\n"
-	   "\n"
-	   "You can set 'receive.denyDeleteCurrent' configuration variable to\n"
-	   "'warn' or 'ignore' in the remote repository to allow deleting the\n"
-	   "current branch, with or without a warning message.\n"
-	   "\n"
-	   "To squelch this message, you can set it to 'refuse'.");
-
-static void refuse_unconfigured_deny_delete_current(void)
-{
-	rp_error("%s", _(refuse_unconfigured_deny_delete_current_msg));
-}
-
-static int command_singleton_iterator(void *cb_data, struct object_id *oid);
-static int update_shallow_ref(struct command *cmd, struct shallow_info *si)
-{
-	struct shallow_lock shallow_lock = SHALLOW_LOCK_INIT;
-	struct oid_array extra = OID_ARRAY_INIT;
-	struct check_connected_options opt = CHECK_CONNECTED_INIT;
-	uint32_t mask = 1 << (cmd->index % 32);
-	int i;
-
-	trace_printf_key(&trace_shallow,
-			 "shallow: update_shallow_ref %s\n", cmd->ref_name);
-	for (i = 0; i < si->shallow->nr; i++)
-		if (si->used_shallow[i] &&
-		    (si->used_shallow[i][cmd->index / 32] & mask) &&
-		    !delayed_reachability_test(si, i))
-			oid_array_append(&extra, &si->shallow->oid[i]);
-
-	opt.env = tmp_objdir_env(tmp_objdir);
-	setup_alternate_shallow(&shallow_lock, &opt.shallow_file, &extra);
-	if (check_connected(command_singleton_iterator, cmd, &opt)) {
-		rollback_shallow_file(the_repository, &shallow_lock);
-		oid_array_clear(&extra);
-		return -1;
-	}
-
-	commit_shallow_file(the_repository, &shallow_lock);
-
-	/*
-	 * Make sure setup_alternate_shallow() for the next ref does
-	 * not lose these new roots..
-	 */
-	for (i = 0; i < extra.nr; i++)
-		register_shallow(the_repository, &extra.oid[i]);
-
-	si->shallow_ref[cmd->index] = 0;
-	oid_array_clear(&extra);
-	return 0;
-}
-
-/*
- * NEEDSWORK: we should consolidate various implementions of "are we
- * on an unborn branch?" test into one, and make the unified one more
- * robust. !get_sha1() based check used here and elsewhere would not
- * allow us to tell an unborn branch from corrupt ref, for example.
- * For the purpose of fixing "deploy-to-update does not work when
- * pushing into an empty repository" issue, this should suffice for
- * now.
- */
-static int head_has_history(void)
-{
-	struct object_id oid;
-
-	return !get_oid("HEAD", &oid);
-}
-
-static const char *push_to_deploy(unsigned char *sha1,
-				  struct strvec *env,
-				  const char *work_tree)
-{
-	const char *update_refresh[] = {
-		"update-index", "-q", "--ignore-submodules", "--refresh", NULL
-	};
-	const char *diff_files[] = {
-		"diff-files", "--quiet", "--ignore-submodules", "--", NULL
-	};
-	const char *diff_index[] = {
-		"diff-index", "--quiet", "--cached", "--ignore-submodules",
-		NULL, "--", NULL
-	};
-	const char *read_tree[] = {
-		"read-tree", "-u", "-m", NULL, NULL
-	};
-	struct child_process child = CHILD_PROCESS_INIT;
-
-	child.argv = update_refresh;
-	child.env = env->v;
-	child.dir = work_tree;
-	child.no_stdin = 1;
-	child.stdout_to_stderr = 1;
-	child.git_cmd = 1;
-	if (run_command(&child))
-		return "Up-to-date check failed";
-
-	/* run_command() does not clean up completely; reinitialize */
-	child_process_init(&child);
-	child.argv = diff_files;
-	child.env = env->v;
-	child.dir = work_tree;
-	child.no_stdin = 1;
-	child.stdout_to_stderr = 1;
-	child.git_cmd = 1;
-	if (run_command(&child))
-		return "Working directory has unstaged changes";
-
-	/* diff-index with either HEAD or an empty tree */
-	diff_index[4] = head_has_history() ? "HEAD" : empty_tree_oid_hex();
-
-	child_process_init(&child);
-	child.argv = diff_index;
-	child.env = env->v;
-	child.no_stdin = 1;
-	child.no_stdout = 1;
-	child.stdout_to_stderr = 0;
-	child.git_cmd = 1;
-	if (run_command(&child))
-		return "Working directory has staged changes";
-
-	read_tree[3] = hash_to_hex(sha1);
-	child_process_init(&child);
-	child.argv = read_tree;
-	child.env = env->v;
-	child.dir = work_tree;
-	child.no_stdin = 1;
-	child.no_stdout = 1;
-	child.stdout_to_stderr = 0;
-	child.git_cmd = 1;
-	if (run_command(&child))
-		return "Could not update working tree to new HEAD";
-
-	return NULL;
-}
-
-static const char *push_to_checkout_hook = "push-to-checkout";
-
-static const char *push_to_checkout(unsigned char *hash,
-				    struct strvec *env,
-				    const char *work_tree)
-{
-	strvec_pushf(env, "GIT_WORK_TREE=%s", absolute_path(work_tree));
-	if (run_hook_le(env->v, push_to_checkout_hook,
-			hash_to_hex(hash), NULL))
-		return "push-to-checkout hook declined";
-	else
-		return NULL;
-}
-
-static const char *update_worktree(unsigned char *sha1, const struct worktree *worktree)
-{
-	const char *retval, *work_tree, *git_dir = NULL;
-	struct strvec env = STRVEC_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();
-
-	strvec_pushf(&env, "GIT_DIR=%s", absolute_path(git_dir));
-
-	if (!find_hook(push_to_checkout_hook))
-		retval = push_to_deploy(sha1, &env, work_tree);
-	else
-		retval = push_to_checkout(sha1, &env, work_tree);
-
-	strvec_clear(&env);
-	return retval;
-}
-
-static const char *update(struct command *cmd, struct shallow_info *si)
-{
-	const char *name = cmd->ref_name;
-	struct strbuf namespaced_name_buf = STRBUF_INIT;
-	static char *namespaced_name;
-	const char *ret;
-	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)) {
-		rp_error("refusing to create funny ref '%s' remotely", name);
-		return "funny refname";
-	}
-
-	strbuf_addf(&namespaced_name_buf, "%s%s", get_git_namespace(), name);
-	free(namespaced_name);
-	namespaced_name = strbuf_detach(&namespaced_name_buf, NULL);
-
-	if (worktree) {
-		switch (deny_current_branch) {
-		case DENY_IGNORE:
-			break;
-		case DENY_WARN:
-			rp_warning("updating the current branch");
-			break;
-		case DENY_REFUSE:
-		case DENY_UNCONFIGURED:
-			rp_error("refusing to update checked out branch: %s", name);
-			if (deny_current_branch == DENY_UNCONFIGURED)
-				refuse_unconfigured_deny();
-			return "branch is currently checked out";
-		case DENY_UPDATE_INSTEAD:
-			/* pass -- let other checks intervene first */
-			do_update_worktree = 1;
-			break;
-		}
-	}
-
-	if (!is_null_oid(new_oid) && !has_object_file(new_oid)) {
-		error("unpack should have generated %s, "
-		      "but I can't find it!", oid_to_hex(new_oid));
-		return "bad pack";
-	}
-
-	if (!is_null_oid(old_oid) && is_null_oid(new_oid)) {
-		if (deny_deletes && starts_with(name, "refs/heads/")) {
-			rp_error("denying ref deletion for %s", name);
-			return "deletion prohibited";
-		}
-
-		if (worktree || (head_name && !strcmp(namespaced_name, head_name))) {
-			switch (deny_delete_current) {
-			case DENY_IGNORE:
-				break;
-			case DENY_WARN:
-				rp_warning("deleting the current branch");
-				break;
-			case DENY_REFUSE:
-			case DENY_UNCONFIGURED:
-			case DENY_UPDATE_INSTEAD:
-				if (deny_delete_current == DENY_UNCONFIGURED)
-					refuse_unconfigured_deny_delete_current();
-				rp_error("refusing to delete the current branch: %s", name);
-				return "deletion of the current branch prohibited";
-			default:
-				return "Invalid denyDeleteCurrent setting";
-			}
-		}
-	}
-
-	if (deny_non_fast_forwards && !is_null_oid(new_oid) &&
-	    !is_null_oid(old_oid) &&
-	    starts_with(name, "refs/heads/")) {
-		struct object *old_object, *new_object;
-		struct commit *old_commit, *new_commit;
-
-		old_object = parse_object(the_repository, old_oid);
-		new_object = parse_object(the_repository, new_oid);
-
-		if (!old_object || !new_object ||
-		    old_object->type != OBJ_COMMIT ||
-		    new_object->type != OBJ_COMMIT) {
-			error("bad sha1 objects for %s", name);
-			return "bad ref";
-		}
-		old_commit = (struct commit *)old_object;
-		new_commit = (struct commit *)new_object;
-		if (!in_merge_bases(old_commit, new_commit)) {
-			rp_error("denying non-fast-forward %s"
-				 " (you should pull first)", name);
-			return "non-fast-forward";
-		}
-	}
-	if (run_update_hook(cmd)) {
-		rp_error("hook declined to update %s", name);
-		return "hook declined";
-	}
-
-	if (do_update_worktree) {
-		ret = update_worktree(new_oid->hash, find_shared_symref("HEAD", name));
-		if (ret)
-			return ret;
-	}
-
-	if (is_null_oid(new_oid)) {
-		struct strbuf err = STRBUF_INIT;
-		if (!parse_object(the_repository, old_oid)) {
-			old_oid = NULL;
-			if (ref_exists(name)) {
-				rp_warning("Allowing deletion of corrupt ref.");
-			} else {
-				rp_warning("Deleting a non-existent ref.");
-				cmd->did_not_exist = 1;
-			}
-		}
-		if (ref_transaction_delete(transaction,
-					   namespaced_name,
-					   old_oid,
-					   0, "push", &err)) {
-			rp_error("%s", err.buf);
-			strbuf_release(&err);
-			return "failed to delete";
-		}
-		strbuf_release(&err);
-		return NULL; /* good */
-	}
-	else {
-		struct strbuf err = STRBUF_INIT;
-		if (shallow_update && si->shallow_ref[cmd->index] &&
-		    update_shallow_ref(cmd, si))
-			return "shallow error";
-
-		if (ref_transaction_update(transaction,
-					   namespaced_name,
-					   new_oid, old_oid,
-					   0, "push",
-					   &err)) {
-			rp_error("%s", err.buf);
-			strbuf_release(&err);
-
-			return "failed to update ref";
-		}
-		strbuf_release(&err);
-
-		return NULL; /* good */
-	}
-}
-
-static void run_update_post_hook(struct command *commands)
-{
-	struct command *cmd;
-	struct child_process proc = CHILD_PROCESS_INIT;
-	const char *hook;
-
-	hook = find_hook("post-update");
-	if (!hook)
-		return;
-
-	for (cmd = commands; cmd; cmd = cmd->next) {
-		if (cmd->error_string || cmd->did_not_exist)
-			continue;
-		if (!proc.args.nr)
-			strvec_push(&proc.args, hook);
-		strvec_push(&proc.args, cmd->ref_name);
-	}
-	if (!proc.args.nr)
-		return;
-
-	proc.no_stdin = 1;
-	proc.stdout_to_stderr = 1;
-	proc.err = use_sideband ? -1 : 0;
-	proc.trace2_hook_name = "post-update";
-
-	if (!start_command(&proc)) {
-		if (use_sideband)
-			copy_to_sideband(proc.err, -1, NULL);
-		finish_command(&proc);
-	}
-}
-
-static void check_aliased_update_internal(struct command *cmd,
-					  struct string_list *list,
-					  const char *dst_name, int flag)
-{
-	struct string_list_item *item;
-	struct command *dst_cmd;
-
-	if (!(flag & REF_ISSYMREF))
-		return;
-
-	if (!dst_name) {
-		rp_error("refusing update to broken symref '%s'", cmd->ref_name);
-		cmd->skip_update = 1;
-		cmd->error_string = "broken symref";
-		return;
-	}
-	dst_name = strip_namespace(dst_name);
-
-	if ((item = string_list_lookup(list, dst_name)) == NULL)
-		return;
-
-	cmd->skip_update = 1;
-
-	dst_cmd = (struct command *) item->util;
-
-	if (oideq(&cmd->old_oid, &dst_cmd->old_oid) &&
-	    oideq(&cmd->new_oid, &dst_cmd->new_oid))
-		return;
-
-	dst_cmd->skip_update = 1;
-
-	rp_error("refusing inconsistent update between symref '%s' (%s..%s) and"
-		 " its target '%s' (%s..%s)",
-		 cmd->ref_name,
-		 find_unique_abbrev(&cmd->old_oid, DEFAULT_ABBREV),
-		 find_unique_abbrev(&cmd->new_oid, DEFAULT_ABBREV),
-		 dst_cmd->ref_name,
-		 find_unique_abbrev(&dst_cmd->old_oid, DEFAULT_ABBREV),
-		 find_unique_abbrev(&dst_cmd->new_oid, DEFAULT_ABBREV));
-
-	cmd->error_string = dst_cmd->error_string =
-		"inconsistent aliased update";
-}
-
-static void check_aliased_update(struct command *cmd, struct string_list *list)
-{
-	struct strbuf buf = STRBUF_INIT;
-	const char *dst_name;
-	int flag;
-
-	strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name);
-	dst_name = resolve_ref_unsafe(buf.buf, 0, NULL, &flag);
-	check_aliased_update_internal(cmd, list, dst_name, flag);
-	strbuf_release(&buf);
-}
-
-static void check_aliased_updates(struct command *commands)
-{
-	struct command *cmd;
-	struct string_list ref_list = STRING_LIST_INIT_NODUP;
-
-	for (cmd = commands; cmd; cmd = cmd->next) {
-		struct string_list_item *item =
-			string_list_append(&ref_list, cmd->ref_name);
-		item->util = (void *)cmd;
-	}
-	string_list_sort(&ref_list);
-
-	for (cmd = commands; cmd; cmd = cmd->next) {
-		if (!cmd->error_string)
-			check_aliased_update(cmd, &ref_list);
-	}
-
-	string_list_clear(&ref_list, 0);
-}
-
-static int command_singleton_iterator(void *cb_data, struct object_id *oid)
-{
-	struct command **cmd_list = cb_data;
-	struct command *cmd = *cmd_list;
-
-	if (!cmd || is_null_oid(&cmd->new_oid))
-		return -1; /* end of list */
-	*cmd_list = NULL; /* this returns only one */
-	oidcpy(oid, &cmd->new_oid);
-	return 0;
-}
-
-static void set_connectivity_errors(struct command *commands,
-				    struct shallow_info *si)
-{
-	struct command *cmd;
-
-	for (cmd = commands; cmd; cmd = cmd->next) {
-		struct command *singleton = cmd;
-		struct check_connected_options opt = CHECK_CONNECTED_INIT;
-
-		if (shallow_update && si->shallow_ref[cmd->index])
-			/* to be checked in update_shallow_ref() */
-			continue;
-
-		opt.env = tmp_objdir_env(tmp_objdir);
-		if (!check_connected(command_singleton_iterator, &singleton,
-				     &opt))
-			continue;
-
-		cmd->error_string = "missing necessary objects";
-	}
-}
-
-struct iterate_data {
-	struct command *cmds;
-	struct shallow_info *si;
-};
-
-static int iterate_receive_command_list(void *cb_data, struct object_id *oid)
-{
-	struct iterate_data *data = cb_data;
-	struct command **cmd_list = &data->cmds;
-	struct command *cmd = *cmd_list;
-
-	for (; cmd; cmd = cmd->next) {
-		if (shallow_update && data->si->shallow_ref[cmd->index])
-			/* to be checked in update_shallow_ref() */
-			continue;
-		if (!is_null_oid(&cmd->new_oid) && !cmd->skip_update) {
-			oidcpy(oid, &cmd->new_oid);
-			*cmd_list = cmd->next;
-			return 0;
-		}
-	}
-	*cmd_list = NULL;
-	return -1; /* end of list */
-}
-
-static void reject_updates_to_hidden(struct command *commands)
-{
-	struct strbuf refname_full = STRBUF_INIT;
-	size_t prefix_len;
-	struct command *cmd;
-
-	strbuf_addstr(&refname_full, get_git_namespace());
-	prefix_len = refname_full.len;
-
-	for (cmd = commands; cmd; cmd = cmd->next) {
-		if (cmd->error_string)
-			continue;
-
-		strbuf_setlen(&refname_full, prefix_len);
-		strbuf_addstr(&refname_full, cmd->ref_name);
-
-		if (!ref_is_hidden(cmd->ref_name, refname_full.buf))
-			continue;
-		if (is_null_oid(&cmd->new_oid))
-			cmd->error_string = "deny deleting a hidden ref";
-		else
-			cmd->error_string = "deny updating a hidden ref";
-	}
-
-	strbuf_release(&refname_full);
-}
-
-static int should_process_cmd(struct command *cmd)
-{
-	return !cmd->error_string && !cmd->skip_update;
-}
-
-static void warn_if_skipped_connectivity_check(struct command *commands,
-					       struct shallow_info *si)
-{
-	struct command *cmd;
-	int checked_connectivity = 1;
-
-	for (cmd = commands; cmd; cmd = cmd->next) {
-		if (should_process_cmd(cmd) && si->shallow_ref[cmd->index]) {
-			error("BUG: connectivity check has not been run on ref %s",
-			      cmd->ref_name);
-			checked_connectivity = 0;
-		}
-	}
-	if (!checked_connectivity)
-		BUG("connectivity check skipped???");
-}
-
-static void execute_commands_non_atomic(struct command *commands,
-					struct shallow_info *si)
-{
-	struct command *cmd;
-	struct strbuf err = STRBUF_INIT;
-
-	for (cmd = commands; cmd; cmd = cmd->next) {
-		if (!should_process_cmd(cmd) || cmd->run_proc_receive)
-			continue;
-
-		transaction = ref_transaction_begin(&err);
-		if (!transaction) {
-			rp_error("%s", err.buf);
-			strbuf_reset(&err);
-			cmd->error_string = "transaction failed to start";
-			continue;
-		}
-
-		cmd->error_string = update(cmd, si);
-
-		if (!cmd->error_string
-		    && ref_transaction_commit(transaction, &err)) {
-			rp_error("%s", err.buf);
-			strbuf_reset(&err);
-			cmd->error_string = "failed to update ref";
-		}
-		ref_transaction_free(transaction);
-	}
-	strbuf_release(&err);
-}
-
-static void execute_commands_atomic(struct command *commands,
-					struct shallow_info *si)
-{
-	struct command *cmd;
-	struct strbuf err = STRBUF_INIT;
-	const char *reported_error = "atomic push failure";
-
-	transaction = ref_transaction_begin(&err);
-	if (!transaction) {
-		rp_error("%s", err.buf);
-		strbuf_reset(&err);
-		reported_error = "transaction failed to start";
-		goto failure;
-	}
-
-	for (cmd = commands; cmd; cmd = cmd->next) {
-		if (!should_process_cmd(cmd) || cmd->run_proc_receive)
-			continue;
-
-		cmd->error_string = update(cmd, si);
-
-		if (cmd->error_string)
-			goto failure;
-	}
-
-	if (ref_transaction_commit(transaction, &err)) {
-		rp_error("%s", err.buf);
-		reported_error = "atomic transaction failed";
-		goto failure;
-	}
-	goto cleanup;
-
-failure:
-	for (cmd = commands; cmd; cmd = cmd->next)
-		if (!cmd->error_string)
-			cmd->error_string = reported_error;
-
-cleanup:
-	ref_transaction_free(transaction);
-	strbuf_release(&err);
-}
-
-static void execute_commands(struct command *commands,
-			     const char *unpacker_error,
-			     struct shallow_info *si,
-			     const struct string_list *push_options)
-{
-	struct check_connected_options opt = CHECK_CONNECTED_INIT;
-	struct command *cmd;
-	struct iterate_data data;
-	struct async muxer;
-	int err_fd = 0;
-	int run_proc_receive = 0;
-
-	if (unpacker_error) {
-		for (cmd = commands; cmd; cmd = cmd->next)
-			cmd->error_string = "unpacker error";
-		return;
-	}
-
-	if (use_sideband) {
-		memset(&muxer, 0, sizeof(muxer));
-		muxer.proc = copy_to_sideband;
-		muxer.in = -1;
-		if (!start_async(&muxer))
-			err_fd = muxer.in;
-		/* ...else, continue without relaying sideband */
-	}
-
-	data.cmds = commands;
-	data.si = si;
-	opt.err_fd = err_fd;
-	opt.progress = err_fd && !quiet;
-	opt.env = tmp_objdir_env(tmp_objdir);
-	if (check_connected(iterate_receive_command_list, &data, &opt))
-		set_connectivity_errors(commands, si);
-
-	if (use_sideband)
-		finish_async(&muxer);
-
-	reject_updates_to_hidden(commands);
-
-	/*
-	 * Try to find commands that have special prefix in their reference names,
-	 * and mark them to run an external "proc-receive" hook later.
-	 */
-	if (proc_receive_ref) {
-		for (cmd = commands; cmd; cmd = cmd->next) {
-			if (!should_process_cmd(cmd))
-				continue;
-
-			if (proc_receive_ref_matches(cmd)) {
-				cmd->run_proc_receive = RUN_PROC_RECEIVE_SCHEDULED;
-				run_proc_receive = 1;
-			}
-		}
-	}
-
-	if (run_receive_hook(commands, "pre-receive", 0, push_options)) {
-		for (cmd = commands; cmd; cmd = cmd->next) {
-			if (!cmd->error_string)
-				cmd->error_string = "pre-receive hook declined";
-		}
-		return;
-	}
-
-	/*
-	 * Now we'll start writing out refs, which means the objects need
-	 * to be in their final positions so that other processes can see them.
-	 */
-	if (tmp_objdir_migrate(tmp_objdir) < 0) {
-		for (cmd = commands; cmd; cmd = cmd->next) {
-			if (!cmd->error_string)
-				cmd->error_string = "unable to migrate objects to permanent storage";
-		}
-		return;
-	}
-	tmp_objdir = NULL;
-
-	check_aliased_updates(commands);
-
-	free(head_name_to_free);
-	head_name = head_name_to_free = resolve_refdup("HEAD", 0, NULL, NULL);
-
-	if (run_proc_receive &&
-	    run_proc_receive_hook(commands, push_options))
-		for (cmd = commands; cmd; cmd = cmd->next)
-			if (!cmd->error_string &&
-			    !(cmd->run_proc_receive & RUN_PROC_RECEIVE_RETURNED) &&
-			    (cmd->run_proc_receive || use_atomic))
-				cmd->error_string = "fail to run proc-receive hook";
-
-	if (use_atomic)
-		execute_commands_atomic(commands, si);
-	else
-		execute_commands_non_atomic(commands, si);
-
-	if (shallow_update)
-		warn_if_skipped_connectivity_check(commands, si);
-}
-
-static struct command **queue_command(struct command **tail,
-				      const char *line,
-				      int linelen)
-{
-	struct object_id old_oid, new_oid;
-	struct command *cmd;
-	const char *refname;
-	int reflen;
-	const char *p;
-
-	if (parse_oid_hex(line, &old_oid, &p) ||
-	    *p++ != ' ' ||
-	    parse_oid_hex(p, &new_oid, &p) ||
-	    *p++ != ' ')
-		die("protocol error: expected old/new/ref, got '%s'", line);
-
-	refname = p;
-	reflen = linelen - (p - line);
-	FLEX_ALLOC_MEM(cmd, ref_name, refname, reflen);
-	oidcpy(&cmd->old_oid, &old_oid);
-	oidcpy(&cmd->new_oid, &new_oid);
-	*tail = cmd;
-	return &cmd->next;
-}
-
-static void queue_commands_from_cert(struct command **tail,
-				     struct strbuf *push_cert)
-{
-	const char *boc, *eoc;
-
-	if (*tail)
-		die("protocol error: got both push certificate and unsigned commands");
-
-	boc = strstr(push_cert->buf, "\n\n");
-	if (!boc)
-		die("malformed push certificate %.*s", 100, push_cert->buf);
-	else
-		boc += 2;
-	eoc = push_cert->buf + parse_signature(push_cert->buf, push_cert->len);
-
-	while (boc < eoc) {
-		const char *eol = memchr(boc, '\n', eoc - boc);
-		tail = queue_command(tail, boc, eol ? eol - boc : eoc - boc);
-		boc = eol ? eol + 1 : eoc;
-	}
-}
-
-static struct command *read_head_info(struct packet_reader *reader,
-				      struct oid_array *shallow)
-{
-	struct command *commands = NULL;
-	struct command **p = &commands;
-	for (;;) {
-		int linelen;
-
-		if (packet_reader_read(reader) != PACKET_READ_NORMAL)
-			break;
-
-		if (reader->pktlen > 8 && starts_with(reader->line, "shallow ")) {
-			struct object_id oid;
-			if (get_oid_hex(reader->line + 8, &oid))
-				die("protocol error: expected shallow sha, got '%s'",
-				    reader->line + 8);
-			oid_array_append(shallow, &oid);
-			continue;
-		}
-
-		linelen = strlen(reader->line);
-		if (linelen < reader->pktlen) {
-			const char *feature_list = reader->line + linelen + 1;
-			const char *hash = NULL;
-			int len = 0;
-			if (parse_feature_request(feature_list, "report-status"))
-				report_status = 1;
-			if (parse_feature_request(feature_list, "report-status-v2"))
-				report_status_v2 = 1;
-			if (parse_feature_request(feature_list, "side-band-64k"))
-				use_sideband = LARGE_PACKET_MAX;
-			if (parse_feature_request(feature_list, "quiet"))
-				quiet = 1;
-			if (advertise_atomic_push
-			    && parse_feature_request(feature_list, "atomic"))
-				use_atomic = 1;
-			if (advertise_push_options
-			    && parse_feature_request(feature_list, "push-options"))
-				use_push_options = 1;
-			hash = parse_feature_value(feature_list, "object-format", &len, NULL);
-			if (!hash) {
-				hash = hash_algos[GIT_HASH_SHA1].name;
-				len = strlen(hash);
-			}
-			if (xstrncmpz(the_hash_algo->name, hash, len))
-				die("error: unsupported object format '%s'", hash);
-		}
-
-		if (!strcmp(reader->line, "push-cert")) {
-			int true_flush = 0;
-			int saved_options = reader->options;
-			reader->options &= ~PACKET_READ_CHOMP_NEWLINE;
-
-			for (;;) {
-				packet_reader_read(reader);
-				if (reader->status == PACKET_READ_FLUSH) {
-					true_flush = 1;
-					break;
-				}
-				if (reader->status != PACKET_READ_NORMAL) {
-					die("protocol error: got an unexpected packet");
-				}
-				if (!strcmp(reader->line, "push-cert-end\n"))
-					break; /* end of cert */
-				strbuf_addstr(&push_cert, reader->line);
-			}
-			reader->options = saved_options;
-
-			if (true_flush)
-				break;
-			continue;
-		}
-
-		p = queue_command(p, reader->line, linelen);
-	}
-
-	if (push_cert.len)
-		queue_commands_from_cert(p, &push_cert);
-
-	return commands;
-}
-
-static void read_push_options(struct packet_reader *reader,
-			      struct string_list *options)
-{
-	while (1) {
-		if (packet_reader_read(reader) != PACKET_READ_NORMAL)
-			break;
-
-		string_list_append(options, reader->line);
-	}
-}
-
-static const char *parse_pack_header(struct pack_header *hdr)
-{
-	switch (read_pack_header(0, hdr)) {
-	case PH_ERROR_EOF:
-		return "eof before pack header was fully read";
-
-	case PH_ERROR_PACK_SIGNATURE:
-		return "protocol error (pack signature mismatch detected)";
-
-	case PH_ERROR_PROTOCOL:
-		return "protocol error (pack version unsupported)";
-
-	default:
-		return "unknown error in parse_pack_header";
-
-	case 0:
-		return NULL;
-	}
-}
-
-static const char *pack_lockfile;
-
-static void push_header_arg(struct strvec *args, struct pack_header *hdr)
-{
-	strvec_pushf(args, "--pack_header=%"PRIu32",%"PRIu32,
-		     ntohl(hdr->hdr_version), ntohl(hdr->hdr_entries));
-}
-
-static const char *unpack(int err_fd, struct shallow_info *si)
-{
-	struct pack_header hdr;
-	const char *hdr_err;
-	int status;
-	struct child_process child = CHILD_PROCESS_INIT;
-	int fsck_objects = (receive_fsck_objects >= 0
-			    ? receive_fsck_objects
-			    : transfer_fsck_objects >= 0
-			    ? transfer_fsck_objects
-			    : 0);
-
-	hdr_err = parse_pack_header(&hdr);
-	if (hdr_err) {
-		if (err_fd > 0)
-			close(err_fd);
-		return hdr_err;
-	}
-
-	if (si->nr_ours || si->nr_theirs) {
-		alt_shallow_file = setup_temporary_shallow(si->shallow);
-		strvec_push(&child.args, "--shallow-file");
-		strvec_push(&child.args, alt_shallow_file);
-	}
-
-	tmp_objdir = tmp_objdir_create();
-	if (!tmp_objdir) {
-		if (err_fd > 0)
-			close(err_fd);
-		return "unable to create temporary object directory";
-	}
-	child.env = tmp_objdir_env(tmp_objdir);
-
-	/*
-	 * Normally we just pass the tmp_objdir environment to the child
-	 * processes that do the heavy lifting, but we may need to see these
-	 * objects ourselves to set up shallow information.
-	 */
-	tmp_objdir_add_as_alternate(tmp_objdir);
-
-	if (ntohl(hdr.hdr_entries) < unpack_limit) {
-		strvec_push(&child.args, "unpack-objects");
-		push_header_arg(&child.args, &hdr);
-		if (quiet)
-			strvec_push(&child.args, "-q");
-		if (fsck_objects)
-			strvec_pushf(&child.args, "--strict%s",
-				     fsck_msg_types.buf);
-		if (max_input_size)
-			strvec_pushf(&child.args, "--max-input-size=%"PRIuMAX,
-				     (uintmax_t)max_input_size);
-		child.no_stdout = 1;
-		child.err = err_fd;
-		child.git_cmd = 1;
-		status = run_command(&child);
-		if (status)
-			return "unpack-objects abnormal exit";
-	} else {
-		char hostname[HOST_NAME_MAX + 1];
-
-		strvec_pushl(&child.args, "index-pack", "--stdin", NULL);
-		push_header_arg(&child.args, &hdr);
-
-		if (xgethostname(hostname, sizeof(hostname)))
-			xsnprintf(hostname, sizeof(hostname), "localhost");
-		strvec_pushf(&child.args,
-			     "--keep=receive-pack %"PRIuMAX" on %s",
-			     (uintmax_t)getpid(),
-			     hostname);
-
-		if (!quiet && err_fd)
-			strvec_push(&child.args, "--show-resolving-progress");
-		if (use_sideband)
-			strvec_push(&child.args, "--report-end-of-input");
-		if (fsck_objects)
-			strvec_pushf(&child.args, "--strict%s",
-				     fsck_msg_types.buf);
-		if (!reject_thin)
-			strvec_push(&child.args, "--fix-thin");
-		if (max_input_size)
-			strvec_pushf(&child.args, "--max-input-size=%"PRIuMAX,
-				     (uintmax_t)max_input_size);
-		child.out = -1;
-		child.err = err_fd;
-		child.git_cmd = 1;
-		status = start_command(&child);
-		if (status)
-			return "index-pack fork failed";
-		pack_lockfile = index_pack_lockfile(child.out);
-		close(child.out);
-		status = finish_command(&child);
-		if (status)
-			return "index-pack abnormal exit";
-		reprepare_packed_git(the_repository);
-	}
-	return NULL;
-}
-
-static const char *unpack_with_sideband(struct shallow_info *si)
-{
-	struct async muxer;
-	const char *ret;
-
-	if (!use_sideband)
-		return unpack(0, si);
-
-	use_keepalive = KEEPALIVE_AFTER_NUL;
-	memset(&muxer, 0, sizeof(muxer));
-	muxer.proc = copy_to_sideband;
-	muxer.in = -1;
-	if (start_async(&muxer))
-		return NULL;
-
-	ret = unpack(muxer.in, si);
-
-	finish_async(&muxer);
-	return ret;
-}
-
-static void prepare_shallow_update(struct shallow_info *si)
-{
-	int i, j, k, bitmap_size = DIV_ROUND_UP(si->ref->nr, 32);
-
-	ALLOC_ARRAY(si->used_shallow, si->shallow->nr);
-	assign_shallow_commits_to_refs(si, si->used_shallow, NULL);
-
-	si->need_reachability_test =
-		xcalloc(si->shallow->nr, sizeof(*si->need_reachability_test));
-	si->reachable =
-		xcalloc(si->shallow->nr, sizeof(*si->reachable));
-	si->shallow_ref = xcalloc(si->ref->nr, sizeof(*si->shallow_ref));
-
-	for (i = 0; i < si->nr_ours; i++)
-		si->need_reachability_test[si->ours[i]] = 1;
-
-	for (i = 0; i < si->shallow->nr; i++) {
-		if (!si->used_shallow[i])
-			continue;
-		for (j = 0; j < bitmap_size; j++) {
-			if (!si->used_shallow[i][j])
-				continue;
-			si->need_reachability_test[i]++;
-			for (k = 0; k < 32; k++)
-				if (si->used_shallow[i][j] & (1U << k))
-					si->shallow_ref[j * 32 + k]++;
-		}
-
-		/*
-		 * true for those associated with some refs and belong
-		 * in "ours" list aka "step 7 not done yet"
-		 */
-		si->need_reachability_test[i] =
-			si->need_reachability_test[i] > 1;
-	}
-
-	/*
-	 * keep hooks happy by forcing a temporary shallow file via
-	 * env variable because we can't add --shallow-file to every
-	 * command. check_connected() will be done with
-	 * true .git/shallow though.
-	 */
-	setenv(GIT_SHALLOW_FILE_ENVIRONMENT, alt_shallow_file, 1);
-}
-
-static void update_shallow_info(struct command *commands,
-				struct shallow_info *si,
-				struct oid_array *ref)
-{
-	struct command *cmd;
-	int *ref_status;
-	remove_nonexistent_theirs_shallow(si);
-	if (!si->nr_ours && !si->nr_theirs) {
-		shallow_update = 0;
-		return;
-	}
-
-	for (cmd = commands; cmd; cmd = cmd->next) {
-		if (is_null_oid(&cmd->new_oid))
-			continue;
-		oid_array_append(ref, &cmd->new_oid);
-		cmd->index = ref->nr - 1;
-	}
-	si->ref = ref;
-
-	if (shallow_update) {
-		prepare_shallow_update(si);
-		return;
-	}
-
-	ALLOC_ARRAY(ref_status, ref->nr);
-	assign_shallow_commits_to_refs(si, NULL, ref_status);
-	for (cmd = commands; cmd; cmd = cmd->next) {
-		if (is_null_oid(&cmd->new_oid))
-			continue;
-		if (ref_status[cmd->index]) {
-			cmd->error_string = "shallow update not allowed";
-			cmd->skip_update = 1;
-		}
-	}
-	free(ref_status);
-}
-
-static void report(struct command *commands, const char *unpack_status)
-{
-	struct command *cmd;
-	struct strbuf buf = STRBUF_INIT;
-
-	packet_buf_write(&buf, "unpack %s\n",
-			 unpack_status ? unpack_status : "ok");
-	for (cmd = commands; cmd; cmd = cmd->next) {
-		if (!cmd->error_string)
-			packet_buf_write(&buf, "ok %s\n",
-					 cmd->ref_name);
-		else
-			packet_buf_write(&buf, "ng %s %s\n",
-					 cmd->ref_name, cmd->error_string);
-	}
-	packet_buf_flush(&buf);
-
-	if (use_sideband)
-		send_sideband(1, 1, buf.buf, buf.len, use_sideband);
-	else
-		write_or_die(1, buf.buf, buf.len);
-	strbuf_release(&buf);
-}
-
-static void report_v2(struct command *commands, const char *unpack_status)
-{
-	struct command *cmd;
-	struct strbuf buf = STRBUF_INIT;
-	struct ref_push_report *report;
-
-	packet_buf_write(&buf, "unpack %s\n",
-			 unpack_status ? unpack_status : "ok");
-	for (cmd = commands; cmd; cmd = cmd->next) {
-		int count = 0;
-
-		if (cmd->error_string) {
-			packet_buf_write(&buf, "ng %s %s\n",
-					 cmd->ref_name,
-					 cmd->error_string);
-			continue;
-		}
-		packet_buf_write(&buf, "ok %s\n",
-				 cmd->ref_name);
-		for (report = cmd->report; report; report = report->next) {
-			if (count++ > 0)
-				packet_buf_write(&buf, "ok %s\n",
-						 cmd->ref_name);
-			if (report->ref_name)
-				packet_buf_write(&buf, "option refname %s\n",
-						 report->ref_name);
-			if (report->old_oid)
-				packet_buf_write(&buf, "option old-oid %s\n",
-						 oid_to_hex(report->old_oid));
-			if (report->new_oid)
-				packet_buf_write(&buf, "option new-oid %s\n",
-						 oid_to_hex(report->new_oid));
-			if (report->forced_update)
-				packet_buf_write(&buf, "option forced-update\n");
-		}
-	}
-	packet_buf_flush(&buf);
-
-	if (use_sideband)
-		send_sideband(1, 1, buf.buf, buf.len, use_sideband);
-	else
-		write_or_die(1, buf.buf, buf.len);
-	strbuf_release(&buf);
-}
-
-static int delete_only(struct command *commands)
-{
-	struct command *cmd;
-	for (cmd = commands; cmd; cmd = cmd->next) {
-		if (!is_null_oid(&cmd->new_oid))
-			return 0;
-	}
-	return 1;
-}
-
-int cmd_receive_pack(int argc, const char **argv, const char *prefix)
-{
-	int advertise_refs = 0;
-	struct command *commands;
-	struct oid_array shallow = OID_ARRAY_INIT;
-	struct oid_array ref = OID_ARRAY_INIT;
-	struct shallow_info si;
-	struct packet_reader reader;
-
-	struct option options[] = {
-		OPT__QUIET(&quiet, N_("quiet")),
-		OPT_HIDDEN_BOOL(0, "stateless-rpc", &stateless_rpc, NULL),
-		OPT_HIDDEN_BOOL(0, "advertise-refs", &advertise_refs, NULL),
-		OPT_HIDDEN_BOOL(0, "reject-thin-pack-for-testing", &reject_thin, NULL),
-		OPT_END()
-	};
-
-	packet_trace_identity("receive-pack");
-
-	argc = parse_options(argc, argv, prefix, options, receive_pack_usage, 0);
-
-	if (argc > 1)
-		usage_msg_opt(_("Too many arguments."), receive_pack_usage, options);
-	if (argc == 0)
-		usage_msg_opt(_("You must specify a directory."), receive_pack_usage, options);
-
-	service_dir = argv[0];
-
-	setup_path();
-
-	if (!enter_repo(service_dir, 0))
-		die("'%s' does not appear to be a git repository", service_dir);
-
-	git_config(receive_pack_config, NULL);
-	if (cert_nonce_seed)
-		push_cert_nonce = prepare_push_cert_nonce(service_dir, time(NULL));
-
-	if (0 <= transfer_unpack_limit)
-		unpack_limit = transfer_unpack_limit;
-	else if (0 <= receive_unpack_limit)
-		unpack_limit = receive_unpack_limit;
-
-	switch (determine_protocol_version_server()) {
-	case protocol_v2:
-		/*
-		 * push support for protocol v2 has not been implemented yet,
-		 * so ignore the request to use v2 and fallback to using v0.
-		 */
-		break;
-	case protocol_v1:
-		/*
-		 * v1 is just the original protocol with a version string,
-		 * so just fall through after writing the version string.
-		 */
-		if (advertise_refs || !stateless_rpc)
-			packet_write_fmt(1, "version 1\n");
-
-		/* fallthrough */
-	case protocol_v0:
-		break;
-	case protocol_unknown_version:
-		BUG("unknown protocol version");
-	}
-
-	if (advertise_refs || !stateless_rpc) {
-		write_head_info();
-	}
-	if (advertise_refs)
-		return 0;
-
-	packet_reader_init(&reader, 0, NULL, 0,
-			   PACKET_READ_CHOMP_NEWLINE |
-			   PACKET_READ_DIE_ON_ERR_PACKET);
-
-	if ((commands = read_head_info(&reader, &shallow)) != NULL) {
-		const char *unpack_status = NULL;
-		struct string_list push_options = STRING_LIST_INIT_DUP;
-
-		if (use_push_options)
-			read_push_options(&reader, &push_options);
-		if (!check_cert_push_options(&push_options)) {
-			struct command *cmd;
-			for (cmd = commands; cmd; cmd = cmd->next)
-				cmd->error_string = "inconsistent push options";
-		}
-
-		prepare_shallow_info(&si, &shallow);
-		if (!si.nr_ours && !si.nr_theirs)
-			shallow_update = 0;
-		if (!delete_only(commands)) {
-			unpack_status = unpack_with_sideband(&si);
-			update_shallow_info(commands, &si, &ref);
-		}
-		use_keepalive = KEEPALIVE_ALWAYS;
-		execute_commands(commands, unpack_status, &si,
-				 &push_options);
-		if (pack_lockfile)
-			unlink_or_warn(pack_lockfile);
-		if (report_status_v2)
-			report_v2(commands, unpack_status);
-		else if (report_status)
-			report(commands, unpack_status);
-		run_receive_hook(commands, "post-receive", 1,
-				 &push_options);
-		run_update_post_hook(commands);
-		string_list_clear(&push_options, 0);
-		if (auto_gc) {
-			const char *argv_gc_auto[] = {
-				"gc", "--auto", "--quiet", NULL,
-			};
-			struct child_process proc = CHILD_PROCESS_INIT;
-
-			proc.no_stdin = 1;
-			proc.stdout_to_stderr = 1;
-			proc.err = use_sideband ? -1 : 0;
-			proc.git_cmd = 1;
-			proc.argv = argv_gc_auto;
-
-			close_object_store(the_repository->objects);
-			if (!start_command(&proc)) {
-				if (use_sideband)
-					copy_to_sideband(proc.err, -1, NULL);
-				finish_command(&proc);
-			}
-		}
-		if (auto_update_server_info)
-			update_server_info(0);
-		clear_shallow_info(&si);
-	}
-	if (use_sideband)
-		packet_flush(1);
-	oid_array_clear(&shallow);
-	oid_array_clear(&ref);
-	free((void *)push_cert_nonce);
-	return 0;
-}
diff --git a/third_party/git/builtin/reflog.c b/third_party/git/builtin/reflog.c
deleted file mode 100644
index ca1d8079f320..000000000000
--- a/third_party/git/builtin/reflog.c
+++ /dev/null
@@ -1,789 +0,0 @@
-#include "builtin.h"
-#include "config.h"
-#include "lockfile.h"
-#include "object-store.h"
-#include "repository.h"
-#include "commit.h"
-#include "refs.h"
-#include "dir.h"
-#include "tree-walk.h"
-#include "diff.h"
-#include "revision.h"
-#include "reachable.h"
-#include "worktree.h"
-
-/* NEEDSWORK: switch to using parse_options */
-static const char reflog_expire_usage[] =
-N_("git reflog expire [--expire=<time>] "
-   "[--expire-unreachable=<time>] "
-   "[--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] "
-   "[--verbose] [--all] <refs>...");
-static const char reflog_delete_usage[] =
-N_("git reflog delete [--rewrite] [--updateref] "
-   "[--dry-run | -n] [--verbose] <refs>...");
-static const char reflog_exists_usage[] =
-N_("git reflog exists <ref>");
-
-static timestamp_t default_reflog_expire;
-static timestamp_t default_reflog_expire_unreachable;
-
-struct cmd_reflog_expire_cb {
-	struct rev_info revs;
-	int stalefix;
-	timestamp_t expire_total;
-	timestamp_t expire_unreachable;
-	int recno;
-};
-
-struct expire_reflog_policy_cb {
-	enum {
-		UE_NORMAL,
-		UE_ALWAYS,
-		UE_HEAD
-	} unreachable_expire_kind;
-	struct commit_list *mark_list;
-	unsigned long mark_limit;
-	struct cmd_reflog_expire_cb cmd;
-	struct commit *tip_commit;
-	struct commit_list *tips;
-};
-
-struct collected_reflog {
-	struct object_id oid;
-	char reflog[FLEX_ARRAY];
-};
-
-struct collect_reflog_cb {
-	struct collected_reflog **e;
-	int alloc;
-	int nr;
-	struct worktree *wt;
-};
-
-/* Remember to update object flag allocation in object.h */
-#define INCOMPLETE	(1u<<10)
-#define STUDYING	(1u<<11)
-#define REACHABLE	(1u<<12)
-
-static int tree_is_complete(const struct object_id *oid)
-{
-	struct tree_desc desc;
-	struct name_entry entry;
-	int complete;
-	struct tree *tree;
-
-	tree = lookup_tree(the_repository, oid);
-	if (!tree)
-		return 0;
-	if (tree->object.flags & SEEN)
-		return 1;
-	if (tree->object.flags & INCOMPLETE)
-		return 0;
-
-	if (!tree->buffer) {
-		enum object_type type;
-		unsigned long size;
-		void *data = read_object_file(oid, &type, &size);
-		if (!data) {
-			tree->object.flags |= INCOMPLETE;
-			return 0;
-		}
-		tree->buffer = data;
-		tree->size = size;
-	}
-	init_tree_desc(&desc, tree->buffer, tree->size);
-	complete = 1;
-	while (tree_entry(&desc, &entry)) {
-		if (!has_object_file(&entry.oid) ||
-		    (S_ISDIR(entry.mode) && !tree_is_complete(&entry.oid))) {
-			tree->object.flags |= INCOMPLETE;
-			complete = 0;
-		}
-	}
-	free_tree_buffer(tree);
-
-	if (complete)
-		tree->object.flags |= SEEN;
-	return complete;
-}
-
-static int commit_is_complete(struct commit *commit)
-{
-	struct object_array study;
-	struct object_array found;
-	int is_incomplete = 0;
-	int i;
-
-	/* early return */
-	if (commit->object.flags & SEEN)
-		return 1;
-	if (commit->object.flags & INCOMPLETE)
-		return 0;
-	/*
-	 * Find all commits that are reachable and are not marked as
-	 * SEEN.  Then make sure the trees and blobs contained are
-	 * complete.  After that, mark these commits also as SEEN.
-	 * If some of the objects that are needed to complete this
-	 * commit are missing, mark this commit as INCOMPLETE.
-	 */
-	memset(&study, 0, sizeof(study));
-	memset(&found, 0, sizeof(found));
-	add_object_array(&commit->object, NULL, &study);
-	add_object_array(&commit->object, NULL, &found);
-	commit->object.flags |= STUDYING;
-	while (study.nr) {
-		struct commit *c;
-		struct commit_list *parent;
-
-		c = (struct commit *)object_array_pop(&study);
-		if (!c->object.parsed && !parse_object(the_repository, &c->object.oid))
-			c->object.flags |= INCOMPLETE;
-
-		if (c->object.flags & INCOMPLETE) {
-			is_incomplete = 1;
-			break;
-		}
-		else if (c->object.flags & SEEN)
-			continue;
-		for (parent = c->parents; parent; parent = parent->next) {
-			struct commit *p = parent->item;
-			if (p->object.flags & STUDYING)
-				continue;
-			p->object.flags |= STUDYING;
-			add_object_array(&p->object, NULL, &study);
-			add_object_array(&p->object, NULL, &found);
-		}
-	}
-	if (!is_incomplete) {
-		/*
-		 * make sure all commits in "found" array have all the
-		 * necessary objects.
-		 */
-		for (i = 0; i < found.nr; i++) {
-			struct commit *c =
-				(struct commit *)found.objects[i].item;
-			if (!tree_is_complete(get_commit_tree_oid(c))) {
-				is_incomplete = 1;
-				c->object.flags |= INCOMPLETE;
-			}
-		}
-		if (!is_incomplete) {
-			/* mark all found commits as complete, iow SEEN */
-			for (i = 0; i < found.nr; i++)
-				found.objects[i].item->flags |= SEEN;
-		}
-	}
-	/* clear flags from the objects we traversed */
-	for (i = 0; i < found.nr; i++)
-		found.objects[i].item->flags &= ~STUDYING;
-	if (is_incomplete)
-		commit->object.flags |= INCOMPLETE;
-	else {
-		/*
-		 * If we come here, we have (1) traversed the ancestry chain
-		 * from the "commit" until we reach SEEN commits (which are
-		 * known to be complete), and (2) made sure that the commits
-		 * encountered during the above traversal refer to trees that
-		 * are complete.  Which means that we know *all* the commits
-		 * we have seen during this process are complete.
-		 */
-		for (i = 0; i < found.nr; i++)
-			found.objects[i].item->flags |= SEEN;
-	}
-	/* free object arrays */
-	object_array_clear(&study);
-	object_array_clear(&found);
-	return !is_incomplete;
-}
-
-static int keep_entry(struct commit **it, struct object_id *oid)
-{
-	struct commit *commit;
-
-	if (is_null_oid(oid))
-		return 1;
-	commit = lookup_commit_reference_gently(the_repository, oid, 1);
-	if (!commit)
-		return 0;
-
-	/*
-	 * Make sure everything in this commit exists.
-	 *
-	 * We have walked all the objects reachable from the refs
-	 * and cache earlier.  The commits reachable by this commit
-	 * must meet SEEN commits -- and then we should mark them as
-	 * SEEN as well.
-	 */
-	if (!commit_is_complete(commit))
-		return 0;
-	*it = commit;
-	return 1;
-}
-
-/*
- * Starting from commits in the cb->mark_list, mark commits that are
- * reachable from them.  Stop the traversal at commits older than
- * the expire_limit and queue them back, so that the caller can call
- * us again to restart the traversal with longer expire_limit.
- */
-static void mark_reachable(struct expire_reflog_policy_cb *cb)
-{
-	struct commit_list *pending;
-	timestamp_t expire_limit = cb->mark_limit;
-	struct commit_list *leftover = NULL;
-
-	for (pending = cb->mark_list; pending; pending = pending->next)
-		pending->item->object.flags &= ~REACHABLE;
-
-	pending = cb->mark_list;
-	while (pending) {
-		struct commit_list *parent;
-		struct commit *commit = pop_commit(&pending);
-		if (commit->object.flags & REACHABLE)
-			continue;
-		if (parse_commit(commit))
-			continue;
-		commit->object.flags |= REACHABLE;
-		if (commit->date < expire_limit) {
-			commit_list_insert(commit, &leftover);
-			continue;
-		}
-		commit->object.flags |= REACHABLE;
-		parent = commit->parents;
-		while (parent) {
-			commit = parent->item;
-			parent = parent->next;
-			if (commit->object.flags & REACHABLE)
-				continue;
-			commit_list_insert(commit, &pending);
-		}
-	}
-	cb->mark_list = leftover;
-}
-
-static int unreachable(struct expire_reflog_policy_cb *cb, struct commit *commit, struct object_id *oid)
-{
-	/*
-	 * We may or may not have the commit yet - if not, look it
-	 * up using the supplied sha1.
-	 */
-	if (!commit) {
-		if (is_null_oid(oid))
-			return 0;
-
-		commit = lookup_commit_reference_gently(the_repository, oid,
-							1);
-
-		/* Not a commit -- keep it */
-		if (!commit)
-			return 0;
-	}
-
-	/* Reachable from the current ref?  Don't prune. */
-	if (commit->object.flags & REACHABLE)
-		return 0;
-
-	if (cb->mark_list && cb->mark_limit) {
-		cb->mark_limit = 0; /* dig down to the root */
-		mark_reachable(cb);
-	}
-
-	return !(commit->object.flags & REACHABLE);
-}
-
-/*
- * Return true iff the specified reflog entry should be expired.
- */
-static int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid,
-				    const char *email, timestamp_t timestamp, int tz,
-				    const char *message, void *cb_data)
-{
-	struct expire_reflog_policy_cb *cb = cb_data;
-	struct commit *old_commit, *new_commit;
-
-	if (timestamp < cb->cmd.expire_total)
-		return 1;
-
-	old_commit = new_commit = NULL;
-	if (cb->cmd.stalefix &&
-	    (!keep_entry(&old_commit, ooid) || !keep_entry(&new_commit, noid)))
-		return 1;
-
-	if (timestamp < cb->cmd.expire_unreachable) {
-		if (cb->unreachable_expire_kind == UE_ALWAYS)
-			return 1;
-		if (unreachable(cb, old_commit, ooid) || unreachable(cb, new_commit, noid))
-			return 1;
-	}
-
-	if (cb->cmd.recno && --(cb->cmd.recno) == 0)
-		return 1;
-
-	return 0;
-}
-
-static int push_tip_to_list(const char *refname, const struct object_id *oid,
-			    int flags, void *cb_data)
-{
-	struct commit_list **list = cb_data;
-	struct commit *tip_commit;
-	if (flags & REF_ISSYMREF)
-		return 0;
-	tip_commit = lookup_commit_reference_gently(the_repository, oid, 1);
-	if (!tip_commit)
-		return 0;
-	commit_list_insert(tip_commit, list);
-	return 0;
-}
-
-static int is_head(const char *refname)
-{
-	switch (ref_type(refname)) {
-	case REF_TYPE_OTHER_PSEUDOREF:
-	case REF_TYPE_MAIN_PSEUDOREF:
-		if (parse_worktree_ref(refname, NULL, NULL, &refname))
-			BUG("not a worktree ref: %s", refname);
-		break;
-	default:
-		break;
-	}
-	return !strcmp(refname, "HEAD");
-}
-
-static void reflog_expiry_prepare(const char *refname,
-				  const struct object_id *oid,
-				  void *cb_data)
-{
-	struct expire_reflog_policy_cb *cb = cb_data;
-
-	if (!cb->cmd.expire_unreachable || is_head(refname)) {
-		cb->tip_commit = NULL;
-		cb->unreachable_expire_kind = UE_HEAD;
-	} else {
-		cb->tip_commit = lookup_commit_reference_gently(the_repository,
-								oid, 1);
-		if (!cb->tip_commit)
-			cb->unreachable_expire_kind = UE_ALWAYS;
-		else
-			cb->unreachable_expire_kind = UE_NORMAL;
-	}
-
-	if (cb->cmd.expire_unreachable <= cb->cmd.expire_total)
-		cb->unreachable_expire_kind = UE_ALWAYS;
-
-	cb->mark_list = NULL;
-	cb->tips = NULL;
-	if (cb->unreachable_expire_kind != UE_ALWAYS) {
-		if (cb->unreachable_expire_kind == UE_HEAD) {
-			struct commit_list *elem;
-
-			for_each_ref(push_tip_to_list, &cb->tips);
-			for (elem = cb->tips; elem; elem = elem->next)
-				commit_list_insert(elem->item, &cb->mark_list);
-		} else {
-			commit_list_insert(cb->tip_commit, &cb->mark_list);
-		}
-		cb->mark_limit = cb->cmd.expire_total;
-		mark_reachable(cb);
-	}
-}
-
-static void reflog_expiry_cleanup(void *cb_data)
-{
-	struct expire_reflog_policy_cb *cb = cb_data;
-
-	if (cb->unreachable_expire_kind != UE_ALWAYS) {
-		if (cb->unreachable_expire_kind == UE_HEAD) {
-			struct commit_list *elem;
-			for (elem = cb->tips; elem; elem = elem->next)
-				clear_commit_marks(elem->item, REACHABLE);
-			free_commit_list(cb->tips);
-		} else {
-			clear_commit_marks(cb->tip_commit, REACHABLE);
-		}
-	}
-}
-
-static int collect_reflog(const char *ref, const struct object_id *oid, int unused, void *cb_data)
-{
-	struct collected_reflog *e;
-	struct collect_reflog_cb *cb = cb_data;
-	struct strbuf newref = STRBUF_INIT;
-
-	/*
-	 * Avoid collecting the same shared ref multiple times because
-	 * they are available via all worktrees.
-	 */
-	if (!cb->wt->is_current && ref_type(ref) == REF_TYPE_NORMAL)
-		return 0;
-
-	strbuf_worktree_ref(cb->wt, &newref, ref);
-	FLEX_ALLOC_STR(e, reflog, newref.buf);
-	strbuf_release(&newref);
-
-	oidcpy(&e->oid, oid);
-	ALLOC_GROW(cb->e, cb->nr + 1, cb->alloc);
-	cb->e[cb->nr++] = e;
-	return 0;
-}
-
-static struct reflog_expire_cfg {
-	struct reflog_expire_cfg *next;
-	timestamp_t expire_total;
-	timestamp_t expire_unreachable;
-	char pattern[FLEX_ARRAY];
-} *reflog_expire_cfg, **reflog_expire_cfg_tail;
-
-static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len)
-{
-	struct reflog_expire_cfg *ent;
-
-	if (!reflog_expire_cfg_tail)
-		reflog_expire_cfg_tail = &reflog_expire_cfg;
-
-	for (ent = reflog_expire_cfg; ent; ent = ent->next)
-		if (!strncmp(ent->pattern, pattern, len) &&
-		    ent->pattern[len] == '\0')
-			return ent;
-
-	FLEX_ALLOC_MEM(ent, pattern, pattern, len);
-	*reflog_expire_cfg_tail = ent;
-	reflog_expire_cfg_tail = &(ent->next);
-	return ent;
-}
-
-/* expiry timer slot */
-#define EXPIRE_TOTAL   01
-#define EXPIRE_UNREACH 02
-
-static int reflog_expire_config(const char *var, const char *value, void *cb)
-{
-	const char *pattern, *key;
-	size_t pattern_len;
-	timestamp_t expire;
-	int slot;
-	struct reflog_expire_cfg *ent;
-
-	if (parse_config_key(var, "gc", &pattern, &pattern_len, &key) < 0)
-		return git_default_config(var, value, cb);
-
-	if (!strcmp(key, "reflogexpire")) {
-		slot = EXPIRE_TOTAL;
-		if (git_config_expiry_date(&expire, var, value))
-			return -1;
-	} else if (!strcmp(key, "reflogexpireunreachable")) {
-		slot = EXPIRE_UNREACH;
-		if (git_config_expiry_date(&expire, var, value))
-			return -1;
-	} else
-		return git_default_config(var, value, cb);
-
-	if (!pattern) {
-		switch (slot) {
-		case EXPIRE_TOTAL:
-			default_reflog_expire = expire;
-			break;
-		case EXPIRE_UNREACH:
-			default_reflog_expire_unreachable = expire;
-			break;
-		}
-		return 0;
-	}
-
-	ent = find_cfg_ent(pattern, pattern_len);
-	if (!ent)
-		return -1;
-	switch (slot) {
-	case EXPIRE_TOTAL:
-		ent->expire_total = expire;
-		break;
-	case EXPIRE_UNREACH:
-		ent->expire_unreachable = expire;
-		break;
-	}
-	return 0;
-}
-
-static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, int slot, const char *ref)
-{
-	struct reflog_expire_cfg *ent;
-
-	if (slot == (EXPIRE_TOTAL|EXPIRE_UNREACH))
-		return; /* both given explicitly -- nothing to tweak */
-
-	for (ent = reflog_expire_cfg; ent; ent = ent->next) {
-		if (!wildmatch(ent->pattern, ref, 0)) {
-			if (!(slot & EXPIRE_TOTAL))
-				cb->expire_total = ent->expire_total;
-			if (!(slot & EXPIRE_UNREACH))
-				cb->expire_unreachable = ent->expire_unreachable;
-			return;
-		}
-	}
-
-	/*
-	 * If unconfigured, make stash never expire
-	 */
-	if (!strcmp(ref, "refs/stash")) {
-		if (!(slot & EXPIRE_TOTAL))
-			cb->expire_total = 0;
-		if (!(slot & EXPIRE_UNREACH))
-			cb->expire_unreachable = 0;
-		return;
-	}
-
-	/* Nothing matched -- use the default value */
-	if (!(slot & EXPIRE_TOTAL))
-		cb->expire_total = default_reflog_expire;
-	if (!(slot & EXPIRE_UNREACH))
-		cb->expire_unreachable = default_reflog_expire_unreachable;
-}
-
-static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
-{
-	struct expire_reflog_policy_cb cb;
-	timestamp_t now = time(NULL);
-	int i, status, do_all, all_worktrees = 1;
-	int explicit_expiry = 0;
-	unsigned int flags = 0;
-
-	default_reflog_expire_unreachable = now - 30 * 24 * 3600;
-	default_reflog_expire = now - 90 * 24 * 3600;
-	git_config(reflog_expire_config, NULL);
-
-	save_commit_buffer = 0;
-	do_all = status = 0;
-	memset(&cb, 0, sizeof(cb));
-
-	cb.cmd.expire_total = default_reflog_expire;
-	cb.cmd.expire_unreachable = default_reflog_expire_unreachable;
-
-	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))
-				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))
-				die(_("'%s' is not a valid timestamp"), arg);
-			explicit_expiry |= EXPIRE_UNREACH;
-		}
-		else if (!strcmp(arg, "--stale-fix"))
-			cb.cmd.stalefix = 1;
-		else if (!strcmp(arg, "--rewrite"))
-			flags |= EXPIRE_REFLOGS_REWRITE;
-		else if (!strcmp(arg, "--updateref"))
-			flags |= EXPIRE_REFLOGS_UPDATE_REF;
-		else if (!strcmp(arg, "--all"))
-			do_all = 1;
-		else if (!strcmp(arg, "--single-worktree"))
-			all_worktrees = 0;
-		else if (!strcmp(arg, "--verbose"))
-			flags |= EXPIRE_REFLOGS_VERBOSE;
-		else if (!strcmp(arg, "--")) {
-			i++;
-			break;
-		}
-		else if (arg[0] == '-')
-			usage(_(reflog_expire_usage));
-		else
-			break;
-	}
-
-	/*
-	 * We can trust the commits and objects reachable from refs
-	 * even in older repository.  We cannot trust what's reachable
-	 * from reflog if the repository was pruned with older git.
-	 */
-	if (cb.cmd.stalefix) {
-		repo_init_revisions(the_repository, &cb.cmd.revs, prefix);
-		if (flags & EXPIRE_REFLOGS_VERBOSE)
-			printf(_("Marking reachable objects..."));
-		mark_reachable_objects(&cb.cmd.revs, 0, 0, NULL);
-		if (flags & EXPIRE_REFLOGS_VERBOSE)
-			putchar('\n');
-	}
-
-	if (do_all) {
-		struct collect_reflog_cb collected;
-		struct worktree **worktrees, **p;
-		int i;
-
-		memset(&collected, 0, sizeof(collected));
-		worktrees = get_worktrees();
-		for (p = worktrees; *p; p++) {
-			if (!all_worktrees && !(*p)->is_current)
-				continue;
-			collected.wt = *p;
-			refs_for_each_reflog(get_worktree_ref_store(*p),
-					     collect_reflog, &collected);
-		}
-		free_worktrees(worktrees);
-		for (i = 0; i < collected.nr; i++) {
-			struct collected_reflog *e = collected.e[i];
-			set_reflog_expiry_param(&cb.cmd, explicit_expiry, e->reflog);
-			status |= reflog_expire(e->reflog, &e->oid, flags,
-						reflog_expiry_prepare,
-						should_expire_reflog_ent,
-						reflog_expiry_cleanup,
-						&cb);
-			free(e);
-		}
-		free(collected.e);
-	}
-
-	for (; i < argc; i++) {
-		char *ref;
-		struct object_id oid;
-		if (!dwim_log(argv[i], strlen(argv[i]), &oid, &ref)) {
-			status |= error(_("%s points nowhere!"), argv[i]);
-			continue;
-		}
-		set_reflog_expiry_param(&cb.cmd, explicit_expiry, ref);
-		status |= reflog_expire(ref, &oid, flags,
-					reflog_expiry_prepare,
-					should_expire_reflog_ent,
-					reflog_expiry_cleanup,
-					&cb);
-	}
-	return status;
-}
-
-static int count_reflog_ent(struct object_id *ooid, struct object_id *noid,
-		const char *email, timestamp_t timestamp, int tz,
-		const char *message, void *cb_data)
-{
-	struct expire_reflog_policy_cb *cb = cb_data;
-	if (!cb->cmd.expire_total || timestamp < cb->cmd.expire_total)
-		cb->cmd.recno++;
-	return 0;
-}
-
-static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
-{
-	struct expire_reflog_policy_cb cb;
-	int i, status = 0;
-	unsigned int flags = 0;
-
-	memset(&cb, 0, sizeof(cb));
-
-	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 (!strcmp(arg, "--rewrite"))
-			flags |= EXPIRE_REFLOGS_REWRITE;
-		else if (!strcmp(arg, "--updateref"))
-			flags |= EXPIRE_REFLOGS_UPDATE_REF;
-		else if (!strcmp(arg, "--verbose"))
-			flags |= EXPIRE_REFLOGS_VERBOSE;
-		else if (!strcmp(arg, "--")) {
-			i++;
-			break;
-		}
-		else if (arg[0] == '-')
-			usage(_(reflog_delete_usage));
-		else
-			break;
-	}
-
-	if (argc - i < 1)
-		return error(_("no reflog specified to delete"));
-
-	for ( ; i < argc; i++) {
-		const char *spec = strstr(argv[i], "@{");
-		struct object_id oid;
-		char *ep, *ref;
-		int recno;
-
-		if (!spec) {
-			status |= error(_("not a reflog: %s"), argv[i]);
-			continue;
-		}
-
-		if (!dwim_log(argv[i], spec - argv[i], &oid, &ref)) {
-			status |= error(_("no reflog for '%s'"), argv[i]);
-			continue;
-		}
-
-		recno = strtoul(spec + 2, &ep, 10);
-		if (*ep == '}') {
-			cb.cmd.recno = -recno;
-			for_each_reflog_ent(ref, count_reflog_ent, &cb);
-		} else {
-			cb.cmd.expire_total = approxidate(spec + 2);
-			for_each_reflog_ent(ref, count_reflog_ent, &cb);
-			cb.cmd.expire_total = 0;
-		}
-
-		status |= reflog_expire(ref, &oid, flags,
-					reflog_expiry_prepare,
-					should_expire_reflog_ent,
-					reflog_expiry_cleanup,
-					&cb);
-		free(ref);
-	}
-	return status;
-}
-
-static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)
-{
-	int i, start = 0;
-
-	for (i = 1; i < argc; i++) {
-		const char *arg = argv[i];
-		if (!strcmp(arg, "--")) {
-			i++;
-			break;
-		}
-		else if (arg[0] == '-')
-			usage(_(reflog_exists_usage));
-		else
-			break;
-	}
-
-	start = i;
-
-	if (argc - start != 1)
-		usage(_(reflog_exists_usage));
-
-	if (check_refname_format(argv[start], REFNAME_ALLOW_ONELEVEL))
-		die(_("invalid ref format: %s"), argv[start]);
-	return !reflog_exists(argv[start]);
-}
-
-/*
- * main "reflog"
- */
-
-static const char reflog_usage[] =
-N_("git reflog [ show | expire | delete | exists ]");
-
-int cmd_reflog(int argc, const char **argv, const char *prefix)
-{
-	if (argc > 1 && !strcmp(argv[1], "-h"))
-		usage(_(reflog_usage));
-
-	/* With no command, we default to showing it. */
-	if (argc < 2 || *argv[1] == '-')
-		return cmd_log_reflog(argc, argv, prefix);
-
-	if (!strcmp(argv[1], "show"))
-		return cmd_log_reflog(argc - 1, argv + 1, prefix);
-
-	if (!strcmp(argv[1], "expire"))
-		return cmd_reflog_expire(argc - 1, argv + 1, prefix);
-
-	if (!strcmp(argv[1], "delete"))
-		return cmd_reflog_delete(argc - 1, argv + 1, prefix);
-
-	if (!strcmp(argv[1], "exists"))
-		return cmd_reflog_exists(argc - 1, argv + 1, prefix);
-
-	return cmd_log_reflog(argc, argv, prefix);
-}
diff --git a/third_party/git/builtin/remote-ext.c b/third_party/git/builtin/remote-ext.c
deleted file mode 100644
index fd3538d4f0e6..000000000000
--- a/third_party/git/builtin/remote-ext.c
+++ /dev/null
@@ -1,202 +0,0 @@
-#include "builtin.h"
-#include "transport.h"
-#include "run-command.h"
-#include "pkt-line.h"
-
-static const char usage_msg[] =
-	"git remote-ext <remote> <url>";
-
-/*
- * URL syntax:
- *	'command [arg1 [arg2 [...]]]'	Invoke command with given arguments.
- *	Special characters:
- *	'% ': Literal space in argument.
- *	'%%': Literal percent sign.
- *	'%S': Name of service (git-upload-pack/git-upload-archive/
- *		git-receive-pack.
- *	'%s': Same as \s, but with possible git- prefix stripped.
- *	'%G': Only allowed as first 'character' of argument. Do not pass this
- *		Argument to command, instead send this as name of repository
- *		in in-line git://-style request (also activates sending this
- *		style of request).
- *	'%V': Only allowed as first 'character' of argument. Used in
- *		conjunction with '%G': Do not pass this argument to command,
- *		instead send this as vhost in git://-style request (note: does
- *		not activate sending git:// style request).
- */
-
-static char *git_req;
-static char *git_req_vhost;
-
-static char *strip_escapes(const char *str, const char *service,
-	const char **next)
-{
-	size_t rpos = 0;
-	int escape = 0;
-	char special = 0;
-	const char *service_noprefix = service;
-	struct strbuf ret = STRBUF_INIT;
-
-	skip_prefix(service_noprefix, "git-", &service_noprefix);
-
-	/* Pass the service to command. */
-	setenv("GIT_EXT_SERVICE", service, 1);
-	setenv("GIT_EXT_SERVICE_NOPREFIX", service_noprefix, 1);
-
-	/* Scan the length of argument. */
-	while (str[rpos] && (escape || str[rpos] != ' ')) {
-		if (escape) {
-			switch (str[rpos]) {
-			case ' ':
-			case '%':
-			case 's':
-			case 'S':
-				break;
-			case 'G':
-			case 'V':
-				special = str[rpos];
-				if (rpos == 1)
-					break;
-				/* fallthrough */
-			default:
-				die("Bad remote-ext placeholder '%%%c'.",
-					str[rpos]);
-			}
-			escape = 0;
-		} else
-			escape = (str[rpos] == '%');
-		rpos++;
-	}
-	if (escape && !str[rpos])
-		die("remote-ext command has incomplete placeholder");
-	*next = str + rpos;
-	if (**next == ' ')
-		++*next;	/* Skip over space */
-
-	/*
-	 * Do the actual placeholder substitution. The string will be short
-	 * enough not to overflow integers.
-	 */
-	rpos = special ? 2 : 0;		/* Skip first 2 bytes in specials. */
-	escape = 0;
-	while (str[rpos] && (escape || str[rpos] != ' ')) {
-		if (escape) {
-			switch (str[rpos]) {
-			case ' ':
-			case '%':
-				strbuf_addch(&ret, str[rpos]);
-				break;
-			case 's':
-				strbuf_addstr(&ret, service_noprefix);
-				break;
-			case 'S':
-				strbuf_addstr(&ret, service);
-				break;
-			}
-			escape = 0;
-		} else
-			switch (str[rpos]) {
-			case '%':
-				escape = 1;
-				break;
-			default:
-				strbuf_addch(&ret, str[rpos]);
-				break;
-			}
-		rpos++;
-	}
-	switch (special) {
-	case 'G':
-		git_req = strbuf_detach(&ret, NULL);
-		return NULL;
-	case 'V':
-		git_req_vhost = strbuf_detach(&ret, NULL);
-		return NULL;
-	default:
-		return strbuf_detach(&ret, NULL);
-	}
-}
-
-static void parse_argv(struct strvec *out, const char *arg, const char *service)
-{
-	while (*arg) {
-		char *expanded = strip_escapes(arg, service, &arg);
-		if (expanded)
-			strvec_push(out, expanded);
-		free(expanded);
-	}
-}
-
-static void send_git_request(int stdin_fd, const char *serv, const char *repo,
-	const char *vhost)
-{
-	if (!vhost)
-		packet_write_fmt(stdin_fd, "%s %s%c", serv, repo, 0);
-	else
-		packet_write_fmt(stdin_fd, "%s %s%chost=%s%c", serv, repo, 0,
-			     vhost, 0);
-}
-
-static int run_child(const char *arg, const char *service)
-{
-	int r;
-	struct child_process child = CHILD_PROCESS_INIT;
-
-	child.in = -1;
-	child.out = -1;
-	child.err = 0;
-	parse_argv(&child.args, arg, service);
-
-	if (start_command(&child) < 0)
-		die("Can't run specified command");
-
-	if (git_req)
-		send_git_request(child.in, service, git_req, git_req_vhost);
-
-	r = bidirectional_transfer_loop(child.out, child.in);
-	if (!r)
-		r = finish_command(&child);
-	else
-		finish_command(&child);
-	return r;
-}
-
-#define MAXCOMMAND 4096
-
-static int command_loop(const char *child)
-{
-	char buffer[MAXCOMMAND];
-
-	while (1) {
-		size_t i;
-		if (!fgets(buffer, MAXCOMMAND - 1, stdin)) {
-			if (ferror(stdin))
-				die("Command input error");
-			exit(0);
-		}
-		/* Strip end of line characters. */
-		i = strlen(buffer);
-		while (i > 0 && isspace(buffer[i - 1]))
-			buffer[--i] = 0;
-
-		if (!strcmp(buffer, "capabilities")) {
-			printf("*connect\n\n");
-			fflush(stdout);
-		} else if (!strncmp(buffer, "connect ", 8)) {
-			printf("\n");
-			fflush(stdout);
-			return run_child(child, buffer + 8);
-		} else {
-			fprintf(stderr, "Bad command");
-			return 1;
-		}
-	}
-}
-
-int cmd_remote_ext(int argc, const char **argv, const char *prefix)
-{
-	if (argc != 3)
-		usage(usage_msg);
-
-	return command_loop(argv[2]);
-}
diff --git a/third_party/git/builtin/remote-fd.c b/third_party/git/builtin/remote-fd.c
deleted file mode 100644
index 91dfe07e06a1..000000000000
--- a/third_party/git/builtin/remote-fd.c
+++ /dev/null
@@ -1,82 +0,0 @@
-#include "builtin.h"
-#include "transport.h"
-
-static const char usage_msg[] =
-	"git remote-fd <remote> <url>";
-
-/*
- * URL syntax:
- *	'fd::<inoutfd>[/<anything>]'		Read/write socket pair
- *						<inoutfd>.
- *	'fd::<infd>,<outfd>[/<anything>]'	Read pipe <infd> and write
- *						pipe <outfd>.
- *	[foo] indicates 'foo' is optional. <anything> is any string.
- *
- * The data output to <outfd>/<inoutfd> should be passed unmolested to
- * git-receive-pack/git-upload-pack/git-upload-archive and output of
- * git-receive-pack/git-upload-pack/git-upload-archive should be passed
- * unmolested to <infd>/<inoutfd>.
- *
- */
-
-#define MAXCOMMAND 4096
-
-static void command_loop(int input_fd, int output_fd)
-{
-	char buffer[MAXCOMMAND];
-
-	while (1) {
-		size_t i;
-		if (!fgets(buffer, MAXCOMMAND - 1, stdin)) {
-			if (ferror(stdin))
-				die("Input error");
-			return;
-		}
-		/* Strip end of line characters. */
-		i = strlen(buffer);
-		while (i > 0 && isspace(buffer[i - 1]))
-			buffer[--i] = 0;
-
-		if (!strcmp(buffer, "capabilities")) {
-			printf("*connect\n\n");
-			fflush(stdout);
-		} else if (!strncmp(buffer, "connect ", 8)) {
-			printf("\n");
-			fflush(stdout);
-			if (bidirectional_transfer_loop(input_fd,
-				output_fd))
-				die("Copying data between file descriptors failed");
-			return;
-		} else {
-			die("Bad command: %s", buffer);
-		}
-	}
-}
-
-int cmd_remote_fd(int argc, const char **argv, const char *prefix)
-{
-	int input_fd = -1;
-	int output_fd = -1;
-	char *end;
-
-	if (argc != 3)
-		usage(usage_msg);
-
-	input_fd = (int)strtoul(argv[2], &end, 10);
-
-	if ((end == argv[2]) || (*end != ',' && *end != '/' && *end))
-		die("Bad URL syntax");
-
-	if (*end == '/' || !*end) {
-		output_fd = input_fd;
-	} else {
-		char *end2;
-		output_fd = (int)strtoul(end + 1, &end2, 10);
-
-		if ((end2 == end + 1) || (*end2 != '/' && *end2))
-			die("Bad URL syntax");
-	}
-
-	command_loop(input_fd, output_fd);
-	return 0;
-}
diff --git a/third_party/git/builtin/remote.c b/third_party/git/builtin/remote.c
deleted file mode 100644
index 64b4b551eb02..000000000000
--- a/third_party/git/builtin/remote.c
+++ /dev/null
@@ -1,1723 +0,0 @@
-#include "builtin.h"
-#include "config.h"
-#include "parse-options.h"
-#include "transport.h"
-#include "remote.h"
-#include "string-list.h"
-#include "strbuf.h"
-#include "run-command.h"
-#include "rebase.h"
-#include "refs.h"
-#include "refspec.h"
-#include "object-store.h"
-#include "strvec.h"
-#include "commit-reach.h"
-
-static const char * const builtin_remote_usage[] = {
-	N_("git remote [-v | --verbose]"),
-	N_("git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--mirror=<fetch|push>] <name> <url>"),
-	N_("git remote rename <old> <new>"),
-	N_("git remote remove <name>"),
-	N_("git remote set-head <name> (-a | --auto | -d | --delete | <branch>)"),
-	N_("git remote [-v | --verbose] show [-n] <name>"),
-	N_("git remote prune [-n | --dry-run] <name>"),
-	N_("git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]"),
-	N_("git remote set-branches [--add] <name> <branch>..."),
-	N_("git remote get-url [--push] [--all] <name>"),
-	N_("git remote set-url [--push] <name> <newurl> [<oldurl>]"),
-	N_("git remote set-url --add <name> <newurl>"),
-	N_("git remote set-url --delete <name> <url>"),
-	NULL
-};
-
-static const char * const builtin_remote_add_usage[] = {
-	N_("git remote add [<options>] <name> <url>"),
-	NULL
-};
-
-static const char * const builtin_remote_rename_usage[] = {
-	N_("git remote rename <old> <new>"),
-	NULL
-};
-
-static const char * const builtin_remote_rm_usage[] = {
-	N_("git remote remove <name>"),
-	NULL
-};
-
-static const char * const builtin_remote_sethead_usage[] = {
-	N_("git remote set-head <name> (-a | --auto | -d | --delete | <branch>)"),
-	NULL
-};
-
-static const char * const builtin_remote_setbranches_usage[] = {
-	N_("git remote set-branches <name> <branch>..."),
-	N_("git remote set-branches --add <name> <branch>..."),
-	NULL
-};
-
-static const char * const builtin_remote_show_usage[] = {
-	N_("git remote show [<options>] <name>"),
-	NULL
-};
-
-static const char * const builtin_remote_prune_usage[] = {
-	N_("git remote prune [<options>] <name>"),
-	NULL
-};
-
-static const char * const builtin_remote_update_usage[] = {
-	N_("git remote update [<options>] [<group> | <remote>]..."),
-	NULL
-};
-
-static const char * const builtin_remote_geturl_usage[] = {
-	N_("git remote get-url [--push] [--all] <name>"),
-	NULL
-};
-
-static const char * const builtin_remote_seturl_usage[] = {
-	N_("git remote set-url [--push] <name> <newurl> [<oldurl>]"),
-	N_("git remote set-url --add <name> <newurl>"),
-	N_("git remote set-url --delete <name> <url>"),
-	NULL
-};
-
-#define GET_REF_STATES (1<<0)
-#define GET_HEAD_NAMES (1<<1)
-#define GET_PUSH_REF_STATES (1<<2)
-
-static int verbose;
-
-static int fetch_remote(const char *name)
-{
-	const char *argv[] = { "fetch", name, NULL, NULL };
-	if (verbose) {
-		argv[1] = "-v";
-		argv[2] = name;
-	}
-	printf_ln(_("Updating %s"), name);
-	if (run_command_v_opt(argv, RUN_GIT_CMD))
-		return error(_("Could not fetch %s"), name);
-	return 0;
-}
-
-enum {
-	TAGS_UNSET = 0,
-	TAGS_DEFAULT = 1,
-	TAGS_SET = 2
-};
-
-#define MIRROR_NONE 0
-#define MIRROR_FETCH 1
-#define MIRROR_PUSH 2
-#define MIRROR_BOTH (MIRROR_FETCH|MIRROR_PUSH)
-
-static void add_branch(const char *key, const char *branchname,
-		       const char *remotename, int mirror, struct strbuf *tmp)
-{
-	strbuf_reset(tmp);
-	strbuf_addch(tmp, '+');
-	if (mirror)
-		strbuf_addf(tmp, "refs/%s:refs/%s",
-				branchname, branchname);
-	else
-		strbuf_addf(tmp, "refs/heads/%s:refs/remotes/%s/%s",
-				branchname, remotename, branchname);
-	git_config_set_multivar(key, tmp->buf, "^$", 0);
-}
-
-static const char mirror_advice[] =
-N_("--mirror is dangerous and deprecated; please\n"
-   "\t use --mirror=fetch or --mirror=push instead");
-
-static int parse_mirror_opt(const struct option *opt, const char *arg, int not)
-{
-	unsigned *mirror = opt->value;
-	if (not)
-		*mirror = MIRROR_NONE;
-	else if (!arg) {
-		warning("%s", _(mirror_advice));
-		*mirror = MIRROR_BOTH;
-	}
-	else if (!strcmp(arg, "fetch"))
-		*mirror = MIRROR_FETCH;
-	else if (!strcmp(arg, "push"))
-		*mirror = MIRROR_PUSH;
-	else
-		return error(_("unknown mirror argument: %s"), arg);
-	return 0;
-}
-
-static int add(int argc, const char **argv)
-{
-	int fetch = 0, fetch_tags = TAGS_DEFAULT;
-	unsigned mirror = MIRROR_NONE;
-	struct string_list track = STRING_LIST_INIT_NODUP;
-	const char *master = NULL;
-	struct remote *remote;
-	struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT;
-	const char *name, *url;
-	int i;
-
-	struct option options[] = {
-		OPT_BOOL('f', "fetch", &fetch, N_("fetch the remote branches")),
-		OPT_SET_INT(0, "tags", &fetch_tags,
-			    N_("import all tags and associated objects when fetching"),
-			    TAGS_SET),
-		OPT_SET_INT(0, NULL, &fetch_tags,
-			    N_("or do not fetch any tag at all (--no-tags)"), TAGS_UNSET),
-		OPT_STRING_LIST('t', "track", &track, N_("branch"),
-				N_("branch(es) to track")),
-		OPT_STRING('m', "master", &master, N_("branch"), N_("master branch")),
-		OPT_CALLBACK_F(0, "mirror", &mirror, "(push|fetch)",
-			N_("set up remote as a mirror to push to or fetch from"),
-			PARSE_OPT_OPTARG | PARSE_OPT_COMP_ARG, parse_mirror_opt),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, NULL, options, builtin_remote_add_usage,
-			     0);
-
-	if (argc != 2)
-		usage_with_options(builtin_remote_add_usage, options);
-
-	if (mirror && master)
-		die(_("specifying a master branch makes no sense with --mirror"));
-	if (mirror && !(mirror & MIRROR_FETCH) && track.nr)
-		die(_("specifying branches to track makes sense only with fetch mirrors"));
-
-	name = argv[0];
-	url = argv[1];
-
-	remote = remote_get(name);
-	if (remote_is_configured(remote, 1))
-		die(_("remote %s already exists."), name);
-
-	strbuf_addf(&buf2, "refs/heads/test:refs/remotes/%s/test", name);
-	if (!valid_fetch_refspec(buf2.buf))
-		die(_("'%s' is not a valid remote name"), name);
-
-	strbuf_addf(&buf, "remote.%s.url", name);
-	git_config_set(buf.buf, url);
-
-	if (!mirror || mirror & MIRROR_FETCH) {
-		strbuf_reset(&buf);
-		strbuf_addf(&buf, "remote.%s.fetch", name);
-		if (track.nr == 0)
-			string_list_append(&track, "*");
-		for (i = 0; i < track.nr; i++) {
-			add_branch(buf.buf, track.items[i].string,
-				   name, mirror, &buf2);
-		}
-	}
-
-	if (mirror & MIRROR_PUSH) {
-		strbuf_reset(&buf);
-		strbuf_addf(&buf, "remote.%s.mirror", name);
-		git_config_set(buf.buf, "true");
-	}
-
-	if (fetch_tags != TAGS_DEFAULT) {
-		strbuf_reset(&buf);
-		strbuf_addf(&buf, "remote.%s.tagopt", name);
-		git_config_set(buf.buf,
-			       fetch_tags == TAGS_SET ? "--tags" : "--no-tags");
-	}
-
-	if (fetch && fetch_remote(name))
-		return 1;
-
-	if (master) {
-		strbuf_reset(&buf);
-		strbuf_addf(&buf, "refs/remotes/%s/HEAD", name);
-
-		strbuf_reset(&buf2);
-		strbuf_addf(&buf2, "refs/remotes/%s/%s", name, master);
-
-		if (create_symref(buf.buf, buf2.buf, "remote add"))
-			return error(_("Could not setup master '%s'"), master);
-	}
-
-	strbuf_release(&buf);
-	strbuf_release(&buf2);
-	string_list_clear(&track, 0);
-
-	return 0;
-}
-
-struct branch_info {
-	char *remote_name;
-	struct string_list merge;
-	enum rebase_type rebase;
-	char *push_remote_name;
-};
-
-static struct string_list branch_list = STRING_LIST_INIT_NODUP;
-
-static const char *abbrev_ref(const char *name, const char *prefix)
-{
-	skip_prefix(name, prefix, &name);
-	return name;
-}
-#define abbrev_branch(name) abbrev_ref((name), "refs/heads/")
-
-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."))
-		return 0;
-
-	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, ' ');
-		}
-		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;
-}
-
-static void read_branches(void)
-{
-	if (branch_list.nr)
-		return;
-	git_config(config_read_branches, NULL);
-}
-
-struct ref_states {
-	struct remote *remote;
-	struct string_list new_refs, stale, tracked, heads, push;
-	int queried;
-};
-
-static int get_ref_states(const struct ref *remote_refs, struct ref_states *states)
-{
-	struct ref *fetch_map = NULL, **tail = &fetch_map;
-	struct ref *ref, *stale_refs;
-	int i;
-
-	for (i = 0; i < states->remote->fetch.nr; i++)
-		if (get_fetch_map(remote_refs, &states->remote->fetch.items[i], &tail, 1))
-			die(_("Could not get fetch map for refspec %s"),
-				states->remote->fetch.raw[i]);
-
-	states->new_refs.strdup_strings = 1;
-	states->tracked.strdup_strings = 1;
-	states->stale.strdup_strings = 1;
-	for (ref = fetch_map; ref; ref = ref->next) {
-		if (!ref->peer_ref || !ref_exists(ref->peer_ref->name))
-			string_list_append(&states->new_refs, abbrev_branch(ref->name));
-		else
-			string_list_append(&states->tracked, abbrev_branch(ref->name));
-	}
-	stale_refs = get_stale_heads(&states->remote->fetch, fetch_map);
-	for (ref = stale_refs; ref; ref = ref->next) {
-		struct string_list_item *item =
-			string_list_append(&states->stale, abbrev_branch(ref->name));
-		item->util = xstrdup(ref->name);
-	}
-	free_refs(stale_refs);
-	free_refs(fetch_map);
-
-	string_list_sort(&states->new_refs);
-	string_list_sort(&states->tracked);
-	string_list_sort(&states->stale);
-
-	return 0;
-}
-
-struct push_info {
-	char *dest;
-	int forced;
-	enum {
-		PUSH_STATUS_CREATE = 0,
-		PUSH_STATUS_DELETE,
-		PUSH_STATUS_UPTODATE,
-		PUSH_STATUS_FASTFORWARD,
-		PUSH_STATUS_OUTOFDATE,
-		PUSH_STATUS_NOTQUERIED
-	} status;
-};
-
-static int get_push_ref_states(const struct ref *remote_refs,
-	struct ref_states *states)
-{
-	struct remote *remote = states->remote;
-	struct ref *ref, *local_refs, *push_map;
-	if (remote->mirror)
-		return 0;
-
-	local_refs = get_local_heads();
-	push_map = copy_ref_list(remote_refs);
-
-	match_push_refs(local_refs, &push_map, &remote->push, MATCH_REFS_NONE);
-
-	states->push.strdup_strings = 1;
-	for (ref = push_map; ref; ref = ref->next) {
-		struct string_list_item *item;
-		struct push_info *info;
-
-		if (!ref->peer_ref)
-			continue;
-		oidcpy(&ref->new_oid, &ref->peer_ref->new_oid);
-
-		item = string_list_append(&states->push,
-					  abbrev_branch(ref->peer_ref->name));
-		item->util = xcalloc(1, sizeof(struct push_info));
-		info = item->util;
-		info->forced = ref->force;
-		info->dest = xstrdup(abbrev_branch(ref->name));
-
-		if (is_null_oid(&ref->new_oid)) {
-			info->status = PUSH_STATUS_DELETE;
-		} else if (oideq(&ref->old_oid, &ref->new_oid))
-			info->status = PUSH_STATUS_UPTODATE;
-		else if (is_null_oid(&ref->old_oid))
-			info->status = PUSH_STATUS_CREATE;
-		else if (has_object_file(&ref->old_oid) &&
-			 ref_newer(&ref->new_oid, &ref->old_oid))
-			info->status = PUSH_STATUS_FASTFORWARD;
-		else
-			info->status = PUSH_STATUS_OUTOFDATE;
-	}
-	free_refs(local_refs);
-	free_refs(push_map);
-	return 0;
-}
-
-static int get_push_ref_states_noquery(struct ref_states *states)
-{
-	int i;
-	struct remote *remote = states->remote;
-	struct string_list_item *item;
-	struct push_info *info;
-
-	if (remote->mirror)
-		return 0;
-
-	states->push.strdup_strings = 1;
-	if (!remote->push.nr) {
-		item = string_list_append(&states->push, _("(matching)"));
-		info = item->util = xcalloc(1, sizeof(struct push_info));
-		info->status = PUSH_STATUS_NOTQUERIED;
-		info->dest = xstrdup(item->string);
-	}
-	for (i = 0; i < remote->push.nr; i++) {
-		const struct refspec_item *spec = &remote->push.items[i];
-		if (spec->matching)
-			item = string_list_append(&states->push, _("(matching)"));
-		else if (strlen(spec->src))
-			item = string_list_append(&states->push, spec->src);
-		else
-			item = string_list_append(&states->push, _("(delete)"));
-
-		info = item->util = xcalloc(1, sizeof(struct push_info));
-		info->forced = spec->force;
-		info->status = PUSH_STATUS_NOTQUERIED;
-		info->dest = xstrdup(spec->dst ? spec->dst : item->string);
-	}
-	return 0;
-}
-
-static int get_head_names(const struct ref *remote_refs, struct ref_states *states)
-{
-	struct ref *ref, *matches;
-	struct ref *fetch_map = NULL, **fetch_map_tail = &fetch_map;
-	struct refspec_item refspec;
-
-	memset(&refspec, 0, sizeof(refspec));
-	refspec.force = 0;
-	refspec.pattern = 1;
-	refspec.src = refspec.dst = "refs/heads/*";
-	states->heads.strdup_strings = 1;
-	get_fetch_map(remote_refs, &refspec, &fetch_map_tail, 0);
-	matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"),
-				    fetch_map, 1);
-	for (ref = matches; ref; ref = ref->next)
-		string_list_append(&states->heads, abbrev_branch(ref->name));
-
-	free_refs(fetch_map);
-	free_refs(matches);
-
-	return 0;
-}
-
-struct known_remote {
-	struct known_remote *next;
-	struct remote *remote;
-};
-
-struct known_remotes {
-	struct remote *to_delete;
-	struct known_remote *list;
-};
-
-static int add_known_remote(struct remote *remote, void *cb_data)
-{
-	struct known_remotes *all = cb_data;
-	struct known_remote *r;
-
-	if (!strcmp(all->to_delete->name, remote->name))
-		return 0;
-
-	r = xmalloc(sizeof(*r));
-	r->remote = remote;
-	r->next = all->list;
-	all->list = r;
-	return 0;
-}
-
-struct branches_for_remote {
-	struct remote *remote;
-	struct string_list *branches, *skipped;
-	struct known_remotes *keep;
-};
-
-static int add_branch_for_removal(const char *refname,
-	const struct object_id *oid, int flags, void *cb_data)
-{
-	struct branches_for_remote *branches = cb_data;
-	struct refspec_item refspec;
-	struct known_remote *kr;
-
-	memset(&refspec, 0, sizeof(refspec));
-	refspec.dst = (char *)refname;
-	if (remote_find_tracking(branches->remote, &refspec))
-		return 0;
-
-	/* don't delete a branch if another remote also uses it */
-	for (kr = branches->keep->list; kr; kr = kr->next) {
-		memset(&refspec, 0, sizeof(refspec));
-		refspec.dst = (char *)refname;
-		if (!remote_find_tracking(kr->remote, &refspec))
-			return 0;
-	}
-
-	/* don't delete non-remote-tracking refs */
-	if (!starts_with(refname, "refs/remotes/")) {
-		/* advise user how to delete local branches */
-		if (starts_with(refname, "refs/heads/"))
-			string_list_append(branches->skipped,
-					   abbrev_branch(refname));
-		/* silently skip over other non-remote refs */
-		return 0;
-	}
-
-	string_list_append(branches->branches, refname);
-
-	return 0;
-}
-
-struct rename_info {
-	const char *old_name;
-	const char *new_name;
-	struct string_list *remote_branches;
-};
-
-static int read_remote_branches(const char *refname,
-	const struct object_id *oid, int flags, void *cb_data)
-{
-	struct rename_info *rename = cb_data;
-	struct strbuf buf = STRBUF_INIT;
-	struct string_list_item *item;
-	int flag;
-	const char *symref;
-
-	strbuf_addf(&buf, "refs/remotes/%s/", rename->old_name);
-	if (starts_with(refname, buf.buf)) {
-		item = string_list_append(rename->remote_branches, refname);
-		symref = resolve_ref_unsafe(refname, RESOLVE_REF_READING,
-					    NULL, &flag);
-		if (symref && (flag & REF_ISSYMREF))
-			item->util = xstrdup(symref);
-		else
-			item->util = NULL;
-	}
-	strbuf_release(&buf);
-
-	return 0;
-}
-
-static int migrate_file(struct remote *remote)
-{
-	struct strbuf buf = STRBUF_INIT;
-	int i;
-
-	strbuf_addf(&buf, "remote.%s.url", remote->name);
-	for (i = 0; i < remote->url_nr; i++)
-		git_config_set_multivar(buf.buf, remote->url[i], "^$", 0);
-	strbuf_reset(&buf);
-	strbuf_addf(&buf, "remote.%s.push", remote->name);
-	for (i = 0; i < remote->push.raw_nr; i++)
-		git_config_set_multivar(buf.buf, remote->push.raw[i], "^$", 0);
-	strbuf_reset(&buf);
-	strbuf_addf(&buf, "remote.%s.fetch", remote->name);
-	for (i = 0; i < remote->fetch.raw_nr; i++)
-		git_config_set_multivar(buf.buf, remote->fetch.raw[i], "^$", 0);
-	if (remote->origin == REMOTE_REMOTES)
-		unlink_or_warn(git_path("remotes/%s", remote->name));
-	else if (remote->origin == REMOTE_BRANCHES)
-		unlink_or_warn(git_path("branches/%s", remote->name));
-	strbuf_release(&buf);
-
-	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[] = {
-		OPT_END()
-	};
-	struct remote *oldremote, *newremote;
-	struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT,
-		old_remote_context = STRBUF_INIT;
-	struct string_list remote_branches = STRING_LIST_INIT_DUP;
-	struct rename_info rename;
-	int i, refspec_updated = 0;
-
-	if (argc != 3)
-		usage_with_options(builtin_remote_rename_usage, options);
-
-	rename.old_name = argv[1];
-	rename.new_name = argv[2];
-	rename.remote_branches = &remote_branches;
-
-	oldremote = remote_get(rename.old_name);
-	if (!remote_is_configured(oldremote, 1))
-		die(_("No such remote: '%s'"), rename.old_name);
-
-	if (!strcmp(rename.old_name, rename.new_name) && oldremote->origin != REMOTE_CONFIG)
-		return migrate_file(oldremote);
-
-	newremote = remote_get(rename.new_name);
-	if (remote_is_configured(newremote, 1))
-		die(_("remote %s already exists."), rename.new_name);
-
-	strbuf_addf(&buf, "refs/heads/test:refs/remotes/%s/test", rename.new_name);
-	if (!valid_fetch_refspec(buf.buf))
-		die(_("'%s' is not a valid remote name"), rename.new_name);
-
-	strbuf_reset(&buf);
-	strbuf_addf(&buf, "remote.%s", rename.old_name);
-	strbuf_addf(&buf2, "remote.%s", rename.new_name);
-	if (git_config_rename_section(buf.buf, buf2.buf) < 1)
-		return error(_("Could not rename config section '%s' to '%s'"),
-				buf.buf, buf2.buf);
-
-	strbuf_reset(&buf);
-	strbuf_addf(&buf, "remote.%s.fetch", rename.new_name);
-	git_config_set_multivar(buf.buf, NULL, NULL, 1);
-	strbuf_addf(&old_remote_context, ":refs/remotes/%s/", rename.old_name);
-	for (i = 0; i < oldremote->fetch.raw_nr; i++) {
-		char *ptr;
-
-		strbuf_reset(&buf2);
-		strbuf_addstr(&buf2, oldremote->fetch.raw[i]);
-		ptr = strstr(buf2.buf, old_remote_context.buf);
-		if (ptr) {
-			refspec_updated = 1;
-			strbuf_splice(&buf2,
-				      ptr-buf2.buf + strlen(":refs/remotes/"),
-				      strlen(rename.old_name), rename.new_name,
-				      strlen(rename.new_name));
-		} else
-			warning(_("Not updating non-default fetch refspec\n"
-				  "\t%s\n"
-				  "\tPlease update the configuration manually if necessary."),
-				buf2.buf);
-
-		git_config_set_multivar(buf.buf, buf2.buf, "^$", 0);
-	}
-
-	read_branches();
-	for (i = 0; i < branch_list.nr; i++) {
-		struct string_list_item *item = branch_list.items + i;
-		struct branch_info *info = item->util;
-		if (info->remote_name && !strcmp(info->remote_name, rename.old_name)) {
-			strbuf_reset(&buf);
-			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)
-		return 0;
-
-	/*
-	 * First remove symrefs, then rename the rest, finally create
-	 * the new symrefs.
-	 */
-	for_each_ref(read_remote_branches, &rename);
-	for (i = 0; i < remote_branches.nr; i++) {
-		struct string_list_item *item = remote_branches.items + i;
-		int flag = 0;
-
-		read_ref_full(item->string, RESOLVE_REF_READING, NULL, &flag);
-		if (!(flag & REF_ISSYMREF))
-			continue;
-		if (delete_ref(NULL, item->string, NULL, REF_NO_DEREF))
-			die(_("deleting '%s' failed"), item->string);
-	}
-	for (i = 0; i < remote_branches.nr; i++) {
-		struct string_list_item *item = remote_branches.items + i;
-
-		if (item->util)
-			continue;
-		strbuf_reset(&buf);
-		strbuf_addstr(&buf, item->string);
-		strbuf_splice(&buf, strlen("refs/remotes/"), strlen(rename.old_name),
-				rename.new_name, strlen(rename.new_name));
-		strbuf_reset(&buf2);
-		strbuf_addf(&buf2, "remote: renamed %s to %s",
-				item->string, buf.buf);
-		if (rename_ref(item->string, buf.buf, buf2.buf))
-			die(_("renaming '%s' failed"), item->string);
-	}
-	for (i = 0; i < remote_branches.nr; i++) {
-		struct string_list_item *item = remote_branches.items + i;
-
-		if (!item->util)
-			continue;
-		strbuf_reset(&buf);
-		strbuf_addstr(&buf, item->string);
-		strbuf_splice(&buf, strlen("refs/remotes/"), strlen(rename.old_name),
-				rename.new_name, strlen(rename.new_name));
-		strbuf_reset(&buf2);
-		strbuf_addstr(&buf2, item->util);
-		strbuf_splice(&buf2, strlen("refs/remotes/"), strlen(rename.old_name),
-				rename.new_name, strlen(rename.new_name));
-		strbuf_reset(&buf3);
-		strbuf_addf(&buf3, "remote: renamed %s to %s",
-				item->string, buf.buf);
-		if (create_symref(buf.buf, buf2.buf, buf3.buf))
-			die(_("creating '%s' failed"), buf.buf);
-	}
-	string_list_clear(&remote_branches, 1);
-
-	handle_push_default(rename.old_name, rename.new_name);
-
-	return 0;
-}
-
-static int rm(int argc, const char **argv)
-{
-	struct option options[] = {
-		OPT_END()
-	};
-	struct remote *remote;
-	struct strbuf buf = STRBUF_INIT;
-	struct known_remotes known_remotes = { NULL, NULL };
-	struct string_list branches = STRING_LIST_INIT_DUP;
-	struct string_list skipped = STRING_LIST_INIT_DUP;
-	struct branches_for_remote cb_data;
-	int i, result;
-
-	memset(&cb_data, 0, sizeof(cb_data));
-	cb_data.branches = &branches;
-	cb_data.skipped = &skipped;
-	cb_data.keep = &known_remotes;
-
-	if (argc != 2)
-		usage_with_options(builtin_remote_rm_usage, options);
-
-	remote = remote_get(argv[1]);
-	if (!remote_is_configured(remote, 1))
-		die(_("No such remote: '%s'"), argv[1]);
-
-	known_remotes.to_delete = remote;
-	for_each_remote(add_known_remote, &known_remotes);
-
-	read_branches();
-	for (i = 0; i < branch_list.nr; i++) {
-		struct string_list_item *item = branch_list.items + i;
-		struct branch_info *info = item->util;
-		if (info->remote_name && !strcmp(info->remote_name, remote->name)) {
-			const char *keys[] = { "remote", "merge", NULL }, **k;
-			for (k = keys; *k; k++) {
-				strbuf_reset(&buf);
-				strbuf_addf(&buf, "branch.%s.%s",
-						item->string, *k);
-				result = git_config_set_gently(buf.buf, NULL);
-				if (result && result != CONFIG_NOTHING_SET)
-					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);
-		}
-	}
-
-	/*
-	 * We cannot just pass a function to for_each_ref() which deletes
-	 * the branches one by one, since for_each_ref() relies on cached
-	 * refs, which are invalidated when deleting a branch.
-	 */
-	cb_data.remote = remote;
-	result = for_each_ref(add_branch_for_removal, &cb_data);
-	strbuf_release(&buf);
-
-	if (!result)
-		result = delete_refs("remote: remove", &branches, REF_NO_DEREF);
-	string_list_clear(&branches, 0);
-
-	if (skipped.nr) {
-		fprintf_ln(stderr,
-			   Q_("Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
-			      "to delete it, use:",
-			      "Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n"
-			      "to delete them, use:",
-			      skipped.nr));
-		for (i = 0; i < skipped.nr; i++)
-			fprintf(stderr, "  git branch -d %s\n",
-				skipped.items[i].string);
-	}
-	string_list_clear(&skipped, 0);
-
-	if (!result) {
-		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;
-}
-
-static void clear_push_info(void *util, const char *string)
-{
-	struct push_info *info = util;
-	free(info->dest);
-	free(info);
-}
-
-static void free_remote_ref_states(struct ref_states *states)
-{
-	string_list_clear(&states->new_refs, 0);
-	string_list_clear(&states->stale, 1);
-	string_list_clear(&states->tracked, 0);
-	string_list_clear(&states->heads, 0);
-	string_list_clear_func(&states->push, clear_push_info);
-}
-
-static int append_ref_to_tracked_list(const char *refname,
-	const struct object_id *oid, int flags, void *cb_data)
-{
-	struct ref_states *states = cb_data;
-	struct refspec_item refspec;
-
-	if (flags & REF_ISSYMREF)
-		return 0;
-
-	memset(&refspec, 0, sizeof(refspec));
-	refspec.dst = (char *)refname;
-	if (!remote_find_tracking(states->remote, &refspec))
-		string_list_append(&states->tracked, abbrev_branch(refspec.src));
-
-	return 0;
-}
-
-static int get_remote_ref_states(const char *name,
-				 struct ref_states *states,
-				 int query)
-{
-	struct transport *transport;
-	const struct ref *remote_refs;
-
-	states->remote = remote_get(name);
-	if (!states->remote)
-		return error(_("No such remote: '%s'"), name);
-
-	read_branches();
-
-	if (query) {
-		transport = transport_get(states->remote, states->remote->url_nr > 0 ?
-			states->remote->url[0] : NULL);
-		remote_refs = transport_get_remote_refs(transport, NULL);
-		transport_disconnect(transport);
-
-		states->queried = 1;
-		if (query & GET_REF_STATES)
-			get_ref_states(remote_refs, states);
-		if (query & GET_HEAD_NAMES)
-			get_head_names(remote_refs, states);
-		if (query & GET_PUSH_REF_STATES)
-			get_push_ref_states(remote_refs, states);
-	} else {
-		for_each_ref(append_ref_to_tracked_list, states);
-		string_list_sort(&states->tracked);
-		get_push_ref_states_noquery(states);
-	}
-
-	return 0;
-}
-
-struct show_info {
-	struct string_list *list;
-	struct ref_states *states;
-	int width, width2;
-	int any_rebase;
-};
-
-static int add_remote_to_show_info(struct string_list_item *item, void *cb_data)
-{
-	struct show_info *info = cb_data;
-	int n = strlen(item->string);
-	if (n > info->width)
-		info->width = n;
-	string_list_insert(info->list, item->string);
-	return 0;
-}
-
-static int show_remote_info_item(struct string_list_item *item, void *cb_data)
-{
-	struct show_info *info = cb_data;
-	struct ref_states *states = info->states;
-	const char *name = item->string;
-
-	if (states->queried) {
-		const char *fmt = "%s";
-		const char *arg = "";
-		if (string_list_has_string(&states->new_refs, name)) {
-			fmt = _(" new (next fetch will store in remotes/%s)");
-			arg = states->remote->name;
-		} else if (string_list_has_string(&states->tracked, name))
-			arg = _(" tracked");
-		else if (string_list_has_string(&states->stale, name))
-			arg = _(" stale (use 'git remote prune' to remove)");
-		else
-			arg = _(" ???");
-		printf("    %-*s", info->width, name);
-		printf(fmt, arg);
-		printf("\n");
-	} else
-		printf("    %s\n", name);
-
-	return 0;
-}
-
-static int add_local_to_show_info(struct string_list_item *branch_item, void *cb_data)
-{
-	struct show_info *show_info = cb_data;
-	struct ref_states *states = show_info->states;
-	struct branch_info *branch_info = branch_item->util;
-	struct string_list_item *item;
-	int n;
-
-	if (!branch_info->merge.nr || !branch_info->remote_name ||
-	    strcmp(states->remote->name, branch_info->remote_name))
-		return 0;
-	if ((n = strlen(branch_item->string)) > show_info->width)
-		show_info->width = n;
-	if (branch_info->rebase >= REBASE_TRUE)
-		show_info->any_rebase = 1;
-
-	item = string_list_insert(show_info->list, branch_item->string);
-	item->util = branch_info;
-
-	return 0;
-}
-
-static int show_local_info_item(struct string_list_item *item, void *cb_data)
-{
-	struct show_info *show_info = cb_data;
-	struct branch_info *branch_info = item->util;
-	struct string_list *merge = &branch_info->merge;
-	int width = show_info->width + 4;
-	int i;
-
-	if (branch_info->rebase >= REBASE_TRUE && 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) {
-		const char *msg;
-		if (branch_info->rebase == REBASE_INTERACTIVE)
-			msg = _("rebases interactively onto remote %s");
-		else if (branch_info->rebase == REBASE_MERGES)
-			msg = _("rebases interactively (with merges) onto "
-				"remote %s");
-		else
-			msg = _("rebases onto remote %s");
-		printf_ln(msg, merge->items[0].string);
-		return 0;
-	} else if (show_info->any_rebase) {
-		printf_ln(_(" merges with remote %s"), merge->items[0].string);
-		width++;
-	} else {
-		printf_ln(_("merges with remote %s"), merge->items[0].string);
-	}
-	for (i = 1; i < merge->nr; i++)
-		printf(_("%-*s    and with remote %s\n"), width, "",
-		       merge->items[i].string);
-
-	return 0;
-}
-
-static int add_push_to_show_info(struct string_list_item *push_item, void *cb_data)
-{
-	struct show_info *show_info = cb_data;
-	struct push_info *push_info = push_item->util;
-	struct string_list_item *item;
-	int n;
-	if ((n = strlen(push_item->string)) > show_info->width)
-		show_info->width = n;
-	if ((n = strlen(push_info->dest)) > show_info->width2)
-		show_info->width2 = n;
-	item = string_list_append(show_info->list, push_item->string);
-	item->util = push_item->util;
-	return 0;
-}
-
-/*
- * Sorting comparison for a string list that has push_info
- * structs in its util field
- */
-static int cmp_string_with_push(const void *va, const void *vb)
-{
-	const struct string_list_item *a = va;
-	const struct string_list_item *b = vb;
-	const struct push_info *a_push = a->util;
-	const struct push_info *b_push = b->util;
-	int cmp = strcmp(a->string, b->string);
-	return cmp ? cmp : strcmp(a_push->dest, b_push->dest);
-}
-
-static int show_push_info_item(struct string_list_item *item, void *cb_data)
-{
-	struct show_info *show_info = cb_data;
-	struct push_info *push_info = item->util;
-	const char *src = item->string, *status = NULL;
-
-	switch (push_info->status) {
-	case PUSH_STATUS_CREATE:
-		status = _("create");
-		break;
-	case PUSH_STATUS_DELETE:
-		status = _("delete");
-		src = _("(none)");
-		break;
-	case PUSH_STATUS_UPTODATE:
-		status = _("up to date");
-		break;
-	case PUSH_STATUS_FASTFORWARD:
-		status = _("fast-forwardable");
-		break;
-	case PUSH_STATUS_OUTOFDATE:
-		status = _("local out of date");
-		break;
-	case PUSH_STATUS_NOTQUERIED:
-		break;
-	}
-	if (status) {
-		if (push_info->forced)
-			printf_ln(_("    %-*s forces to %-*s (%s)"), show_info->width, src,
-			       show_info->width2, push_info->dest, status);
-		else
-			printf_ln(_("    %-*s pushes to %-*s (%s)"), show_info->width, src,
-			       show_info->width2, push_info->dest, status);
-	} else {
-		if (push_info->forced)
-			printf_ln(_("    %-*s forces to %s"), show_info->width, src,
-			       push_info->dest);
-		else
-			printf_ln(_("    %-*s pushes to %s"), show_info->width, src,
-			       push_info->dest);
-	}
-	return 0;
-}
-
-static int get_one_entry(struct remote *remote, void *priv)
-{
-	struct string_list *list = priv;
-	struct strbuf url_buf = STRBUF_INIT;
-	const char **url;
-	int i, url_nr;
-
-	if (remote->url_nr > 0) {
-		strbuf_addf(&url_buf, "%s (fetch)", remote->url[0]);
-		string_list_append(list, remote->name)->util =
-				strbuf_detach(&url_buf, NULL);
-	} else
-		string_list_append(list, remote->name)->util = NULL;
-	if (remote->pushurl_nr) {
-		url = remote->pushurl;
-		url_nr = remote->pushurl_nr;
-	} else {
-		url = remote->url;
-		url_nr = remote->url_nr;
-	}
-	for (i = 0; i < url_nr; i++)
-	{
-		strbuf_addf(&url_buf, "%s (push)", url[i]);
-		string_list_append(list, remote->name)->util =
-				strbuf_detach(&url_buf, NULL);
-	}
-
-	return 0;
-}
-
-static int show_all(void)
-{
-	struct string_list list = STRING_LIST_INIT_NODUP;
-	int result;
-
-	list.strdup_strings = 1;
-	result = for_each_remote(get_one_entry, &list);
-
-	if (!result) {
-		int i;
-
-		string_list_sort(&list);
-		for (i = 0; i < list.nr; i++) {
-			struct string_list_item *item = list.items + i;
-			if (verbose)
-				printf("%s\t%s\n", item->string,
-					item->util ? (const char *)item->util : "");
-			else {
-				if (i && !strcmp((item - 1)->string, item->string))
-					continue;
-				printf("%s\n", item->string);
-			}
-		}
-	}
-	string_list_clear(&list, 1);
-	return result;
-}
-
-static int show(int argc, const char **argv)
-{
-	int no_query = 0, result = 0, query_flag = 0;
-	struct option options[] = {
-		OPT_BOOL('n', NULL, &no_query, N_("do not query remotes")),
-		OPT_END()
-	};
-	struct ref_states states;
-	struct string_list info_list = STRING_LIST_INIT_NODUP;
-	struct show_info info;
-
-	argc = parse_options(argc, argv, NULL, options, builtin_remote_show_usage,
-			     0);
-
-	if (argc < 1)
-		return show_all();
-
-	if (!no_query)
-		query_flag = (GET_REF_STATES | GET_HEAD_NAMES | GET_PUSH_REF_STATES);
-
-	memset(&states, 0, sizeof(states));
-	memset(&info, 0, sizeof(info));
-	info.states = &states;
-	info.list = &info_list;
-	for (; argc; argc--, argv++) {
-		int i;
-		const char **url;
-		int url_nr;
-
-		get_remote_ref_states(*argv, &states, query_flag);
-
-		printf_ln(_("* remote %s"), *argv);
-		printf_ln(_("  Fetch URL: %s"), states.remote->url_nr > 0 ?
-		       states.remote->url[0] : _("(no URL)"));
-		if (states.remote->pushurl_nr) {
-			url = states.remote->pushurl;
-			url_nr = states.remote->pushurl_nr;
-		} else {
-			url = states.remote->url;
-			url_nr = states.remote->url_nr;
-		}
-		for (i = 0; i < url_nr; i++)
-			/*
-			 * TRANSLATORS: the colon ':' should align
-			 * with the one in " Fetch URL: %s"
-			 * translation.
-			 */
-			printf_ln(_("  Push  URL: %s"), url[i]);
-		if (!i)
-			printf_ln(_("  Push  URL: %s"), _("(no URL)"));
-		if (no_query)
-			printf_ln(_("  HEAD branch: %s"), _("(not queried)"));
-		else if (!states.heads.nr)
-			printf_ln(_("  HEAD branch: %s"), _("(unknown)"));
-		else if (states.heads.nr == 1)
-			printf_ln(_("  HEAD branch: %s"), states.heads.items[0].string);
-		else {
-			printf(_("  HEAD branch (remote HEAD is ambiguous,"
-				 " may be one of the following):\n"));
-			for (i = 0; i < states.heads.nr; i++)
-				printf("    %s\n", states.heads.items[i].string);
-		}
-
-		/* remote branch info */
-		info.width = 0;
-		for_each_string_list(&states.new_refs, add_remote_to_show_info, &info);
-		for_each_string_list(&states.tracked, add_remote_to_show_info, &info);
-		for_each_string_list(&states.stale, add_remote_to_show_info, &info);
-		if (info.list->nr)
-			printf_ln(Q_("  Remote branch:%s",
-				     "  Remote branches:%s",
-				     info.list->nr),
-				  no_query ? _(" (status not queried)") : "");
-		for_each_string_list(info.list, show_remote_info_item, &info);
-		string_list_clear(info.list, 0);
-
-		/* git pull info */
-		info.width = 0;
-		info.any_rebase = 0;
-		for_each_string_list(&branch_list, add_local_to_show_info, &info);
-		if (info.list->nr)
-			printf_ln(Q_("  Local branch configured for 'git pull':",
-				     "  Local branches configured for 'git pull':",
-				     info.list->nr));
-		for_each_string_list(info.list, show_local_info_item, &info);
-		string_list_clear(info.list, 0);
-
-		/* git push info */
-		if (states.remote->mirror)
-			printf_ln(_("  Local refs will be mirrored by 'git push'"));
-
-		info.width = info.width2 = 0;
-		for_each_string_list(&states.push, add_push_to_show_info, &info);
-		QSORT(info.list->items, info.list->nr, cmp_string_with_push);
-		if (info.list->nr)
-			printf_ln(Q_("  Local ref configured for 'git push'%s:",
-				     "  Local refs configured for 'git push'%s:",
-				     info.list->nr),
-				  no_query ? _(" (status not queried)") : "");
-		for_each_string_list(info.list, show_push_info_item, &info);
-		string_list_clear(info.list, 0);
-
-		free_remote_ref_states(&states);
-	}
-
-	return result;
-}
-
-static int set_head(int argc, const char **argv)
-{
-	int i, opt_a = 0, opt_d = 0, result = 0;
-	struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT;
-	char *head_name = NULL;
-
-	struct option options[] = {
-		OPT_BOOL('a', "auto", &opt_a,
-			 N_("set refs/remotes/<name>/HEAD according to remote")),
-		OPT_BOOL('d', "delete", &opt_d,
-			 N_("delete refs/remotes/<name>/HEAD")),
-		OPT_END()
-	};
-	argc = parse_options(argc, argv, NULL, options, builtin_remote_sethead_usage,
-			     0);
-	if (argc)
-		strbuf_addf(&buf, "refs/remotes/%s/HEAD", argv[0]);
-
-	if (!opt_a && !opt_d && argc == 2) {
-		head_name = xstrdup(argv[1]);
-	} else if (opt_a && !opt_d && argc == 1) {
-		struct ref_states states;
-		memset(&states, 0, sizeof(states));
-		get_remote_ref_states(argv[0], &states, GET_HEAD_NAMES);
-		if (!states.heads.nr)
-			result |= error(_("Cannot determine remote HEAD"));
-		else if (states.heads.nr > 1) {
-			result |= error(_("Multiple remote HEAD branches. "
-					  "Please choose one explicitly with:"));
-			for (i = 0; i < states.heads.nr; i++)
-				fprintf(stderr, "  git remote set-head %s %s\n",
-					argv[0], states.heads.items[i].string);
-		} else
-			head_name = xstrdup(states.heads.items[0].string);
-		free_remote_ref_states(&states);
-	} else if (opt_d && !opt_a && argc == 1) {
-		if (delete_ref(NULL, buf.buf, NULL, REF_NO_DEREF))
-			result |= error(_("Could not delete %s"), buf.buf);
-	} else
-		usage_with_options(builtin_remote_sethead_usage, options);
-
-	if (head_name) {
-		strbuf_addf(&buf2, "refs/remotes/%s/%s", argv[0], head_name);
-		/* make sure it's valid */
-		if (!ref_exists(buf2.buf))
-			result |= error(_("Not a valid ref: %s"), buf2.buf);
-		else if (create_symref(buf.buf, buf2.buf, "remote set-head"))
-			result |= error(_("Could not setup %s"), buf.buf);
-		else if (opt_a)
-			printf("%s/HEAD set to %s\n", argv[0], head_name);
-		free(head_name);
-	}
-
-	strbuf_release(&buf);
-	strbuf_release(&buf2);
-	return result;
-}
-
-static int prune_remote(const char *remote, int dry_run)
-{
-	int result = 0;
-	struct ref_states states;
-	struct string_list refs_to_prune = STRING_LIST_INIT_NODUP;
-	struct string_list_item *item;
-	const char *dangling_msg = dry_run
-		? _(" %s will become dangling!")
-		: _(" %s has become dangling!");
-
-	memset(&states, 0, sizeof(states));
-	get_remote_ref_states(remote, &states, GET_REF_STATES);
-
-	if (!states.stale.nr) {
-		free_remote_ref_states(&states);
-		return 0;
-	}
-
-	printf_ln(_("Pruning %s"), remote);
-	printf_ln(_("URL: %s"),
-		  states.remote->url_nr
-		  ? states.remote->url[0]
-		  : _("(no URL)"));
-
-	for_each_string_list_item(item, &states.stale)
-		string_list_append(&refs_to_prune, item->util);
-	string_list_sort(&refs_to_prune);
-
-	if (!dry_run)
-		result |= delete_refs("remote: prune", &refs_to_prune, 0);
-
-	for_each_string_list_item(item, &states.stale) {
-		const char *refname = item->util;
-
-		if (dry_run)
-			printf_ln(_(" * [would prune] %s"),
-			       abbrev_ref(refname, "refs/remotes/"));
-		else
-			printf_ln(_(" * [pruned] %s"),
-			       abbrev_ref(refname, "refs/remotes/"));
-	}
-
-	warn_dangling_symrefs(stdout, dangling_msg, &refs_to_prune);
-
-	string_list_clear(&refs_to_prune, 0);
-	free_remote_ref_states(&states);
-	return result;
-}
-
-static int prune(int argc, const char **argv)
-{
-	int dry_run = 0, result = 0;
-	struct option options[] = {
-		OPT__DRY_RUN(&dry_run, N_("dry run")),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, NULL, options, builtin_remote_prune_usage,
-			     0);
-
-	if (argc < 1)
-		usage_with_options(builtin_remote_prune_usage, options);
-
-	for (; argc; argc--, argv++)
-		result |= prune_remote(*argv, dry_run);
-
-	return result;
-}
-
-static int get_remote_default(const char *key, const char *value, void *priv)
-{
-	if (strcmp(key, "remotes.default") == 0) {
-		int *found = priv;
-		*found = 1;
-	}
-	return 0;
-}
-
-static int update(int argc, const char **argv)
-{
-	int i, prune = -1;
-	struct option options[] = {
-		OPT_BOOL('p', "prune", &prune,
-			 N_("prune remotes after fetching")),
-		OPT_END()
-	};
-	struct strvec fetch_argv = STRVEC_INIT;
-	int default_defined = 0;
-	int retval;
-
-	argc = parse_options(argc, argv, NULL, options, builtin_remote_update_usage,
-			     PARSE_OPT_KEEP_ARGV0);
-
-	strvec_push(&fetch_argv, "fetch");
-
-	if (prune != -1)
-		strvec_push(&fetch_argv, prune ? "--prune" : "--no-prune");
-	if (verbose)
-		strvec_push(&fetch_argv, "-v");
-	strvec_push(&fetch_argv, "--multiple");
-	if (argc < 2)
-		strvec_push(&fetch_argv, "default");
-	for (i = 1; i < argc; i++)
-		strvec_push(&fetch_argv, argv[i]);
-
-	if (strcmp(fetch_argv.v[fetch_argv.nr-1], "default") == 0) {
-		git_config(get_remote_default, &default_defined);
-		if (!default_defined) {
-			strvec_pop(&fetch_argv);
-			strvec_push(&fetch_argv, "--all");
-		}
-	}
-
-	retval = run_command_v_opt(fetch_argv.v, RUN_GIT_CMD);
-	strvec_clear(&fetch_argv);
-	return retval;
-}
-
-static int remove_all_fetch_refspecs(const char *key)
-{
-	return git_config_set_multivar_gently(key, NULL, NULL, 1);
-}
-
-static void add_branches(struct remote *remote, const char **branches,
-			 const char *key)
-{
-	const char *remotename = remote->name;
-	int mirror = remote->mirror;
-	struct strbuf refspec = STRBUF_INIT;
-
-	for (; *branches; branches++)
-		add_branch(key, *branches, remotename, mirror, &refspec);
-
-	strbuf_release(&refspec);
-}
-
-static int set_remote_branches(const char *remotename, const char **branches,
-				int add_mode)
-{
-	struct strbuf key = STRBUF_INIT;
-	struct remote *remote;
-
-	strbuf_addf(&key, "remote.%s.fetch", remotename);
-
-	remote = remote_get(remotename);
-	if (!remote_is_configured(remote, 1))
-		die(_("No such remote '%s'"), remotename);
-
-	if (!add_mode && remove_all_fetch_refspecs(key.buf)) {
-		strbuf_release(&key);
-		return 1;
-	}
-	add_branches(remote, branches, key.buf);
-
-	strbuf_release(&key);
-	return 0;
-}
-
-static int set_branches(int argc, const char **argv)
-{
-	int add_mode = 0;
-	struct option options[] = {
-		OPT_BOOL('\0', "add", &add_mode, N_("add branch")),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, NULL, options,
-			     builtin_remote_setbranches_usage, 0);
-	if (argc == 0) {
-		error(_("no remote specified"));
-		usage_with_options(builtin_remote_setbranches_usage, options);
-	}
-	argv[argc] = NULL;
-
-	return set_remote_branches(argv[0], argv + 1, add_mode);
-}
-
-static int get_url(int argc, const char **argv)
-{
-	int i, push_mode = 0, all_mode = 0;
-	const char *remotename = NULL;
-	struct remote *remote;
-	const char **url;
-	int url_nr;
-	struct option options[] = {
-		OPT_BOOL('\0', "push", &push_mode,
-			 N_("query push URLs rather than fetch URLs")),
-		OPT_BOOL('\0', "all", &all_mode,
-			 N_("return all URLs")),
-		OPT_END()
-	};
-	argc = parse_options(argc, argv, NULL, options, builtin_remote_geturl_usage, 0);
-
-	if (argc != 1)
-		usage_with_options(builtin_remote_geturl_usage, options);
-
-	remotename = argv[0];
-
-	remote = remote_get(remotename);
-	if (!remote_is_configured(remote, 1))
-		die(_("No such remote '%s'"), remotename);
-
-	url_nr = 0;
-	if (push_mode) {
-		url = remote->pushurl;
-		url_nr = remote->pushurl_nr;
-	}
-	/* else fetch mode */
-
-	/* Use the fetch URL when no push URLs were found or requested. */
-	if (!url_nr) {
-		url = remote->url;
-		url_nr = remote->url_nr;
-	}
-
-	if (!url_nr)
-		die(_("no URLs configured for remote '%s'"), remotename);
-
-	if (all_mode) {
-		for (i = 0; i < url_nr; i++)
-			printf_ln("%s", url[i]);
-	} else {
-		printf_ln("%s", *url);
-	}
-
-	return 0;
-}
-
-static int set_url(int argc, const char **argv)
-{
-	int i, push_mode = 0, add_mode = 0, delete_mode = 0;
-	int matches = 0, negative_matches = 0;
-	const char *remotename = NULL;
-	const char *newurl = NULL;
-	const char *oldurl = NULL;
-	struct remote *remote;
-	regex_t old_regex;
-	const char **urlset;
-	int urlset_nr;
-	struct strbuf name_buf = STRBUF_INIT;
-	struct option options[] = {
-		OPT_BOOL('\0', "push", &push_mode,
-			 N_("manipulate push URLs")),
-		OPT_BOOL('\0', "add", &add_mode,
-			 N_("add URL")),
-		OPT_BOOL('\0', "delete", &delete_mode,
-			    N_("delete URLs")),
-		OPT_END()
-	};
-	argc = parse_options(argc, argv, NULL, options, builtin_remote_seturl_usage,
-			     PARSE_OPT_KEEP_ARGV0);
-
-	if (add_mode && delete_mode)
-		die(_("--add --delete doesn't make sense"));
-
-	if (argc < 3 || argc > 4 || ((add_mode || delete_mode) && argc != 3))
-		usage_with_options(builtin_remote_seturl_usage, options);
-
-	remotename = argv[1];
-	newurl = argv[2];
-	if (argc > 3)
-		oldurl = argv[3];
-
-	if (delete_mode)
-		oldurl = newurl;
-
-	remote = remote_get(remotename);
-	if (!remote_is_configured(remote, 1))
-		die(_("No such remote '%s'"), remotename);
-
-	if (push_mode) {
-		strbuf_addf(&name_buf, "remote.%s.pushurl", remotename);
-		urlset = remote->pushurl;
-		urlset_nr = remote->pushurl_nr;
-	} else {
-		strbuf_addf(&name_buf, "remote.%s.url", remotename);
-		urlset = remote->url;
-		urlset_nr = remote->url_nr;
-	}
-
-	/* Special cases that add new entry. */
-	if ((!oldurl && !delete_mode) || add_mode) {
-		if (add_mode)
-			git_config_set_multivar(name_buf.buf, newurl,
-						       "^$", 0);
-		else
-			git_config_set(name_buf.buf, newurl);
-		goto out;
-	}
-
-	/* Old URL specified. Demand that one matches. */
-	if (regcomp(&old_regex, oldurl, REG_EXTENDED))
-		die(_("Invalid old URL pattern: %s"), oldurl);
-
-	for (i = 0; i < urlset_nr; i++)
-		if (!regexec(&old_regex, urlset[i], 0, NULL, 0))
-			matches++;
-		else
-			negative_matches++;
-	if (!delete_mode && !matches)
-		die(_("No such URL found: %s"), oldurl);
-	if (delete_mode && !negative_matches && !push_mode)
-		die(_("Will not delete all non-push URLs"));
-
-	regfree(&old_regex);
-
-	if (!delete_mode)
-		git_config_set_multivar(name_buf.buf, newurl, oldurl, 0);
-	else
-		git_config_set_multivar(name_buf.buf, NULL, oldurl, 1);
-out:
-	strbuf_release(&name_buf);
-	return 0;
-}
-
-int cmd_remote(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_remote_usage,
-		PARSE_OPT_STOP_AT_NON_OPTION);
-
-	if (argc < 1)
-		result = show_all();
-	else if (!strcmp(argv[0], "add"))
-		result = add(argc, argv);
-	else if (!strcmp(argv[0], "rename"))
-		result = mv(argc, argv);
-	else if (!strcmp(argv[0], "rm") || !strcmp(argv[0], "remove"))
-		result = rm(argc, argv);
-	else if (!strcmp(argv[0], "set-head"))
-		result = set_head(argc, argv);
-	else if (!strcmp(argv[0], "set-branches"))
-		result = set_branches(argc, argv);
-	else if (!strcmp(argv[0], "get-url"))
-		result = get_url(argc, argv);
-	else if (!strcmp(argv[0], "set-url"))
-		result = set_url(argc, argv);
-	else if (!strcmp(argv[0], "show"))
-		result = show(argc, argv);
-	else if (!strcmp(argv[0], "prune"))
-		result = prune(argc, argv);
-	else if (!strcmp(argv[0], "update"))
-		result = update(argc, argv);
-	else {
-		error(_("Unknown subcommand: %s"), argv[0]);
-		usage_with_options(builtin_remote_usage, options);
-	}
-
-	return result ? 1 : 0;
-}
diff --git a/third_party/git/builtin/repack.c b/third_party/git/builtin/repack.c
deleted file mode 100644
index 01e7767c7928..000000000000
--- a/third_party/git/builtin/repack.c
+++ /dev/null
@@ -1,580 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "dir.h"
-#include "parse-options.h"
-#include "run-command.h"
-#include "sigchain.h"
-#include "strbuf.h"
-#include "string-list.h"
-#include "strvec.h"
-#include "midx.h"
-#include "packfile.h"
-#include "prune-packed.h"
-#include "object-store.h"
-#include "promisor-remote.h"
-#include "shallow.h"
-
-static int delta_base_offset = 1;
-static int pack_kept_objects = -1;
-static int write_bitmaps = -1;
-static int use_delta_islands;
-static char *packdir, *packtmp;
-
-static const char *const git_repack_usage[] = {
-	N_("git repack [<options>]"),
-	NULL
-};
-
-static const char incremental_bitmap_conflict_error[] = N_(
-"Incremental repacks are incompatible with bitmap indexes.  Use\n"
-"--no-write-bitmap-index or disable the pack.writebitmaps configuration."
-);
-
-
-static int repack_config(const char *var, const char *value, void *cb)
-{
-	if (!strcmp(var, "repack.usedeltabaseoffset")) {
-		delta_base_offset = git_config_bool(var, value);
-		return 0;
-	}
-	if (!strcmp(var, "repack.packkeptobjects")) {
-		pack_kept_objects = git_config_bool(var, value);
-		return 0;
-	}
-	if (!strcmp(var, "repack.writebitmaps") ||
-	    !strcmp(var, "pack.writebitmaps")) {
-		write_bitmaps = git_config_bool(var, value);
-		return 0;
-	}
-	if (!strcmp(var, "repack.usedeltaislands")) {
-		use_delta_islands = git_config_bool(var, value);
-		return 0;
-	}
-	return git_default_config(var, value, cb);
-}
-
-/*
- * Remove temporary $GIT_OBJECT_DIRECTORY/pack/.tmp-$$-pack-* files.
- */
-static void remove_temporary_files(void)
-{
-	struct strbuf buf = STRBUF_INIT;
-	size_t dirlen, prefixlen;
-	DIR *dir;
-	struct dirent *e;
-
-	dir = opendir(packdir);
-	if (!dir)
-		return;
-
-	/* Point at the slash at the end of ".../objects/pack/" */
-	dirlen = strlen(packdir) + 1;
-	strbuf_addstr(&buf, packtmp);
-	/* Hold the length of  ".tmp-%d-pack-" */
-	prefixlen = buf.len - dirlen;
-
-	while ((e = readdir(dir))) {
-		if (strncmp(e->d_name, buf.buf + dirlen, prefixlen))
-			continue;
-		strbuf_setlen(&buf, dirlen);
-		strbuf_addstr(&buf, e->d_name);
-		unlink(buf.buf);
-	}
-	closedir(dir);
-	strbuf_release(&buf);
-}
-
-static void remove_pack_on_signal(int signo)
-{
-	remove_temporary_files();
-	sigchain_pop(signo);
-	raise(signo);
-}
-
-/*
- * Adds all packs hex strings to the fname list, which do not
- * have a corresponding .keep file. These packs are not to
- * be kept if we are going to pack everything into one file.
- */
-static void get_non_kept_pack_filenames(struct string_list *fname_list,
-					const struct string_list *extra_keep)
-{
-	DIR *dir;
-	struct dirent *e;
-	char *fname;
-
-	if (!(dir = opendir(packdir)))
-		return;
-
-	while ((e = readdir(dir)) != NULL) {
-		size_t len;
-		int i;
-
-		for (i = 0; i < extra_keep->nr; i++)
-			if (!fspathcmp(e->d_name, extra_keep->items[i].string))
-				break;
-		if (extra_keep->nr > 0 && i < extra_keep->nr)
-			continue;
-
-		if (!strip_suffix(e->d_name, ".pack", &len))
-			continue;
-
-		fname = xmemdupz(e->d_name, len);
-
-		if (!file_exists(mkpath("%s/%s.keep", packdir, fname)))
-			string_list_append_nodup(fname_list, fname);
-		else
-			free(fname);
-	}
-	closedir(dir);
-}
-
-static void remove_redundant_pack(const char *dir_name, const char *base_name)
-{
-	struct strbuf buf = STRBUF_INIT;
-	struct multi_pack_index *m = get_local_multi_pack_index(the_repository);
-	strbuf_addf(&buf, "%s.pack", base_name);
-	if (m && midx_contains_pack(m, buf.buf))
-		clear_midx_file(the_repository);
-	strbuf_insertf(&buf, 0, "%s/", dir_name);
-	unlink_pack_path(buf.buf, 1);
-	strbuf_release(&buf);
-}
-
-struct pack_objects_args {
-	const char *window;
-	const char *window_memory;
-	const char *depth;
-	const char *threads;
-	const char *max_pack_size;
-	int no_reuse_delta;
-	int no_reuse_object;
-	int quiet;
-	int local;
-};
-
-static void prepare_pack_objects(struct child_process *cmd,
-				 const struct pack_objects_args *args)
-{
-	strvec_push(&cmd->args, "pack-objects");
-	if (args->window)
-		strvec_pushf(&cmd->args, "--window=%s", args->window);
-	if (args->window_memory)
-		strvec_pushf(&cmd->args, "--window-memory=%s", args->window_memory);
-	if (args->depth)
-		strvec_pushf(&cmd->args, "--depth=%s", args->depth);
-	if (args->threads)
-		strvec_pushf(&cmd->args, "--threads=%s", args->threads);
-	if (args->max_pack_size)
-		strvec_pushf(&cmd->args, "--max-pack-size=%s", args->max_pack_size);
-	if (args->no_reuse_delta)
-		strvec_pushf(&cmd->args, "--no-reuse-delta");
-	if (args->no_reuse_object)
-		strvec_pushf(&cmd->args, "--no-reuse-object");
-	if (args->local)
-		strvec_push(&cmd->args,  "--local");
-	if (args->quiet)
-		strvec_push(&cmd->args,  "--quiet");
-	if (delta_base_offset)
-		strvec_push(&cmd->args,  "--delta-base-offset");
-	strvec_push(&cmd->args, packtmp);
-	cmd->git_cmd = 1;
-	cmd->out = -1;
-}
-
-/*
- * Write oid to the given struct child_process's stdin, starting it first if
- * necessary.
- */
-static int write_oid(const struct object_id *oid, struct packed_git *pack,
-		     uint32_t pos, void *data)
-{
-	struct child_process *cmd = data;
-
-	if (cmd->in == -1) {
-		if (start_command(cmd))
-			die(_("could not start pack-objects to repack promisor objects"));
-	}
-
-	xwrite(cmd->in, oid_to_hex(oid), the_hash_algo->hexsz);
-	xwrite(cmd->in, "\n", 1);
-	return 0;
-}
-
-static void repack_promisor_objects(const struct pack_objects_args *args,
-				    struct string_list *names)
-{
-	struct child_process cmd = CHILD_PROCESS_INIT;
-	FILE *out;
-	struct strbuf line = STRBUF_INIT;
-
-	prepare_pack_objects(&cmd, args);
-	cmd.in = -1;
-
-	/*
-	 * NEEDSWORK: Giving pack-objects only the OIDs without any ordering
-	 * hints may result in suboptimal deltas in the resulting pack. See if
-	 * the OIDs can be sent with fake paths such that pack-objects can use a
-	 * {type -> existing pack order} ordering when computing deltas instead
-	 * of a {type -> size} ordering, which may produce better deltas.
-	 */
-	for_each_packed_object(write_oid, &cmd,
-			       FOR_EACH_OBJECT_PROMISOR_ONLY);
-
-	if (cmd.in == -1)
-		/* No packed objects; cmd was never started */
-		return;
-
-	close(cmd.in);
-
-	out = xfdopen(cmd.out, "r");
-	while (strbuf_getline_lf(&line, out) != EOF) {
-		char *promisor_name;
-		int fd;
-		if (line.len != the_hash_algo->hexsz)
-			die(_("repack: Expecting full hex object ID lines only from pack-objects."));
-		string_list_append(names, line.buf);
-
-		/*
-		 * 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);
-		fd = open(promisor_name, O_CREAT|O_EXCL|O_WRONLY, 0600);
-		if (fd < 0)
-			die_errno(_("unable to create '%s'"), promisor_name);
-		close(fd);
-		free(promisor_name);
-	}
-	fclose(out);
-	if (finish_command(&cmd))
-		die(_("could not finish pack-objects to repack promisor objects"));
-}
-
-#define ALL_INTO_ONE 1
-#define LOOSEN_UNREACHABLE 2
-
-int cmd_repack(int argc, const char **argv, const char *prefix)
-{
-	struct {
-		const char *name;
-		unsigned optional:1;
-	} exts[] = {
-		{".pack"},
-		{".idx"},
-		{".bitmap", 1},
-		{".promisor", 1},
-	};
-	struct child_process cmd = CHILD_PROCESS_INIT;
-	struct string_list_item *item;
-	struct string_list names = STRING_LIST_INIT_DUP;
-	struct string_list rollback = STRING_LIST_INIT_NODUP;
-	struct string_list existing_packs = STRING_LIST_INIT_DUP;
-	struct strbuf line = STRBUF_INIT;
-	int i, ext, ret, failed;
-	FILE *out;
-
-	/* variables to be filled by option parsing */
-	int pack_everything = 0;
-	int delete_redundant = 0;
-	const char *unpack_unreachable = NULL;
-	int keep_unreachable = 0;
-	struct string_list keep_pack_list = STRING_LIST_INIT_NODUP;
-	int no_update_server_info = 0;
-	struct pack_objects_args po_args = {NULL};
-
-	struct option builtin_repack_options[] = {
-		OPT_BIT('a', NULL, &pack_everything,
-				N_("pack everything in a single pack"), ALL_INTO_ONE),
-		OPT_BIT('A', NULL, &pack_everything,
-				N_("same as -a, and turn unreachable objects loose"),
-				   LOOSEN_UNREACHABLE | ALL_INTO_ONE),
-		OPT_BOOL('d', NULL, &delete_redundant,
-				N_("remove redundant packs, and run git-prune-packed")),
-		OPT_BOOL('f', NULL, &po_args.no_reuse_delta,
-				N_("pass --no-reuse-delta to git-pack-objects")),
-		OPT_BOOL('F', NULL, &po_args.no_reuse_object,
-				N_("pass --no-reuse-object to git-pack-objects")),
-		OPT_BOOL('n', NULL, &no_update_server_info,
-				N_("do not run git-update-server-info")),
-		OPT__QUIET(&po_args.quiet, N_("be quiet")),
-		OPT_BOOL('l', "local", &po_args.local,
-				N_("pass --local to git-pack-objects")),
-		OPT_BOOL('b', "write-bitmap-index", &write_bitmaps,
-				N_("write bitmap index")),
-		OPT_BOOL('i', "delta-islands", &use_delta_islands,
-				N_("pass --delta-islands to git-pack-objects")),
-		OPT_STRING(0, "unpack-unreachable", &unpack_unreachable, N_("approxidate"),
-				N_("with -A, do not loosen objects older than this")),
-		OPT_BOOL('k', "keep-unreachable", &keep_unreachable,
-				N_("with -a, repack unreachable objects")),
-		OPT_STRING(0, "window", &po_args.window, N_("n"),
-				N_("size of the window used for delta compression")),
-		OPT_STRING(0, "window-memory", &po_args.window_memory, N_("bytes"),
-				N_("same as the above, but limit memory size instead of entries count")),
-		OPT_STRING(0, "depth", &po_args.depth, N_("n"),
-				N_("limits the maximum delta depth")),
-		OPT_STRING(0, "threads", &po_args.threads, N_("n"),
-				N_("limits the maximum number of threads")),
-		OPT_STRING(0, "max-pack-size", &po_args.max_pack_size, N_("bytes"),
-				N_("maximum size of each packfile")),
-		OPT_BOOL(0, "pack-kept-objects", &pack_kept_objects,
-				N_("repack objects in packs marked with .keep")),
-		OPT_STRING_LIST(0, "keep-pack", &keep_pack_list, N_("name"),
-				N_("do not repack this pack")),
-		OPT_END()
-	};
-
-	git_config(repack_config, NULL);
-
-	argc = parse_options(argc, argv, prefix, builtin_repack_options,
-				git_repack_usage, 0);
-
-	if (delete_redundant && repository_format_precious_objects)
-		die(_("cannot delete packs in a precious-objects repo"));
-
-	if (keep_unreachable &&
-	    (unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE)))
-		die(_("--keep-unreachable and -A are incompatible"));
-
-	if (write_bitmaps < 0) {
-		if (!(pack_everything & ALL_INTO_ONE) ||
-		    !is_bare_repository())
-			write_bitmaps = 0;
-	}
-	if (pack_kept_objects < 0)
-		pack_kept_objects = write_bitmaps > 0;
-
-	if (write_bitmaps && !(pack_everything & ALL_INTO_ONE))
-		die(_(incremental_bitmap_conflict_error));
-
-	packdir = mkpathdup("%s/pack", get_object_directory());
-	packtmp = mkpathdup("%s/.tmp-%d-pack", packdir, (int)getpid());
-
-	sigchain_push_common(remove_pack_on_signal);
-
-	prepare_pack_objects(&cmd, &po_args);
-
-	strvec_push(&cmd.args, "--keep-true-parents");
-	if (!pack_kept_objects)
-		strvec_push(&cmd.args, "--honor-pack-keep");
-	for (i = 0; i < keep_pack_list.nr; i++)
-		strvec_pushf(&cmd.args, "--keep-pack=%s",
-			     keep_pack_list.items[i].string);
-	strvec_push(&cmd.args, "--non-empty");
-	strvec_push(&cmd.args, "--all");
-	strvec_push(&cmd.args, "--reflog");
-	strvec_push(&cmd.args, "--indexed-objects");
-	if (has_promisor_remote())
-		strvec_push(&cmd.args, "--exclude-promisor-objects");
-	if (write_bitmaps > 0)
-		strvec_push(&cmd.args, "--write-bitmap-index");
-	else if (write_bitmaps < 0)
-		strvec_push(&cmd.args, "--write-bitmap-index-quiet");
-	if (use_delta_islands)
-		strvec_push(&cmd.args, "--delta-islands");
-
-	if (pack_everything & ALL_INTO_ONE) {
-		get_non_kept_pack_filenames(&existing_packs, &keep_pack_list);
-
-		repack_promisor_objects(&po_args, &names);
-
-		if (existing_packs.nr && delete_redundant) {
-			if (unpack_unreachable) {
-				strvec_pushf(&cmd.args,
-					     "--unpack-unreachable=%s",
-					     unpack_unreachable);
-				strvec_push(&cmd.env_array, "GIT_REF_PARANOIA=1");
-			} else if (pack_everything & LOOSEN_UNREACHABLE) {
-				strvec_push(&cmd.args,
-					    "--unpack-unreachable");
-			} else if (keep_unreachable) {
-				strvec_push(&cmd.args, "--keep-unreachable");
-				strvec_push(&cmd.args, "--pack-loose-unreachable");
-			} else {
-				strvec_push(&cmd.env_array, "GIT_REF_PARANOIA=1");
-			}
-		}
-	} else {
-		strvec_push(&cmd.args, "--unpacked");
-		strvec_push(&cmd.args, "--incremental");
-	}
-
-	cmd.no_stdin = 1;
-
-	ret = start_command(&cmd);
-	if (ret)
-		return ret;
-
-	out = xfdopen(cmd.out, "r");
-	while (strbuf_getline_lf(&line, out) != EOF) {
-		if (line.len != the_hash_algo->hexsz)
-			die(_("repack: Expecting full hex object ID lines only from pack-objects."));
-		string_list_append(&names, line.buf);
-	}
-	fclose(out);
-	ret = finish_command(&cmd);
-	if (ret)
-		return ret;
-
-	if (!names.nr && !po_args.quiet)
-		printf_ln(_("Nothing new to pack."));
-
-	close_object_store(the_repository->objects);
-
-	/*
-	 * Ok we have prepared all new packfiles.
-	 * First see if there are packs of the same name and if so
-	 * if we can move them out of the way (this can happen if we
-	 * repacked immediately after packing fully.
-	 */
-	failed = 0;
-	for_each_string_list_item(item, &names) {
-		for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
-			char *fname, *fname_old;
-
-			fname = mkpathdup("%s/pack-%s%s", packdir,
-						item->string, exts[ext].name);
-			if (!file_exists(fname)) {
-				free(fname);
-				continue;
-			}
-
-			fname_old = mkpathdup("%s/old-%s%s", packdir,
-						item->string, exts[ext].name);
-			if (file_exists(fname_old))
-				if (unlink(fname_old))
-					failed = 1;
-
-			if (!failed && rename(fname, fname_old)) {
-				free(fname);
-				free(fname_old);
-				failed = 1;
-				break;
-			} else {
-				string_list_append(&rollback, fname);
-				free(fname_old);
-			}
-		}
-		if (failed)
-			break;
-	}
-	if (failed) {
-		struct string_list rollback_failure = STRING_LIST_INIT_DUP;
-		for_each_string_list_item(item, &rollback) {
-			char *fname, *fname_old;
-			fname = mkpathdup("%s/%s", packdir, item->string);
-			fname_old = mkpathdup("%s/old-%s", packdir, item->string);
-			if (rename(fname_old, fname))
-				string_list_append(&rollback_failure, fname);
-			free(fname);
-			free(fname_old);
-		}
-
-		if (rollback_failure.nr) {
-			int i;
-			fprintf(stderr,
-				_("WARNING: Some packs in use have been renamed by\n"
-				  "WARNING: prefixing old- to their name, in order to\n"
-				  "WARNING: replace them with the new version of the\n"
-				  "WARNING: file.  But the operation failed, and the\n"
-				  "WARNING: attempt to rename them back to their\n"
-				  "WARNING: original names also failed.\n"
-				  "WARNING: Please rename them in %s manually:\n"), packdir);
-			for (i = 0; i < rollback_failure.nr; i++)
-				fprintf(stderr, "WARNING:   old-%s -> %s\n",
-					rollback_failure.items[i].string,
-					rollback_failure.items[i].string);
-		}
-		exit(1);
-	}
-
-	/* Now the ones with the same name are out of the way... */
-	for_each_string_list_item(item, &names) {
-		for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
-			char *fname, *fname_old;
-			struct stat statbuffer;
-			int exists = 0;
-			fname = mkpathdup("%s/pack-%s%s",
-					packdir, item->string, exts[ext].name);
-			fname_old = mkpathdup("%s-%s%s",
-					packtmp, item->string, exts[ext].name);
-			if (!stat(fname_old, &statbuffer)) {
-				statbuffer.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
-				chmod(fname_old, statbuffer.st_mode);
-				exists = 1;
-			}
-			if (exists || !exts[ext].optional) {
-				if (rename(fname_old, fname))
-					die_errno(_("renaming '%s' failed"), fname_old);
-			}
-			free(fname);
-			free(fname_old);
-		}
-	}
-
-	/* Remove the "old-" files */
-	for_each_string_list_item(item, &names) {
-		for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
-			char *fname;
-			fname = mkpathdup("%s/old-%s%s",
-					  packdir,
-					  item->string,
-					  exts[ext].name);
-			if (remove_path(fname))
-				warning(_("failed to remove '%s'"), fname);
-			free(fname);
-		}
-	}
-
-	/* End of pack replacement. */
-
-	reprepare_packed_git(the_repository);
-
-	if (delete_redundant) {
-		const int hexsz = the_hash_algo->hexsz;
-		int opts = 0;
-		string_list_sort(&names);
-		for_each_string_list_item(item, &existing_packs) {
-			char *sha1;
-			size_t len = strlen(item->string);
-			if (len < hexsz)
-				continue;
-			sha1 = item->string + len - hexsz;
-			if (!string_list_has_string(&names, sha1))
-				remove_redundant_pack(packdir, item->string);
-		}
-		if (!po_args.quiet && isatty(2))
-			opts |= PRUNE_PACKED_VERBOSE;
-		prune_packed_objects(opts);
-
-		if (!keep_unreachable &&
-		    (!(pack_everything & LOOSEN_UNREACHABLE) ||
-		     unpack_unreachable) &&
-		    is_repository_shallow(the_repository))
-			prune_shallow(PRUNE_QUICK);
-	}
-
-	if (!no_update_server_info)
-		update_server_info(0);
-	remove_temporary_files();
-
-	if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX, 0))
-		write_midx_file(get_object_directory(), 0);
-
-	string_list_clear(&names, 0);
-	string_list_clear(&rollback, 0);
-	string_list_clear(&existing_packs, 0);
-	strbuf_release(&line);
-
-	return 0;
-}
diff --git a/third_party/git/builtin/replace.c b/third_party/git/builtin/replace.c
deleted file mode 100644
index cd4876591174..000000000000
--- a/third_party/git/builtin/replace.c
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
- * Builtin "git replace"
- *
- * Copyright (c) 2008 Christian Couder <chriscool@tuxfamily.org>
- *
- * Based on builtin/tag.c by Kristian Hรธgsberg <krh@redhat.com>
- * and Carlos Rica <jasampler@gmail.com> that was itself based on
- * git-tag.sh and mktag.c by Linus Torvalds.
- */
-
-#include "cache.h"
-#include "config.h"
-#include "builtin.h"
-#include "refs.h"
-#include "parse-options.h"
-#include "run-command.h"
-#include "object-store.h"
-#include "repository.h"
-#include "tag.h"
-
-static const char * const git_replace_usage[] = {
-	N_("git replace [-f] <object> <replacement>"),
-	N_("git replace [-f] --edit <object>"),
-	N_("git replace [-f] --graft <commit> [<parent>...]"),
-	N_("git replace [-f] --convert-graft-file"),
-	N_("git replace -d <object>..."),
-	N_("git replace [--format=<format>] [-l [<pattern>]]"),
-	NULL
-};
-
-enum replace_format {
-	REPLACE_FORMAT_SHORT,
-	REPLACE_FORMAT_MEDIUM,
-	REPLACE_FORMAT_LONG
-};
-
-struct show_data {
-	const char *pattern;
-	enum replace_format format;
-};
-
-static int show_reference(struct repository *r, const char *refname,
-			  const struct object_id *oid,
-			  int flag, void *cb_data)
-{
-	struct show_data *data = cb_data;
-
-	if (!wildmatch(data->pattern, refname, 0)) {
-		if (data->format == REPLACE_FORMAT_SHORT)
-			printf("%s\n", refname);
-		else if (data->format == REPLACE_FORMAT_MEDIUM)
-			printf("%s -> %s\n", refname, oid_to_hex(oid));
-		else { /* data->format == REPLACE_FORMAT_LONG */
-			struct object_id object;
-			enum object_type obj_type, repl_type;
-
-			if (get_oid(refname, &object))
-				return error(_("failed to resolve '%s' as a valid ref"), refname);
-
-			obj_type = oid_object_info(r, &object, NULL);
-			repl_type = oid_object_info(r, oid, NULL);
-
-			printf("%s (%s) -> %s (%s)\n", refname, type_name(obj_type),
-			       oid_to_hex(oid), type_name(repl_type));
-		}
-	}
-
-	return 0;
-}
-
-static int list_replace_refs(const char *pattern, const char *format)
-{
-	struct show_data data;
-
-	if (pattern == NULL)
-		pattern = "*";
-	data.pattern = pattern;
-
-	if (format == NULL || *format == '\0' || !strcmp(format, "short"))
-		data.format = REPLACE_FORMAT_SHORT;
-	else if (!strcmp(format, "medium"))
-		data.format = REPLACE_FORMAT_MEDIUM;
-	else if (!strcmp(format, "long"))
-		data.format = REPLACE_FORMAT_LONG;
-	/*
-	 * Please update _git_replace() in git-completion.bash when
-	 * you add new format
-	 */
-	else
-		return error(_("invalid replace format '%s'\n"
-			       "valid formats are 'short', 'medium' and 'long'"),
-			     format);
-
-	for_each_replace_ref(the_repository, show_reference, (void *)&data);
-
-	return 0;
-}
-
-typedef int (*each_replace_name_fn)(const char *name, const char *ref,
-				    const struct object_id *oid);
-
-static int for_each_replace_name(const char **argv, each_replace_name_fn fn)
-{
-	const char **p, *full_hex;
-	struct strbuf ref = STRBUF_INIT;
-	size_t base_len;
-	int had_error = 0;
-	struct object_id oid;
-
-	strbuf_addstr(&ref, git_replace_ref_base);
-	base_len = ref.len;
-
-	for (p = argv; *p; p++) {
-		if (get_oid(*p, &oid)) {
-			error("failed to resolve '%s' as a valid ref", *p);
-			had_error = 1;
-			continue;
-		}
-
-		strbuf_setlen(&ref, base_len);
-		strbuf_addstr(&ref, oid_to_hex(&oid));
-		full_hex = ref.buf + base_len;
-
-		if (read_ref(ref.buf, &oid)) {
-			error(_("replace ref '%s' not found"), full_hex);
-			had_error = 1;
-			continue;
-		}
-		if (fn(full_hex, ref.buf, &oid))
-			had_error = 1;
-	}
-	strbuf_release(&ref);
-	return had_error;
-}
-
-static int delete_replace_ref(const char *name, const char *ref,
-			      const struct object_id *oid)
-{
-	if (delete_ref(NULL, ref, oid, 0))
-		return 1;
-	printf_ln(_("Deleted replace ref '%s'"), name);
-	return 0;
-}
-
-static int check_ref_valid(struct object_id *object,
-			    struct object_id *prev,
-			    struct strbuf *ref,
-			    int force)
-{
-	strbuf_reset(ref);
-	strbuf_addf(ref, "%s%s", git_replace_ref_base, oid_to_hex(object));
-	if (check_refname_format(ref->buf, 0))
-		return error(_("'%s' is not a valid ref name"), ref->buf);
-
-	if (read_ref(ref->buf, prev))
-		oidclr(prev);
-	else if (!force)
-		return error(_("replace ref '%s' already exists"), ref->buf);
-	return 0;
-}
-
-static int replace_object_oid(const char *object_ref,
-			       struct object_id *object,
-			       const char *replace_ref,
-			       struct object_id *repl,
-			       int force)
-{
-	struct object_id prev;
-	enum object_type obj_type, repl_type;
-	struct strbuf ref = STRBUF_INIT;
-	struct ref_transaction *transaction;
-	struct strbuf err = STRBUF_INIT;
-	int res = 0;
-
-	obj_type = oid_object_info(the_repository, object, NULL);
-	repl_type = oid_object_info(the_repository, repl, NULL);
-	if (!force && obj_type != repl_type)
-		return error(_("Objects must be of the same type.\n"
-			       "'%s' points to a replaced object of type '%s'\n"
-			       "while '%s' points to a replacement object of "
-			       "type '%s'."),
-			     object_ref, type_name(obj_type),
-			     replace_ref, type_name(repl_type));
-
-	if (check_ref_valid(object, &prev, &ref, force)) {
-		strbuf_release(&ref);
-		return -1;
-	}
-
-	transaction = ref_transaction_begin(&err);
-	if (!transaction ||
-	    ref_transaction_update(transaction, ref.buf, repl, &prev,
-				   0, NULL, &err) ||
-	    ref_transaction_commit(transaction, &err))
-		res = error("%s", err.buf);
-
-	ref_transaction_free(transaction);
-	strbuf_release(&ref);
-	return res;
-}
-
-static int replace_object(const char *object_ref, const char *replace_ref, int force)
-{
-	struct object_id object, repl;
-
-	if (get_oid(object_ref, &object))
-		return error(_("failed to resolve '%s' as a valid ref"),
-			     object_ref);
-	if (get_oid(replace_ref, &repl))
-		return error(_("failed to resolve '%s' as a valid ref"),
-			     replace_ref);
-
-	return replace_object_oid(object_ref, &object, replace_ref, &repl, force);
-}
-
-/*
- * Write the contents of the object named by "sha1" to the file "filename".
- * If "raw" is true, then the object's raw contents are printed according to
- * "type". Otherwise, we pretty-print the contents for human editing.
- */
-static int export_object(const struct object_id *oid, enum object_type type,
-			  int raw, const char *filename)
-{
-	struct child_process cmd = CHILD_PROCESS_INIT;
-	int fd;
-
-	fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
-	if (fd < 0)
-		return error_errno(_("unable to open %s for writing"), filename);
-
-	strvec_push(&cmd.args, "--no-replace-objects");
-	strvec_push(&cmd.args, "cat-file");
-	if (raw)
-		strvec_push(&cmd.args, type_name(type));
-	else
-		strvec_push(&cmd.args, "-p");
-	strvec_push(&cmd.args, oid_to_hex(oid));
-	cmd.git_cmd = 1;
-	cmd.out = fd;
-
-	if (run_command(&cmd))
-		return error(_("cat-file reported failure"));
-	return 0;
-}
-
-/*
- * Read a previously-exported (and possibly edited) object back from "filename",
- * interpreting it as "type", and writing the result to the object database.
- * The sha1 of the written object is returned via sha1.
- */
-static int import_object(struct object_id *oid, enum object_type type,
-			  int raw, const char *filename)
-{
-	int fd;
-
-	fd = open(filename, O_RDONLY);
-	if (fd < 0)
-		return error_errno(_("unable to open %s for reading"), filename);
-
-	if (!raw && type == OBJ_TREE) {
-		const char *argv[] = { "mktree", NULL };
-		struct child_process cmd = CHILD_PROCESS_INIT;
-		struct strbuf result = STRBUF_INIT;
-
-		cmd.argv = argv;
-		cmd.git_cmd = 1;
-		cmd.in = fd;
-		cmd.out = -1;
-
-		if (start_command(&cmd)) {
-			close(fd);
-			return error(_("unable to spawn mktree"));
-		}
-
-		if (strbuf_read(&result, cmd.out, the_hash_algo->hexsz + 1) < 0) {
-			error_errno(_("unable to read from mktree"));
-			close(fd);
-			close(cmd.out);
-			return -1;
-		}
-		close(cmd.out);
-
-		if (finish_command(&cmd)) {
-			strbuf_release(&result);
-			return error(_("mktree reported failure"));
-		}
-		if (get_oid_hex(result.buf, oid) < 0) {
-			strbuf_release(&result);
-			return error(_("mktree did not return an object name"));
-		}
-
-		strbuf_release(&result);
-	} else {
-		struct stat st;
-		int flags = HASH_FORMAT_CHECK | HASH_WRITE_OBJECT;
-
-		if (fstat(fd, &st) < 0) {
-			error_errno(_("unable to fstat %s"), filename);
-			close(fd);
-			return -1;
-		}
-		if (index_fd(the_repository->index, oid, fd, &st, type, NULL, flags) < 0)
-			return error(_("unable to write object to database"));
-		/* index_fd close()s fd for us */
-	}
-
-	/*
-	 * No need to close(fd) here; both run-command and index-fd
-	 * will have done it for us.
-	 */
-	return 0;
-}
-
-static int edit_and_replace(const char *object_ref, int force, int raw)
-{
-	char *tmpfile;
-	enum object_type type;
-	struct object_id old_oid, new_oid, prev;
-	struct strbuf ref = STRBUF_INIT;
-
-	if (get_oid(object_ref, &old_oid) < 0)
-		return error(_("not a valid object name: '%s'"), object_ref);
-
-	type = oid_object_info(the_repository, &old_oid, NULL);
-	if (type < 0)
-		return error(_("unable to get object type for %s"),
-			     oid_to_hex(&old_oid));
-
-	if (check_ref_valid(&old_oid, &prev, &ref, force)) {
-		strbuf_release(&ref);
-		return -1;
-	}
-	strbuf_release(&ref);
-
-	tmpfile = git_pathdup("REPLACE_EDITOBJ");
-	if (export_object(&old_oid, type, raw, tmpfile)) {
-		free(tmpfile);
-		return -1;
-	}
-	if (launch_editor(tmpfile, NULL, NULL) < 0) {
-		free(tmpfile);
-		return error(_("editing object file failed"));
-	}
-	if (import_object(&new_oid, type, raw, tmpfile)) {
-		free(tmpfile);
-		return -1;
-	}
-	free(tmpfile);
-
-	if (oideq(&old_oid, &new_oid))
-		return error(_("new object is the same as the old one: '%s'"), oid_to_hex(&old_oid));
-
-	return replace_object_oid(object_ref, &old_oid, "replacement", &new_oid, force);
-}
-
-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_end = parent_start;
-
-	while (starts_with(parent_end, "parent "))
-		parent_end += hexsz + 8; /* "parent " + "hex sha1" + "\n" */
-
-	/* prepare new parents */
-	for (i = 0; i < argc; i++) {
-		struct object_id oid;
-		struct commit *commit;
-
-		if (get_oid(argv[i], &oid) < 0) {
-			strbuf_release(&new_parents);
-			return error(_("not a valid object name: '%s'"),
-				     argv[i]);
-		}
-		commit = lookup_commit_reference(the_repository, &oid);
-		if (!commit) {
-			strbuf_release(&new_parents);
-			return error(_("could not parse %s as a commit"), argv[i]);
-		}
-		strbuf_addf(&new_parents, "parent %s\n", oid_to_hex(&commit->object.oid));
-	}
-
-	/* replace existing parents with new ones */
-	strbuf_splice(buf, parent_start - buf->buf, parent_end - parent_start,
-		      new_parents.buf, new_parents.len);
-
-	strbuf_release(&new_parents);
-	return 0;
-}
-
-struct check_mergetag_data {
-	int argc;
-	const char **argv;
-};
-
-static int check_one_mergetag(struct commit *commit,
-			       struct commit_extra_header *extra,
-			       void *data)
-{
-	struct check_mergetag_data *mergetag_data = (struct check_mergetag_data *)data;
-	const char *ref = mergetag_data->argv[0];
-	struct object_id tag_oid;
-	struct tag *tag;
-	int i;
-
-	hash_object_file(the_hash_algo, 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);
-	if (parse_tag_buffer(the_repository, tag, extra->value, extra->len))
-		return error(_("malformed mergetag in commit '%s'"), ref);
-
-	/* iterate over new parents */
-	for (i = 1; i < mergetag_data->argc; i++) {
-		struct object_id oid;
-		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))
-			return 0; /* found */
-	}
-
-	return error(_("original commit '%s' contains mergetag '%s' that is "
-		       "discarded; use --edit instead of --graft"), ref,
-		     oid_to_hex(&tag_oid));
-}
-
-static int check_mergetags(struct commit *commit, int argc, const char **argv)
-{
-	struct check_mergetag_data mergetag_data;
-
-	mergetag_data.argc = argc;
-	mergetag_data.argv = argv;
-	return for_each_mergetag(check_one_mergetag, commit, &mergetag_data);
-}
-
-static int create_graft(int argc, const char **argv, int force, int gentle)
-{
-	struct object_id old_oid, new_oid;
-	const char *old_ref = argv[0];
-	struct commit *commit;
-	struct strbuf buf = STRBUF_INIT;
-	const char *buffer;
-	unsigned long size;
-
-	if (get_oid(old_ref, &old_oid) < 0)
-		return error(_("not a valid object name: '%s'"), old_ref);
-	commit = lookup_commit_reference(the_repository, &old_oid);
-	if (!commit)
-		return error(_("could not parse %s"), old_ref);
-
-	buffer = get_commit_buffer(commit, &size);
-	strbuf_add(&buf, buffer, size);
-	unuse_commit_buffer(commit, buffer);
-
-	if (replace_parents(&buf, argc - 1, &argv[1]) < 0) {
-		strbuf_release(&buf);
-		return -1;
-	}
-
-	if (remove_signature(&buf)) {
-		warning(_("the original commit '%s' has a gpg signature"), old_ref);
-		warning(_("the signature will be removed in the replacement commit!"));
-	}
-
-	if (check_mergetags(commit, argc, argv)) {
-		strbuf_release(&buf);
-		return -1;
-	}
-
-	if (write_object_file(buf.buf, buf.len, commit_type, &new_oid)) {
-		strbuf_release(&buf);
-		return error(_("could not write replacement commit for: '%s'"),
-			     old_ref);
-	}
-
-	strbuf_release(&buf);
-
-	if (oideq(&commit->object.oid, &new_oid)) {
-		if (gentle) {
-			warning(_("graft for '%s' unnecessary"),
-				oid_to_hex(&commit->object.oid));
-			return 0;
-		}
-		return error(_("new commit is the same as the old one: '%s'"),
-			     oid_to_hex(&commit->object.oid));
-	}
-
-	return replace_object_oid(old_ref, &commit->object.oid,
-				  "replacement", &new_oid, force);
-}
-
-static int convert_graft_file(int force)
-{
-	const char *graft_file = get_graft_file(the_repository);
-	FILE *fp = fopen_or_warn(graft_file, "r");
-	struct strbuf buf = STRBUF_INIT, err = STRBUF_INIT;
-	struct strvec args = STRVEC_INIT;
-
-	if (!fp)
-		return -1;
-
-	advice_graft_file_deprecated = 0;
-	while (strbuf_getline(&buf, fp) != EOF) {
-		if (*buf.buf == '#')
-			continue;
-
-		strvec_split(&args, buf.buf);
-		if (args.nr && create_graft(args.nr, args.v, force, 1))
-			strbuf_addf(&err, "\n\t%s", buf.buf);
-		strvec_clear(&args);
-	}
-	fclose(fp);
-
-	strbuf_release(&buf);
-
-	if (!err.len)
-		return unlink_or_warn(graft_file);
-
-	warning(_("could not convert the following graft(s):\n%s"), err.buf);
-	strbuf_release(&err);
-
-	return -1;
-}
-
-int cmd_replace(int argc, const char **argv, const char *prefix)
-{
-	int force = 0;
-	int raw = 0;
-	const char *format = NULL;
-	enum {
-		MODE_UNSPECIFIED = 0,
-		MODE_LIST,
-		MODE_DELETE,
-		MODE_EDIT,
-		MODE_GRAFT,
-		MODE_CONVERT_GRAFT_FILE,
-		MODE_REPLACE
-	} cmdmode = MODE_UNSPECIFIED;
-	struct option options[] = {
-		OPT_CMDMODE('l', "list", &cmdmode, N_("list replace refs"), MODE_LIST),
-		OPT_CMDMODE('d', "delete", &cmdmode, N_("delete replace refs"), MODE_DELETE),
-		OPT_CMDMODE('e', "edit", &cmdmode, N_("edit existing object"), MODE_EDIT),
-		OPT_CMDMODE('g', "graft", &cmdmode, N_("change a commit's parents"), MODE_GRAFT),
-		OPT_CMDMODE(0, "convert-graft-file", &cmdmode, N_("convert existing graft file"), MODE_CONVERT_GRAFT_FILE),
-		OPT_BOOL_F('f', "force", &force, N_("replace the ref if it exists"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT_BOOL(0, "raw", &raw, N_("do not pretty-print contents for --edit")),
-		OPT_STRING(0, "format", &format, N_("format"), N_("use this format")),
-		OPT_END()
-	};
-
-	read_replace_refs = 0;
-	git_config(git_default_config, NULL);
-
-	argc = parse_options(argc, argv, prefix, options, git_replace_usage, 0);
-
-	if (!cmdmode)
-		cmdmode = argc ? MODE_REPLACE : MODE_LIST;
-
-	if (format && cmdmode != MODE_LIST)
-		usage_msg_opt(_("--format cannot be used when not listing"),
-			      git_replace_usage, options);
-
-	if (force &&
-	    cmdmode != MODE_REPLACE &&
-	    cmdmode != MODE_EDIT &&
-	    cmdmode != MODE_GRAFT &&
-	    cmdmode != MODE_CONVERT_GRAFT_FILE)
-		usage_msg_opt(_("-f only makes sense when writing a replacement"),
-			      git_replace_usage, options);
-
-	if (raw && cmdmode != MODE_EDIT)
-		usage_msg_opt(_("--raw only makes sense with --edit"),
-			      git_replace_usage, options);
-
-	switch (cmdmode) {
-	case MODE_DELETE:
-		if (argc < 1)
-			usage_msg_opt(_("-d needs at least one argument"),
-				      git_replace_usage, options);
-		return for_each_replace_name(argv, delete_replace_ref);
-
-	case MODE_REPLACE:
-		if (argc != 2)
-			usage_msg_opt(_("bad number of arguments"),
-				      git_replace_usage, options);
-		return replace_object(argv[0], argv[1], force);
-
-	case MODE_EDIT:
-		if (argc != 1)
-			usage_msg_opt(_("-e needs exactly one argument"),
-				      git_replace_usage, options);
-		return edit_and_replace(argv[0], force, raw);
-
-	case MODE_GRAFT:
-		if (argc < 1)
-			usage_msg_opt(_("-g needs at least one argument"),
-				      git_replace_usage, options);
-		return create_graft(argc, argv, force, 0);
-
-	case MODE_CONVERT_GRAFT_FILE:
-		if (argc != 0)
-			usage_msg_opt(_("--convert-graft-file takes no argument"),
-				      git_replace_usage, options);
-		return !!convert_graft_file(force);
-
-	case MODE_LIST:
-		if (argc > 1)
-			usage_msg_opt(_("only one pattern can be given with -l"),
-				      git_replace_usage, options);
-		return list_replace_refs(argv[0], format);
-
-	default:
-		BUG("invalid cmdmode %d", (int)cmdmode);
-	}
-}
diff --git a/third_party/git/builtin/rerere.c b/third_party/git/builtin/rerere.c
deleted file mode 100644
index fd3be17b976c..000000000000
--- a/third_party/git/builtin/rerere.c
+++ /dev/null
@@ -1,120 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "dir.h"
-#include "parse-options.h"
-#include "string-list.h"
-#include "rerere.h"
-#include "xdiff/xdiff.h"
-#include "xdiff-interface.h"
-#include "pathspec.h"
-
-static const char * const rerere_usage[] = {
-	N_("git rerere [clear | forget <path>... | status | remaining | diff | gc]"),
-	NULL,
-};
-
-static int outf(void *dummy, mmbuffer_t *ptr, int nbuf)
-{
-	int i;
-	for (i = 0; i < nbuf; i++)
-		if (write_in_full(1, ptr[i].ptr, ptr[i].size) < 0)
-			return -1;
-	return 0;
-}
-
-static int diff_two(const char *file1, const char *label1,
-		const char *file2, const char *label2)
-{
-	xpparam_t xpp;
-	xdemitconf_t xecfg;
-	xdemitcb_t ecb;
-	mmfile_t minus, plus;
-	int ret;
-
-	if (read_mmfile(&minus, file1) || read_mmfile(&plus, file2))
-		return -1;
-
-	printf("--- a/%s\n+++ b/%s\n", label1, label2);
-	fflush(stdout);
-	memset(&xpp, 0, sizeof(xpp));
-	xpp.flags = 0;
-	memset(&xecfg, 0, sizeof(xecfg));
-	xecfg.ctxlen = 3;
-	ecb.out_hunk = NULL;
-	ecb.out_line = outf;
-	ret = xdi_diff(&minus, &plus, &xpp, &xecfg, &ecb);
-
-	free(minus.ptr);
-	free(plus.ptr);
-	return ret;
-}
-
-int cmd_rerere(int argc, const char **argv, const char *prefix)
-{
-	struct string_list merge_rr = STRING_LIST_INIT_DUP;
-	int i, autoupdate = -1, flags = 0;
-
-	struct option options[] = {
-		OPT_SET_INT(0, "rerere-autoupdate", &autoupdate,
-			N_("register clean resolutions in index"), 1),
-		OPT_END(),
-	};
-
-	argc = parse_options(argc, argv, prefix, options, rerere_usage, 0);
-
-	git_config(git_xmerge_config, NULL);
-
-	if (autoupdate == 1)
-		flags = RERERE_AUTOUPDATE;
-	if (autoupdate == 0)
-		flags = RERERE_NOAUTOUPDATE;
-
-	if (argc < 1)
-		return repo_rerere(the_repository, flags);
-
-	if (!strcmp(argv[0], "forget")) {
-		struct pathspec pathspec;
-		if (argc < 2)
-			warning(_("'git rerere forget' without paths is deprecated"));
-		parse_pathspec(&pathspec, 0, PATHSPEC_PREFER_CWD,
-			       prefix, argv + 1);
-		return rerere_forget(the_repository, &pathspec);
-	}
-
-	if (!strcmp(argv[0], "clear")) {
-		rerere_clear(the_repository, &merge_rr);
-	} else if (!strcmp(argv[0], "gc"))
-		rerere_gc(the_repository, &merge_rr);
-	else if (!strcmp(argv[0], "status")) {
-		if (setup_rerere(the_repository, &merge_rr,
-				 flags | RERERE_READONLY) < 0)
-			return 0;
-		for (i = 0; i < merge_rr.nr; i++)
-			printf("%s\n", merge_rr.items[i].string);
-	} else if (!strcmp(argv[0], "remaining")) {
-		rerere_remaining(the_repository, &merge_rr);
-		for (i = 0; i < merge_rr.nr; i++) {
-			if (merge_rr.items[i].util != RERERE_RESOLVED)
-				printf("%s\n", merge_rr.items[i].string);
-			else
-				/* prepare for later call to
-				 * string_list_clear() */
-				merge_rr.items[i].util = NULL;
-		}
-	} else if (!strcmp(argv[0], "diff")) {
-		if (setup_rerere(the_repository, &merge_rr,
-				 flags | RERERE_READONLY) < 0)
-			return 0;
-		for (i = 0; i < merge_rr.nr; i++) {
-			const char *path = merge_rr.items[i].string;
-			const struct rerere_id *id = merge_rr.items[i].util;
-			if (diff_two(rerere_path(id, "preimage"), path, path, path))
-				die(_("unable to generate diff for '%s'"), rerere_path(id, NULL));
-		}
-	} else
-		usage_with_options(rerere_usage, options);
-
-	string_list_clear(&merge_rr, 1);
-	return 0;
-}
diff --git a/third_party/git/builtin/reset.c b/third_party/git/builtin/reset.c
deleted file mode 100644
index c635b062c3a7..000000000000
--- a/third_party/git/builtin/reset.c
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * "git reset" builtin command
- *
- * Copyright (c) 2007 Carlos Rica
- *
- * Based on git-reset.sh, which is
- *
- * Copyright (c) 2005, 2006 Linus Torvalds and Junio C Hamano
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "config.h"
-#include "lockfile.h"
-#include "tag.h"
-#include "object.h"
-#include "pretty.h"
-#include "run-command.h"
-#include "refs.h"
-#include "diff.h"
-#include "diffcore.h"
-#include "tree.h"
-#include "branch.h"
-#include "parse-options.h"
-#include "unpack-trees.h"
-#include "cache-tree.h"
-#include "submodule.h"
-#include "submodule-config.h"
-
-#define REFRESH_INDEX_DELAY_WARNING_IN_MS (2 * 1000)
-
-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>...]"),
-	NULL
-};
-
-enum reset_type { MIXED, SOFT, HARD, MERGE, KEEP, NONE };
-static const char *reset_type_names[] = {
-	N_("mixed"), N_("soft"), N_("hard"), N_("merge"), N_("keep"), NULL
-};
-
-static inline int is_merge(void)
-{
-	return !access(git_path_merge_head(the_repository), F_OK);
-}
-
-static int reset_index(const char *ref, const struct object_id *oid, int reset_type, int quiet)
-{
-	int i, nr = 0;
-	struct tree_desc desc[2];
-	struct tree *tree;
-	struct unpack_trees_options opts;
-	int ret = -1;
-
-	memset(&opts, 0, sizeof(opts));
-	opts.head_idx = 1;
-	opts.src_index = &the_index;
-	opts.dst_index = &the_index;
-	opts.fn = oneway_merge;
-	opts.merge = 1;
-	init_checkout_metadata(&opts.meta, ref, oid, NULL);
-	if (!quiet)
-		opts.verbose_update = 1;
-	switch (reset_type) {
-	case KEEP:
-	case MERGE:
-		opts.update = 1;
-		break;
-	case HARD:
-		opts.update = 1;
-		/* fallthrough */
-	default:
-		opts.reset = 1;
-	}
-
-	read_cache_unmerged();
-
-	if (reset_type == KEEP) {
-		struct object_id head_oid;
-		if (get_oid("HEAD", &head_oid))
-			return error(_("You do not have a valid HEAD."));
-		if (!fill_tree_descriptor(the_repository, desc + nr, &head_oid))
-			return error(_("Failed to find tree of HEAD."));
-		nr++;
-		opts.fn = twoway_merge;
-	}
-
-	if (!fill_tree_descriptor(the_repository, desc + nr, oid)) {
-		error(_("Failed to find tree of %s."), oid_to_hex(oid));
-		goto out;
-	}
-	nr++;
-
-	if (unpack_trees(nr, desc, &opts))
-		goto out;
-
-	if (reset_type == MIXED || reset_type == HARD) {
-		tree = parse_tree_indirect(oid);
-		prime_cache_tree(the_repository, the_repository->index, tree);
-	}
-
-	ret = 0;
-
-out:
-	for (i = 0; i < nr; i++)
-		free((void *)desc[i].buffer);
-	return ret;
-}
-
-static void print_new_head_line(struct commit *commit)
-{
-	struct strbuf buf = STRBUF_INIT;
-
-	printf(_("HEAD is now at %s"),
-		find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV));
-
-	pp_commit_easy(CMIT_FMT_ONELINE, commit, &buf);
-	if (buf.len > 0)
-		printf(" %s", buf.buf);
-	putchar('\n');
-	strbuf_release(&buf);
-}
-
-static void update_index_from_diff(struct diff_queue_struct *q,
-		struct diff_options *opt, void *data)
-{
-	int i;
-	int intent_to_add = *(int *)data;
-
-	for (i = 0; i < q->nr; i++) {
-		struct diff_filespec *one = q->queue[i]->one;
-		int is_missing = !(one->mode && !is_null_oid(&one->oid));
-		struct cache_entry *ce;
-
-		if (is_missing && !intent_to_add) {
-			remove_file_from_cache(one->path);
-			continue;
-		}
-
-		ce = make_cache_entry(&the_index, one->mode, &one->oid, one->path,
-				      0, 0);
-		if (!ce)
-			die(_("make_cache_entry failed for path '%s'"),
-			    one->path);
-		if (is_missing) {
-			ce->ce_flags |= CE_INTENT_TO_ADD;
-			set_object_name_for_intent_to_add_entry(ce);
-		}
-		add_cache_entry(ce, ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
-	}
-}
-
-static int read_from_tree(const struct pathspec *pathspec,
-			  struct object_id *tree_oid,
-			  int intent_to_add)
-{
-	struct diff_options opt;
-
-	memset(&opt, 0, sizeof(opt));
-	copy_pathspec(&opt.pathspec, pathspec);
-	opt.output_format = DIFF_FORMAT_CALLBACK;
-	opt.format_callback = update_index_from_diff;
-	opt.format_callback_data = &intent_to_add;
-	opt.flags.override_submodule_config = 1;
-	opt.repo = the_repository;
-
-	if (do_diff_cache(tree_oid, &opt))
-		return 1;
-	diffcore_std(&opt);
-	diff_flush(&opt);
-	clear_pathspec(&opt.pathspec);
-
-	return 0;
-}
-
-static void set_reflog_message(struct strbuf *sb, const char *action,
-			       const char *rev)
-{
-	const char *rla = getenv("GIT_REFLOG_ACTION");
-
-	strbuf_reset(sb);
-	if (rla)
-		strbuf_addf(sb, "%s: %s", rla, action);
-	else if (rev)
-		strbuf_addf(sb, "reset: moving to %s", rev);
-	else
-		strbuf_addf(sb, "reset: %s", action);
-}
-
-static void die_if_unmerged_cache(int reset_type)
-{
-	if (is_merge() || unmerged_cache())
-		die(_("Cannot do a %s reset in the middle of a merge."),
-		    _(reset_type_names[reset_type]));
-
-}
-
-static void parse_args(struct pathspec *pathspec,
-		       const char **argv, const char *prefix,
-		       int patch_mode,
-		       const char **rev_ret)
-{
-	const char *rev = "HEAD";
-	struct object_id unused;
-	/*
-	 * Possible arguments are:
-	 *
-	 * git reset [-opts] [<rev>]
-	 * git reset [-opts] <tree> [<paths>...]
-	 * git reset [-opts] <tree> -- [<paths>...]
-	 * git reset [-opts] -- [<paths>...]
-	 * git reset [-opts] <paths>...
-	 *
-	 * At this point, argv points immediately after [-opts].
-	 */
-
-	if (argv[0]) {
-		if (!strcmp(argv[0], "--")) {
-			argv++; /* reset to HEAD, possibly with paths */
-		} else if (argv[1] && !strcmp(argv[1], "--")) {
-			rev = argv[0];
-			argv += 2;
-		}
-		/*
-		 * Otherwise, argv[0] could be either <rev> or <paths> and
-		 * has to be unambiguous. If there is a single argument, it
-		 * can not be a tree
-		 */
-		else if ((!argv[1] && !get_oid_committish(argv[0], &unused)) ||
-			 (argv[1] && !get_oid_treeish(argv[0], &unused))) {
-			/*
-			 * Ok, argv[0] looks like a commit/tree; it should not
-			 * be a filename.
-			 */
-			verify_non_filename(prefix, argv[0]);
-			rev = *argv++;
-		} else {
-			/* Otherwise we treat this as a filename */
-			verify_filename(prefix, argv[0], 1);
-		}
-	}
-	*rev_ret = rev;
-
-	if (read_cache() < 0)
-		die(_("index file corrupt"));
-
-	parse_pathspec(pathspec, 0,
-		       PATHSPEC_PREFER_FULL |
-		       (patch_mode ? PATHSPEC_PREFIX_ORIGIN : 0),
-		       prefix, argv);
-}
-
-static int reset_refs(const char *rev, const struct object_id *oid)
-{
-	int update_ref_status;
-	struct strbuf msg = STRBUF_INIT;
-	struct object_id *orig = NULL, oid_orig,
-		*old_orig = NULL, oid_old_orig;
-
-	if (!get_oid("ORIG_HEAD", &oid_old_orig))
-		old_orig = &oid_old_orig;
-	if (!get_oid("HEAD", &oid_orig)) {
-		orig = &oid_orig;
-		set_reflog_message(&msg, "updating ORIG_HEAD", NULL);
-		update_ref(msg.buf, "ORIG_HEAD", orig, old_orig, 0,
-			   UPDATE_REFS_MSG_ON_ERR);
-	} else if (old_orig)
-		delete_ref(NULL, "ORIG_HEAD", old_orig, 0);
-	set_reflog_message(&msg, "updating HEAD", rev);
-	update_ref_status = update_ref(msg.buf, "HEAD", oid, orig, 0,
-				       UPDATE_REFS_MSG_ON_ERR);
-	strbuf_release(&msg);
-	return update_ref_status;
-}
-
-static int git_reset_config(const char *var, const char *value, void *cb)
-{
-	if (!strcmp(var, "submodule.recurse"))
-		return git_default_submodule_config(var, value, cb);
-
-	return git_default_config(var, value, 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;
-	struct object_id oid;
-	struct pathspec pathspec;
-	int intent_to_add = 0;
-	const struct option options[] = {
-		OPT__QUIET(&quiet, N_("be quiet, only report errors")),
-		OPT_SET_INT(0, "mixed", &reset_type,
-						N_("reset HEAD and index"), MIXED),
-		OPT_SET_INT(0, "soft", &reset_type, N_("reset only HEAD"), SOFT),
-		OPT_SET_INT(0, "hard", &reset_type,
-				N_("reset HEAD, index and working tree"), HARD),
-		OPT_SET_INT(0, "merge", &reset_type,
-				N_("reset HEAD, index and working tree"), MERGE),
-		OPT_SET_INT(0, "keep", &reset_type,
-				N_("reset HEAD but keep local changes"), KEEP),
-		OPT_CALLBACK_F(0, "recurse-submodules", NULL,
-			    "reset", "control recursive updating of submodules",
-			    PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater),
-		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()
-	};
-
-	git_config(git_reset_config, NULL);
-	git_config_get_bool("reset.quiet", &quiet);
-
-	argc = parse_options(argc, argv, prefix, options, git_reset_usage,
-						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) {
-		struct commit *commit;
-		if (get_oid_committish(rev, &oid))
-			die(_("Failed to resolve '%s' as a valid revision."), rev);
-		commit = lookup_commit_reference(the_repository, &oid);
-		if (!commit)
-			die(_("Could not parse object '%s'."), rev);
-		oidcpy(&oid, &commit->object.oid);
-	} else {
-		struct tree *tree;
-		if (get_oid_treeish(rev, &oid))
-			die(_("Failed to resolve '%s' as a valid tree."), rev);
-		tree = parse_tree_indirect(&oid);
-		if (!tree)
-			die(_("Could not parse object '%s'."), rev);
-		oidcpy(&oid, &tree->object.oid);
-	}
-
-	if (patch_mode) {
-		if (reset_type != NONE)
-			die(_("--patch is incompatible with --{hard,mixed,soft}"));
-		trace2_cmd_mode("patch-interactive");
-		return run_add_interactive(rev, "--patch=reset", &pathspec);
-	}
-
-	/* git reset tree [--] paths... can be used to
-	 * load chosen paths from the tree into the index without
-	 * affecting the working tree nor HEAD. */
-	if (pathspec.nr) {
-		if (reset_type == MIXED)
-			warning(_("--mixed with paths is deprecated; use 'git reset -- <paths>' instead."));
-		else if (reset_type != NONE)
-			die(_("Cannot do %s reset with paths."),
-					_(reset_type_names[reset_type]));
-	}
-	if (reset_type == NONE)
-		reset_type = MIXED; /* by default */
-
-	if (pathspec.nr)
-		trace2_cmd_mode("path");
-	else
-		trace2_cmd_mode(reset_type_names[reset_type]);
-
-	if (reset_type != SOFT && (reset_type != MIXED || get_git_work_tree()))
-		setup_work_tree();
-
-	if (reset_type == MIXED && is_bare_repository())
-		die(_("%s reset is not allowed in a bare repository"),
-		    _(reset_type_names[reset_type]));
-
-	if (intent_to_add && reset_type != MIXED)
-		die(_("-N can only be used with --mixed"));
-
-	/* Soft reset does not touch the index file nor the working tree
-	 * at all, but requires them in a good order.  Other resets reset
-	 * the index file to the tree object we are switching to. */
-	if (reset_type == SOFT || reset_type == KEEP)
-		die_if_unmerged_cache(reset_type);
-
-	if (reset_type != SOFT) {
-		struct lock_file lock = LOCK_INIT;
-		hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
-		if (reset_type == MIXED) {
-			int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
-			if (read_from_tree(&pathspec, &oid, intent_to_add))
-				return 1;
-			the_index.updated_skipworktree = 1;
-			if (!quiet && get_git_work_tree()) {
-				uint64_t t_begin, t_delta_in_ms;
-
-				t_begin = getnanotime();
-				refresh_index(&the_index, flags, NULL, NULL,
-					      _("Unstaged changes after reset:"));
-				t_delta_in_ms = (getnanotime() - t_begin) / 1000000;
-				if (advice_reset_quiet_warning && t_delta_in_ms > REFRESH_INDEX_DELAY_WARNING_IN_MS) {
-					printf(_("\nIt took %.2f seconds to enumerate unstaged changes after reset.  You can\n"
-						"use '--quiet' to avoid this.  Set the config setting reset.quiet to true\n"
-						"to make this the default.\n"), t_delta_in_ms / 1000.0);
-				}
-			}
-		} else {
-			struct object_id dummy;
-			char *ref = NULL;
-			int err;
-
-			dwim_ref(rev, strlen(rev), &dummy, &ref, 0);
-			if (ref && !starts_with(ref, "refs/"))
-				ref = NULL;
-
-			err = reset_index(ref, &oid, reset_type, quiet);
-			if (reset_type == KEEP && !err)
-				err = reset_index(ref, &oid, MIXED, quiet);
-			if (err)
-				die(_("Could not reset index file to revision '%s'."), rev);
-			free(ref);
-		}
-
-		if (write_locked_index(&the_index, &lock, COMMIT_LOCK))
-			die(_("Could not write new index file."));
-	}
-
-	if (!pathspec.nr && !unborn) {
-		/* Any resets without paths update HEAD to the head being
-		 * switched to, saving the previous head in ORIG_HEAD before. */
-		update_ref_status = reset_refs(rev, &oid);
-
-		if (reset_type == HARD && !update_ref_status && !quiet)
-			print_new_head_line(lookup_commit_reference(the_repository, &oid));
-	}
-	if (!pathspec.nr)
-		remove_branch_state(the_repository, 0);
-
-	return update_ref_status;
-}
diff --git a/third_party/git/builtin/rev-list.c b/third_party/git/builtin/rev-list.c
deleted file mode 100644
index 25c6c3b38d4b..000000000000
--- a/third_party/git/builtin/rev-list.c
+++ /dev/null
@@ -1,694 +0,0 @@
-#include "cache.h"
-#include "config.h"
-#include "commit.h"
-#include "diff.h"
-#include "revision.h"
-#include "list-objects.h"
-#include "list-objects-filter.h"
-#include "list-objects-filter-options.h"
-#include "object.h"
-#include "object-store.h"
-#include "pack.h"
-#include "pack-bitmap.h"
-#include "builtin.h"
-#include "log-tree.h"
-#include "graph.h"
-#include "bisect.h"
-#include "progress.h"
-#include "reflog-walk.h"
-#include "oidset.h"
-#include "packfile.h"
-
-static const char rev_list_usage[] =
-"git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
-"  limiting output:\n"
-"    --max-count=<n>\n"
-"    --max-age=<epoch>\n"
-"    --min-age=<epoch>\n"
-"    --sparse\n"
-"    --no-merges\n"
-"    --min-parents=<n>\n"
-"    --no-min-parents\n"
-"    --max-parents=<n>\n"
-"    --no-max-parents\n"
-"    --remove-empty\n"
-"    --all\n"
-"    --branches\n"
-"    --tags\n"
-"    --remotes\n"
-"    --stdin\n"
-"    --quiet\n"
-"  ordering output:\n"
-"    --topo-order\n"
-"    --date-order\n"
-"    --reverse\n"
-"  formatting output:\n"
-"    --parents\n"
-"    --children\n"
-"    --objects | --objects-edge\n"
-"    --unpacked\n"
-"    --header | --pretty\n"
-"    --[no-]object-names\n"
-"    --abbrev=<n> | --no-abbrev\n"
-"    --abbrev-commit\n"
-"    --left-right\n"
-"    --count\n"
-"  special purpose:\n"
-"    --bisect\n"
-"    --bisect-vars\n"
-"    --bisect-all"
-;
-
-static struct progress *progress;
-static unsigned progress_counter;
-
-static struct list_objects_filter_options filter_options;
-static struct oidset omitted_objects;
-static int arg_print_omitted; /* print objects omitted by filter */
-
-static struct oidset missing_objects;
-enum missing_action {
-	MA_ERROR = 0,    /* fail if any missing objects are encountered */
-	MA_ALLOW_ANY,    /* silently allow ALL missing objects */
-	MA_PRINT,        /* print ALL missing objects in special section */
-	MA_ALLOW_PROMISOR, /* silently allow all missing PROMISOR objects */
-};
-static enum missing_action arg_missing_action;
-
-/* display only the oid of each object encountered */
-static int arg_show_object_names = 1;
-
-#define DEFAULT_OIDSET_SIZE     (16*1024)
-
-static void finish_commit(struct commit *commit);
-static void show_commit(struct commit *commit, void *data)
-{
-	struct rev_list_info *info = data;
-	struct rev_info *revs = info->revs;
-
-	display_progress(progress, ++progress_counter);
-
-	if (info->flags & REV_LIST_QUIET) {
-		finish_commit(commit);
-		return;
-	}
-
-	graph_show_commit(revs->graph);
-
-	if (revs->count) {
-		if (commit->object.flags & PATCHSAME)
-			revs->count_same++;
-		else if (commit->object.flags & SYMMETRIC_LEFT)
-			revs->count_left++;
-		else
-			revs->count_right++;
-		finish_commit(commit);
-		return;
-	}
-
-	if (info->show_timestamp)
-		printf("%"PRItime" ", commit->date);
-	if (info->header_prefix)
-		fputs(info->header_prefix, stdout);
-
-	if (!revs->graph)
-		fputs(get_revision_mark(revs, commit), stdout);
-	if (revs->abbrev_commit && revs->abbrev)
-		fputs(find_unique_abbrev(&commit->object.oid, revs->abbrev),
-		      stdout);
-	else
-		fputs(oid_to_hex(&commit->object.oid), stdout);
-	if (revs->print_parents) {
-		struct commit_list *parents = commit->parents;
-		while (parents) {
-			printf(" %s", oid_to_hex(&parents->item->object.oid));
-			parents = parents->next;
-		}
-	}
-	if (revs->children.name) {
-		struct commit_list *children;
-
-		children = lookup_decoration(&revs->children, &commit->object);
-		while (children) {
-			printf(" %s", oid_to_hex(&children->item->object.oid));
-			children = children->next;
-		}
-	}
-	show_decorations(revs, commit);
-	if (revs->commit_format == CMIT_FMT_ONELINE)
-		putchar(' ');
-	else
-		putchar('\n');
-
-	if (revs->verbose_header) {
-		struct strbuf buf = STRBUF_INIT;
-		struct pretty_print_context ctx = {0};
-		ctx.abbrev = revs->abbrev;
-		ctx.date_mode = revs->date_mode;
-		ctx.date_mode_explicit = revs->date_mode_explicit;
-		ctx.fmt = revs->commit_format;
-		ctx.output_encoding = get_log_output_encoding();
-		ctx.color = revs->diffopt.use_color;
-		pretty_print_commit(&ctx, commit, &buf);
-		if (buf.len) {
-			if (revs->commit_format != CMIT_FMT_ONELINE)
-				graph_show_oneline(revs->graph);
-
-			graph_show_commit_msg(revs->graph, stdout, &buf);
-
-			/*
-			 * Add a newline after the commit message.
-			 *
-			 * Usually, this newline produces a blank
-			 * padding line between entries, in which case
-			 * we need to add graph padding on this line.
-			 *
-			 * However, the commit message may not end in a
-			 * newline.  In this case the newline simply
-			 * ends the last line of the commit message,
-			 * and we don't need any graph output.  (This
-			 * always happens with CMIT_FMT_ONELINE, and it
-			 * happens with CMIT_FMT_USERFORMAT when the
-			 * format doesn't explicitly end in a newline.)
-			 */
-			if (buf.len && buf.buf[buf.len - 1] == '\n')
-				graph_show_padding(revs->graph);
-			putchar(info->hdr_termination);
-		} else {
-			/*
-			 * If the message buffer is empty, just show
-			 * the rest of the graph output for this
-			 * commit.
-			 */
-			if (graph_show_remainder(revs->graph))
-				putchar('\n');
-			if (revs->commit_format == CMIT_FMT_ONELINE)
-				putchar('\n');
-		}
-		strbuf_release(&buf);
-	} else {
-		if (graph_show_remainder(revs->graph))
-			putchar('\n');
-	}
-	maybe_flush_or_die(stdout, "stdout");
-	finish_commit(commit);
-}
-
-static void finish_commit(struct commit *commit)
-{
-	if (commit->parents) {
-		free_commit_list(commit->parents);
-		commit->parents = NULL;
-	}
-	free_commit_buffer(the_repository->parsed_objects,
-			   commit);
-}
-
-static inline void finish_object__ma(struct object *obj)
-{
-	/*
-	 * Whether or not we try to dynamically fetch missing objects
-	 * from the server, we currently DO NOT have the object.  We
-	 * can either print, allow (ignore), or conditionally allow
-	 * (ignore) them.
-	 */
-	switch (arg_missing_action) {
-	case MA_ERROR:
-		die("missing %s object '%s'",
-		    type_name(obj->type), oid_to_hex(&obj->oid));
-		return;
-
-	case MA_ALLOW_ANY:
-		return;
-
-	case MA_PRINT:
-		oidset_insert(&missing_objects, &obj->oid);
-		return;
-
-	case MA_ALLOW_PROMISOR:
-		if (is_promisor_object(&obj->oid))
-			return;
-		die("unexpected missing %s object '%s'",
-		    type_name(obj->type), oid_to_hex(&obj->oid));
-		return;
-
-	default:
-		BUG("unhandled missing_action");
-		return;
-	}
-}
-
-static int finish_object(struct object *obj, const char *name, void *cb_data)
-{
-	struct rev_list_info *info = cb_data;
-	if (oid_object_info_extended(the_repository, &obj->oid, NULL, 0) < 0) {
-		finish_object__ma(obj);
-		return 1;
-	}
-	if (info->revs->verify_objects && !obj->parsed && obj->type != OBJ_COMMIT)
-		parse_object(the_repository, &obj->oid);
-	return 0;
-}
-
-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
-		printf("%s\n", oid_to_hex(&obj->oid));
-}
-
-static void show_edge(struct commit *commit)
-{
-	printf("-%s\n", oid_to_hex(&commit->object.oid));
-}
-
-static void print_var_str(const char *var, const char *val)
-{
-	printf("%s='%s'\n", var, val);
-}
-
-static void print_var_int(const char *var, int val)
-{
-	printf("%s=%d\n", var, val);
-}
-
-static int show_bisect_vars(struct rev_list_info *info, int reaches, int all)
-{
-	int cnt, flags = info->flags;
-	char hex[GIT_MAX_HEXSZ + 1] = "";
-	struct commit_list *tried;
-	struct rev_info *revs = info->revs;
-
-	if (!revs->commits)
-		return 1;
-
-	revs->commits = filter_skipped(revs->commits, &tried,
-				       flags & BISECT_SHOW_ALL,
-				       NULL, NULL);
-
-	/*
-	 * revs->commits can reach "reaches" commits among
-	 * "all" commits.  If it is good, then there are
-	 * (all-reaches) commits left to be bisected.
-	 * On the other hand, if it is bad, then the set
-	 * to bisect is "reaches".
-	 * A bisect set of size N has (N-1) commits further
-	 * to test, as we already know one bad one.
-	 */
-	cnt = all - reaches;
-	if (cnt < reaches)
-		cnt = reaches;
-
-	if (revs->commits)
-		oid_to_hex_r(hex, &revs->commits->item->object.oid);
-
-	if (flags & BISECT_SHOW_ALL) {
-		traverse_commit_list(revs, show_commit, show_object, info);
-		printf("------\n");
-	}
-
-	print_var_str("bisect_rev", hex);
-	print_var_int("bisect_nr", cnt - 1);
-	print_var_int("bisect_good", all - reaches - 1);
-	print_var_int("bisect_bad", reaches - 1);
-	print_var_int("bisect_all", all);
-	print_var_int("bisect_steps", estimate_bisect_steps(all));
-
-	return 0;
-}
-
-static int show_object_fast(
-	const struct object_id *oid,
-	enum object_type type,
-	int exclude,
-	uint32_t name_hash,
-	struct packed_git *found_pack,
-	off_t found_offset)
-{
-	fprintf(stdout, "%s\n", oid_to_hex(oid));
-	return 1;
-}
-
-static inline int parse_missing_action_value(const char *value)
-{
-	if (!strcmp(value, "error")) {
-		arg_missing_action = MA_ERROR;
-		return 1;
-	}
-
-	if (!strcmp(value, "allow-any")) {
-		arg_missing_action = MA_ALLOW_ANY;
-		fetch_if_missing = 0;
-		return 1;
-	}
-
-	if (!strcmp(value, "print")) {
-		arg_missing_action = MA_PRINT;
-		fetch_if_missing = 0;
-		return 1;
-	}
-
-	if (!strcmp(value, "allow-promisor")) {
-		arg_missing_action = MA_ALLOW_PROMISOR;
-		fetch_if_missing = 0;
-		return 1;
-	}
-
-	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;
-	struct rev_list_info info;
-	struct setup_revision_opt s_r_opt = {
-		.allow_exclude_promisor_objects = 1,
-	};
-	int i;
-	int bisect_list = 0;
-	int bisect_show_vars = 0;
-	int bisect_find_all = 0;
-	int use_bitmap_index = 0;
-	const char *show_progress = NULL;
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage(rev_list_usage);
-
-	git_config(git_default_config, NULL);
-	repo_init_revisions(the_repository, &revs, prefix);
-	revs.abbrev = DEFAULT_ABBREV;
-	revs.commit_format = CMIT_FMT_UNSPECIFIED;
-
-	/*
-	 * Scan the argument list before invoking setup_revisions(), so that we
-	 * know if fetch_if_missing needs to be set to 0.
-	 *
-	 * "--exclude-promisor-objects" acts as a pre-filter on missing objects
-	 * by not crossing the boundary from realized objects to promisor
-	 * objects.
-	 *
-	 * Let "--missing" to conditionally set fetch_if_missing.
-	 */
-	for (i = 1; i < argc; i++) {
-		const char *arg = argv[i];
-		if (!strcmp(arg, "--exclude-promisor-objects")) {
-			fetch_if_missing = 0;
-			revs.exclude_promisor_objects = 1;
-			break;
-		}
-	}
-	for (i = 1; i < argc; i++) {
-		const char *arg = argv[i];
-		if (skip_prefix(arg, "--missing=", &arg)) {
-			if (revs.exclude_promisor_objects)
-				die(_("cannot combine --exclude-promisor-objects and --missing"));
-			if (parse_missing_action_value(arg))
-				break;
-		}
-	}
-
-	if (arg_missing_action)
-		revs.do_not_die_on_missing_tree = 1;
-
-	argc = setup_revisions(argc, argv, &revs, &s_r_opt);
-
-	memset(&info, 0, sizeof(info));
-	info.revs = &revs;
-	if (revs.bisect)
-		bisect_list = 1;
-
-	if (revs.diffopt.flags.quick)
-		info.flags |= REV_LIST_QUIET;
-	for (i = 1 ; i < argc; i++) {
-		const char *arg = argv[i];
-
-		if (!strcmp(arg, "--header")) {
-			revs.verbose_header = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--timestamp")) {
-			info.show_timestamp = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--bisect")) {
-			bisect_list = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--bisect-all")) {
-			bisect_list = 1;
-			bisect_find_all = 1;
-			info.flags |= BISECT_SHOW_ALL;
-			revs.show_decorations = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--bisect-vars")) {
-			bisect_list = 1;
-			bisect_show_vars = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--use-bitmap-index")) {
-			use_bitmap_index = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--test-bitmap")) {
-			test_bitmap_walk(&revs);
-			return 0;
-		}
-		if (skip_prefix(arg, "--progress=", &arg)) {
-			show_progress = arg;
-			continue;
-		}
-
-		if (skip_prefix(arg, ("--" CL_ARG__FILTER "="), &arg)) {
-			parse_list_objects_filter(&filter_options, arg);
-			if (filter_options.choice && !revs.blob_objects)
-				die(_("object filtering requires --objects"));
-			continue;
-		}
-		if (!strcmp(arg, ("--no-" CL_ARG__FILTER))) {
-			list_objects_filter_set_no_filter(&filter_options);
-			continue;
-		}
-		if (!strcmp(arg, "--filter-print-omitted")) {
-			arg_print_omitted = 1;
-			continue;
-		}
-
-		if (!strcmp(arg, "--exclude-promisor-objects"))
-			continue; /* already handled above */
-		if (skip_prefix(arg, "--missing=", &arg))
-			continue; /* already handled above */
-
-		if (!strcmp(arg, ("--no-object-names"))) {
-			arg_show_object_names = 0;
-			continue;
-		}
-
-		if (!strcmp(arg, ("--object-names"))) {
-			arg_show_object_names = 1;
-			continue;
-		}
-
-		usage(rev_list_usage);
-
-	}
-	if (revs.commit_format != CMIT_FMT_UNSPECIFIED) {
-		/* The command line has a --pretty  */
-		info.hdr_termination = '\n';
-		if (revs.commit_format == CMIT_FMT_ONELINE)
-			info.header_prefix = "";
-		else
-			info.header_prefix = "commit ";
-	}
-	else if (revs.verbose_header)
-		/* Only --header was specified */
-		revs.commit_format = CMIT_FMT_RAW;
-
-	if ((!revs.commits && reflog_walk_empty(revs.reflog_info) &&
-	     (!(revs.tag_objects || revs.tree_objects || revs.blob_objects) &&
-	      !revs.pending.nr) &&
-	     !revs.rev_input_given && !revs.read_from_stdin) ||
-	    revs.diff)
-		usage(rev_list_usage);
-
-	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"));
-
-	save_commit_buffer = (revs.verbose_header ||
-			      revs.grep_filter.pattern_list ||
-			      revs.grep_filter.header_list);
-	if (bisect_list)
-		revs.limited = 1;
-
-	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 (prepare_revision_walk(&revs))
-		die("revision walk setup failed");
-	if (revs.tree_objects)
-		mark_edges_uninteresting(&revs, show_edge, 0);
-
-	if (bisect_list) {
-		int reaches, all;
-		unsigned bisect_flags = 0;
-
-		if (bisect_find_all)
-			bisect_flags |= FIND_BISECTION_ALL;
-
-		if (revs.first_parent_only)
-			bisect_flags |= FIND_BISECTION_FIRST_PARENT_ONLY;
-
-		find_bisection(&revs.commits, &reaches, &all, bisect_flags);
-
-		if (bisect_show_vars)
-			return show_bisect_vars(&info, reaches, all);
-	}
-
-	if (arg_print_omitted)
-		oidset_init(&omitted_objects, DEFAULT_OIDSET_SIZE);
-	if (arg_missing_action == MA_PRINT)
-		oidset_init(&missing_objects, DEFAULT_OIDSET_SIZE);
-
-	traverse_commit_list_filtered(
-		&filter_options, &revs, show_commit, show_object, &info,
-		(arg_print_omitted ? &omitted_objects : NULL));
-
-	if (arg_print_omitted) {
-		struct oidset_iter iter;
-		struct object_id *oid;
-		oidset_iter_init(&omitted_objects, &iter);
-		while ((oid = oidset_iter_next(&iter)))
-			printf("~%s\n", oid_to_hex(oid));
-		oidset_clear(&omitted_objects);
-	}
-	if (arg_missing_action == MA_PRINT) {
-		struct oidset_iter iter;
-		struct object_id *oid;
-		oidset_iter_init(&missing_objects, &iter);
-		while ((oid = oidset_iter_next(&iter)))
-			printf("?%s\n", oid_to_hex(oid));
-		oidset_clear(&missing_objects);
-	}
-
-	stop_progress(&progress);
-
-	if (revs.count) {
-		if (revs.left_right && revs.cherry_mark)
-			printf("%d\t%d\t%d\n", revs.count_left, revs.count_right, revs.count_same);
-		else if (revs.left_right)
-			printf("%d\t%d\n", revs.count_left, revs.count_right);
-		else if (revs.cherry_mark)
-			printf("%d\t%d\n", revs.count_left + revs.count_right, revs.count_same);
-		else
-			printf("%d\n", revs.count_left + revs.count_right);
-	}
-
-	return 0;
-}
diff --git a/third_party/git/builtin/rev-parse.c b/third_party/git/builtin/rev-parse.c
deleted file mode 100644
index ed200c8af128..000000000000
--- a/third_party/git/builtin/rev-parse.c
+++ /dev/null
@@ -1,984 +0,0 @@
-/*
- * rev-parse.c
- *
- * Copyright (C) Linus Torvalds, 2005
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "config.h"
-#include "commit.h"
-#include "refs.h"
-#include "quote.h"
-#include "builtin.h"
-#include "parse-options.h"
-#include "diff.h"
-#include "revision.h"
-#include "split-index.h"
-#include "submodule.h"
-#include "commit-reach.h"
-#include "shallow.h"
-
-#define DO_REVS		1
-#define DO_NOREV	2
-#define DO_FLAGS	4
-#define DO_NONFLAGS	8
-static int filter = ~0;
-
-static const char *def;
-
-#define NORMAL 0
-#define REVERSED 1
-static int show_type = NORMAL;
-
-#define SHOW_SYMBOLIC_ASIS 1
-#define SHOW_SYMBOLIC_FULL 2
-static int symbolic;
-static int abbrev;
-static int abbrev_ref;
-static int abbrev_ref_strict;
-static int output_sq;
-
-static int stuck_long;
-static struct string_list *ref_excludes;
-
-/*
- * Some arguments are relevant "revision" arguments,
- * others are about output format or other details.
- * This sorts it all out.
- */
-static int is_rev_argument(const char *arg)
-{
-	static const char *rev_args[] = {
-		"--all",
-		"--bisect",
-		"--dense",
-		"--branches=",
-		"--branches",
-		"--header",
-		"--ignore-missing",
-		"--max-age=",
-		"--max-count=",
-		"--min-age=",
-		"--no-merges",
-		"--min-parents=",
-		"--no-min-parents",
-		"--max-parents=",
-		"--no-max-parents",
-		"--objects",
-		"--objects-edge",
-		"--parents",
-		"--pretty",
-		"--remotes=",
-		"--remotes",
-		"--glob=",
-		"--sparse",
-		"--tags=",
-		"--tags",
-		"--topo-order",
-		"--date-order",
-		"--unpacked",
-		NULL
-	};
-	const char **p = rev_args;
-
-	/* accept -<digit>, like traditional "head" */
-	if ((*arg == '-') && isdigit(arg[1]))
-		return 1;
-
-	for (;;) {
-		const char *str = *p++;
-		int len;
-		if (!str)
-			return 0;
-		len = strlen(str);
-		if (!strcmp(arg, str) ||
-		    (str[len-1] == '=' && !strncmp(arg, str, len)))
-			return 1;
-	}
-}
-
-/* Output argument as a string, either SQ or normal */
-static void show(const char *arg)
-{
-	if (output_sq) {
-		int sq = '\'', ch;
-
-		putchar(sq);
-		while ((ch = *arg++)) {
-			if (ch == sq)
-				fputs("'\\'", stdout);
-			putchar(ch);
-		}
-		putchar(sq);
-		putchar(' ');
-	}
-	else
-		puts(arg);
-}
-
-/* Like show(), but with a negation prefix according to type */
-static void show_with_type(int type, const char *arg)
-{
-	if (type != show_type)
-		putchar('^');
-	show(arg);
-}
-
-/* Output a revision, only if filter allows it */
-static void show_rev(int type, const struct object_id *oid, const char *name)
-{
-	if (!(filter & DO_REVS))
-		return;
-	def = NULL;
-
-	if ((symbolic || abbrev_ref) && name) {
-		if (symbolic == SHOW_SYMBOLIC_FULL || abbrev_ref) {
-			struct object_id discard;
-			char *full;
-
-			switch (dwim_ref(name, strlen(name), &discard, &full, 0)) {
-			case 0:
-				/*
-				 * Not found -- not a ref.  We could
-				 * emit "name" here, but symbolic-full
-				 * users are interested in finding the
-				 * refs spelled in full, and they would
-				 * need to filter non-refs if we did so.
-				 */
-				break;
-			case 1: /* happy */
-				if (abbrev_ref)
-					full = shorten_unambiguous_ref(full,
-						abbrev_ref_strict);
-				show_with_type(type, full);
-				break;
-			default: /* ambiguous */
-				error("refname '%s' is ambiguous", name);
-				break;
-			}
-			free(full);
-		} else {
-			show_with_type(type, name);
-		}
-	}
-	else if (abbrev)
-		show_with_type(type, find_unique_abbrev(oid, abbrev));
-	else
-		show_with_type(type, oid_to_hex(oid));
-}
-
-/* Output a flag, only if filter allows it. */
-static int show_flag(const char *arg)
-{
-	if (!(filter & DO_FLAGS))
-		return 0;
-	if (filter & (is_rev_argument(arg) ? DO_REVS : DO_NOREV)) {
-		show(arg);
-		return 1;
-	}
-	return 0;
-}
-
-static int show_default(void)
-{
-	const char *s = def;
-
-	if (s) {
-		struct object_id oid;
-
-		def = NULL;
-		if (!get_oid(s, &oid)) {
-			show_rev(NORMAL, &oid, s);
-			return 1;
-		}
-	}
-	return 0;
-}
-
-static int show_reference(const char *refname, const struct object_id *oid, int flag, void *cb_data)
-{
-	if (ref_excluded(ref_excludes, refname))
-		return 0;
-	show_rev(NORMAL, oid, refname);
-	return 0;
-}
-
-static int anti_reference(const char *refname, const struct object_id *oid, int flag, void *cb_data)
-{
-	show_rev(REVERSED, oid, refname);
-	return 0;
-}
-
-static int show_abbrev(const struct object_id *oid, void *cb_data)
-{
-	show_rev(NORMAL, oid, NULL);
-	return 0;
-}
-
-static void show_datestring(const char *flag, const char *datestr)
-{
-	char *buffer;
-
-	/* date handling requires both flags and revs */
-	if ((filter & (DO_FLAGS | DO_REVS)) != (DO_FLAGS | DO_REVS))
-		return;
-	buffer = xstrfmt("%s%"PRItime, flag, approxidate(datestr));
-	show(buffer);
-	free(buffer);
-}
-
-static int show_file(const char *arg, int output_prefix)
-{
-	show_default();
-	if ((filter & (DO_NONFLAGS|DO_NOREV)) == (DO_NONFLAGS|DO_NOREV)) {
-		if (output_prefix) {
-			const char *prefix = startup_info->prefix;
-			char *fname = prefix_filename(prefix, arg);
-			show(fname);
-			free(fname);
-		} else
-			show(arg);
-		return 1;
-	}
-	return 0;
-}
-
-static int try_difference(const char *arg)
-{
-	char *dotdot;
-	struct object_id start_oid;
-	struct object_id end_oid;
-	const char *end;
-	const char *start;
-	int symmetric;
-	static const char head_by_default[] = "HEAD";
-
-	if (!(dotdot = strstr(arg, "..")))
-		return 0;
-	end = dotdot + 2;
-	start = arg;
-	symmetric = (*end == '.');
-
-	*dotdot = 0;
-	end += symmetric;
-
-	if (!*end)
-		end = head_by_default;
-	if (dotdot == arg)
-		start = head_by_default;
-
-	if (start == head_by_default && end == head_by_default &&
-	    !symmetric) {
-		/*
-		 * Just ".."?  That is not a range but the
-		 * pathspec for the parent directory.
-		 */
-		*dotdot = '.';
-		return 0;
-	}
-
-	if (!get_oid_committish(start, &start_oid) && !get_oid_committish(end, &end_oid)) {
-		show_rev(NORMAL, &end_oid, end);
-		show_rev(symmetric ? NORMAL : REVERSED, &start_oid, start);
-		if (symmetric) {
-			struct commit_list *exclude;
-			struct commit *a, *b;
-			a = lookup_commit_reference(the_repository, &start_oid);
-			b = lookup_commit_reference(the_repository, &end_oid);
-			if (!a || !b) {
-				*dotdot = '.';
-				return 0;
-			}
-			exclude = get_merge_bases(a, b);
-			while (exclude) {
-				struct commit *commit = pop_commit(&exclude);
-				show_rev(REVERSED, &commit->object.oid, NULL);
-			}
-		}
-		*dotdot = '.';
-		return 1;
-	}
-	*dotdot = '.';
-	return 0;
-}
-
-static int try_parent_shorthands(const char *arg)
-{
-	char *dotdot;
-	struct object_id oid;
-	struct commit *commit;
-	struct commit_list *parents;
-	int parent_number;
-	int include_rev = 0;
-	int include_parents = 0;
-	int exclude_parent = 0;
-
-	if ((dotdot = strstr(arg, "^!"))) {
-		include_rev = 1;
-		if (dotdot[2])
-			return 0;
-	} else if ((dotdot = strstr(arg, "^@"))) {
-		include_parents = 1;
-		if (dotdot[2])
-			return 0;
-	} else if ((dotdot = strstr(arg, "^-"))) {
-		include_rev = 1;
-		exclude_parent = 1;
-
-		if (dotdot[2]) {
-			char *end;
-			exclude_parent = strtoul(dotdot + 2, &end, 10);
-			if (*end != '\0' || !exclude_parent)
-				return 0;
-		}
-	} else
-		return 0;
-
-	*dotdot = 0;
-	if (get_oid_committish(arg, &oid) ||
-	    !(commit = lookup_commit_reference(the_repository, &oid))) {
-		*dotdot = '^';
-		return 0;
-	}
-
-	if (exclude_parent &&
-	    exclude_parent > commit_list_count(commit->parents)) {
-		*dotdot = '^';
-		return 0;
-	}
-
-	if (include_rev)
-		show_rev(NORMAL, &oid, arg);
-	for (parents = commit->parents, parent_number = 1;
-	     parents;
-	     parents = parents->next, parent_number++) {
-		char *name = NULL;
-
-		if (exclude_parent && parent_number != exclude_parent)
-			continue;
-
-		if (symbolic)
-			name = xstrfmt("%s^%d", arg, parent_number);
-		show_rev(include_parents ? NORMAL : REVERSED,
-			 &parents->item->object.oid, name);
-		free(name);
-	}
-
-	*dotdot = '^';
-	return 1;
-}
-
-static int parseopt_dump(const struct option *o, const char *arg, int unset)
-{
-	struct strbuf *parsed = o->value;
-	if (unset)
-		strbuf_addf(parsed, " --no-%s", o->long_name);
-	else if (o->short_name && (o->long_name == NULL || !stuck_long))
-		strbuf_addf(parsed, " -%c", o->short_name);
-	else
-		strbuf_addf(parsed, " --%s", o->long_name);
-	if (arg) {
-		if (!stuck_long)
-			strbuf_addch(parsed, ' ');
-		else if (o->long_name)
-			strbuf_addch(parsed, '=');
-		sq_quote_buf(parsed, arg);
-	}
-	return 0;
-}
-
-static const char *skipspaces(const char *s)
-{
-	while (isspace(*s))
-		s++;
-	return s;
-}
-
-static char *findspace(const char *s)
-{
-	for (; *s; s++)
-		if (isspace(*s))
-			return (char*)s;
-	return NULL;
-}
-
-static int cmd_parseopt(int argc, const char **argv, const char *prefix)
-{
-	static int keep_dashdash = 0, stop_at_non_option = 0;
-	static char const * const parseopt_usage[] = {
-		N_("git rev-parse --parseopt [<options>] -- [<args>...]"),
-		NULL
-	};
-	static struct option parseopt_opts[] = {
-		OPT_BOOL(0, "keep-dashdash", &keep_dashdash,
-					N_("keep the `--` passed as an arg")),
-		OPT_BOOL(0, "stop-at-non-option", &stop_at_non_option,
-					N_("stop parsing after the "
-					   "first non-option argument")),
-		OPT_BOOL(0, "stuck-long", &stuck_long,
-					N_("output in stuck long form")),
-		OPT_END(),
-	};
-	static const char * const flag_chars = "*=?!";
-
-	struct strbuf sb = STRBUF_INIT, parsed = STRBUF_INIT;
-	const char **usage = NULL;
-	struct option *opts = NULL;
-	int onb = 0, osz = 0, unb = 0, usz = 0;
-
-	strbuf_addstr(&parsed, "set --");
-	argc = parse_options(argc, argv, prefix, parseopt_opts, parseopt_usage,
-	                     PARSE_OPT_KEEP_DASHDASH);
-	if (argc < 1 || strcmp(argv[0], "--"))
-		usage_with_options(parseopt_usage, parseopt_opts);
-
-	/* get the usage up to the first line with a -- on it */
-	for (;;) {
-		if (strbuf_getline(&sb, stdin) == EOF)
-			die("premature end of input");
-		ALLOC_GROW(usage, unb + 1, usz);
-		if (!strcmp("--", sb.buf)) {
-			if (unb < 1)
-				die("no usage string given before the `--' separator");
-			usage[unb] = NULL;
-			break;
-		}
-		usage[unb++] = strbuf_detach(&sb, NULL);
-	}
-
-	/* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */
-	while (strbuf_getline(&sb, stdin) != EOF) {
-		const char *s;
-		char *help;
-		struct option *o;
-
-		if (!sb.len)
-			continue;
-
-		ALLOC_GROW(opts, onb + 1, osz);
-		memset(opts + onb, 0, sizeof(opts[onb]));
-
-		o = &opts[onb++];
-		help = findspace(sb.buf);
-		if (!help || sb.buf == help) {
-			o->type = OPTION_GROUP;
-			o->help = xstrdup(skipspaces(sb.buf));
-			continue;
-		}
-
-		*help = '\0';
-
-		o->type = OPTION_CALLBACK;
-		o->help = xstrdup(skipspaces(help+1));
-		o->value = &parsed;
-		o->flags = PARSE_OPT_NOARG;
-		o->callback = &parseopt_dump;
-
-		/* name(s) */
-		s = strpbrk(sb.buf, flag_chars);
-		if (s == NULL)
-			s = help;
-
-		if (s - sb.buf == 1) /* short option only */
-			o->short_name = *sb.buf;
-		else if (sb.buf[1] != ',') /* long option only */
-			o->long_name = xmemdupz(sb.buf, s - sb.buf);
-		else {
-			o->short_name = *sb.buf;
-			o->long_name = xmemdupz(sb.buf + 2, s - sb.buf - 2);
-		}
-
-		/* flags */
-		while (s < help) {
-			switch (*s++) {
-			case '=':
-				o->flags &= ~PARSE_OPT_NOARG;
-				continue;
-			case '?':
-				o->flags &= ~PARSE_OPT_NOARG;
-				o->flags |= PARSE_OPT_OPTARG;
-				continue;
-			case '!':
-				o->flags |= PARSE_OPT_NONEG;
-				continue;
-			case '*':
-				o->flags |= PARSE_OPT_HIDDEN;
-				continue;
-			}
-			s--;
-			break;
-		}
-
-		if (s < help)
-			o->argh = xmemdupz(s, help - s);
-	}
-	strbuf_release(&sb);
-
-	/* put an OPT_END() */
-	ALLOC_GROW(opts, onb + 1, osz);
-	memset(opts + onb, 0, sizeof(opts[onb]));
-	argc = parse_options(argc, argv, prefix, opts, usage,
-			(keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0) |
-			(stop_at_non_option ? PARSE_OPT_STOP_AT_NON_OPTION : 0) |
-			PARSE_OPT_SHELL_EVAL);
-
-	strbuf_addstr(&parsed, " --");
-	sq_quote_argv(&parsed, argv);
-	puts(parsed.buf);
-	return 0;
-}
-
-static int cmd_sq_quote(int argc, const char **argv)
-{
-	struct strbuf buf = STRBUF_INIT;
-
-	if (argc)
-		sq_quote_argv(&buf, argv);
-	printf("%s\n", buf.buf);
-	strbuf_release(&buf);
-
-	return 0;
-}
-
-static void die_no_single_rev(int quiet)
-{
-	if (quiet)
-		exit(1);
-	else
-		die("Needed a single revision");
-}
-
-static const char builtin_rev_parse_usage[] =
-N_("git rev-parse --parseopt [<options>] -- [<args>...]\n"
-   "   or: git rev-parse --sq-quote [<arg>...]\n"
-   "   or: git rev-parse [<options>] [<arg>...]\n"
-   "\n"
-   "Run \"git rev-parse --parseopt -h\" for more information on the first usage.");
-
-/*
- * Parse "opt" or "opt=<value>", setting value respectively to either
- * NULL or the string after "=".
- */
-static int opt_with_value(const char *arg, const char *opt, const char **value)
-{
-	if (skip_prefix(arg, opt, &arg)) {
-		if (!*arg) {
-			*value = NULL;
-			return 1;
-		}
-		if (*arg++ == '=') {
-			*value = arg;
-			return 1;
-		}
-	}
-	return 0;
-}
-
-static void handle_ref_opt(const char *pattern, const char *prefix)
-{
-	if (pattern)
-		for_each_glob_ref_in(show_reference, pattern, prefix, NULL);
-	else
-		for_each_ref_in(prefix, show_reference, NULL);
-	clear_ref_exclusion(&ref_excludes);
-}
-
-int cmd_rev_parse(int argc, const char **argv, const char *prefix)
-{
-	int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0;
-	int did_repo_setup = 0;
-	int has_dashdash = 0;
-	int output_prefix = 0;
-	struct object_id oid;
-	unsigned int flags = 0;
-	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);
-
-	if (argc > 1 && !strcmp("--sq-quote", argv[1]))
-		return cmd_sq_quote(argc - 2, argv + 2);
-
-	if (argc > 1 && !strcmp("-h", argv[1]))
-		usage(builtin_rev_parse_usage);
-
-	for (i = 1; i < argc; i++) {
-		if (!strcmp(argv[i], "--")) {
-			has_dashdash = 1;
-			break;
-		}
-	}
-
-	/* No options; just report on whether we're in a git repo or not. */
-	if (argc == 1) {
-		setup_git_directory();
-		git_config(git_default_config, NULL);
-		return 0;
-	}
-
-	for (i = 1; i < argc; i++) {
-		const char *arg = argv[i];
-
-		if (!strcmp(arg, "--local-env-vars")) {
-			int i;
-			for (i = 0; local_repo_env[i]; i++)
-				printf("%s\n", local_repo_env[i]);
-			continue;
-		}
-		if (!strcmp(arg, "--resolve-git-dir")) {
-			const char *gitdir = argv[++i];
-			if (!gitdir)
-				die("--resolve-git-dir requires an argument");
-			gitdir = resolve_gitdir(gitdir);
-			if (!gitdir)
-				die("not a gitdir '%s'", argv[i]);
-			puts(gitdir);
-			continue;
-		}
-
-		/* The rest of the options require a git repository. */
-		if (!did_repo_setup) {
-			prefix = setup_git_directory();
-			git_config(git_default_config, NULL);
-			did_repo_setup = 1;
-		}
-
-		if (!strcmp(arg, "--git-path")) {
-			if (!argv[i + 1])
-				die("--git-path requires an argument");
-			strbuf_reset(&buf);
-			puts(relative_path(git_path("%s", argv[i + 1]),
-					   prefix, &buf));
-			i++;
-			continue;
-		}
-		if (as_is) {
-			if (show_file(arg, output_prefix) && as_is < 2)
-				verify_filename(prefix, arg, 0);
-			continue;
-		}
-		if (!strcmp(arg,"-n")) {
-			if (++i >= argc)
-				die("-n requires an argument");
-			if ((filter & DO_FLAGS) && (filter & DO_REVS)) {
-				show(arg);
-				show(argv[i]);
-			}
-			continue;
-		}
-		if (starts_with(arg, "-n")) {
-			if ((filter & DO_FLAGS) && (filter & DO_REVS))
-				show(arg);
-			continue;
-		}
-
-		if (*arg == '-') {
-			if (!strcmp(arg, "--")) {
-				as_is = 2;
-				/* Pass on the "--" if we show anything but files.. */
-				if (filter & (DO_FLAGS | DO_REVS))
-					show_file(arg, 0);
-				continue;
-			}
-			if (!strcmp(arg, "--default")) {
-				def = argv[++i];
-				if (!def)
-					die("--default requires an argument");
-				continue;
-			}
-			if (!strcmp(arg, "--prefix")) {
-				prefix = argv[++i];
-				if (!prefix)
-					die("--prefix requires an argument");
-				startup_info->prefix = prefix;
-				output_prefix = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--revs-only")) {
-				filter &= ~DO_NOREV;
-				continue;
-			}
-			if (!strcmp(arg, "--no-revs")) {
-				filter &= ~DO_REVS;
-				continue;
-			}
-			if (!strcmp(arg, "--flags")) {
-				filter &= ~DO_NONFLAGS;
-				continue;
-			}
-			if (!strcmp(arg, "--no-flags")) {
-				filter &= ~DO_FLAGS;
-				continue;
-			}
-			if (!strcmp(arg, "--verify")) {
-				filter &= ~(DO_FLAGS|DO_NOREV);
-				verify = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--quiet") || !strcmp(arg, "-q")) {
-				quiet = 1;
-				flags |= GET_OID_QUIETLY;
-				continue;
-			}
-			if (opt_with_value(arg, "--short", &arg)) {
-				filter &= ~(DO_FLAGS|DO_NOREV);
-				verify = 1;
-				abbrev = DEFAULT_ABBREV;
-				if (!arg)
-					continue;
-				abbrev = strtoul(arg, NULL, 10);
-				if (abbrev < MINIMUM_ABBREV)
-					abbrev = MINIMUM_ABBREV;
-				else if (hexsz <= abbrev)
-					abbrev = hexsz;
-				continue;
-			}
-			if (!strcmp(arg, "--sq")) {
-				output_sq = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--not")) {
-				show_type ^= REVERSED;
-				continue;
-			}
-			if (!strcmp(arg, "--symbolic")) {
-				symbolic = SHOW_SYMBOLIC_ASIS;
-				continue;
-			}
-			if (!strcmp(arg, "--symbolic-full-name")) {
-				symbolic = SHOW_SYMBOLIC_FULL;
-				continue;
-			}
-			if (opt_with_value(arg, "--abbrev-ref", &arg)) {
-				abbrev_ref = 1;
-				abbrev_ref_strict = warn_ambiguous_refs;
-				if (arg) {
-					if (!strcmp(arg, "strict"))
-						abbrev_ref_strict = 1;
-					else if (!strcmp(arg, "loose"))
-						abbrev_ref_strict = 0;
-					else
-						die("unknown mode for --abbrev-ref: %s",
-						    arg);
-				}
-				continue;
-			}
-			if (!strcmp(arg, "--all")) {
-				for_each_ref(show_reference, NULL);
-				clear_ref_exclusion(&ref_excludes);
-				continue;
-			}
-			if (skip_prefix(arg, "--disambiguate=", &arg)) {
-				for_each_abbrev(arg, show_abbrev, NULL);
-				continue;
-			}
-			if (!strcmp(arg, "--bisect")) {
-				for_each_fullref_in("refs/bisect/bad", show_reference, NULL, 0);
-				for_each_fullref_in("refs/bisect/good", anti_reference, NULL, 0);
-				continue;
-			}
-			if (opt_with_value(arg, "--branches", &arg)) {
-				handle_ref_opt(arg, "refs/heads/");
-				continue;
-			}
-			if (opt_with_value(arg, "--tags", &arg)) {
-				handle_ref_opt(arg, "refs/tags/");
-				continue;
-			}
-			if (skip_prefix(arg, "--glob=", &arg)) {
-				handle_ref_opt(arg, NULL);
-				continue;
-			}
-			if (opt_with_value(arg, "--remotes", &arg)) {
-				handle_ref_opt(arg, "refs/remotes/");
-				continue;
-			}
-			if (skip_prefix(arg, "--exclude=", &arg)) {
-				add_ref_exclusion(&ref_excludes, arg);
-				continue;
-			}
-			if (!strcmp(arg, "--show-toplevel")) {
-				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")) {
-				struct strbuf superproject = STRBUF_INIT;
-				if (get_superproject_working_tree(&superproject))
-					puts(superproject.buf);
-				strbuf_release(&superproject);
-				continue;
-			}
-			if (!strcmp(arg, "--show-prefix")) {
-				if (prefix)
-					puts(prefix);
-				else
-					putchar('\n');
-				continue;
-			}
-			if (!strcmp(arg, "--show-cdup")) {
-				const char *pfx = prefix;
-				if (!is_inside_work_tree()) {
-					const char *work_tree =
-						get_git_work_tree();
-					if (work_tree)
-						printf("%s\n", work_tree);
-					continue;
-				}
-				while (pfx) {
-					pfx = strchr(pfx, '/');
-					if (pfx) {
-						pfx++;
-						printf("../");
-					}
-				}
-				putchar('\n');
-				continue;
-			}
-			if (!strcmp(arg, "--git-dir") ||
-			    !strcmp(arg, "--absolute-git-dir")) {
-				const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
-				char *cwd;
-				int len;
-				if (arg[2] == 'g') {	/* --git-dir */
-					if (gitdir) {
-						puts(gitdir);
-						continue;
-					}
-					if (!prefix) {
-						puts(".git");
-						continue;
-					}
-				} else {		/* --absolute-git-dir */
-					if (!gitdir && !prefix)
-						gitdir = ".git";
-					if (gitdir) {
-						struct strbuf realpath = STRBUF_INIT;
-						strbuf_realpath(&realpath, gitdir, 1);
-						puts(realpath.buf);
-						strbuf_release(&realpath);
-						continue;
-					}
-				}
-				cwd = xgetcwd();
-				len = strlen(cwd);
-				printf("%s%s.git\n", cwd, len && cwd[len-1] != '/' ? "/" : "");
-				free(cwd);
-				continue;
-			}
-			if (!strcmp(arg, "--git-common-dir")) {
-				strbuf_reset(&buf);
-				puts(relative_path(get_git_common_dir(),
-						   prefix, &buf));
-				continue;
-			}
-			if (!strcmp(arg, "--is-inside-git-dir")) {
-				printf("%s\n", is_inside_git_dir() ? "true"
-						: "false");
-				continue;
-			}
-			if (!strcmp(arg, "--is-inside-work-tree")) {
-				printf("%s\n", is_inside_work_tree() ? "true"
-						: "false");
-				continue;
-			}
-			if (!strcmp(arg, "--is-bare-repository")) {
-				printf("%s\n", is_bare_repository() ? "true"
-						: "false");
-				continue;
-			}
-			if (!strcmp(arg, "--is-shallow-repository")) {
-				printf("%s\n",
-						is_repository_shallow(the_repository) ? "true"
-						: "false");
-				continue;
-			}
-			if (!strcmp(arg, "--shared-index-path")) {
-				if (read_cache() < 0)
-					die(_("Could not read the index"));
-				if (the_index.split_index) {
-					const struct object_id *oid = &the_index.split_index->base_oid;
-					const char *path = git_path("sharedindex.%s", oid_to_hex(oid));
-					strbuf_reset(&buf);
-					puts(relative_path(path, prefix, &buf));
-				}
-				continue;
-			}
-			if (skip_prefix(arg, "--since=", &arg)) {
-				show_datestring("--max-age=", arg);
-				continue;
-			}
-			if (skip_prefix(arg, "--after=", &arg)) {
-				show_datestring("--max-age=", arg);
-				continue;
-			}
-			if (skip_prefix(arg, "--before=", &arg)) {
-				show_datestring("--min-age=", arg);
-				continue;
-			}
-			if (skip_prefix(arg, "--until=", &arg)) {
-				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;
-		}
-
-		/* Not a flag argument */
-		if (try_difference(arg))
-			continue;
-		if (try_parent_shorthands(arg))
-			continue;
-		name = arg;
-		type = NORMAL;
-		if (*arg == '^') {
-			name++;
-			type = REVERSED;
-		}
-		if (!get_oid_with_context(the_repository, name,
-					  flags, &oid, &unused)) {
-			if (verify)
-				revs_count++;
-			else
-				show_rev(type, &oid, name);
-			continue;
-		}
-		if (verify)
-			die_no_single_rev(quiet);
-		if (has_dashdash)
-			die("bad revision '%s'", arg);
-		as_is = 1;
-		if (!show_file(arg, output_prefix))
-			continue;
-		verify_filename(prefix, arg, 1);
-	}
-	strbuf_release(&buf);
-	if (verify) {
-		if (revs_count == 1) {
-			show_rev(type, &oid, name);
-			return 0;
-		} else if (revs_count == 0 && show_default())
-			return 0;
-		die_no_single_rev(quiet);
-	} else
-		show_default();
-	return 0;
-}
diff --git a/third_party/git/builtin/revert.c b/third_party/git/builtin/revert.c
deleted file mode 100644
index f61cc5d82cf2..000000000000
--- a/third_party/git/builtin/revert.c
+++ /dev/null
@@ -1,247 +0,0 @@
-#include "cache.h"
-#include "config.h"
-#include "builtin.h"
-#include "parse-options.h"
-#include "diff.h"
-#include "revision.h"
-#include "rerere.h"
-#include "dir.h"
-#include "sequencer.h"
-#include "branch.h"
-
-/*
- * This implements the builtins revert and cherry-pick.
- *
- * Copyright (c) 2007 Johannes E. Schindelin
- *
- * Based on git-revert.sh, which is
- *
- * Copyright (c) 2005 Linus Torvalds
- * Copyright (c) 2005 Junio C Hamano
- */
-
-static const char * const revert_usage[] = {
-	N_("git revert [<options>] <commit-ish>..."),
-	N_("git revert <subcommand>"),
-	NULL
-};
-
-static const char * const cherry_pick_usage[] = {
-	N_("git cherry-pick [<options>] <commit-ish>..."),
-	N_("git cherry-pick <subcommand>"),
-	NULL
-};
-
-static const char *action_name(const struct replay_opts *opts)
-{
-	return opts->action == REPLAY_REVERT ? "revert" : "cherry-pick";
-}
-
-static const char * const *revert_or_cherry_pick_usage(struct replay_opts *opts)
-{
-	return opts->action == REPLAY_REVERT ? revert_usage : cherry_pick_usage;
-}
-
-static int option_parse_x(const struct option *opt,
-			  const char *arg, int unset)
-{
-	struct replay_opts **opts_ptr = opt->value;
-	struct replay_opts *opts = *opts_ptr;
-
-	if (unset)
-		return 0;
-
-	ALLOC_GROW(opts->xopts, opts->xopts_nr + 1, opts->xopts_alloc);
-	opts->xopts[opts->xopts_nr++] = xstrdup(arg);
-	return 0;
-}
-
-static int option_parse_m(const struct option *opt,
-			  const char *arg, int unset)
-{
-	struct replay_opts *replay = opt->value;
-	char *end;
-
-	if (unset) {
-		replay->mainline = 0;
-		return 0;
-	}
-
-	replay->mainline = strtol(arg, &end, 10);
-	if (*end || replay->mainline <= 0)
-		return error(_("option `%s' expects a number greater than zero"),
-			     opt->long_name);
-
-	return 0;
-}
-
-LAST_ARG_MUST_BE_NULL
-static void verify_opt_compatible(const char *me, const char *base_opt, ...)
-{
-	const char *this_opt;
-	va_list ap;
-
-	va_start(ap, base_opt);
-	while ((this_opt = va_arg(ap, const char *))) {
-		if (va_arg(ap, int))
-			break;
-	}
-	va_end(ap);
-
-	if (this_opt)
-		die(_("%s: %s cannot be used with %s"), me, this_opt, base_opt);
-}
-
-static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
-{
-	const char * const * usage_str = revert_or_cherry_pick_usage(opts);
-	const char *me = action_name(opts);
-	const char *cleanup_arg = NULL;
-	int cmd = 0;
-	struct option base_options[] = {
-		OPT_CMDMODE(0, "quit", &cmd, N_("end revert or cherry-pick sequence"), 'q'),
-		OPT_CMDMODE(0, "continue", &cmd, N_("resume revert or cherry-pick sequence"), 'c'),
-		OPT_CMDMODE(0, "abort", &cmd, N_("cancel revert or cherry-pick sequence"), 'a'),
-		OPT_CMDMODE(0, "skip", &cmd, N_("skip current commit and continue"), 's'),
-		OPT_CLEANUP(&cleanup_arg),
-		OPT_BOOL('n', "no-commit", &opts->no_commit, N_("don't automatically commit")),
-		OPT_BOOL('e', "edit", &opts->edit, N_("edit the commit message")),
-		OPT_NOOP_NOARG('r', NULL),
-		OPT_BOOL('s', "signoff", &opts->signoff, N_("add Signed-off-by:")),
-		OPT_CALLBACK('m', "mainline", opts, N_("parent-number"),
-			     N_("select mainline parent"), option_parse_m),
-		OPT_RERERE_AUTOUPDATE(&opts->allow_rerere_auto),
-		OPT_STRING(0, "strategy", &opts->strategy, N_("strategy"), N_("merge strategy")),
-		OPT_CALLBACK('X', "strategy-option", &opts, N_("option"),
-			N_("option for merge strategy"), option_parse_x),
-		{ OPTION_STRING, 'S', "gpg-sign", &opts->gpg_sign, N_("key-id"),
-		  N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
-		OPT_END()
-	};
-	struct option *options = base_options;
-
-	if (opts->action == REPLAY_PICK) {
-		struct option cp_extra[] = {
-			OPT_BOOL('x', NULL, &opts->record_origin, N_("append commit name")),
-			OPT_BOOL(0, "ff", &opts->allow_ff, N_("allow fast-forward")),
-			OPT_BOOL(0, "allow-empty", &opts->allow_empty, N_("preserve initially empty commits")),
-			OPT_BOOL(0, "allow-empty-message", &opts->allow_empty_message, N_("allow commits with empty messages")),
-			OPT_BOOL(0, "keep-redundant-commits", &opts->keep_redundant_commits, N_("keep redundant, empty commits")),
-			OPT_END(),
-		};
-		options = parse_options_concat(options, cp_extra);
-	}
-
-	argc = parse_options(argc, argv, NULL, options, usage_str,
-			PARSE_OPT_KEEP_ARGV0 |
-			PARSE_OPT_KEEP_UNKNOWN);
-
-	/* implies allow_empty */
-	if (opts->keep_redundant_commits)
-		opts->allow_empty = 1;
-
-	if (cleanup_arg) {
-		opts->default_msg_cleanup = get_cleanup_mode(cleanup_arg, 1);
-		opts->explicit_cleanup = 1;
-	}
-
-	/* Check for incompatible command line arguments */
-	if (cmd) {
-		char *this_operation;
-		if (cmd == 'q')
-			this_operation = "--quit";
-		else if (cmd == 'c')
-			this_operation = "--continue";
-		else if (cmd == 's')
-			this_operation = "--skip";
-		else {
-			assert(cmd == 'a');
-			this_operation = "--abort";
-		}
-
-		verify_opt_compatible(me, this_operation,
-				"--no-commit", opts->no_commit,
-				"--signoff", opts->signoff,
-				"--mainline", opts->mainline,
-				"--strategy", opts->strategy ? 1 : 0,
-				"--strategy-option", opts->xopts ? 1 : 0,
-				"-x", opts->record_origin,
-				"--ff", opts->allow_ff,
-				"--rerere-autoupdate", opts->allow_rerere_auto == RERERE_AUTOUPDATE,
-				"--no-rerere-autoupdate", opts->allow_rerere_auto == RERERE_NOAUTOUPDATE,
-				NULL);
-	}
-
-	if (opts->allow_ff)
-		verify_opt_compatible(me, "--ff",
-				"--signoff", opts->signoff,
-				"--no-commit", opts->no_commit,
-				"-x", opts->record_origin,
-				"--edit", opts->edit,
-				NULL);
-
-	if (cmd) {
-		opts->revs = NULL;
-	} else {
-		struct setup_revision_opt s_r_opt;
-		opts->revs = xmalloc(sizeof(*opts->revs));
-		repo_init_revisions(the_repository, opts->revs, NULL);
-		opts->revs->no_walk = REVISION_WALK_NO_WALK_UNSORTED;
-		if (argc < 2)
-			usage_with_options(usage_str, options);
-		if (!strcmp(argv[1], "-"))
-			argv[1] = "@{-1}";
-		memset(&s_r_opt, 0, sizeof(s_r_opt));
-		s_r_opt.assume_dashdash = 1;
-		argc = setup_revisions(argc, argv, opts->revs, &s_r_opt);
-	}
-
-	if (argc > 1)
-		usage_with_options(usage_str, options);
-
-	/* These option values will be free()d */
-	opts->gpg_sign = xstrdup_or_null(opts->gpg_sign);
-	opts->strategy = xstrdup_or_null(opts->strategy);
-
-	if (cmd == 'q') {
-		int ret = sequencer_remove_state(opts);
-		if (!ret)
-			remove_branch_state(the_repository, 0);
-		return ret;
-	}
-	if (cmd == 'c')
-		return sequencer_continue(the_repository, opts);
-	if (cmd == 'a')
-		return sequencer_rollback(the_repository, opts);
-	if (cmd == 's')
-		return sequencer_skip(the_repository, opts);
-	return sequencer_pick_revisions(the_repository, opts);
-}
-
-int cmd_revert(int argc, const char **argv, const char *prefix)
-{
-	struct replay_opts opts = REPLAY_OPTS_INIT;
-	int res;
-
-	if (isatty(0))
-		opts.edit = 1;
-	opts.action = REPLAY_REVERT;
-	sequencer_init_config(&opts);
-	res = run_sequencer(argc, argv, &opts);
-	if (res < 0)
-		die(_("revert failed"));
-	return res;
-}
-
-int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
-{
-	struct replay_opts opts = REPLAY_OPTS_INIT;
-	int res;
-
-	opts.action = REPLAY_PICK;
-	sequencer_init_config(&opts);
-	res = run_sequencer(argc, argv, &opts);
-	if (res < 0)
-		die(_("cherry-pick failed"));
-	return res;
-}
diff --git a/third_party/git/builtin/rm.c b/third_party/git/builtin/rm.c
deleted file mode 100644
index 4858631e0f02..000000000000
--- a/third_party/git/builtin/rm.c
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- * "git rm" builtin command
- *
- * Copyright (C) Linus Torvalds 2006
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "config.h"
-#include "lockfile.h"
-#include "dir.h"
-#include "cache-tree.h"
-#include "tree-walk.h"
-#include "parse-options.h"
-#include "string-list.h"
-#include "submodule.h"
-#include "pathspec.h"
-
-static const char * const builtin_rm_usage[] = {
-	N_("git rm [<options>] [--] <file>..."),
-	NULL
-};
-
-static struct {
-	int nr, alloc;
-	struct {
-		const char *name;
-		char is_submodule;
-	} *entry;
-} list;
-
-static int get_ours_cache_pos(const char *path, int pos)
-{
-	int i = -pos - 1;
-
-	while ((i < active_nr) && !strcmp(active_cache[i]->name, path)) {
-		if (ce_stage(active_cache[i]) == 2)
-			return i;
-		i++;
-	}
-	return -1;
-}
-
-static void print_error_files(struct string_list *files_list,
-			      const char *main_msg,
-			      const char *hints_msg,
-			      int *errs)
-{
-	if (files_list->nr) {
-		int i;
-		struct strbuf err_msg = STRBUF_INIT;
-
-		strbuf_addstr(&err_msg, main_msg);
-		for (i = 0; i < files_list->nr; i++)
-			strbuf_addf(&err_msg,
-				    "\n    %s",
-				    files_list->items[i].string);
-		if (advice_rm_hints)
-			strbuf_addstr(&err_msg, hints_msg);
-		*errs = error("%s", err_msg.buf);
-		strbuf_release(&err_msg);
-	}
-}
-
-static void submodules_absorb_gitdir_if_needed(void)
-{
-	int i;
-	for (i = 0; i < list.nr; i++) {
-		const char *name = list.entry[i].name;
-		int pos;
-		const struct cache_entry *ce;
-
-		pos = cache_name_pos(name, strlen(name));
-		if (pos < 0) {
-			pos = get_ours_cache_pos(name, pos);
-			if (pos < 0)
-				continue;
-		}
-		ce = active_cache[pos];
-
-		if (!S_ISGITLINK(ce->ce_mode) ||
-		    !file_exists(ce->name) ||
-		    is_empty_dir(name))
-			continue;
-
-		if (!submodule_uses_gitfile(name))
-			absorb_git_dir_into_superproject(name,
-				ABSORB_GITDIR_RECURSE_SUBMODULES);
-	}
-}
-
-static int check_local_mod(struct object_id *head, int index_only)
-{
-	/*
-	 * Items in list are already sorted in the cache order,
-	 * so we could do this a lot more efficiently by using
-	 * tree_desc based traversal if we wanted to, but I am
-	 * lazy, and who cares if removal of files is a tad
-	 * slower than the theoretical maximum speed?
-	 */
-	int i, no_head;
-	int errs = 0;
-	struct string_list files_staged = STRING_LIST_INIT_NODUP;
-	struct string_list files_cached = STRING_LIST_INIT_NODUP;
-	struct string_list files_local = STRING_LIST_INIT_NODUP;
-
-	no_head = is_null_oid(head);
-	for (i = 0; i < list.nr; i++) {
-		struct stat st;
-		int pos;
-		const struct cache_entry *ce;
-		const char *name = list.entry[i].name;
-		struct object_id oid;
-		unsigned short mode;
-		int local_changes = 0;
-		int staged_changes = 0;
-
-		pos = cache_name_pos(name, strlen(name));
-		if (pos < 0) {
-			/*
-			 * Skip unmerged entries except for populated submodules
-			 * that could lose history when removed.
-			 */
-			pos = get_ours_cache_pos(name, pos);
-			if (pos < 0)
-				continue;
-
-			if (!S_ISGITLINK(active_cache[pos]->ce_mode) ||
-			    is_empty_dir(name))
-				continue;
-		}
-		ce = active_cache[pos];
-
-		if (lstat(ce->name, &st) < 0) {
-			if (!is_missing_file_error(errno))
-				warning_errno(_("failed to stat '%s'"), ce->name);
-			/* It already vanished from the working tree */
-			continue;
-		}
-		else if (S_ISDIR(st.st_mode)) {
-			/* if a file was removed and it is now a
-			 * directory, that is the same as ENOENT as
-			 * far as git is concerned; we do not track
-			 * directories unless they are submodules.
-			 */
-			if (!S_ISGITLINK(ce->ce_mode))
-				continue;
-		}
-
-		/*
-		 * "rm" of a path that has changes need to be treated
-		 * carefully not to allow losing local changes
-		 * accidentally.  A local change could be (1) file in
-		 * work tree is different since the index; and/or (2)
-		 * the user staged a content that is different from
-		 * the current commit in the index.
-		 *
-		 * In such a case, you would need to --force the
-		 * removal.  However, "rm --cached" (remove only from
-		 * the index) is safe if the index matches the file in
-		 * the work tree or the HEAD commit, as it means that
-		 * the content being removed is available elsewhere.
-		 */
-
-		/*
-		 * Is the index different from the file in the work tree?
-		 * If it's a submodule, is its work tree modified?
-		 */
-		if (ce_match_stat(ce, &st, 0) ||
-		    (S_ISGITLINK(ce->ce_mode) &&
-		     bad_to_remove_submodule(ce->name,
-				SUBMODULE_REMOVAL_DIE_ON_ERROR |
-				SUBMODULE_REMOVAL_IGNORE_IGNORED_UNTRACKED)))
-			local_changes = 1;
-
-		/*
-		 * Is the index different from the HEAD commit?  By
-		 * definition, before the very initial commit,
-		 * anything staged in the index is treated by the same
-		 * way as changed from the HEAD.
-		 */
-		if (no_head
-		     || get_tree_entry(the_repository, head, name, &oid, &mode)
-		     || ce->ce_mode != create_ce_mode(mode)
-		     || !oideq(&ce->oid, &oid))
-			staged_changes = 1;
-
-		/*
-		 * If the index does not match the file in the work
-		 * tree and if it does not match the HEAD commit
-		 * either, (1) "git rm" without --cached definitely
-		 * will lose information; (2) "git rm --cached" will
-		 * lose information unless it is about removing an
-		 * "intent to add" entry.
-		 */
-		if (local_changes && staged_changes) {
-			if (!index_only || !ce_intent_to_add(ce))
-				string_list_append(&files_staged, name);
-		}
-		else if (!index_only) {
-			if (staged_changes)
-				string_list_append(&files_cached, name);
-			if (local_changes)
-				string_list_append(&files_local, name);
-		}
-	}
-	print_error_files(&files_staged,
-			  Q_("the following file has staged content different "
-			     "from both the\nfile and the HEAD:",
-			     "the following files have staged content different"
-			     " from both the\nfile and the HEAD:",
-			     files_staged.nr),
-			  _("\n(use -f to force removal)"),
-			  &errs);
-	string_list_clear(&files_staged, 0);
-	print_error_files(&files_cached,
-			  Q_("the following file has changes "
-			     "staged in the index:",
-			     "the following files have changes "
-			     "staged in the index:", files_cached.nr),
-			  _("\n(use --cached to keep the file,"
-			    " or -f to force removal)"),
-			  &errs);
-	string_list_clear(&files_cached, 0);
-
-	print_error_files(&files_local,
-			  Q_("the following file has local modifications:",
-			     "the following files have local modifications:",
-			     files_local.nr),
-			  _("\n(use --cached to keep the file,"
-			    " or -f to force removal)"),
-			  &errs);
-	string_list_clear(&files_local, 0);
-
-	return errs;
-}
-
-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 struct option builtin_rm_options[] = {
-	OPT__DRY_RUN(&show_only, N_("dry run")),
-	OPT__QUIET(&quiet, N_("do not list removed files")),
-	OPT_BOOL( 0 , "cached",         &index_only, N_("only remove from the index")),
-	OPT__FORCE(&force, N_("override the up-to-date check"), PARSE_OPT_NOCOMPLETE),
-	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(),
-};
-
-int cmd_rm(int argc, const char **argv, const char *prefix)
-{
-	struct lock_file lock_file = LOCK_INIT;
-	int i;
-	struct pathspec pathspec;
-	char *seen;
-
-	git_config(git_default_config, NULL);
-
-	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 (!index_only)
-		setup_work_tree();
-
-	hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
-
-	if (read_cache() < 0)
-		die(_("index file corrupt"));
-
-	refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, &pathspec, NULL, NULL);
-
-	seen = xcalloc(pathspec.nr, 1);
-
-	for (i = 0; i < active_nr; i++) {
-		const struct cache_entry *ce = active_cache[i];
-		if (!ce_path_match(&the_index, ce, &pathspec, seen))
-			continue;
-		ALLOC_GROW(list.entry, list.nr + 1, list.alloc);
-		list.entry[list.nr].name = xstrdup(ce->name);
-		list.entry[list.nr].is_submodule = S_ISGITLINK(ce->ce_mode);
-		if (list.entry[list.nr++].is_submodule &&
-		    !is_staging_gitmodules_ok(&the_index))
-			die(_("please stage your changes to .gitmodules or stash them to proceed"));
-	}
-
-	if (pathspec.nr) {
-		const char *original;
-		int seen_any = 0;
-		for (i = 0; i < pathspec.nr; i++) {
-			original = pathspec.items[i].original;
-			if (!seen[i]) {
-				if (!ignore_unmatch) {
-					die(_("pathspec '%s' did not match any files"),
-					    original);
-				}
-			}
-			else {
-				seen_any = 1;
-			}
-			if (!recursive && seen[i] == MATCHED_RECURSIVELY)
-				die(_("not removing '%s' recursively without -r"),
-				    *original ? original : ".");
-		}
-
-		if (!seen_any)
-			exit(0);
-	}
-
-	if (!index_only)
-		submodules_absorb_gitdir_if_needed();
-
-	/*
-	 * If not forced, the file, the index and the HEAD (if exists)
-	 * must match; but the file can already been removed, since
-	 * this sequence is a natural "novice" way:
-	 *
-	 *	rm F; git rm F
-	 *
-	 * Further, if HEAD commit exists, "diff-index --cached" must
-	 * report no changes unless forced.
-	 */
-	if (!force) {
-		struct object_id oid;
-		if (get_oid("HEAD", &oid))
-			oidclr(&oid);
-		if (check_local_mod(&oid, index_only))
-			exit(1);
-	}
-
-	/*
-	 * First remove the names from the index: we won't commit
-	 * the index unless all of them succeed.
-	 */
-	for (i = 0; i < list.nr; i++) {
-		const char *path = list.entry[i].name;
-		if (!quiet)
-			printf("rm '%s'\n", path);
-
-		if (remove_file_from_cache(path))
-			die(_("git rm: unable to remove %s"), path);
-	}
-
-	if (show_only)
-		return 0;
-
-	/*
-	 * Then, unless we used "--cached", remove the filenames from
-	 * the workspace. If we fail to remove the first one, we
-	 * abort the "git rm" (but once we've successfully removed
-	 * any file at all, we'll go ahead and commit to it all:
-	 * by then we've already committed ourselves and can't fail
-	 * in the middle)
-	 */
-	if (!index_only) {
-		int removed = 0, gitmodules_modified = 0;
-		struct strbuf buf = STRBUF_INIT;
-		for (i = 0; i < list.nr; i++) {
-			const char *path = list.entry[i].name;
-			if (list.entry[i].is_submodule) {
-				strbuf_reset(&buf);
-				strbuf_addstr(&buf, path);
-				if (remove_dir_recursively(&buf, 0))
-					die(_("could not remove '%s'"), path);
-
-				removed = 1;
-				if (!remove_path_from_gitmodules(path))
-					gitmodules_modified = 1;
-				continue;
-			}
-			if (!remove_path(path)) {
-				removed = 1;
-				continue;
-			}
-			if (!removed)
-				die_errno("git rm: '%s'", path);
-		}
-		strbuf_release(&buf);
-		if (gitmodules_modified)
-			stage_updated_gitmodules(&the_index);
-	}
-
-	if (write_locked_index(&the_index, &lock_file,
-			       COMMIT_LOCK | SKIP_IF_UNCHANGED))
-		die(_("Unable to write new index file"));
-
-	return 0;
-}
diff --git a/third_party/git/builtin/send-pack.c b/third_party/git/builtin/send-pack.c
deleted file mode 100644
index 7af148d7332f..000000000000
--- a/third_party/git/builtin/send-pack.c
+++ /dev/null
@@ -1,328 +0,0 @@
-#include "builtin.h"
-#include "config.h"
-#include "commit.h"
-#include "refs.h"
-#include "pkt-line.h"
-#include "sideband.h"
-#include "run-command.h"
-#include "remote.h"
-#include "connect.h"
-#include "send-pack.h"
-#include "quote.h"
-#include "transport.h"
-#include "version.h"
-#include "oid-array.h"
-#include "gpg-interface.h"
-#include "gettext.h"
-#include "protocol.h"
-
-static const char * const send_pack_usage[] = {
-	N_("git send-pack [--all | --mirror] [--dry-run] [--force] "
-	  "[--receive-pack=<git-receive-pack>] [--verbose] [--thin] [--atomic] "
-	  "[<host>:]<directory> [<ref>...]\n"
-	  "  --all and explicit <ref> specification are mutually exclusive."),
-	NULL,
-};
-
-static struct send_pack_args args;
-
-static void print_helper_status(struct ref *ref)
-{
-	struct strbuf buf = STRBUF_INIT;
-	struct ref_push_report *report;
-
-	for (; ref; ref = ref->next) {
-		const char *msg = NULL;
-		const char *res;
-		int count = 0;
-
-		switch(ref->status) {
-		case REF_STATUS_NONE:
-			res = "error";
-			msg = "no match";
-			break;
-
-		case REF_STATUS_OK:
-			res = "ok";
-			break;
-
-		case REF_STATUS_UPTODATE:
-			res = "ok";
-			msg = "up to date";
-			break;
-
-		case REF_STATUS_REJECT_NONFASTFORWARD:
-			res = "error";
-			msg = "non-fast forward";
-			break;
-
-		case REF_STATUS_REJECT_FETCH_FIRST:
-			res = "error";
-			msg = "fetch first";
-			break;
-
-		case REF_STATUS_REJECT_NEEDS_FORCE:
-			res = "error";
-			msg = "needs force";
-			break;
-
-		case REF_STATUS_REJECT_STALE:
-			res = "error";
-			msg = "stale info";
-			break;
-
-		case REF_STATUS_REJECT_ALREADY_EXISTS:
-			res = "error";
-			msg = "already exists";
-			break;
-
-		case REF_STATUS_REJECT_NODELETE:
-		case REF_STATUS_REMOTE_REJECT:
-			res = "error";
-			break;
-
-		case REF_STATUS_EXPECTING_REPORT:
-		default:
-			continue;
-		}
-
-		strbuf_reset(&buf);
-		strbuf_addf(&buf, "%s %s", res, ref->name);
-		if (ref->remote_status)
-			msg = ref->remote_status;
-		if (msg) {
-			strbuf_addch(&buf, ' ');
-			quote_two_c_style(&buf, "", msg, 0);
-		}
-		strbuf_addch(&buf, '\n');
-
-		if (ref->status == REF_STATUS_OK) {
-			for (report = ref->report; report; report = report->next) {
-				if (count++ > 0)
-					strbuf_addf(&buf, "ok %s\n", ref->name);
-				if (report->ref_name)
-					strbuf_addf(&buf, "option refname %s\n",
-						report->ref_name);
-				if (report->old_oid)
-					strbuf_addf(&buf, "option old-oid %s\n",
-						oid_to_hex(report->old_oid));
-				if (report->new_oid)
-					strbuf_addf(&buf, "option new-oid %s\n",
-						oid_to_hex(report->new_oid));
-				if (report->forced_update)
-					strbuf_addstr(&buf, "option forced-update\n");
-			}
-		}
-		write_or_die(1, buf.buf, buf.len);
-	}
-	strbuf_release(&buf);
-}
-
-static int send_pack_config(const char *k, const char *v, void *cb)
-{
-	git_gpg_config(k, v, NULL);
-
-	if (!strcmp(k, "push.gpgsign")) {
-		const char *value;
-		if (!git_config_get_value("push.gpgsign", &value)) {
-			switch (git_parse_maybe_bool(value)) {
-			case 0:
-				args.push_cert = SEND_PACK_PUSH_CERT_NEVER;
-				break;
-			case 1:
-				args.push_cert = SEND_PACK_PUSH_CERT_ALWAYS;
-				break;
-			default:
-				if (value && !strcasecmp(value, "if-asked"))
-					args.push_cert = SEND_PACK_PUSH_CERT_IF_ASKED;
-				else
-					return error("Invalid value for '%s'", k);
-			}
-		}
-	}
-	return git_default_config(k, v, cb);
-}
-
-int cmd_send_pack(int argc, const char **argv, const char *prefix)
-{
-	struct refspec rs = REFSPEC_INIT_PUSH;
-	const char *remote_name = NULL;
-	struct remote *remote = NULL;
-	const char *dest = NULL;
-	int fd[2];
-	struct child_process *conn;
-	struct oid_array extra_have = OID_ARRAY_INIT;
-	struct oid_array shallow = OID_ARRAY_INIT;
-	struct ref *remote_refs, *local_refs;
-	int ret;
-	int helper_status = 0;
-	int send_all = 0;
-	int verbose = 0;
-	const char *receivepack = "git-receive-pack";
-	unsigned dry_run = 0;
-	unsigned send_mirror = 0;
-	unsigned force_update = 0;
-	unsigned quiet = 0;
-	int push_cert = 0;
-	struct string_list push_options = STRING_LIST_INIT_NODUP;
-	unsigned use_thin_pack = 0;
-	unsigned atomic = 0;
-	unsigned stateless_rpc = 0;
-	int flags;
-	unsigned int reject_reasons;
-	int progress = -1;
-	int from_stdin = 0;
-	struct push_cas_option cas = {0};
-	struct packet_reader reader;
-
-	struct option options[] = {
-		OPT__VERBOSITY(&verbose),
-		OPT_STRING(0, "receive-pack", &receivepack, "receive-pack", N_("receive pack program")),
-		OPT_STRING(0, "exec", &receivepack, "receive-pack", N_("receive pack program")),
-		OPT_STRING(0, "remote", &remote_name, "remote", N_("remote name")),
-		OPT_BOOL(0, "all", &send_all, N_("push all refs")),
-		OPT_BOOL('n' , "dry-run", &dry_run, N_("dry run")),
-		OPT_BOOL(0, "mirror", &send_mirror, N_("mirror all refs")),
-		OPT_BOOL('f', "force", &force_update, N_("force updates")),
-		OPT_CALLBACK_F(0, "signed", &push_cert, "(yes|no|if-asked)", N_("GPG sign the push"),
-		  PARSE_OPT_OPTARG, option_parse_push_signed),
-		OPT_STRING_LIST(0, "push-option", &push_options,
-				N_("server-specific"),
-				N_("option to transmit")),
-		OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
-		OPT_BOOL(0, "thin", &use_thin_pack, N_("use thin pack")),
-		OPT_BOOL(0, "atomic", &atomic, N_("request atomic transaction on remote side")),
-		OPT_BOOL(0, "stateless-rpc", &stateless_rpc, N_("use stateless RPC protocol")),
-		OPT_BOOL(0, "stdin", &from_stdin, N_("read refs from stdin")),
-		OPT_BOOL(0, "helper-status", &helper_status, N_("print status from remote helper")),
-		OPT_CALLBACK_F(0, CAS_OPT_NAME, &cas, N_("<refname>:<expect>"),
-		  N_("require old value of ref to be at this value"),
-		  PARSE_OPT_OPTARG, parseopt_push_cas_option),
-		OPT_END()
-	};
-
-	git_config(send_pack_config, NULL);
-	argc = parse_options(argc, argv, prefix, options, send_pack_usage, 0);
-	if (argc > 0) {
-		dest = argv[0];
-		refspec_appendn(&rs, argv + 1, argc - 1);
-	}
-
-	if (!dest)
-		usage_with_options(send_pack_usage, options);
-
-	args.verbose = verbose;
-	args.dry_run = dry_run;
-	args.send_mirror = send_mirror;
-	args.force_update = force_update;
-	args.quiet = quiet;
-	args.push_cert = push_cert;
-	args.progress = progress;
-	args.use_thin_pack = use_thin_pack;
-	args.atomic = atomic;
-	args.stateless_rpc = stateless_rpc;
-	args.push_options = push_options.nr ? &push_options : NULL;
-
-	if (from_stdin) {
-		if (args.stateless_rpc) {
-			const char *buf;
-			while ((buf = packet_read_line(0, NULL)))
-				refspec_append(&rs, buf);
-		} else {
-			struct strbuf line = STRBUF_INIT;
-			while (strbuf_getline(&line, stdin) != EOF)
-				refspec_append(&rs, line.buf);
-			strbuf_release(&line);
-		}
-	}
-
-	/*
-	 * --all and --mirror are incompatible; neither makes sense
-	 * with any refspecs.
-	 */
-	if ((rs.nr > 0 && (send_all || args.send_mirror)) ||
-	    (send_all && args.send_mirror))
-		usage_with_options(send_pack_usage, options);
-
-	if (remote_name) {
-		remote = remote_get(remote_name);
-		if (!remote_has_url(remote, dest)) {
-			die("Destination %s is not a uri for %s",
-			    dest, remote_name);
-		}
-	}
-
-	if (progress == -1)
-		progress = !args.quiet && isatty(2);
-	args.progress = progress;
-
-	if (args.stateless_rpc) {
-		conn = NULL;
-		fd[0] = 0;
-		fd[1] = 1;
-	} else {
-		conn = git_connect(fd, dest, receivepack,
-			args.verbose ? CONNECT_VERBOSE : 0);
-	}
-
-	packet_reader_init(&reader, fd[0], NULL, 0,
-			   PACKET_READ_CHOMP_NEWLINE |
-			   PACKET_READ_GENTLE_ON_EOF |
-			   PACKET_READ_DIE_ON_ERR_PACKET);
-
-	switch (discover_version(&reader)) {
-	case protocol_v2:
-		die("support for protocol v2 not implemented yet");
-		break;
-	case protocol_v1:
-	case protocol_v0:
-		get_remote_heads(&reader, &remote_refs, REF_NORMAL,
-				 &extra_have, &shallow);
-		break;
-	case protocol_unknown_version:
-		BUG("unknown protocol version");
-	}
-
-	local_refs = get_local_heads();
-
-	flags = MATCH_REFS_NONE;
-
-	if (send_all)
-		flags |= MATCH_REFS_ALL;
-	if (args.send_mirror)
-		flags |= MATCH_REFS_MIRROR;
-
-	/* match them up */
-	if (match_push_refs(local_refs, &remote_refs, &rs, flags))
-		return -1;
-
-	if (!is_empty_cas(&cas))
-		apply_push_cas(&cas, remote, remote_refs);
-
-	set_ref_status_for_push(remote_refs, args.send_mirror,
-		args.force_update);
-
-	ret = send_pack(&args, fd, conn, remote_refs, &extra_have);
-
-	if (helper_status)
-		print_helper_status(remote_refs);
-
-	close(fd[1]);
-	close(fd[0]);
-
-	ret |= finish_connect(conn);
-
-	if (!helper_status)
-		transport_print_push_status(dest, remote_refs, args.verbose, 0, &reject_reasons);
-
-	if (!args.dry_run && remote) {
-		struct ref *ref;
-		for (ref = remote_refs; ref; ref = ref->next)
-			transport_update_tracking_ref(remote, ref, args.verbose);
-	}
-
-	if (!ret && !transport_refs_pushed(remote_refs))
-		fprintf(stderr, "Everything up-to-date\n");
-
-	return ret;
-}
diff --git a/third_party/git/builtin/shortlog.c b/third_party/git/builtin/shortlog.c
deleted file mode 100644
index 0a5c4968f64e..000000000000
--- a/third_party/git/builtin/shortlog.c
+++ /dev/null
@@ -1,538 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "commit.h"
-#include "diff.h"
-#include "string-list.h"
-#include "revision.h"
-#include "utf8.h"
-#include "mailmap.h"
-#include "shortlog.h"
-#include "parse-options.h"
-#include "trailer.h"
-
-static char const * const shortlog_usage[] = {
-	N_("git shortlog [<options>] [<revision-range>] [[--] <path>...]"),
-	N_("git log --pretty=short | git shortlog [<options>]"),
-	NULL
-};
-
-/*
- * The util field of our string_list_items will contain one of two things:
- *
- *   - if --summary is not in use, it will point to a string list of the
- *     oneline subjects assigned to this author
- *
- *   - if --summary is in use, we don't need that list; we only need to know
- *     its size. So we abuse the pointer slot to store our integer counter.
- *
- *  This macro accesses the latter.
- */
-#define UTIL_TO_INT(x) ((intptr_t)(x)->util)
-
-static int compare_by_counter(const void *a1, const void *a2)
-{
-	const struct string_list_item *i1 = a1, *i2 = a2;
-	return UTIL_TO_INT(i2) - UTIL_TO_INT(i1);
-}
-
-static int compare_by_list(const void *a1, const void *a2)
-{
-	const struct string_list_item *i1 = a1, *i2 = a2;
-	const struct string_list *l1 = i1->util, *l2 = i2->util;
-
-	if (l1->nr < l2->nr)
-		return 1;
-	else if (l1->nr == l2->nr)
-		return 0;
-	else
-		return -1;
-}
-
-static void insert_one_record(struct shortlog *log,
-			      const char *ident,
-			      const char *oneline)
-{
-	struct string_list_item *item;
-
-	item = string_list_insert(&log->list, ident);
-
-	if (log->summary)
-		item->util = (void *)(UTIL_TO_INT(item) + 1);
-	else {
-		const char *dot3 = log->common_repo_prefix;
-		char *buffer, *p;
-		struct strbuf subject = STRBUF_INIT;
-		const char *eol;
-
-		/* Skip any leading whitespace, including any blank lines. */
-		while (*oneline && isspace(*oneline))
-			oneline++;
-		eol = strchr(oneline, '\n');
-		if (!eol)
-			eol = oneline + strlen(oneline);
-		if (starts_with(oneline, "[PATCH")) {
-			char *eob = strchr(oneline, ']');
-			if (eob && (!eol || eob < eol))
-				oneline = eob + 1;
-		}
-		while (*oneline && isspace(*oneline) && *oneline != '\n')
-			oneline++;
-		format_subject(&subject, oneline, " ");
-		buffer = strbuf_detach(&subject, NULL);
-
-		if (dot3) {
-			int dot3len = strlen(dot3);
-			if (dot3len > 5) {
-				while ((p = strstr(buffer, dot3)) != NULL) {
-					int taillen = strlen(p) - dot3len;
-					memcpy(p, "/.../", 5);
-					memmove(p + 5, p + dot3len, taillen + 1);
-				}
-			}
-		}
-
-		if (item->util == NULL)
-			item->util = xcalloc(1, sizeof(struct string_list));
-		string_list_append(item->util, buffer);
-	}
-}
-
-static int parse_ident(struct shortlog *log,
-		       struct strbuf *out, const char *in)
-{
-	const char *mailbuf, *namebuf;
-	size_t namelen, maillen;
-	struct ident_split ident;
-
-	if (split_ident_line(&ident, in, strlen(in)))
-		return -1;
-
-	namebuf = ident.name_begin;
-	mailbuf = ident.mail_begin;
-	namelen = ident.name_end - ident.name_begin;
-	maillen = ident.mail_end - ident.mail_begin;
-
-	map_user(&log->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
-	strbuf_add(out, namebuf, namelen);
-	if (log->email)
-		strbuf_addf(out, " <%.*s>", (int)maillen, mailbuf);
-
-	return 0;
-}
-
-static void read_from_stdin(struct shortlog *log)
-{
-	struct strbuf ident = STRBUF_INIT;
-	struct strbuf mapped_ident = STRBUF_INIT;
-	struct strbuf oneline = STRBUF_INIT;
-	static const char *author_match[2] = { "Author: ", "author " };
-	static const char *committer_match[2] = { "Commit: ", "committer " };
-	const char **match;
-
-	if (HAS_MULTI_BITS(log->groups))
-		die(_("using multiple --group options with stdin is not supported"));
-
-	switch (log->groups) {
-	case SHORTLOG_GROUP_AUTHOR:
-		match = author_match;
-		break;
-	case SHORTLOG_GROUP_COMMITTER:
-		match = committer_match;
-		break;
-	case SHORTLOG_GROUP_TRAILER:
-		die(_("using --group=trailer with stdin is not supported"));
-	default:
-		BUG("unhandled shortlog group");
-	}
-
-	while (strbuf_getline_lf(&ident, stdin) != EOF) {
-		const char *v;
-		if (!skip_prefix(ident.buf, match[0], &v) &&
-		    !skip_prefix(ident.buf, match[1], &v))
-			continue;
-		while (strbuf_getline_lf(&oneline, stdin) != EOF &&
-		       oneline.len)
-			; /* discard headers */
-		while (strbuf_getline_lf(&oneline, stdin) != EOF &&
-		       !oneline.len)
-			; /* discard blanks */
-
-		strbuf_reset(&mapped_ident);
-		if (parse_ident(log, &mapped_ident, v) < 0)
-			continue;
-
-		insert_one_record(log, mapped_ident.buf, oneline.buf);
-	}
-	strbuf_release(&ident);
-	strbuf_release(&mapped_ident);
-	strbuf_release(&oneline);
-}
-
-struct strset_item {
-	struct hashmap_entry ent;
-	char value[FLEX_ARRAY];
-};
-
-struct strset {
-	struct hashmap map;
-};
-
-#define STRSET_INIT { { NULL } }
-
-static int strset_item_hashcmp(const void *hash_data,
-			       const struct hashmap_entry *entry,
-			       const struct hashmap_entry *entry_or_key,
-			       const void *keydata)
-{
-	const struct strset_item *a, *b;
-
-	a = container_of(entry, const struct strset_item, ent);
-	if (keydata)
-		return strcmp(a->value, keydata);
-
-	b = container_of(entry_or_key, const struct strset_item, ent);
-	return strcmp(a->value, b->value);
-}
-
-/*
- * Adds "str" to the set if it was not already present; returns true if it was
- * already there.
- */
-static int strset_check_and_add(struct strset *ss, const char *str)
-{
-	unsigned int hash = strhash(str);
-	struct strset_item *item;
-
-	if (!ss->map.table)
-		hashmap_init(&ss->map, strset_item_hashcmp, NULL, 0);
-
-	if (hashmap_get_from_hash(&ss->map, hash, str))
-		return 1;
-
-	FLEX_ALLOC_STR(item, value, str);
-	hashmap_entry_init(&item->ent, hash);
-	hashmap_add(&ss->map, &item->ent);
-	return 0;
-}
-
-static void strset_clear(struct strset *ss)
-{
-	if (!ss->map.table)
-		return;
-	hashmap_free_entries(&ss->map, struct strset_item, ent);
-}
-
-static void insert_records_from_trailers(struct shortlog *log,
-					 struct strset *dups,
-					 struct commit *commit,
-					 struct pretty_print_context *ctx,
-					 const char *oneline)
-{
-	struct trailer_iterator iter;
-	const char *commit_buffer, *body;
-	struct strbuf ident = STRBUF_INIT;
-
-	/*
-	 * Using format_commit_message("%B") would be simpler here, but
-	 * this saves us copying the message.
-	 */
-	commit_buffer = logmsg_reencode(commit, NULL, ctx->output_encoding);
-	body = strstr(commit_buffer, "\n\n");
-	if (!body)
-		return;
-
-	trailer_iterator_init(&iter, body);
-	while (trailer_iterator_advance(&iter)) {
-		const char *value = iter.val.buf;
-
-		if (!string_list_has_string(&log->trailers, iter.key.buf))
-			continue;
-
-		strbuf_reset(&ident);
-		if (!parse_ident(log, &ident, value))
-			value = ident.buf;
-
-		if (strset_check_and_add(dups, value))
-			continue;
-		insert_one_record(log, value, oneline);
-	}
-	trailer_iterator_release(&iter);
-
-	strbuf_release(&ident);
-	unuse_commit_buffer(commit, commit_buffer);
-}
-
-void shortlog_add_commit(struct shortlog *log, struct commit *commit)
-{
-	struct strbuf ident = STRBUF_INIT;
-	struct strbuf oneline = STRBUF_INIT;
-	struct strset dups = STRSET_INIT;
-	struct pretty_print_context ctx = {0};
-	const char *oneline_str;
-
-	ctx.fmt = CMIT_FMT_USERFORMAT;
-	ctx.abbrev = log->abbrev;
-	ctx.print_email_subject = 1;
-	ctx.date_mode.type = DATE_NORMAL;
-	ctx.output_encoding = get_log_output_encoding();
-
-	if (!log->summary) {
-		if (log->user_format)
-			pretty_print_commit(&ctx, commit, &oneline);
-		else
-			format_commit_message(commit, "%s", &oneline, &ctx);
-	}
-	oneline_str = oneline.len ? oneline.buf : "<none>";
-
-	if (log->groups & SHORTLOG_GROUP_AUTHOR) {
-		strbuf_reset(&ident);
-		format_commit_message(commit,
-				      log->email ? "%aN <%aE>" : "%aN",
-				      &ident, &ctx);
-		if (!HAS_MULTI_BITS(log->groups) ||
-		    !strset_check_and_add(&dups, ident.buf))
-			insert_one_record(log, ident.buf, oneline_str);
-	}
-	if (log->groups & SHORTLOG_GROUP_COMMITTER) {
-		strbuf_reset(&ident);
-		format_commit_message(commit,
-				      log->email ? "%cN <%cE>" : "%cN",
-				      &ident, &ctx);
-		if (!HAS_MULTI_BITS(log->groups) ||
-		    !strset_check_and_add(&dups, ident.buf))
-			insert_one_record(log, ident.buf, oneline_str);
-	}
-	if (log->groups & SHORTLOG_GROUP_TRAILER) {
-		insert_records_from_trailers(log, &dups, commit, &ctx, oneline_str);
-	}
-
-	strset_clear(&dups);
-	strbuf_release(&ident);
-	strbuf_release(&oneline);
-}
-
-static void get_from_rev(struct rev_info *rev, struct shortlog *log)
-{
-	struct commit *commit;
-
-	if (prepare_revision_walk(rev))
-		die(_("revision walk setup failed"));
-	while ((commit = get_revision(rev)) != NULL)
-		shortlog_add_commit(log, commit);
-}
-
-static int parse_uint(char const **arg, int comma, int defval)
-{
-	unsigned long ul;
-	int ret;
-	char *endp;
-
-	ul = strtoul(*arg, &endp, 10);
-	if (*endp && *endp != comma)
-		return -1;
-	if (ul > INT_MAX)
-		return -1;
-	ret = *arg == endp ? defval : (int)ul;
-	*arg = *endp ? endp + 1 : endp;
-	return ret;
-}
-
-static const char wrap_arg_usage[] = "-w[<width>[,<indent1>[,<indent2>]]]";
-#define DEFAULT_WRAPLEN 76
-#define DEFAULT_INDENT1 6
-#define DEFAULT_INDENT2 9
-
-static int parse_wrap_args(const struct option *opt, const char *arg, int unset)
-{
-	struct shortlog *log = opt->value;
-
-	log->wrap_lines = !unset;
-	if (unset)
-		return 0;
-	if (!arg) {
-		log->wrap = DEFAULT_WRAPLEN;
-		log->in1 = DEFAULT_INDENT1;
-		log->in2 = DEFAULT_INDENT2;
-		return 0;
-	}
-
-	log->wrap = parse_uint(&arg, ',', DEFAULT_WRAPLEN);
-	log->in1 = parse_uint(&arg, ',', DEFAULT_INDENT1);
-	log->in2 = parse_uint(&arg, '\0', DEFAULT_INDENT2);
-	if (log->wrap < 0 || log->in1 < 0 || log->in2 < 0)
-		return error(wrap_arg_usage);
-	if (log->wrap &&
-	    ((log->in1 && log->wrap <= log->in1) ||
-	     (log->in2 && log->wrap <= log->in2)))
-		return error(wrap_arg_usage);
-	return 0;
-}
-
-static int parse_group_option(const struct option *opt, const char *arg, int unset)
-{
-	struct shortlog *log = opt->value;
-	const char *field;
-
-	if (unset) {
-		log->groups = 0;
-		string_list_clear(&log->trailers, 0);
-	} else if (!strcasecmp(arg, "author"))
-		log->groups |= SHORTLOG_GROUP_AUTHOR;
-	else if (!strcasecmp(arg, "committer"))
-		log->groups |= SHORTLOG_GROUP_COMMITTER;
-	else if (skip_prefix(arg, "trailer:", &field)) {
-		log->groups |= SHORTLOG_GROUP_TRAILER;
-		string_list_append(&log->trailers, field);
-	} else
-		return error(_("unknown group type: %s"), arg);
-
-	return 0;
-}
-
-
-void shortlog_init(struct shortlog *log)
-{
-	memset(log, 0, sizeof(*log));
-
-	read_mailmap(&log->mailmap, &log->common_repo_prefix);
-
-	log->list.strdup_strings = 1;
-	log->wrap = DEFAULT_WRAPLEN;
-	log->in1 = DEFAULT_INDENT1;
-	log->in2 = DEFAULT_INDENT2;
-	log->trailers.strdup_strings = 1;
-	log->trailers.cmp = strcasecmp;
-}
-
-int cmd_shortlog(int argc, const char **argv, const char *prefix)
-{
-	struct shortlog log = { STRING_LIST_INIT_NODUP };
-	struct rev_info rev;
-	int nongit = !startup_info->have_repository;
-
-	const struct option options[] = {
-		OPT_BIT('c', "committer", &log.groups,
-			N_("Group by committer rather than author"),
-			SHORTLOG_GROUP_COMMITTER),
-		OPT_BOOL('n', "numbered", &log.sort_by_number,
-			 N_("sort output according to the number of commits per author")),
-		OPT_BOOL('s', "summary", &log.summary,
-			 N_("Suppress commit descriptions, only provides commit count")),
-		OPT_BOOL('e', "email", &log.email,
-			 N_("Show the email address of each author")),
-		OPT_CALLBACK_F('w', NULL, &log, N_("<w>[,<i1>[,<i2>]]"),
-			N_("Linewrap output"), PARSE_OPT_OPTARG,
-			&parse_wrap_args),
-		OPT_CALLBACK(0, "group", &log, N_("field"),
-			N_("Group by field"), parse_group_option),
-		OPT_END(),
-	};
-
-	struct parse_opt_ctx_t ctx;
-
-	git_config(git_default_config, NULL);
-	shortlog_init(&log);
-	repo_init_revisions(the_repository, &rev, prefix);
-	parse_options_start(&ctx, argc, argv, prefix, options,
-			    PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0);
-
-	for (;;) {
-		switch (parse_options_step(&ctx, options, shortlog_usage)) {
-		case PARSE_OPT_HELP:
-		case PARSE_OPT_ERROR:
-			exit(129);
-		case PARSE_OPT_COMPLETE:
-			exit(0);
-		case PARSE_OPT_DONE:
-			goto parse_done;
-		}
-		parse_revision_opt(&rev, &ctx, options, shortlog_usage);
-	}
-parse_done:
-	argc = parse_options_end(&ctx);
-
-	if (nongit && argc > 1) {
-		error(_("too many arguments given outside repository"));
-		usage_with_options(shortlog_usage, options);
-	}
-
-	if (setup_revisions(argc, argv, &rev, NULL) != 1) {
-		error(_("unrecognized argument: %s"), argv[1]);
-		usage_with_options(shortlog_usage, options);
-	}
-
-	log.user_format = rev.commit_format == CMIT_FMT_USERFORMAT;
-	log.abbrev = rev.abbrev;
-	log.file = rev.diffopt.file;
-
-	if (!log.groups)
-		log.groups = SHORTLOG_GROUP_AUTHOR;
-	string_list_sort(&log.trailers);
-
-	/* assume HEAD if from a tty */
-	if (!nongit && !rev.pending.nr && isatty(0))
-		add_head_to_pending(&rev);
-	if (rev.pending.nr == 0) {
-		if (isatty(0))
-			fprintf(stderr, _("(reading log message from standard input)\n"));
-		read_from_stdin(&log);
-	}
-	else
-		get_from_rev(&rev, &log);
-
-	shortlog_output(&log);
-	if (log.file != stdout)
-		fclose(log.file);
-	return 0;
-}
-
-static void add_wrapped_shortlog_msg(struct strbuf *sb, const char *s,
-				     const struct shortlog *log)
-{
-	strbuf_add_wrapped_text(sb, s, log->in1, log->in2, log->wrap);
-	strbuf_addch(sb, '\n');
-}
-
-void shortlog_output(struct shortlog *log)
-{
-	int i, j;
-	struct strbuf sb = STRBUF_INIT;
-
-	if (log->sort_by_number)
-		QSORT(log->list.items, log->list.nr,
-		      log->summary ? compare_by_counter : compare_by_list);
-	for (i = 0; i < log->list.nr; i++) {
-		const struct string_list_item *item = &log->list.items[i];
-		if (log->summary) {
-			fprintf(log->file, "%6d\t%s\n",
-				(int)UTIL_TO_INT(item), item->string);
-		} else {
-			struct string_list *onelines = item->util;
-			fprintf(log->file, "%s (%d):\n",
-				item->string, onelines->nr);
-			for (j = onelines->nr - 1; j >= 0; j--) {
-				const char *msg = onelines->items[j].string;
-
-				if (log->wrap_lines) {
-					strbuf_reset(&sb);
-					add_wrapped_shortlog_msg(&sb, msg, log);
-					fwrite(sb.buf, sb.len, 1, log->file);
-				}
-				else
-					fprintf(log->file, "      %s\n", msg);
-			}
-			putc('\n', log->file);
-			onelines->strdup_strings = 1;
-			string_list_clear(onelines, 0);
-			free(onelines);
-		}
-
-		log->list.items[i].util = NULL;
-	}
-
-	strbuf_release(&sb);
-	log->list.strdup_strings = 1;
-	string_list_clear(&log->list, 1);
-	clear_mailmap(&log->mailmap);
-}
diff --git a/third_party/git/builtin/show-branch.c b/third_party/git/builtin/show-branch.c
deleted file mode 100644
index d6d2dabeca87..000000000000
--- a/third_party/git/builtin/show-branch.c
+++ /dev/null
@@ -1,954 +0,0 @@
-#include "cache.h"
-#include "config.h"
-#include "pretty.h"
-#include "refs.h"
-#include "builtin.h"
-#include "color.h"
-#include "strvec.h"
-#include "parse-options.h"
-#include "dir.h"
-#include "commit-slab.h"
-
-static const char* show_branch_usage[] = {
-    N_("git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\n"
-       "		[--current] [--color[=<when>] | --no-color] [--sparse]\n"
-       "		[--more=<n> | --list | --independent | --merge-base]\n"
-       "		[--no-name | --sha1-name] [--topics] [(<rev> | <glob>)...]"),
-    N_("git show-branch (-g | --reflog)[=<n>[,<base>]] [--list] [<ref>]"),
-    NULL
-};
-
-static int showbranch_use_color = -1;
-
-static struct strvec default_args = STRVEC_INIT;
-
-/*
- * TODO: convert this use of commit->object.flags to commit-slab
- * instead to store a pointer to ref name directly. Then use the same
- * UNINTERESTING definition from revision.h here.
- */
-#define UNINTERESTING	01
-
-#define REV_SHIFT	 2
-#define MAX_REVS	(FLAG_BITS - REV_SHIFT) /* should not exceed bits_per_int - REV_SHIFT */
-
-#define DEFAULT_REFLOG	4
-
-static const char *get_color_code(int idx)
-{
-	if (want_color(showbranch_use_color))
-		return column_colors_ansi[idx % column_colors_ansi_max];
-	return "";
-}
-
-static const char *get_color_reset_code(void)
-{
-	if (want_color(showbranch_use_color))
-		return GIT_COLOR_RESET;
-	return "";
-}
-
-static struct commit *interesting(struct commit_list *list)
-{
-	while (list) {
-		struct commit *commit = list->item;
-		list = list->next;
-		if (commit->object.flags & UNINTERESTING)
-			continue;
-		return commit;
-	}
-	return NULL;
-}
-
-struct commit_name {
-	const char *head_name; /* which head's ancestor? */
-	int generation; /* how many parents away from head_name */
-};
-
-define_commit_slab(commit_name_slab, struct commit_name *);
-static struct commit_name_slab name_slab;
-
-static struct commit_name *commit_to_name(struct commit *commit)
-{
-	return *commit_name_slab_at(&name_slab, commit);
-}
-
-
-/* Name the commit as nth generation ancestor of head_name;
- * we count only the first-parent relationship for naming purposes.
- */
-static void name_commit(struct commit *commit, const char *head_name, int nth)
-{
-	struct commit_name *name;
-
-	name = *commit_name_slab_at(&name_slab, commit);
-	if (!name) {
-		name = xmalloc(sizeof(*name));
-		*commit_name_slab_at(&name_slab, commit) = name;
-	}
-	name->head_name = head_name;
-	name->generation = nth;
-}
-
-/* Parent is the first parent of the commit.  We may name it
- * as (n+1)th generation ancestor of the same head_name as
- * commit is nth generation ancestor of, if that generation
- * number is better than the name it already has.
- */
-static void name_parent(struct commit *commit, struct commit *parent)
-{
-	struct commit_name *commit_name = commit_to_name(commit);
-	struct commit_name *parent_name = commit_to_name(parent);
-	if (!commit_name)
-		return;
-	if (!parent_name ||
-	    commit_name->generation + 1 < parent_name->generation)
-		name_commit(parent, commit_name->head_name,
-			    commit_name->generation + 1);
-}
-
-static int name_first_parent_chain(struct commit *c)
-{
-	int i = 0;
-	while (c) {
-		struct commit *p;
-		if (!commit_to_name(c))
-			break;
-		if (!c->parents)
-			break;
-		p = c->parents->item;
-		if (!commit_to_name(p)) {
-			name_parent(c, p);
-			i++;
-		}
-		else
-			break;
-		c = p;
-	}
-	return i;
-}
-
-static void name_commits(struct commit_list *list,
-			 struct commit **rev,
-			 char **ref_name,
-			 int num_rev)
-{
-	struct commit_list *cl;
-	struct commit *c;
-	int i;
-
-	/* First give names to the given heads */
-	for (cl = list; cl; cl = cl->next) {
-		c = cl->item;
-		if (commit_to_name(c))
-			continue;
-		for (i = 0; i < num_rev; i++) {
-			if (rev[i] == c) {
-				name_commit(c, ref_name[i], 0);
-				break;
-			}
-		}
-	}
-
-	/* Then commits on the first parent ancestry chain */
-	do {
-		i = 0;
-		for (cl = list; cl; cl = cl->next) {
-			i += name_first_parent_chain(cl->item);
-		}
-	} while (i);
-
-	/* Finally, any unnamed commits */
-	do {
-		i = 0;
-		for (cl = list; cl; cl = cl->next) {
-			struct commit_list *parents;
-			struct commit_name *n;
-			int nth;
-			c = cl->item;
-			if (!commit_to_name(c))
-				continue;
-			n = commit_to_name(c);
-			parents = c->parents;
-			nth = 0;
-			while (parents) {
-				struct commit *p = parents->item;
-				struct strbuf newname = STRBUF_INIT;
-				parents = parents->next;
-				nth++;
-				if (commit_to_name(p))
-					continue;
-				switch (n->generation) {
-				case 0:
-					strbuf_addstr(&newname, n->head_name);
-					break;
-				case 1:
-					strbuf_addf(&newname, "%s^", n->head_name);
-					break;
-				default:
-					strbuf_addf(&newname, "%s~%d",
-						    n->head_name, n->generation);
-					break;
-				}
-				if (nth == 1)
-					strbuf_addch(&newname, '^');
-				else
-					strbuf_addf(&newname, "^%d", nth);
-				name_commit(p, strbuf_detach(&newname, NULL), 0);
-				i++;
-				name_first_parent_chain(p);
-			}
-		}
-	} while (i);
-}
-
-static int mark_seen(struct commit *commit, struct commit_list **seen_p)
-{
-	if (!commit->object.flags) {
-		commit_list_insert(commit, seen_p);
-		return 1;
-	}
-	return 0;
-}
-
-static void join_revs(struct commit_list **list_p,
-		      struct commit_list **seen_p,
-		      int num_rev, int extra)
-{
-	int all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
-	int all_revs = all_mask & ~((1u << REV_SHIFT) - 1);
-
-	while (*list_p) {
-		struct commit_list *parents;
-		int still_interesting = !!interesting(*list_p);
-		struct commit *commit = pop_commit(list_p);
-		int flags = commit->object.flags & all_mask;
-
-		if (!still_interesting && extra <= 0)
-			break;
-
-		mark_seen(commit, seen_p);
-		if ((flags & all_revs) == all_revs)
-			flags |= UNINTERESTING;
-		parents = commit->parents;
-
-		while (parents) {
-			struct commit *p = parents->item;
-			int this_flag = p->object.flags;
-			parents = parents->next;
-			if ((this_flag & flags) == flags)
-				continue;
-			parse_commit(p);
-			if (mark_seen(p, seen_p) && !still_interesting)
-				extra--;
-			p->object.flags |= flags;
-			commit_list_insert_by_date(p, list_p);
-		}
-	}
-
-	/*
-	 * Postprocess to complete well-poisoning.
-	 *
-	 * At this point we have all the commits we have seen in
-	 * seen_p list.  Mark anything that can be reached from
-	 * uninteresting commits not interesting.
-	 */
-	for (;;) {
-		int changed = 0;
-		struct commit_list *s;
-		for (s = *seen_p; s; s = s->next) {
-			struct commit *c = s->item;
-			struct commit_list *parents;
-
-			if (((c->object.flags & all_revs) != all_revs) &&
-			    !(c->object.flags & UNINTERESTING))
-				continue;
-
-			/* The current commit is either a merge base or
-			 * already uninteresting one.  Mark its parents
-			 * as uninteresting commits _only_ if they are
-			 * already parsed.  No reason to find new ones
-			 * here.
-			 */
-			parents = c->parents;
-			while (parents) {
-				struct commit *p = parents->item;
-				parents = parents->next;
-				if (!(p->object.flags & UNINTERESTING)) {
-					p->object.flags |= UNINTERESTING;
-					changed = 1;
-				}
-			}
-		}
-		if (!changed)
-			break;
-	}
-}
-
-static void show_one_commit(struct commit *commit, int no_name)
-{
-	struct strbuf pretty = STRBUF_INIT;
-	const char *pretty_str = "(unavailable)";
-	struct commit_name *name = commit_to_name(commit);
-
-	if (commit->object.parsed) {
-		pp_commit_easy(CMIT_FMT_ONELINE, commit, &pretty);
-		pretty_str = pretty.buf;
-	}
-	skip_prefix(pretty_str, "[PATCH] ", &pretty_str);
-
-	if (!no_name) {
-		if (name && name->head_name) {
-			printf("[%s", name->head_name);
-			if (name->generation) {
-				if (name->generation == 1)
-					printf("^");
-				else
-					printf("~%d", name->generation);
-			}
-			printf("] ");
-		}
-		else
-			printf("[%s] ",
-			       find_unique_abbrev(&commit->object.oid,
-						  DEFAULT_ABBREV));
-	}
-	puts(pretty_str);
-	strbuf_release(&pretty);
-}
-
-static char *ref_name[MAX_REVS + 1];
-static int ref_name_cnt;
-
-static const char *find_digit_prefix(const char *s, int *v)
-{
-	const char *p;
-	int ver;
-	char ch;
-
-	for (p = s, ver = 0;
-	     '0' <= (ch = *p) && ch <= '9';
-	     p++)
-		ver = ver * 10 + ch - '0';
-	*v = ver;
-	return p;
-}
-
-
-static int version_cmp(const char *a, const char *b)
-{
-	while (1) {
-		int va, vb;
-
-		a = find_digit_prefix(a, &va);
-		b = find_digit_prefix(b, &vb);
-		if (va != vb)
-			return va - vb;
-
-		while (1) {
-			int ca = *a;
-			int cb = *b;
-			if ('0' <= ca && ca <= '9')
-				ca = 0;
-			if ('0' <= cb && cb <= '9')
-				cb = 0;
-			if (ca != cb)
-				return ca - cb;
-			if (!ca)
-				break;
-			a++;
-			b++;
-		}
-		if (!*a && !*b)
-			return 0;
-	}
-}
-
-static int compare_ref_name(const void *a_, const void *b_)
-{
-	const char * const*a = a_, * const*b = b_;
-	return version_cmp(*a, *b);
-}
-
-static void sort_ref_range(int bottom, int top)
-{
-	QSORT(ref_name + bottom, top - bottom, compare_ref_name);
-}
-
-static int append_ref(const char *refname, const struct object_id *oid,
-		      int allow_dups)
-{
-	struct commit *commit = lookup_commit_reference_gently(the_repository,
-							       oid, 1);
-	int i;
-
-	if (!commit)
-		return 0;
-
-	if (!allow_dups) {
-		/* Avoid adding the same thing twice */
-		for (i = 0; i < ref_name_cnt; i++)
-			if (!strcmp(refname, ref_name[i]))
-				return 0;
-	}
-	if (MAX_REVS <= ref_name_cnt) {
-		warning(Q_("ignoring %s; cannot handle more than %d ref",
-			   "ignoring %s; cannot handle more than %d refs",
-			   MAX_REVS), refname, MAX_REVS);
-		return 0;
-	}
-	ref_name[ref_name_cnt++] = xstrdup(refname);
-	ref_name[ref_name_cnt] = NULL;
-	return 0;
-}
-
-static int append_head_ref(const char *refname, const struct object_id *oid,
-			   int flag, void *cb_data)
-{
-	struct object_id tmp;
-	int ofs = 11;
-	if (!starts_with(refname, "refs/heads/"))
-		return 0;
-	/* If both heads/foo and tags/foo exists, get_sha1 would
-	 * get confused.
-	 */
-	if (get_oid(refname + ofs, &tmp) || !oideq(&tmp, oid))
-		ofs = 5;
-	return append_ref(refname + ofs, oid, 0);
-}
-
-static int append_remote_ref(const char *refname, const struct object_id *oid,
-			     int flag, void *cb_data)
-{
-	struct object_id tmp;
-	int ofs = 13;
-	if (!starts_with(refname, "refs/remotes/"))
-		return 0;
-	/* If both heads/foo and tags/foo exists, get_sha1 would
-	 * get confused.
-	 */
-	if (get_oid(refname + ofs, &tmp) || !oideq(&tmp, oid))
-		ofs = 5;
-	return append_ref(refname + ofs, oid, 0);
-}
-
-static int append_tag_ref(const char *refname, const struct object_id *oid,
-			  int flag, void *cb_data)
-{
-	if (!starts_with(refname, "refs/tags/"))
-		return 0;
-	return append_ref(refname + 5, oid, 0);
-}
-
-static const char *match_ref_pattern = NULL;
-static int match_ref_slash = 0;
-
-static int append_matching_ref(const char *refname, const struct object_id *oid,
-			       int flag, void *cb_data)
-{
-	/* we want to allow pattern hold/<asterisk> to show all
-	 * branches under refs/heads/hold/, and v0.99.9? to show
-	 * refs/tags/v0.99.9a and friends.
-	 */
-	const char *tail;
-	int slash = count_slashes(refname);
-	for (tail = refname; *tail && match_ref_slash < slash; )
-		if (*tail++ == '/')
-			slash--;
-	if (!*tail)
-		return 0;
-	if (wildmatch(match_ref_pattern, tail, 0))
-		return 0;
-	if (starts_with(refname, "refs/heads/"))
-		return append_head_ref(refname, oid, flag, cb_data);
-	if (starts_with(refname, "refs/tags/"))
-		return append_tag_ref(refname, oid, flag, cb_data);
-	return append_ref(refname, oid, 0);
-}
-
-static void snarf_refs(int head, int remotes)
-{
-	if (head) {
-		int orig_cnt = ref_name_cnt;
-
-		for_each_ref(append_head_ref, NULL);
-		sort_ref_range(orig_cnt, ref_name_cnt);
-	}
-	if (remotes) {
-		int orig_cnt = ref_name_cnt;
-
-		for_each_ref(append_remote_ref, NULL);
-		sort_ref_range(orig_cnt, ref_name_cnt);
-	}
-}
-
-static int rev_is_head(const char *head, const char *name,
-		       unsigned char *head_sha1, unsigned char *sha1)
-{
-	if (!head || (head_sha1 && sha1 && !hasheq(head_sha1, sha1)))
-		return 0;
-	skip_prefix(head, "refs/heads/", &head);
-	if (!skip_prefix(name, "refs/heads/", &name))
-		skip_prefix(name, "heads/", &name);
-	return !strcmp(head, name);
-}
-
-static int show_merge_base(struct commit_list *seen, int num_rev)
-{
-	int all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
-	int all_revs = all_mask & ~((1u << REV_SHIFT) - 1);
-	int exit_status = 1;
-
-	while (seen) {
-		struct commit *commit = pop_commit(&seen);
-		int flags = commit->object.flags & all_mask;
-		if (!(flags & UNINTERESTING) &&
-		    ((flags & all_revs) == all_revs)) {
-			puts(oid_to_hex(&commit->object.oid));
-			exit_status = 0;
-			commit->object.flags |= UNINTERESTING;
-		}
-	}
-	return exit_status;
-}
-
-static int show_independent(struct commit **rev,
-			    int num_rev,
-			    unsigned int *rev_mask)
-{
-	int i;
-
-	for (i = 0; i < num_rev; i++) {
-		struct commit *commit = rev[i];
-		unsigned int flag = rev_mask[i];
-
-		if (commit->object.flags == flag)
-			puts(oid_to_hex(&commit->object.oid));
-		commit->object.flags |= UNINTERESTING;
-	}
-	return 0;
-}
-
-static void append_one_rev(const char *av)
-{
-	struct object_id revkey;
-	if (!get_oid(av, &revkey)) {
-		append_ref(av, &revkey, 0);
-		return;
-	}
-	if (strpbrk(av, "*?[")) {
-		/* glob style match */
-		int saved_matches = ref_name_cnt;
-
-		match_ref_pattern = av;
-		match_ref_slash = count_slashes(av);
-		for_each_ref(append_matching_ref, NULL);
-		if (saved_matches == ref_name_cnt &&
-		    ref_name_cnt < MAX_REVS)
-			error(_("no matching refs with %s"), av);
-		sort_ref_range(saved_matches, ref_name_cnt);
-		return;
-	}
-	die("bad sha1 reference %s", av);
-}
-
-static int git_show_branch_config(const char *var, const char *value, void *cb)
-{
-	if (!strcmp(var, "showbranch.default")) {
-		if (!value)
-			return config_error_nonbool(var);
-		/*
-		 * default_arg is now passed to parse_options(), so we need to
-		 * mimic the real argv a bit better.
-		 */
-		if (!default_args.nr)
-			strvec_push(&default_args, "show-branch");
-		strvec_push(&default_args, value);
-		return 0;
-	}
-
-	if (!strcmp(var, "color.showbranch")) {
-		showbranch_use_color = git_config_colorbool(var, value);
-		return 0;
-	}
-
-	return git_color_default_config(var, value, cb);
-}
-
-static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
-{
-	/* If the commit is tip of the named branches, do not
-	 * omit it.
-	 * Otherwise, if it is a merge that is reachable from only one
-	 * tip, it is not that interesting.
-	 */
-	int i, flag, count;
-	for (i = 0; i < n; i++)
-		if (rev[i] == commit)
-			return 0;
-	flag = commit->object.flags;
-	for (i = count = 0; i < n; i++) {
-		if (flag & (1u << (i + REV_SHIFT)))
-			count++;
-	}
-	if (count == 1)
-		return 1;
-	return 0;
-}
-
-static int reflog = 0;
-
-static int parse_reflog_param(const struct option *opt, const char *arg,
-			      int unset)
-{
-	char *ep;
-	const char **base = (const char **)opt->value;
-	BUG_ON_OPT_NEG(unset);
-	if (!arg)
-		arg = "";
-	reflog = strtoul(arg, &ep, 10);
-	if (*ep == ',')
-		*base = ep + 1;
-	else if (*ep)
-		return error("unrecognized reflog param '%s'", arg);
-	else
-		*base = NULL;
-	if (reflog <= 0)
-		reflog = DEFAULT_REFLOG;
-	return 0;
-}
-
-int cmd_show_branch(int ac, const char **av, const char *prefix)
-{
-	struct commit *rev[MAX_REVS], *commit;
-	char *reflog_msg[MAX_REVS];
-	struct commit_list *list = NULL, *seen = NULL;
-	unsigned int rev_mask[MAX_REVS];
-	int num_rev, i, extra = 0;
-	int all_heads = 0, all_remotes = 0;
-	int all_mask, all_revs;
-	enum rev_sort_order sort_order = REV_SORT_IN_GRAPH_ORDER;
-	char *head;
-	struct object_id head_oid;
-	int merge_base = 0;
-	int independent = 0;
-	int no_name = 0;
-	int sha1_name = 0;
-	int shown_merge_point = 0;
-	int with_current_branch = 0;
-	int head_at = -1;
-	int topics = 0;
-	int dense = 1;
-	const char *reflog_base = NULL;
-	struct option builtin_show_branch_options[] = {
-		OPT_BOOL('a', "all", &all_heads,
-			 N_("show remote-tracking and local branches")),
-		OPT_BOOL('r', "remotes", &all_remotes,
-			 N_("show remote-tracking branches")),
-		OPT__COLOR(&showbranch_use_color,
-			    N_("color '*!+-' corresponding to the branch")),
-		{ OPTION_INTEGER, 0, "more", &extra, N_("n"),
-			    N_("show <n> more commits after the common ancestor"),
-			    PARSE_OPT_OPTARG, NULL, (intptr_t)1 },
-		OPT_SET_INT(0, "list", &extra, N_("synonym to more=-1"), -1),
-		OPT_BOOL(0, "no-name", &no_name, N_("suppress naming strings")),
-		OPT_BOOL(0, "current", &with_current_branch,
-			 N_("include the current branch")),
-		OPT_BOOL(0, "sha1-name", &sha1_name,
-			 N_("name commits with their object names")),
-		OPT_BOOL(0, "merge-base", &merge_base,
-			 N_("show possible merge bases")),
-		OPT_BOOL(0, "independent", &independent,
-			    N_("show refs unreachable from any other ref")),
-		OPT_SET_INT(0, "topo-order", &sort_order,
-			    N_("show commits in topological order"),
-			    REV_SORT_IN_GRAPH_ORDER),
-		OPT_BOOL(0, "topics", &topics,
-			 N_("show only commits not on the first branch")),
-		OPT_SET_INT(0, "sparse", &dense,
-			    N_("show merges reachable from only one tip"), 0),
-		OPT_SET_INT(0, "date-order", &sort_order,
-			    N_("topologically sort, maintaining date order "
-			       "where possible"),
-			    REV_SORT_BY_COMMIT_DATE),
-		OPT_CALLBACK_F('g', "reflog", &reflog_base, N_("<n>[,<base>]"),
-			    N_("show <n> most recent ref-log entries starting at "
-			       "base"),
-			    PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
-			    parse_reflog_param),
-		OPT_END()
-	};
-
-	init_commit_name_slab(&name_slab);
-
-	git_config(git_show_branch_config, NULL);
-
-	/* If nothing is specified, try the default first */
-	if (ac == 1 && default_args.nr) {
-		ac = default_args.nr;
-		av = default_args.v;
-	}
-
-	ac = parse_options(ac, av, prefix, builtin_show_branch_options,
-			   show_branch_usage, PARSE_OPT_STOP_AT_NON_OPTION);
-	if (all_heads)
-		all_remotes = 1;
-
-	if (extra || reflog) {
-		/* "listing" mode is incompatible with
-		 * independent nor merge-base modes.
-		 */
-		if (independent || merge_base)
-			usage_with_options(show_branch_usage,
-					   builtin_show_branch_options);
-		if (reflog && ((0 < extra) || all_heads || all_remotes))
-			/*
-			 * Asking for --more in reflog mode does not
-			 * make sense.  --list is Ok.
-			 *
-			 * Also --all and --remotes do not make sense either.
-			 */
-			die(_("--reflog is incompatible with --all, --remotes, "
-			      "--independent or --merge-base"));
-	}
-
-	/* If nothing is specified, show all branches by default */
-	if (ac <= topics && all_heads + all_remotes == 0)
-		all_heads = 1;
-
-	if (reflog) {
-		struct object_id oid;
-		char *ref;
-		int base = 0;
-		unsigned int flags = 0;
-
-		if (ac == 0) {
-			static const char *fake_av[2];
-
-			fake_av[0] = resolve_refdup("HEAD",
-						    RESOLVE_REF_READING, &oid,
-						    NULL);
-			fake_av[1] = NULL;
-			av = fake_av;
-			ac = 1;
-			if (!*av)
-				die(_("no branches given, and HEAD is not valid"));
-		}
-		if (ac != 1)
-			die(_("--reflog option needs one branch name"));
-
-		if (MAX_REVS < reflog)
-			die(Q_("only %d entry can be shown at one time.",
-			       "only %d entries can be shown at one time.",
-			       MAX_REVS), MAX_REVS);
-		if (!dwim_ref(*av, strlen(*av), &oid, &ref, 0))
-			die(_("no such ref %s"), *av);
-
-		/* Has the base been specified? */
-		if (reflog_base) {
-			char *ep;
-			base = strtoul(reflog_base, &ep, 10);
-			if (*ep) {
-				/* Ah, that is a date spec... */
-				timestamp_t at;
-				at = approxidate(reflog_base);
-				read_ref_at(get_main_ref_store(the_repository),
-					    ref, flags, at, -1, &oid, NULL,
-					    NULL, NULL, &base);
-			}
-		}
-
-		for (i = 0; i < reflog; i++) {
-			char *logmsg;
-			char *nth_desc;
-			const char *msg;
-			timestamp_t timestamp;
-			int tz;
-
-			if (read_ref_at(get_main_ref_store(the_repository),
-					ref, flags, 0, base + i, &oid, &logmsg,
-					&timestamp, &tz, NULL)) {
-				reflog = i;
-				break;
-			}
-			msg = strchr(logmsg, '\t');
-			if (!msg)
-				msg = "(none)";
-			else
-				msg++;
-			reflog_msg[i] = xstrfmt("(%s) %s",
-						show_date(timestamp, tz,
-							  DATE_MODE(RELATIVE)),
-						msg);
-			free(logmsg);
-
-			nth_desc = xstrfmt("%s@{%d}", *av, base+i);
-			append_ref(nth_desc, &oid, 1);
-			free(nth_desc);
-		}
-		free(ref);
-	}
-	else {
-		while (0 < ac) {
-			append_one_rev(*av);
-			ac--; av++;
-		}
-		if (all_heads + all_remotes)
-			snarf_refs(all_heads, all_remotes);
-	}
-
-	head = resolve_refdup("HEAD", RESOLVE_REF_READING,
-			      &head_oid, NULL);
-
-	if (with_current_branch && head) {
-		int has_head = 0;
-		for (i = 0; !has_head && i < ref_name_cnt; i++) {
-			/* We are only interested in adding the branch
-			 * HEAD points at.
-			 */
-			if (rev_is_head(head,
-					ref_name[i],
-					head_oid.hash, NULL))
-				has_head++;
-		}
-		if (!has_head) {
-			const char *name = head;
-			skip_prefix(name, "refs/heads/", &name);
-			append_one_rev(name);
-		}
-	}
-
-	if (!ref_name_cnt) {
-		fprintf(stderr, "No revs to be shown.\n");
-		exit(0);
-	}
-
-	for (num_rev = 0; ref_name[num_rev]; num_rev++) {
-		struct object_id revkey;
-		unsigned int flag = 1u << (num_rev + REV_SHIFT);
-
-		if (MAX_REVS <= num_rev)
-			die(Q_("cannot handle more than %d rev.",
-			       "cannot handle more than %d revs.",
-			       MAX_REVS), MAX_REVS);
-		if (get_oid(ref_name[num_rev], &revkey))
-			die(_("'%s' is not a valid ref."), ref_name[num_rev]);
-		commit = lookup_commit_reference(the_repository, &revkey);
-		if (!commit)
-			die(_("cannot find commit %s (%s)"),
-			    ref_name[num_rev], oid_to_hex(&revkey));
-		parse_commit(commit);
-		mark_seen(commit, &seen);
-
-		/* rev#0 uses bit REV_SHIFT, rev#1 uses bit REV_SHIFT+1,
-		 * and so on.  REV_SHIFT bits from bit 0 are used for
-		 * internal bookkeeping.
-		 */
-		commit->object.flags |= flag;
-		if (commit->object.flags == flag)
-			commit_list_insert_by_date(commit, &list);
-		rev[num_rev] = commit;
-	}
-	for (i = 0; i < num_rev; i++)
-		rev_mask[i] = rev[i]->object.flags;
-
-	if (0 <= extra)
-		join_revs(&list, &seen, num_rev, extra);
-
-	commit_list_sort_by_date(&seen);
-
-	if (merge_base)
-		return show_merge_base(seen, num_rev);
-
-	if (independent)
-		return show_independent(rev, num_rev, rev_mask);
-
-	/* Show list; --more=-1 means list-only */
-	if (1 < num_rev || extra < 0) {
-		for (i = 0; i < num_rev; i++) {
-			int j;
-			int is_head = rev_is_head(head,
-						  ref_name[i],
-						  head_oid.hash,
-						  rev[i]->object.oid.hash);
-			if (extra < 0)
-				printf("%c [%s] ",
-				       is_head ? '*' : ' ', ref_name[i]);
-			else {
-				for (j = 0; j < i; j++)
-					putchar(' ');
-				printf("%s%c%s [%s] ",
-				       get_color_code(i),
-				       is_head ? '*' : '!',
-				       get_color_reset_code(), ref_name[i]);
-			}
-
-			if (!reflog) {
-				/* header lines never need name */
-				show_one_commit(rev[i], 1);
-			}
-			else
-				puts(reflog_msg[i]);
-
-			if (is_head)
-				head_at = i;
-		}
-		if (0 <= extra) {
-			for (i = 0; i < num_rev; i++)
-				putchar('-');
-			putchar('\n');
-		}
-	}
-	if (extra < 0)
-		exit(0);
-
-	/* Sort topologically */
-	sort_in_topological_order(&seen, sort_order);
-
-	/* Give names to commits */
-	if (!sha1_name && !no_name)
-		name_commits(seen, rev, ref_name, num_rev);
-
-	all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
-	all_revs = all_mask & ~((1u << REV_SHIFT) - 1);
-
-	while (seen) {
-		struct commit *commit = pop_commit(&seen);
-		int this_flag = commit->object.flags;
-		int is_merge_point = ((this_flag & all_revs) == all_revs);
-
-		shown_merge_point |= is_merge_point;
-
-		if (1 < num_rev) {
-			int is_merge = !!(commit->parents &&
-					  commit->parents->next);
-			if (topics &&
-			    !is_merge_point &&
-			    (this_flag & (1u << REV_SHIFT)))
-				continue;
-			if (dense && is_merge &&
-			    omit_in_dense(commit, rev, num_rev))
-				continue;
-			for (i = 0; i < num_rev; i++) {
-				int mark;
-				if (!(this_flag & (1u << (i + REV_SHIFT))))
-					mark = ' ';
-				else if (is_merge)
-					mark = '-';
-				else if (i == head_at)
-					mark = '*';
-				else
-					mark = '+';
-				printf("%s%c%s",
-				       get_color_code(i),
-				       mark, get_color_reset_code());
-			}
-			putchar(' ');
-		}
-		show_one_commit(commit, no_name);
-
-		if (shown_merge_point && --extra < 0)
-			break;
-	}
-	return 0;
-}
diff --git a/third_party/git/builtin/show-index.c b/third_party/git/builtin/show-index.c
deleted file mode 100644
index 8106b03a6b32..000000000000
--- a/third_party/git/builtin/show-index.c
+++ /dev/null
@@ -1,106 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "pack.h"
-#include "parse-options.h"
-
-static const char *const show_index_usage[] = {
-	"git show-index [--object-format=<hash-algorithm>]",
-	NULL
-};
-
-int cmd_show_index(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	unsigned nr;
-	unsigned int version;
-	static unsigned int top_index[256];
-	unsigned hashsz;
-	const char *hash_name = NULL;
-	int hash_algo;
-	const struct option show_index_options[] = {
-		OPT_STRING(0, "object-format", &hash_name, N_("hash-algorithm"),
-			   N_("specify the hash algorithm to use")),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, show_index_options, show_index_usage, 0);
-
-	if (hash_name) {
-		hash_algo = hash_algo_by_name(hash_name);
-		if (hash_algo == GIT_HASH_UNKNOWN)
-			die(_("Unknown hash algorithm"));
-		repo_set_hash_algo(the_repository, hash_algo);
-	}
-
-	hashsz = the_hash_algo->rawsz;
-
-	if (fread(top_index, 2 * 4, 1, stdin) != 1)
-		die("unable to read header");
-	if (top_index[0] == htonl(PACK_IDX_SIGNATURE)) {
-		version = ntohl(top_index[1]);
-		if (version < 2 || version > 2)
-			die("unknown index version");
-		if (fread(top_index, 256 * 4, 1, stdin) != 1)
-			die("unable to read index");
-	} else {
-		version = 1;
-		if (fread(&top_index[2], 254 * 4, 1, stdin) != 1)
-			die("unable to read index");
-	}
-	nr = 0;
-	for (i = 0; i < 256; i++) {
-		unsigned n = ntohl(top_index[i]);
-		if (n < nr)
-			die("corrupt index file");
-		nr = n;
-	}
-	if (version == 1) {
-		for (i = 0; i < nr; i++) {
-			unsigned int offset, entry[(GIT_MAX_RAWSZ + 4) / sizeof(unsigned int)];
-
-			if (fread(entry, 4 + hashsz, 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)));
-		}
-	} else {
-		unsigned off64_nr = 0;
-		struct {
-			struct object_id oid;
-			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)
-				die("unable to read sha1 %u/%u", i, nr);
-		for (i = 0; i < nr; i++)
-			if (fread(&entries[i].crc, 4, 1, stdin) != 1)
-				die("unable to read crc %u/%u", i, nr);
-		for (i = 0; i < nr; i++)
-			if (fread(&entries[i].off, 4, 1, stdin) != 1)
-				die("unable to read 32b offset %u/%u", i, nr);
-		for (i = 0; i < nr; i++) {
-			uint64_t offset;
-			uint32_t off = ntohl(entries[i].off);
-			if (!(off & 0x80000000)) {
-				offset = off;
-			} else {
-				uint32_t off64[2];
-				if ((off & 0x7fffffff) != off64_nr)
-					die("inconsistent 64b offset index");
-				if (fread(off64, 8, 1, stdin) != 1)
-					die("unable to read 64b offset %u", off64_nr);
-				offset = (((uint64_t)ntohl(off64[0])) << 32) |
-						     ntohl(off64[1]);
-				off64_nr++;
-			}
-			printf("%" PRIuMAX " %s (%08"PRIx32")\n",
-			       (uintmax_t) offset,
-			       oid_to_hex(&entries[i].oid),
-			       ntohl(entries[i].crc));
-		}
-		free(entries);
-	}
-	return 0;
-}
diff --git a/third_party/git/builtin/show-ref.c b/third_party/git/builtin/show-ref.c
deleted file mode 100644
index ae60b4acf2f4..000000000000
--- a/third_party/git/builtin/show-ref.c
+++ /dev/null
@@ -1,226 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "refs.h"
-#include "object-store.h"
-#include "object.h"
-#include "tag.h"
-#include "string-list.h"
-#include "parse-options.h"
-
-static const char * const show_ref_usage[] = {
-	N_("git show-ref [-q | --quiet] [--verify] [--head] [-d | --dereference] [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [<pattern>...]"),
-	N_("git show-ref --exclude-existing[=<pattern>]"),
-	NULL
-};
-
-static int deref_tags, show_head, tags_only, heads_only, found_match, verify,
-	   quiet, hash_only, abbrev, exclude_arg;
-static const char **pattern;
-static const char *exclude_existing_arg;
-
-static void show_one(const char *refname, const struct object_id *oid)
-{
-	const char *hex;
-	struct object_id peeled;
-
-	if (!has_object_file(oid))
-		die("git show-ref: bad ref %s (%s)", refname,
-		    oid_to_hex(oid));
-
-	if (quiet)
-		return;
-
-	hex = find_unique_abbrev(oid, abbrev);
-	if (hash_only)
-		printf("%s\n", hex);
-	else
-		printf("%s %s\n", hex, refname);
-
-	if (!deref_tags)
-		return;
-
-	if (!peel_ref(refname, &peeled)) {
-		hex = find_unique_abbrev(&peeled, abbrev);
-		printf("%s %s^{}\n", hex, refname);
-	}
-}
-
-static int show_ref(const char *refname, const struct object_id *oid,
-		    int flag, void *cbdata)
-{
-	if (show_head && !strcmp(refname, "HEAD"))
-		goto match;
-
-	if (tags_only || heads_only) {
-		int match;
-
-		match = heads_only && starts_with(refname, "refs/heads/");
-		match |= tags_only && starts_with(refname, "refs/tags/");
-		if (!match)
-			return 0;
-	}
-	if (pattern) {
-		int reflen = strlen(refname);
-		const char **p = pattern, *m;
-		while ((m = *p++) != NULL) {
-			int len = strlen(m);
-			if (len > reflen)
-				continue;
-			if (memcmp(m, refname + reflen - len, len))
-				continue;
-			if (len == reflen)
-				goto match;
-			if (refname[reflen - len - 1] == '/')
-				goto match;
-		}
-		return 0;
-	}
-
-match:
-	found_match++;
-
-	show_one(refname, oid);
-
-	return 0;
-}
-
-static int add_existing(const char *refname, const struct object_id *oid,
-			int flag, void *cbdata)
-{
-	struct string_list *list = (struct string_list *)cbdata;
-	string_list_insert(list, refname);
-	return 0;
-}
-
-/*
- * read "^(?:<anything>\s)?<refname>(?:\^\{\})?$" from the standard input,
- * and
- * (1) strip "^{}" at the end of line if any;
- * (2) ignore if match is provided and does not head-match refname;
- * (3) warn if refname is not a well-formed refname and skip;
- * (4) ignore if refname is a ref that exists in the local repository;
- * (5) otherwise output the line.
- */
-static int exclude_existing(const char *match)
-{
-	static struct string_list existing_refs = STRING_LIST_INIT_DUP;
-	char buf[1024];
-	int matchlen = match ? strlen(match) : 0;
-
-	for_each_ref(add_existing, &existing_refs);
-	while (fgets(buf, sizeof(buf), stdin)) {
-		char *ref;
-		int len = strlen(buf);
-
-		if (len > 0 && buf[len - 1] == '\n')
-			buf[--len] = '\0';
-		if (3 <= len && !strcmp(buf + len - 3, "^{}")) {
-			len -= 3;
-			buf[len] = '\0';
-		}
-		for (ref = buf + len; buf < ref; ref--)
-			if (isspace(ref[-1]))
-				break;
-		if (match) {
-			int reflen = buf + len - ref;
-			if (reflen < matchlen)
-				continue;
-			if (strncmp(ref, match, matchlen))
-				continue;
-		}
-		if (check_refname_format(ref, 0)) {
-			warning("ref '%s' ignored", ref);
-			continue;
-		}
-		if (!string_list_has_string(&existing_refs, ref)) {
-			printf("%s\n", buf);
-		}
-	}
-	return 0;
-}
-
-static int hash_callback(const struct option *opt, const char *arg, int unset)
-{
-	hash_only = 1;
-	/* Use full length SHA1 if no argument */
-	if (!arg)
-		return 0;
-	return parse_opt_abbrev_cb(opt, arg, unset);
-}
-
-static int exclude_existing_callback(const struct option *opt, const char *arg,
-				     int unset)
-{
-	BUG_ON_OPT_NEG(unset);
-	exclude_arg = 1;
-	*(const char **)opt->value = arg;
-	return 0;
-}
-
-static const struct option show_ref_options[] = {
-	OPT_BOOL(0, "tags", &tags_only, N_("only show tags (can be combined with heads)")),
-	OPT_BOOL(0, "heads", &heads_only, N_("only show heads (can be combined with tags)")),
-	OPT_BOOL(0, "verify", &verify, N_("stricter reference checking, "
-		    "requires exact ref path")),
-	OPT_HIDDEN_BOOL('h', NULL, &show_head,
-			N_("show the HEAD reference, even if it would be filtered out")),
-	OPT_BOOL(0, "head", &show_head,
-	  N_("show the HEAD reference, even if it would be filtered out")),
-	OPT_BOOL('d', "dereference", &deref_tags,
-		    N_("dereference tags into object IDs")),
-	OPT_CALLBACK_F('s', "hash", &abbrev, N_("n"),
-		       N_("only show SHA1 hash using <n> digits"),
-		       PARSE_OPT_OPTARG, &hash_callback),
-	OPT__ABBREV(&abbrev),
-	OPT__QUIET(&quiet,
-		   N_("do not print results to stdout (useful with --verify)")),
-	OPT_CALLBACK_F(0, "exclude-existing", &exclude_existing_arg,
-		       N_("pattern"), N_("show refs from stdin that aren't in local repository"),
-		       PARSE_OPT_OPTARG | PARSE_OPT_NONEG, exclude_existing_callback),
-	OPT_END()
-};
-
-int cmd_show_ref(int argc, const char **argv, const char *prefix)
-{
-	git_config(git_default_config, NULL);
-
-	argc = parse_options(argc, argv, prefix, show_ref_options,
-			     show_ref_usage, 0);
-
-	if (exclude_arg)
-		return exclude_existing(exclude_existing_arg);
-
-	pattern = argv;
-	if (!*pattern)
-		pattern = NULL;
-
-	if (verify) {
-		if (!pattern)
-			die("--verify requires a reference");
-		while (*pattern) {
-			struct object_id oid;
-
-			if ((starts_with(*pattern, "refs/") || !strcmp(*pattern, "HEAD")) &&
-			    !read_ref(*pattern, &oid)) {
-				show_one(*pattern, &oid);
-			}
-			else if (!quiet)
-				die("'%s' - not a valid ref", *pattern);
-			else
-				return 1;
-			pattern++;
-		}
-		return 0;
-	}
-
-	if (show_head)
-		head_ref(show_ref, NULL);
-	for_each_ref(show_ref, NULL);
-	if (!found_match) {
-		if (verify && !quiet)
-			die("No match");
-		return 1;
-	}
-	return 0;
-}
diff --git a/third_party/git/builtin/sparse-checkout.c b/third_party/git/builtin/sparse-checkout.c
deleted file mode 100644
index e3140db2a0a6..000000000000
--- a/third_party/git/builtin/sparse-checkout.c
+++ /dev/null
@@ -1,663 +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|reapply|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 char const * const builtin_sparse_checkout_list_usage[] = {
-	N_("git sparse-checkout list"),
-	NULL
-};
-
-static int sparse_checkout_list(int argc, const char **argv)
-{
-	static struct option builtin_sparse_checkout_list_options[] = {
-		OPT_END(),
-	};
-	struct pattern_list pl;
-	char *sparse_filename;
-	int res;
-
-	argc = parse_options(argc, argv, NULL,
-			     builtin_sparse_checkout_list_options,
-			     builtin_sparse_checkout_list_usage, 0);
-
-	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)
-{
-	enum update_sparsity_result result;
-	struct unpack_trees_options o;
-	struct lock_file lock_file = LOCK_INIT;
-	struct repository *r = the_repository;
-
-	/* If no branch has been checked out, there are no updates to make. */
-	if (is_index_unborn(r->index))
-		return UPDATE_SPARSITY_SUCCESS;
-
-	memset(&o, 0, sizeof(o));
-	o.verbose_update = isatty(2);
-	o.update = 1;
-	o.head_idx = -1;
-	o.src_index = r->index;
-	o.dst_index = r->index;
-	o.skip_sparse_checkout = 0;
-	o.pl = pl;
-
-	setup_work_tree();
-
-	repo_hold_locked_index(r, &lock_file, LOCK_DIE_ON_ERROR);
-
-	setup_unpack_trees_porcelain(&o, "sparse-checkout");
-	result = update_sparsity(&o);
-	clear_unpack_trees_porcelain(&o);
-
-	if (result == UPDATE_SPARSITY_WARNINGS)
-		/*
-		 * We don't do any special handling of warnings from untracked
-		 * files in the way or dirty entries that can't be removed.
-		 */
-		result = UPDATE_SPARSITY_SUCCESS;
-	if (result == UPDATE_SPARSITY_SUCCESS)
-		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 (upgrade_repository_format(1) < 0)
-		die(_("unable to upgrade repository format to enable worktreeConfig"));
-	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);
-
-	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);
-
-	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 char const * const builtin_sparse_checkout_reapply_usage[] = {
-	N_("git sparse-checkout reapply"),
-	NULL
-};
-
-static int sparse_checkout_reapply(int argc, const char **argv)
-{
-	static struct option builtin_sparse_checkout_reapply_options[] = {
-		OPT_END(),
-	};
-
-	argc = parse_options(argc, argv, NULL,
-			     builtin_sparse_checkout_reapply_options,
-			     builtin_sparse_checkout_reapply_usage, 0);
-
-	repo_read_index(the_repository);
-	return update_working_directory(NULL);
-}
-
-static char const * const builtin_sparse_checkout_disable_usage[] = {
-	N_("git sparse-checkout disable"),
-	NULL
-};
-
-static int sparse_checkout_disable(int argc, const char **argv)
-{
-	static struct option builtin_sparse_checkout_disable_options[] = {
-		OPT_END(),
-	};
-	struct pattern_list pl;
-	struct strbuf match_all = STRBUF_INIT;
-
-	argc = parse_options(argc, argv, NULL,
-			     builtin_sparse_checkout_disable_options,
-			     builtin_sparse_checkout_disable_usage, 0);
-
-	repo_read_index(the_repository);
-
-	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], "reapply"))
-			return sparse_checkout_reapply(argc, argv);
-		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
deleted file mode 100644
index 3f811f30506a..000000000000
--- a/third_party/git/builtin/stash.c
+++ /dev/null
@@ -1,1612 +0,0 @@
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "config.h"
-#include "parse-options.h"
-#include "refs.h"
-#include "lockfile.h"
-#include "cache-tree.h"
-#include "unpack-trees.h"
-#include "merge-recursive.h"
-#include "strvec.h"
-#include "run-command.h"
-#include "dir.h"
-#include "rerere.h"
-#include "revision.h"
-#include "log-tree.h"
-#include "diffcore.h"
-#include "exec-cmd.h"
-
-#define INCLUDE_ALL_FILES 2
-
-static const char * const git_stash_usage[] = {
-	N_("git stash list [<options>]"),
-	N_("git stash show [<options>] [<stash>]"),
-	N_("git stash drop [-q|--quiet] [<stash>]"),
-	N_("git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>]"),
-	N_("git stash branch <branchname> [<stash>]"),
-	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>]"),
-	NULL
-};
-
-static const char * const git_stash_list_usage[] = {
-	N_("git stash list [<options>]"),
-	NULL
-};
-
-static const char * const git_stash_show_usage[] = {
-	N_("git stash show [<options>] [<stash>]"),
-	NULL
-};
-
-static const char * const git_stash_drop_usage[] = {
-	N_("git stash drop [-q|--quiet] [<stash>]"),
-	NULL
-};
-
-static const char * const git_stash_pop_usage[] = {
-	N_("git stash pop [--index] [-q|--quiet] [<stash>]"),
-	NULL
-};
-
-static const char * const git_stash_apply_usage[] = {
-	N_("git stash apply [--index] [-q|--quiet] [<stash>]"),
-	NULL
-};
-
-static const char * const git_stash_branch_usage[] = {
-	N_("git stash branch <branchname> [<stash>]"),
-	NULL
-};
-
-static const char * const git_stash_clear_usage[] = {
-	N_("git stash clear"),
-	NULL
-};
-
-static const char * const git_stash_store_usage[] = {
-	N_("git stash store [-m|--message <message>] [-q|--quiet] <commit>"),
-	NULL
-};
-
-static const char * const git_stash_push_usage[] = {
-	N_("git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
-	   "          [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"
-	   "          [--] [<pathspec>...]]"),
-	NULL
-};
-
-static const char * const git_stash_save_usage[] = {
-	N_("git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
-	   "          [-u|--include-untracked] [-a|--all] [<message>]"),
-	NULL
-};
-
-static const char *ref_stash = "refs/stash";
-static struct strbuf stash_index_path = STRBUF_INIT;
-
-/*
- * w_commit is set to the commit containing the working tree
- * b_commit is set to the base commit
- * i_commit is set to the commit containing the index tree
- * u_commit is set to the commit containing the untracked files tree
- * w_tree is set to the working tree
- * b_tree is set to the base tree
- * i_tree is set to the index tree
- * u_tree is set to the untracked files tree
- */
-struct stash_info {
-	struct object_id w_commit;
-	struct object_id b_commit;
-	struct object_id i_commit;
-	struct object_id u_commit;
-	struct object_id w_tree;
-	struct object_id b_tree;
-	struct object_id i_tree;
-	struct object_id u_tree;
-	struct strbuf revision;
-	int is_stash_ref;
-	int has_u;
-};
-
-static void free_stash_info(struct stash_info *info)
-{
-	strbuf_release(&info->revision);
-}
-
-static void assert_stash_like(struct stash_info *info, const char *revision)
-{
-	if (get_oidf(&info->b_commit, "%s^1", revision) ||
-	    get_oidf(&info->w_tree, "%s:", revision) ||
-	    get_oidf(&info->b_tree, "%s^1:", revision) ||
-	    get_oidf(&info->i_tree, "%s^2:", revision))
-		die(_("'%s' is not a stash-like commit"), revision);
-}
-
-static int get_stash_info(struct stash_info *info, int argc, const char **argv)
-{
-	int ret;
-	char *end_of_rev;
-	char *expanded_ref;
-	const char *revision;
-	const char *commit = NULL;
-	struct object_id dummy;
-	struct strbuf symbolic = STRBUF_INIT;
-
-	if (argc > 1) {
-		int i;
-		struct strbuf refs_msg = STRBUF_INIT;
-
-		for (i = 0; i < argc; i++)
-			strbuf_addf(&refs_msg, " '%s'", argv[i]);
-
-		fprintf_ln(stderr, _("Too many revisions specified:%s"),
-			   refs_msg.buf);
-		strbuf_release(&refs_msg);
-
-		return -1;
-	}
-
-	if (argc == 1)
-		commit = argv[0];
-
-	strbuf_init(&info->revision, 0);
-	if (!commit) {
-		if (!ref_exists(ref_stash)) {
-			free_stash_info(info);
-			fprintf_ln(stderr, _("No stash entries found."));
-			return -1;
-		}
-
-		strbuf_addf(&info->revision, "%s@{0}", ref_stash);
-	} else if (strspn(commit, "0123456789") == strlen(commit)) {
-		strbuf_addf(&info->revision, "%s@{%s}", ref_stash, commit);
-	} else {
-		strbuf_addstr(&info->revision, commit);
-	}
-
-	revision = info->revision.buf;
-
-	if (get_oid(revision, &info->w_commit)) {
-		error(_("%s is not a valid reference"), revision);
-		free_stash_info(info);
-		return -1;
-	}
-
-	assert_stash_like(info, revision);
-
-	info->has_u = !get_oidf(&info->u_tree, "%s^3:", revision);
-
-	end_of_rev = strchrnul(revision, '@');
-	strbuf_add(&symbolic, revision, end_of_rev - revision);
-
-	ret = dwim_ref(symbolic.buf, symbolic.len, &dummy, &expanded_ref, 0);
-	strbuf_release(&symbolic);
-	switch (ret) {
-	case 0: /* Not found, but valid ref */
-		info->is_stash_ref = 0;
-		break;
-	case 1:
-		info->is_stash_ref = !strcmp(expanded_ref, ref_stash);
-		break;
-	default: /* Invalid or ambiguous */
-		free_stash_info(info);
-	}
-
-	free(expanded_ref);
-	return !(ret == 0 || ret == 1);
-}
-
-static int do_clear_stash(void)
-{
-	struct object_id obj;
-	if (get_oid(ref_stash, &obj))
-		return 0;
-
-	return delete_ref(NULL, ref_stash, &obj, 0);
-}
-
-static int clear_stash(int argc, const char **argv, const char *prefix)
-{
-	struct option options[] = {
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, options,
-			     git_stash_clear_usage,
-			     PARSE_OPT_STOP_AT_NON_OPTION);
-
-	if (argc)
-		return error(_("git stash clear with parameters is "
-			       "unimplemented"));
-
-	return do_clear_stash();
-}
-
-static int reset_tree(struct object_id *i_tree, int update, int reset)
-{
-	int nr_trees = 1;
-	struct unpack_trees_options opts;
-	struct tree_desc t[MAX_UNPACK_TREES];
-	struct tree *tree;
-	struct lock_file lock_file = LOCK_INIT;
-
-	read_cache_preload(NULL);
-	if (refresh_cache(REFRESH_QUIET))
-		return -1;
-
-	hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
-
-	memset(&opts, 0, sizeof(opts));
-
-	tree = parse_tree_indirect(i_tree);
-	if (parse_tree(tree))
-		return -1;
-
-	init_tree_desc(t, tree->buffer, tree->size);
-
-	opts.head_idx = 1;
-	opts.src_index = &the_index;
-	opts.dst_index = &the_index;
-	opts.merge = 1;
-	opts.reset = reset;
-	opts.update = update;
-	opts.fn = oneway_merge;
-
-	if (unpack_trees(nr_trees, t, &opts))
-		return -1;
-
-	if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
-		return error(_("unable to write new index file"));
-
-	return 0;
-}
-
-static int diff_tree_binary(struct strbuf *out, struct object_id *w_commit)
-{
-	struct child_process cp = CHILD_PROCESS_INIT;
-	const char *w_commit_hex = oid_to_hex(w_commit);
-
-	/*
-	 * Diff-tree would not be very hard to replace with a native function,
-	 * however it should be done together with apply_cached.
-	 */
-	cp.git_cmd = 1;
-	strvec_pushl(&cp.args, "diff-tree", "--binary", NULL);
-	strvec_pushf(&cp.args, "%s^2^..%s^2", w_commit_hex, w_commit_hex);
-
-	return pipe_command(&cp, NULL, 0, out, 0, NULL, 0);
-}
-
-static int apply_cached(struct strbuf *out)
-{
-	struct child_process cp = CHILD_PROCESS_INIT;
-
-	/*
-	 * Apply currently only reads either from stdin or a file, thus
-	 * apply_all_patches would have to be updated to optionally take a
-	 * buffer.
-	 */
-	cp.git_cmd = 1;
-	strvec_pushl(&cp.args, "apply", "--cached", NULL);
-	return pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 0);
-}
-
-static int reset_head(void)
-{
-	struct child_process cp = CHILD_PROCESS_INIT;
-
-	/*
-	 * Reset is overall quite simple, however there is no current public
-	 * API for resetting.
-	 */
-	cp.git_cmd = 1;
-	strvec_push(&cp.args, "reset");
-
-	return run_command(&cp);
-}
-
-static void add_diff_to_buf(struct diff_queue_struct *q,
-			    struct diff_options *options,
-			    void *data)
-{
-	int i;
-
-	for (i = 0; i < q->nr; i++) {
-		strbuf_addstr(data, q->queue[i]->one->path);
-
-		/* NUL-terminate: will be fed to update-index -z */
-		strbuf_addch(data, '\0');
-	}
-}
-
-static int get_newly_staged(struct strbuf *out, struct object_id *c_tree)
-{
-	struct child_process cp = CHILD_PROCESS_INIT;
-	const char *c_tree_hex = oid_to_hex(c_tree);
-
-	/*
-	 * diff-index is very similar to diff-tree above, and should be
-	 * converted together with update_index.
-	 */
-	cp.git_cmd = 1;
-	strvec_pushl(&cp.args, "diff-index", "--cached", "--name-only",
-		     "--diff-filter=A", NULL);
-	strvec_push(&cp.args, c_tree_hex);
-	return pipe_command(&cp, NULL, 0, out, 0, NULL, 0);
-}
-
-static int update_index(struct strbuf *out)
-{
-	struct child_process cp = CHILD_PROCESS_INIT;
-
-	/*
-	 * Update-index is very complicated and may need to have a public
-	 * function exposed in order to remove this forking.
-	 */
-	cp.git_cmd = 1;
-	strvec_pushl(&cp.args, "update-index", "--add", "--stdin", NULL);
-	return pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 0);
-}
-
-static int restore_untracked(struct object_id *u_tree)
-{
-	int res;
-	struct child_process cp = CHILD_PROCESS_INIT;
-
-	/*
-	 * We need to run restore files from a given index, but without
-	 * affecting the current index, so we use GIT_INDEX_FILE with
-	 * run_command to fork processes that will not interfere.
-	 */
-	cp.git_cmd = 1;
-	strvec_push(&cp.args, "read-tree");
-	strvec_push(&cp.args, oid_to_hex(u_tree));
-	strvec_pushf(&cp.env_array, "GIT_INDEX_FILE=%s",
-		     stash_index_path.buf);
-	if (run_command(&cp)) {
-		remove_path(stash_index_path.buf);
-		return -1;
-	}
-
-	child_process_init(&cp);
-	cp.git_cmd = 1;
-	strvec_pushl(&cp.args, "checkout-index", "--all", NULL);
-	strvec_pushf(&cp.env_array, "GIT_INDEX_FILE=%s",
-		     stash_index_path.buf);
-
-	res = run_command(&cp);
-	remove_path(stash_index_path.buf);
-	return res;
-}
-
-static int do_apply_stash(const char *prefix, struct stash_info *info,
-			  int index, int quiet)
-{
-	int ret;
-	int has_index = index;
-	struct merge_options o;
-	struct object_id c_tree;
-	struct object_id index_tree;
-	struct commit *result;
-	const struct object_id *bases[1];
-
-	read_cache_preload(NULL);
-	if (refresh_and_write_cache(REFRESH_QUIET, 0, 0))
-		return -1;
-
-	if (write_cache_as_tree(&c_tree, 0, NULL))
-		return error(_("cannot apply a stash in the middle of a merge"));
-
-	if (index) {
-		if (oideq(&info->b_tree, &info->i_tree) ||
-		    oideq(&c_tree, &info->i_tree)) {
-			has_index = 0;
-		} else {
-			struct strbuf out = STRBUF_INIT;
-
-			if (diff_tree_binary(&out, &info->w_commit)) {
-				strbuf_release(&out);
-				return error(_("could not generate diff %s^!."),
-					     oid_to_hex(&info->w_commit));
-			}
-
-			ret = apply_cached(&out);
-			strbuf_release(&out);
-			if (ret)
-				return error(_("conflicts in index."
-					       "Try without --index."));
-
-			discard_cache();
-			read_cache();
-			if (write_cache_as_tree(&index_tree, 0, NULL))
-				return error(_("could not save index tree"));
-
-			reset_head();
-			discard_cache();
-			read_cache();
-		}
-	}
-
-	if (info->has_u && restore_untracked(&info->u_tree))
-		return error(_("could not restore untracked files from stash"));
-
-	init_merge_options(&o, the_repository);
-
-	o.branch1 = "Updated upstream";
-	o.branch2 = "Stashed changes";
-
-	if (oideq(&info->b_tree, &c_tree))
-		o.branch1 = "Version stash was based on";
-
-	if (quiet)
-		o.verbosity = 0;
-
-	if (o.verbosity >= 3)
-		printf_ln(_("Merging %s with %s"), o.branch1, o.branch2);
-
-	bases[0] = &info->b_tree;
-
-	ret = merge_recursive_generic(&o, &c_tree, &info->w_tree, 1, bases,
-				      &result);
-	if (ret) {
-		rerere(0);
-
-		if (index)
-			fprintf_ln(stderr, _("Index was not unstashed."));
-
-		return ret;
-	}
-
-	if (has_index) {
-		if (reset_tree(&index_tree, 0, 0))
-			return -1;
-	} else {
-		struct strbuf out = STRBUF_INIT;
-
-		if (get_newly_staged(&out, &c_tree)) {
-			strbuf_release(&out);
-			return -1;
-		}
-
-		if (reset_tree(&c_tree, 0, 1)) {
-			strbuf_release(&out);
-			return -1;
-		}
-
-		ret = update_index(&out);
-		strbuf_release(&out);
-		if (ret)
-			return -1;
-
-		/* read back the result of update_index() back from the disk */
-		discard_cache();
-		read_cache();
-	}
-
-	if (!quiet) {
-		struct child_process cp = CHILD_PROCESS_INIT;
-
-		/*
-		 * Status is quite simple and could be replaced with calls to
-		 * wt_status in the future, but it adds complexities which may
-		 * require more tests.
-		 */
-		cp.git_cmd = 1;
-		cp.dir = prefix;
-		strvec_pushf(&cp.env_array, GIT_WORK_TREE_ENVIRONMENT"=%s",
-			     absolute_path(get_git_work_tree()));
-		strvec_pushf(&cp.env_array, GIT_DIR_ENVIRONMENT"=%s",
-			     absolute_path(get_git_dir()));
-		strvec_push(&cp.args, "status");
-		run_command(&cp);
-	}
-
-	return 0;
-}
-
-static int apply_stash(int argc, const char **argv, const char *prefix)
-{
-	int ret;
-	int quiet = 0;
-	int index = 0;
-	struct stash_info info;
-	struct option options[] = {
-		OPT__QUIET(&quiet, N_("be quiet, only report errors")),
-		OPT_BOOL(0, "index", &index,
-			 N_("attempt to recreate the index")),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, options,
-			     git_stash_apply_usage, 0);
-
-	if (get_stash_info(&info, argc, argv))
-		return -1;
-
-	ret = do_apply_stash(prefix, &info, index, quiet);
-	free_stash_info(&info);
-	return ret;
-}
-
-static int do_drop_stash(struct stash_info *info, int quiet)
-{
-	int ret;
-	struct child_process cp_reflog = CHILD_PROCESS_INIT;
-	struct child_process cp = CHILD_PROCESS_INIT;
-
-	/*
-	 * reflog does not provide a simple function for deleting refs. One will
-	 * need to be added to avoid implementing too much reflog code here
-	 */
-
-	cp_reflog.git_cmd = 1;
-	strvec_pushl(&cp_reflog.args, "reflog", "delete", "--updateref",
-		     "--rewrite", NULL);
-	strvec_push(&cp_reflog.args, info->revision.buf);
-	ret = run_command(&cp_reflog);
-	if (!ret) {
-		if (!quiet)
-			printf_ln(_("Dropped %s (%s)"), info->revision.buf,
-				  oid_to_hex(&info->w_commit));
-	} else {
-		return error(_("%s: Could not drop stash entry"),
-			     info->revision.buf);
-	}
-
-	/*
-	 * This could easily be replaced by get_oid, but currently it will throw
-	 * a fatal error when a reflog is empty, which we can not recover from.
-	 */
-	cp.git_cmd = 1;
-	/* Even though --quiet is specified, rev-parse still outputs the hash */
-	cp.no_stdout = 1;
-	strvec_pushl(&cp.args, "rev-parse", "--verify", "--quiet", NULL);
-	strvec_pushf(&cp.args, "%s@{0}", ref_stash);
-	ret = run_command(&cp);
-
-	/* do_clear_stash if we just dropped the last stash entry */
-	if (ret)
-		do_clear_stash();
-
-	return 0;
-}
-
-static void assert_stash_ref(struct stash_info *info)
-{
-	if (!info->is_stash_ref) {
-		error(_("'%s' is not a stash reference"), info->revision.buf);
-		free_stash_info(info);
-		exit(1);
-	}
-}
-
-static int drop_stash(int argc, const char **argv, const char *prefix)
-{
-	int ret;
-	int quiet = 0;
-	struct stash_info info;
-	struct option options[] = {
-		OPT__QUIET(&quiet, N_("be quiet, only report errors")),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, options,
-			     git_stash_drop_usage, 0);
-
-	if (get_stash_info(&info, argc, argv))
-		return -1;
-
-	assert_stash_ref(&info);
-
-	ret = do_drop_stash(&info, quiet);
-	free_stash_info(&info);
-	return ret;
-}
-
-static int pop_stash(int argc, const char **argv, const char *prefix)
-{
-	int ret;
-	int index = 0;
-	int quiet = 0;
-	struct stash_info info;
-	struct option options[] = {
-		OPT__QUIET(&quiet, N_("be quiet, only report errors")),
-		OPT_BOOL(0, "index", &index,
-			 N_("attempt to recreate the index")),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, options,
-			     git_stash_pop_usage, 0);
-
-	if (get_stash_info(&info, argc, argv))
-		return -1;
-
-	assert_stash_ref(&info);
-	if ((ret = do_apply_stash(prefix, &info, index, quiet)))
-		printf_ln(_("The stash entry is kept in case "
-			    "you need it again."));
-	else
-		ret = do_drop_stash(&info, quiet);
-
-	free_stash_info(&info);
-	return ret;
-}
-
-static int branch_stash(int argc, const char **argv, const char *prefix)
-{
-	int ret;
-	const char *branch = NULL;
-	struct stash_info info;
-	struct child_process cp = CHILD_PROCESS_INIT;
-	struct option options[] = {
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, options,
-			     git_stash_branch_usage, 0);
-
-	if (!argc) {
-		fprintf_ln(stderr, _("No branch name specified"));
-		return -1;
-	}
-
-	branch = argv[0];
-
-	if (get_stash_info(&info, argc - 1, argv + 1))
-		return -1;
-
-	cp.git_cmd = 1;
-	strvec_pushl(&cp.args, "checkout", "-b", NULL);
-	strvec_push(&cp.args, branch);
-	strvec_push(&cp.args, oid_to_hex(&info.b_commit));
-	ret = run_command(&cp);
-	if (!ret)
-		ret = do_apply_stash(prefix, &info, 1, 0);
-	if (!ret && info.is_stash_ref)
-		ret = do_drop_stash(&info, 0);
-
-	free_stash_info(&info);
-
-	return ret;
-}
-
-static int list_stash(int argc, const char **argv, const char *prefix)
-{
-	struct child_process cp = CHILD_PROCESS_INIT;
-	struct option options[] = {
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, options,
-			     git_stash_list_usage,
-			     PARSE_OPT_KEEP_UNKNOWN);
-
-	if (!ref_exists(ref_stash))
-		return 0;
-
-	cp.git_cmd = 1;
-	strvec_pushl(&cp.args, "log", "--format=%gd: %gs", "-g",
-		     "--first-parent", "-m", NULL);
-	strvec_pushv(&cp.args, argv);
-	strvec_push(&cp.args, ref_stash);
-	strvec_push(&cp.args, "--");
-	return run_command(&cp);
-}
-
-static int show_stat = 1;
-static int show_patch;
-static int use_legacy_stash;
-
-static int git_stash_config(const char *var, const char *value, void *cb)
-{
-	if (!strcmp(var, "stash.showstat")) {
-		show_stat = git_config_bool(var, value);
-		return 0;
-	}
-	if (!strcmp(var, "stash.showpatch")) {
-		show_patch = git_config_bool(var, value);
-		return 0;
-	}
-	if (!strcmp(var, "stash.usebuiltin")) {
-		use_legacy_stash = !git_config_bool(var, value);
-		return 0;
-	}
-	return git_diff_basic_config(var, value, cb);
-}
-
-static int show_stash(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	int ret = 0;
-	struct stash_info info;
-	struct rev_info rev;
-	struct strvec stash_args = STRVEC_INIT;
-	struct strvec revision_args = STRVEC_INIT;
-	struct option options[] = {
-		OPT_END()
-	};
-
-	init_diff_ui_defaults();
-	git_config(git_diff_ui_config, NULL);
-	init_revisions(&rev, prefix);
-
-	strvec_push(&revision_args, argv[0]);
-	for (i = 1; i < argc; i++) {
-		if (argv[i][0] != '-')
-			strvec_push(&stash_args, argv[i]);
-		else
-			strvec_push(&revision_args, argv[i]);
-	}
-
-	ret = get_stash_info(&info, stash_args.nr, stash_args.v);
-	strvec_clear(&stash_args);
-	if (ret)
-		return -1;
-
-	/*
-	 * The config settings are applied only if there are not passed
-	 * any options.
-	 */
-	if (revision_args.nr == 1) {
-		if (show_stat)
-			rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT;
-
-		if (show_patch)
-			rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
-
-		if (!show_stat && !show_patch) {
-			free_stash_info(&info);
-			return 0;
-		}
-	}
-
-	argc = setup_revisions(revision_args.nr, revision_args.v, &rev, NULL);
-	if (argc > 1) {
-		free_stash_info(&info);
-		usage_with_options(git_stash_show_usage, options);
-	}
-	if (!rev.diffopt.output_format) {
-		rev.diffopt.output_format = DIFF_FORMAT_PATCH;
-		diff_setup_done(&rev.diffopt);
-	}
-
-	rev.diffopt.flags.recursive = 1;
-	setup_diff_pager(&rev.diffopt);
-	diff_tree_oid(&info.b_commit, &info.w_commit, "", &rev.diffopt);
-	log_tree_diff_flush(&rev);
-
-	free_stash_info(&info);
-	return diff_result_code(&rev.diffopt, 0);
-}
-
-static int do_store_stash(const struct object_id *w_commit, const char *stash_msg,
-			  int quiet)
-{
-	if (!stash_msg)
-		stash_msg = "Created via \"git stash store\".";
-
-	if (update_ref(stash_msg, ref_stash, w_commit, NULL,
-		       REF_FORCE_CREATE_REFLOG,
-		       quiet ? UPDATE_REFS_QUIET_ON_ERR :
-		       UPDATE_REFS_MSG_ON_ERR)) {
-		if (!quiet) {
-			fprintf_ln(stderr, _("Cannot update %s with %s"),
-				   ref_stash, oid_to_hex(w_commit));
-		}
-		return -1;
-	}
-
-	return 0;
-}
-
-static int store_stash(int argc, const char **argv, const char *prefix)
-{
-	int quiet = 0;
-	const char *stash_msg = NULL;
-	struct object_id obj;
-	struct object_context dummy;
-	struct option options[] = {
-		OPT__QUIET(&quiet, N_("be quiet")),
-		OPT_STRING('m', "message", &stash_msg, "message",
-			   N_("stash message")),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, options,
-			     git_stash_store_usage,
-			     PARSE_OPT_KEEP_UNKNOWN);
-
-	if (argc != 1) {
-		if (!quiet)
-			fprintf_ln(stderr, _("\"git stash store\" requires one "
-					     "<commit> argument"));
-		return -1;
-	}
-
-	if (get_oid_with_context(the_repository,
-				 argv[0], quiet ? GET_OID_QUIETLY : 0, &obj,
-				 &dummy)) {
-		if (!quiet)
-			fprintf_ln(stderr, _("Cannot update %s with %s"),
-					     ref_stash, argv[0]);
-		return -1;
-	}
-
-	return do_store_stash(&obj, stash_msg, quiet);
-}
-
-static void add_pathspecs(struct strvec *args,
-			  const struct pathspec *ps) {
-	int i;
-
-	for (i = 0; i < ps->nr; i++)
-		strvec_push(args, ps->items[i].original);
-}
-
-/*
- * `untracked_files` will be filled with the names of untracked files.
- * The return value is:
- *
- * = 0 if there are not any untracked files
- * > 0 if there are untracked files
- */
-static int get_untracked_files(const struct pathspec *ps, int include_untracked,
-			       struct strbuf *untracked_files)
-{
-	int i;
-	int found = 0;
-	struct dir_struct dir;
-
-	dir_init(&dir);
-	if (include_untracked != INCLUDE_ALL_FILES)
-		setup_standard_excludes(&dir);
-
-	fill_directory(&dir, the_repository->index, ps);
-	for (i = 0; i < dir.nr; i++) {
-		struct dir_entry *ent = dir.entries[i];
-		found++;
-		strbuf_addstr(untracked_files, ent->name);
-		/* NUL-terminate: will be fed to update-index -z */
-		strbuf_addch(untracked_files, '\0');
-	}
-
-	dir_clear(&dir);
-	return found;
-}
-
-/*
- * The return value of `check_changes_tracked_files()` can be:
- *
- * < 0 if there was an error
- * = 0 if there are no changes.
- * > 0 if there are changes.
- */
-static int check_changes_tracked_files(const struct pathspec *ps)
-{
-	int result;
-	struct rev_info rev;
-	struct object_id dummy;
-	int ret = 0;
-
-	/* No initial commit. */
-	if (get_oid("HEAD", &dummy))
-		return -1;
-
-	if (read_cache() < 0)
-		return -1;
-
-	init_revisions(&rev, NULL);
-	copy_pathspec(&rev.prune_data, ps);
-
-	rev.diffopt.flags.quick = 1;
-	rev.diffopt.flags.ignore_submodules = 1;
-	rev.abbrev = 0;
-
-	add_head_to_pending(&rev);
-	diff_setup_done(&rev.diffopt);
-
-	result = run_diff_index(&rev, 1);
-	if (diff_result_code(&rev.diffopt, result)) {
-		ret = 1;
-		goto done;
-	}
-
-	object_array_clear(&rev.pending);
-	result = run_diff_files(&rev, 0);
-	if (diff_result_code(&rev.diffopt, result)) {
-		ret = 1;
-		goto done;
-	}
-
-done:
-	clear_pathspec(&rev.prune_data);
-	return ret;
-}
-
-/*
- * The function will fill `untracked_files` with the names of untracked files
- * It will return 1 if there were any changes and 0 if there were not.
- */
-static int check_changes(const struct pathspec *ps, int include_untracked,
-			 struct strbuf *untracked_files)
-{
-	int ret = 0;
-	if (check_changes_tracked_files(ps))
-		ret = 1;
-
-	if (include_untracked && get_untracked_files(ps, include_untracked,
-						     untracked_files))
-		ret = 1;
-
-	return ret;
-}
-
-static int save_untracked_files(struct stash_info *info, struct strbuf *msg,
-				struct strbuf files)
-{
-	int ret = 0;
-	struct strbuf untracked_msg = STRBUF_INIT;
-	struct child_process cp_upd_index = CHILD_PROCESS_INIT;
-	struct index_state istate = { NULL };
-
-	cp_upd_index.git_cmd = 1;
-	strvec_pushl(&cp_upd_index.args, "update-index", "-z", "--add",
-		     "--remove", "--stdin", NULL);
-	strvec_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s",
-			 stash_index_path.buf);
-
-	strbuf_addf(&untracked_msg, "untracked files on %s\n", msg->buf);
-	if (pipe_command(&cp_upd_index, files.buf, files.len, NULL, 0,
-			 NULL, 0)) {
-		ret = -1;
-		goto done;
-	}
-
-	if (write_index_as_tree(&info->u_tree, &istate, stash_index_path.buf, 0,
-				NULL)) {
-		ret = -1;
-		goto done;
-	}
-
-	if (commit_tree(untracked_msg.buf, untracked_msg.len,
-			&info->u_tree, NULL, &info->u_commit, NULL, NULL)) {
-		ret = -1;
-		goto done;
-	}
-
-done:
-	discard_index(&istate);
-	strbuf_release(&untracked_msg);
-	remove_path(stash_index_path.buf);
-	return ret;
-}
-
-static int stash_patch(struct stash_info *info, const struct pathspec *ps,
-		       struct strbuf *out_patch, int quiet)
-{
-	int ret = 0;
-	struct child_process cp_read_tree = 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);
-
-	cp_read_tree.git_cmd = 1;
-	strvec_pushl(&cp_read_tree.args, "read-tree", "HEAD", NULL);
-	strvec_pushf(&cp_read_tree.env_array, "GIT_INDEX_FILE=%s",
-		     stash_index_path.buf);
-	if (run_command(&cp_read_tree)) {
-		ret = -1;
-		goto done;
-	}
-
-	/* 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);
-
-	/* State of the working tree. */
-	if (write_index_as_tree(&info->w_tree, &istate, stash_index_path.buf, 0,
-				NULL)) {
-		ret = -1;
-		goto done;
-	}
-
-	cp_diff_tree.git_cmd = 1;
-	strvec_pushl(&cp_diff_tree.args, "diff-tree", "-p", "-U1", "HEAD",
-		     oid_to_hex(&info->w_tree), "--", NULL);
-	if (pipe_command(&cp_diff_tree, NULL, 0, out_patch, 0, NULL, 0)) {
-		ret = -1;
-		goto done;
-	}
-
-	if (!out_patch->len) {
-		if (!quiet)
-			fprintf_ln(stderr, _("No changes selected"));
-		ret = 1;
-	}
-
-done:
-	discard_index(&istate);
-	remove_path(stash_index_path.buf);
-	return ret;
-}
-
-static int stash_working_tree(struct stash_info *info, const struct pathspec *ps)
-{
-	int ret = 0;
-	struct rev_info rev;
-	struct child_process cp_upd_index = CHILD_PROCESS_INIT;
-	struct strbuf diff_output = STRBUF_INIT;
-	struct index_state istate = { NULL };
-
-	init_revisions(&rev, NULL);
-	copy_pathspec(&rev.prune_data, ps);
-
-	set_alternate_index_output(stash_index_path.buf);
-	if (reset_tree(&info->i_tree, 0, 0)) {
-		ret = -1;
-		goto done;
-	}
-	set_alternate_index_output(NULL);
-
-	rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
-	rev.diffopt.format_callback = add_diff_to_buf;
-	rev.diffopt.format_callback_data = &diff_output;
-
-	if (read_cache_preload(&rev.diffopt.pathspec) < 0) {
-		ret = -1;
-		goto done;
-	}
-
-	add_pending_object(&rev, parse_object(the_repository, &info->b_commit),
-			   "");
-	if (run_diff_index(&rev, 0)) {
-		ret = -1;
-		goto done;
-	}
-
-	cp_upd_index.git_cmd = 1;
-	strvec_pushl(&cp_upd_index.args, "update-index",
-		     "--ignore-skip-worktree-entries",
-		     "-z", "--add", "--remove", "--stdin", NULL);
-	strvec_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s",
-		     stash_index_path.buf);
-
-	if (pipe_command(&cp_upd_index, diff_output.buf, diff_output.len,
-			 NULL, 0, NULL, 0)) {
-		ret = -1;
-		goto done;
-	}
-
-	if (write_index_as_tree(&info->w_tree, &istate, stash_index_path.buf, 0,
-				NULL)) {
-		ret = -1;
-		goto done;
-	}
-
-done:
-	discard_index(&istate);
-	UNLEAK(rev);
-	object_array_clear(&rev.pending);
-	clear_pathspec(&rev.prune_data);
-	strbuf_release(&diff_output);
-	remove_path(stash_index_path.buf);
-	return ret;
-}
-
-static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_buf,
-			   int include_untracked, int patch_mode,
-			   struct stash_info *info, struct strbuf *patch,
-			   int quiet)
-{
-	int ret = 0;
-	int flags = 0;
-	int untracked_commit_option = 0;
-	const char *head_short_sha1 = NULL;
-	const char *branch_ref = NULL;
-	const char *branch_name = "(no branch)";
-	struct commit *head_commit = NULL;
-	struct commit_list *parents = NULL;
-	struct strbuf msg = STRBUF_INIT;
-	struct strbuf commit_tree_label = STRBUF_INIT;
-	struct strbuf untracked_files = STRBUF_INIT;
-
-	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;
-	}
-
-	if (get_oid("HEAD", &info->b_commit)) {
-		if (!quiet)
-			fprintf_ln(stderr, _("You do not have "
-					     "the initial commit yet"));
-		ret = -1;
-		goto done;
-	} else {
-		head_commit = lookup_commit(the_repository, &info->b_commit);
-	}
-
-	if (!check_changes(ps, include_untracked, &untracked_files)) {
-		ret = 1;
-		goto done;
-	}
-
-	branch_ref = resolve_ref_unsafe("HEAD", 0, NULL, &flags);
-	if (flags & REF_ISSYMREF)
-		branch_name = strrchr(branch_ref, '/') + 1;
-	head_short_sha1 = find_unique_abbrev(&head_commit->object.oid,
-					     DEFAULT_ABBREV);
-	strbuf_addf(&msg, "%s: %s ", branch_name, head_short_sha1);
-	pp_commit_easy(CMIT_FMT_ONELINE, head_commit, &msg);
-
-	strbuf_addf(&commit_tree_label, "index on %s\n", msg.buf);
-	commit_list_insert(head_commit, &parents);
-	if (write_cache_as_tree(&info->i_tree, 0, NULL) ||
-	    commit_tree(commit_tree_label.buf, commit_tree_label.len,
-			&info->i_tree, parents, &info->i_commit, NULL, NULL)) {
-		if (!quiet)
-			fprintf_ln(stderr, _("Cannot save the current "
-					     "index state"));
-		ret = -1;
-		goto done;
-	}
-
-	if (include_untracked) {
-		if (save_untracked_files(info, &msg, untracked_files)) {
-			if (!quiet)
-				fprintf_ln(stderr, _("Cannot save "
-						     "the untracked files"));
-			ret = -1;
-			goto done;
-		}
-		untracked_commit_option = 1;
-	}
-	if (patch_mode) {
-		ret = stash_patch(info, ps, patch, quiet);
-		if (ret < 0) {
-			if (!quiet)
-				fprintf_ln(stderr, _("Cannot save the current "
-						     "worktree state"));
-			goto done;
-		} else if (ret > 0) {
-			goto done;
-		}
-	} else {
-		if (stash_working_tree(info, ps)) {
-			if (!quiet)
-				fprintf_ln(stderr, _("Cannot save the current "
-						     "worktree state"));
-			ret = -1;
-			goto done;
-		}
-	}
-
-	if (!stash_msg_buf->len)
-		strbuf_addf(stash_msg_buf, "WIP on %s", msg.buf);
-	else
-		strbuf_insertf(stash_msg_buf, 0, "On %s: ", branch_name);
-
-	/*
-	 * `parents` will be empty after calling `commit_tree()`, so there is
-	 * no need to call `free_commit_list()`
-	 */
-	parents = NULL;
-	if (untracked_commit_option)
-		commit_list_insert(lookup_commit(the_repository,
-						 &info->u_commit),
-				   &parents);
-	commit_list_insert(lookup_commit(the_repository, &info->i_commit),
-			   &parents);
-	commit_list_insert(head_commit, &parents);
-
-	if (commit_tree(stash_msg_buf->buf, stash_msg_buf->len, &info->w_tree,
-			parents, &info->w_commit, NULL, NULL)) {
-		if (!quiet)
-			fprintf_ln(stderr, _("Cannot record "
-					     "working tree state"));
-		ret = -1;
-		goto done;
-	}
-
-done:
-	strbuf_release(&commit_tree_label);
-	strbuf_release(&msg);
-	strbuf_release(&untracked_files);
-	return ret;
-}
-
-static int create_stash(int argc, const char **argv, const char *prefix)
-{
-	int ret = 0;
-	struct strbuf stash_msg_buf = STRBUF_INIT;
-	struct stash_info info;
-	struct pathspec ps;
-
-	/* Starting with argv[1], since argv[0] is "create" */
-	strbuf_join_argv(&stash_msg_buf, argc - 1, ++argv, ' ');
-
-	memset(&ps, 0, sizeof(ps));
-	if (!check_changes_tracked_files(&ps))
-		return 0;
-
-	ret = do_create_stash(&ps, &stash_msg_buf, 0, 0, &info,
-			      NULL, 0);
-	if (!ret)
-		printf_ln("%s", oid_to_hex(&info.w_commit));
-
-	strbuf_release(&stash_msg_buf);
-	return ret;
-}
-
-static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int quiet,
-			 int keep_index, int patch_mode, int include_untracked)
-{
-	int ret = 0;
-	struct stash_info info;
-	struct strbuf patch = STRBUF_INIT;
-	struct strbuf stash_msg_buf = STRBUF_INIT;
-	struct strbuf untracked_files = STRBUF_INIT;
-
-	if (patch_mode && keep_index == -1)
-		keep_index = 1;
-
-	if (patch_mode && include_untracked) {
-		fprintf_ln(stderr, _("Can't use --patch and --include-untracked"
-				     " or --all at the same time"));
-		ret = -1;
-		goto done;
-	}
-
-	read_cache_preload(NULL);
-	if (!include_untracked && ps->nr) {
-		int i;
-		char *ps_matched = xcalloc(ps->nr, 1);
-
-		for (i = 0; i < active_nr; i++)
-			ce_path_match(&the_index, active_cache[i], ps,
-				      ps_matched);
-
-		if (report_path_error(ps_matched, ps)) {
-			fprintf_ln(stderr, _("Did you forget to 'git add'?"));
-			ret = -1;
-			free(ps_matched);
-			goto done;
-		}
-		free(ps_matched);
-	}
-
-	if (refresh_and_write_cache(REFRESH_QUIET, 0, 0)) {
-		ret = -1;
-		goto done;
-	}
-
-	if (!check_changes(ps, include_untracked, &untracked_files)) {
-		if (!quiet)
-			printf_ln(_("No local changes to save"));
-		goto done;
-	}
-
-	if (!reflog_exists(ref_stash) && do_clear_stash()) {
-		ret = -1;
-		if (!quiet)
-			fprintf_ln(stderr, _("Cannot initialize stash"));
-		goto done;
-	}
-
-	if (stash_msg)
-		strbuf_addstr(&stash_msg_buf, stash_msg);
-	if (do_create_stash(ps, &stash_msg_buf, include_untracked, patch_mode,
-			    &info, &patch, quiet)) {
-		ret = -1;
-		goto done;
-	}
-
-	if (do_store_stash(&info.w_commit, stash_msg_buf.buf, 1)) {
-		ret = -1;
-		if (!quiet)
-			fprintf_ln(stderr, _("Cannot save the current status"));
-		goto done;
-	}
-
-	if (!quiet)
-		printf_ln(_("Saved working directory and index state %s"),
-			  stash_msg_buf.buf);
-
-	if (!patch_mode) {
-		if (include_untracked && !ps->nr) {
-			struct child_process cp = CHILD_PROCESS_INIT;
-
-			cp.git_cmd = 1;
-			strvec_pushl(&cp.args, "clean", "--force",
-				     "--quiet", "-d", NULL);
-			if (include_untracked == INCLUDE_ALL_FILES)
-				strvec_push(&cp.args, "-x");
-			if (run_command(&cp)) {
-				ret = -1;
-				goto done;
-			}
-		}
-		discard_cache();
-		if (ps->nr) {
-			struct child_process cp_add = CHILD_PROCESS_INIT;
-			struct child_process cp_diff = CHILD_PROCESS_INIT;
-			struct child_process cp_apply = CHILD_PROCESS_INIT;
-			struct strbuf out = STRBUF_INIT;
-
-			cp_add.git_cmd = 1;
-			strvec_push(&cp_add.args, "add");
-			if (!include_untracked)
-				strvec_push(&cp_add.args, "-u");
-			if (include_untracked == INCLUDE_ALL_FILES)
-				strvec_push(&cp_add.args, "--force");
-			strvec_push(&cp_add.args, "--");
-			add_pathspecs(&cp_add.args, ps);
-			if (run_command(&cp_add)) {
-				ret = -1;
-				goto done;
-			}
-
-			cp_diff.git_cmd = 1;
-			strvec_pushl(&cp_diff.args, "diff-index", "-p",
-				     "--cached", "--binary", "HEAD", "--",
-				     NULL);
-			add_pathspecs(&cp_diff.args, ps);
-			if (pipe_command(&cp_diff, NULL, 0, &out, 0, NULL, 0)) {
-				ret = -1;
-				goto done;
-			}
-
-			cp_apply.git_cmd = 1;
-			strvec_pushl(&cp_apply.args, "apply", "--index",
-				     "-R", NULL);
-			if (pipe_command(&cp_apply, out.buf, out.len, NULL, 0,
-					 NULL, 0)) {
-				ret = -1;
-				goto done;
-			}
-		} else {
-			struct child_process cp = CHILD_PROCESS_INIT;
-			cp.git_cmd = 1;
-			strvec_pushl(&cp.args, "reset", "--hard", "-q",
-				     "--no-recurse-submodules", NULL);
-			if (run_command(&cp)) {
-				ret = -1;
-				goto done;
-			}
-		}
-
-		if (keep_index == 1 && !is_null_oid(&info.i_tree)) {
-			struct child_process cp = CHILD_PROCESS_INIT;
-
-			cp.git_cmd = 1;
-			strvec_pushl(&cp.args, "checkout", "--no-overlay",
-				     oid_to_hex(&info.i_tree), "--", NULL);
-			if (!ps->nr)
-				strvec_push(&cp.args, ":/");
-			else
-				add_pathspecs(&cp.args, ps);
-			if (run_command(&cp)) {
-				ret = -1;
-				goto done;
-			}
-		}
-		goto done;
-	} else {
-		struct child_process cp = CHILD_PROCESS_INIT;
-
-		cp.git_cmd = 1;
-		strvec_pushl(&cp.args, "apply", "-R", NULL);
-
-		if (pipe_command(&cp, patch.buf, patch.len, NULL, 0, NULL, 0)) {
-			if (!quiet)
-				fprintf_ln(stderr, _("Cannot remove "
-						     "worktree changes"));
-			ret = -1;
-			goto done;
-		}
-
-		if (keep_index < 1) {
-			struct child_process cp = CHILD_PROCESS_INIT;
-
-			cp.git_cmd = 1;
-			strvec_pushl(&cp.args, "reset", "-q", "--", NULL);
-			add_pathspecs(&cp.args, ps);
-			if (run_command(&cp)) {
-				ret = -1;
-				goto done;
-			}
-		}
-		goto done;
-	}
-
-done:
-	strbuf_release(&stash_msg_buf);
-	return ret;
-}
-
-static int push_stash(int argc, const char **argv, const char *prefix,
-		      int push_assumed)
-{
-	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,
-			 N_("keep index")),
-		OPT_BOOL('p', "patch", &patch_mode,
-			 N_("stash in patch mode")),
-		OPT__QUIET(&quiet, N_("quiet mode")),
-		OPT_BOOL('u', "include-untracked", &include_untracked,
-			 N_("include untracked files in stash")),
-		OPT_SET_INT('a', "all", &include_untracked,
-			    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");
-		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]);
-		}
-	}
-
-	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);
-}
-
-static int save_stash(int argc, const char **argv, const char *prefix)
-{
-	int keep_index = -1;
-	int patch_mode = 0;
-	int include_untracked = 0;
-	int quiet = 0;
-	int ret = 0;
-	const char *stash_msg = NULL;
-	struct pathspec ps;
-	struct strbuf stash_msg_buf = STRBUF_INIT;
-	struct option options[] = {
-		OPT_BOOL('k', "keep-index", &keep_index,
-			 N_("keep index")),
-		OPT_BOOL('p', "patch", &patch_mode,
-			 N_("stash in patch mode")),
-		OPT__QUIET(&quiet, N_("quiet mode")),
-		OPT_BOOL('u', "include-untracked", &include_untracked,
-			 N_("include untracked files in stash")),
-		OPT_SET_INT('a', "all", &include_untracked,
-			    N_("include ignore files"), 2),
-		OPT_STRING('m', "message", &stash_msg, "message",
-			   N_("stash message")),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, options,
-			     git_stash_save_usage,
-			     PARSE_OPT_KEEP_DASHDASH);
-
-	if (argc)
-		stash_msg = strbuf_join_argv(&stash_msg_buf, argc, argv, ' ');
-
-	memset(&ps, 0, sizeof(ps));
-	ret = do_push_stash(&ps, stash_msg, quiet, keep_index,
-			    patch_mode, include_untracked);
-
-	strbuf_release(&stash_msg_buf);
-	return ret;
-}
-
-int cmd_stash(int argc, const char **argv, const char *prefix)
-{
-	pid_t pid = getpid();
-	const char *index_file;
-	struct strvec args = STRVEC_INIT;
-
-	struct option options[] = {
-		OPT_END()
-	};
-
-	git_config(git_stash_config, NULL);
-
-	if (use_legacy_stash ||
-	    !git_env_bool("GIT_TEST_STASH_USE_BUILTIN", -1))
-		warning(_("the stash.useBuiltin support has been removed!\n"
-			  "See its entry in 'git help config' for details."));
-
-	argc = parse_options(argc, argv, prefix, options, git_stash_usage,
-			     PARSE_OPT_KEEP_UNKNOWN | PARSE_OPT_KEEP_DASHDASH);
-
-	index_file = get_index_file();
-	strbuf_addf(&stash_index_path, "%s.stash.%" PRIuMAX, index_file,
-		    (uintmax_t)pid);
-
-	if (!argc)
-		return !!push_stash(0, NULL, prefix, 0);
-	else if (!strcmp(argv[0], "apply"))
-		return !!apply_stash(argc, argv, prefix);
-	else if (!strcmp(argv[0], "clear"))
-		return !!clear_stash(argc, argv, prefix);
-	else if (!strcmp(argv[0], "drop"))
-		return !!drop_stash(argc, argv, prefix);
-	else if (!strcmp(argv[0], "pop"))
-		return !!pop_stash(argc, argv, prefix);
-	else if (!strcmp(argv[0], "branch"))
-		return !!branch_stash(argc, argv, prefix);
-	else if (!strcmp(argv[0], "list"))
-		return !!list_stash(argc, argv, prefix);
-	else if (!strcmp(argv[0], "show"))
-		return !!show_stash(argc, argv, prefix);
-	else if (!strcmp(argv[0], "store"))
-		return !!store_stash(argc, argv, 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);
-	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' */
-	strvec_push(&args, "push");
-	strvec_pushv(&args, argv);
-	return !!push_stash(args.nr, args.v, prefix, 1);
-}
diff --git a/third_party/git/builtin/stripspace.c b/third_party/git/builtin/stripspace.c
deleted file mode 100644
index be33eb83c1b7..000000000000
--- a/third_party/git/builtin/stripspace.c
+++ /dev/null
@@ -1,65 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "parse-options.h"
-#include "strbuf.h"
-
-static void comment_lines(struct strbuf *buf)
-{
-	char *msg;
-	size_t len;
-
-	msg = strbuf_detach(buf, &len);
-	strbuf_add_commented_lines(buf, msg, len);
-	free(msg);
-}
-
-static const char * const stripspace_usage[] = {
-	N_("git stripspace [-s | --strip-comments]"),
-	N_("git stripspace [-c | --comment-lines]"),
-	NULL
-};
-
-enum stripspace_mode {
-	STRIP_DEFAULT = 0,
-	STRIP_COMMENTS,
-	COMMENT_LINES
-};
-
-int cmd_stripspace(int argc, const char **argv, const char *prefix)
-{
-	struct strbuf buf = STRBUF_INIT;
-	enum stripspace_mode mode = STRIP_DEFAULT;
-	int nongit;
-
-	const struct option options[] = {
-		OPT_CMDMODE('s', "strip-comments", &mode,
-			    N_("skip and remove all lines starting with comment character"),
-			    STRIP_COMMENTS),
-		OPT_CMDMODE('c', "comment-lines", &mode,
-			    N_("prepend comment character and space to each line"),
-			    COMMENT_LINES),
-		OPT_END()
-	};
-
-	argc = parse_options(argc, argv, prefix, options, stripspace_usage, 0);
-	if (argc)
-		usage_with_options(stripspace_usage, options);
-
-	if (mode == STRIP_COMMENTS || mode == COMMENT_LINES) {
-		setup_git_directory_gently(&nongit);
-		git_config(git_default_config, NULL);
-	}
-
-	if (strbuf_read(&buf, 0, 1024) < 0)
-		die_errno("could not read the input");
-
-	if (mode == STRIP_DEFAULT || mode == STRIP_COMMENTS)
-		strbuf_stripspace(&buf, mode == STRIP_COMMENTS);
-	else
-		comment_lines(&buf);
-
-	write_or_die(1, buf.buf, buf.len);
-	strbuf_release(&buf);
-	return 0;
-}
diff --git a/third_party/git/builtin/submodule--helper.c b/third_party/git/builtin/submodule--helper.c
deleted file mode 100644
index c30896c89788..000000000000
--- a/third_party/git/builtin/submodule--helper.c
+++ /dev/null
@@ -1,2800 +0,0 @@
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "repository.h"
-#include "cache.h"
-#include "config.h"
-#include "parse-options.h"
-#include "quote.h"
-#include "pathspec.h"
-#include "dir.h"
-#include "submodule.h"
-#include "submodule-config.h"
-#include "string-list.h"
-#include "run-command.h"
-#include "remote.h"
-#include "refs.h"
-#include "refspec.h"
-#include "connect.h"
-#include "revision.h"
-#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)
-#define OPT_RECURSIVE (1 << 2)
-#define OPT_FORCE (1 << 3)
-
-typedef void (*each_submodule_fn)(const struct cache_entry *list_item,
-				  void *cb_data);
-
-static char *get_default_remote(void)
-{
-	char *dest = NULL, *ret;
-	struct strbuf sb = STRBUF_INIT;
-	const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
-
-	if (!refname)
-		die(_("No such ref: %s"), "HEAD");
-
-	/* detached HEAD */
-	if (!strcmp(refname, "HEAD"))
-		return xstrdup("origin");
-
-	if (!skip_prefix(refname, "refs/heads/", &refname))
-		die(_("Expecting a full ref name, got %s"), refname);
-
-	strbuf_addf(&sb, "branch.%s.remote", refname);
-	if (git_config_get_string(sb.buf, &dest))
-		ret = xstrdup("origin");
-	else
-		ret = dest;
-
-	strbuf_release(&sb);
-	return ret;
-}
-
-static int print_default_remote(int argc, const char **argv, const char *prefix)
-{
-	char *remote;
-
-	if (argc != 1)
-		die(_("submodule--helper print-default-remote takes no arguments"));
-
-	remote = get_default_remote();
-	if (remote)
-		printf("%s\n", remote);
-
-	free(remote);
-	return 0;
-}
-
-static int starts_with_dot_slash(const char *str)
-{
-	return str[0] == '.' && is_dir_sep(str[1]);
-}
-
-static int starts_with_dot_dot_slash(const char *str)
-{
-	return str[0] == '.' && str[1] == '.' && is_dir_sep(str[2]);
-}
-
-/*
- * Returns 1 if it was the last chop before ':'.
- */
-static int chop_last_dir(char **remoteurl, int is_relative)
-{
-	char *rfind = find_last_dir_sep(*remoteurl);
-	if (rfind) {
-		*rfind = '\0';
-		return 0;
-	}
-
-	rfind = strrchr(*remoteurl, ':');
-	if (rfind) {
-		*rfind = '\0';
-		return 1;
-	}
-
-	if (is_relative || !strcmp(".", *remoteurl))
-		die(_("cannot strip one component off url '%s'"),
-			*remoteurl);
-
-	free(*remoteurl);
-	*remoteurl = xstrdup(".");
-	return 0;
-}
-
-/*
- * The `url` argument is the URL that navigates to the submodule origin
- * repo. When relative, this URL is relative to the superproject origin
- * URL repo. The `up_path` argument, if specified, is the relative
- * path that navigates from the submodule working tree to the superproject
- * working tree. Returns the origin URL of the submodule.
- *
- * Return either an absolute URL or filesystem path (if the superproject
- * origin URL is an absolute URL or filesystem path, respectively) or a
- * relative file system path (if the superproject origin URL is a relative
- * file system path).
- *
- * When the output is a relative file system path, the path is either
- * relative to the submodule working tree, if up_path is specified, or to
- * the superproject working tree otherwise.
- *
- * NEEDSWORK: This works incorrectly on the domain and protocol part.
- * remote_url      url              outcome          expectation
- * http://a.com/b  ../c             http://a.com/c   as is
- * http://a.com/b/ ../c             http://a.com/c   same as previous line, but
- *                                                   ignore trailing slash in url
- * http://a.com/b  ../../c          http://c         error out
- * http://a.com/b  ../../../c       http:/c          error out
- * http://a.com/b  ../../../../c    http:c           error out
- * http://a.com/b  ../../../../../c    .:c           error out
- * NEEDSWORK: Given how chop_last_dir() works, this function is broken
- * when a local part has a colon in its path component, too.
- */
-static char *relative_url(const char *remote_url,
-				const char *url,
-				const char *up_path)
-{
-	int is_relative = 0;
-	int colonsep = 0;
-	char *out;
-	char *remoteurl = xstrdup(remote_url);
-	struct strbuf sb = STRBUF_INIT;
-	size_t len = strlen(remoteurl);
-
-	if (is_dir_sep(remoteurl[len-1]))
-		remoteurl[len-1] = '\0';
-
-	if (!url_is_local_not_ssh(remoteurl) || is_absolute_path(remoteurl))
-		is_relative = 0;
-	else {
-		is_relative = 1;
-		/*
-		 * Prepend a './' to ensure all relative
-		 * remoteurls start with './' or '../'
-		 */
-		if (!starts_with_dot_slash(remoteurl) &&
-		    !starts_with_dot_dot_slash(remoteurl)) {
-			strbuf_reset(&sb);
-			strbuf_addf(&sb, "./%s", remoteurl);
-			free(remoteurl);
-			remoteurl = strbuf_detach(&sb, NULL);
-		}
-	}
-	/*
-	 * When the url starts with '../', remove that and the
-	 * last directory in remoteurl.
-	 */
-	while (url) {
-		if (starts_with_dot_dot_slash(url)) {
-			url += 3;
-			colonsep |= chop_last_dir(&remoteurl, is_relative);
-		} else if (starts_with_dot_slash(url))
-			url += 2;
-		else
-			break;
-	}
-	strbuf_reset(&sb);
-	strbuf_addf(&sb, "%s%s%s", remoteurl, colonsep ? ":" : "/", url);
-	if (ends_with(url, "/"))
-		strbuf_setlen(&sb, sb.len - 1);
-	free(remoteurl);
-
-	if (starts_with_dot_slash(sb.buf))
-		out = xstrdup(sb.buf + 2);
-	else
-		out = xstrdup(sb.buf);
-	strbuf_reset(&sb);
-
-	if (!up_path || !is_relative)
-		return out;
-
-	strbuf_addf(&sb, "%s%s", up_path, out);
-	free(out);
-	return strbuf_detach(&sb, NULL);
-}
-
-static int resolve_relative_url(int argc, const char **argv, const char *prefix)
-{
-	char *remoteurl = NULL;
-	char *remote = get_default_remote();
-	const char *up_path = NULL;
-	char *res;
-	const char *url;
-	struct strbuf sb = STRBUF_INIT;
-
-	if (argc != 2 && argc != 3)
-		die("resolve-relative-url only accepts one or two arguments");
-
-	url = argv[1];
-	strbuf_addf(&sb, "remote.%s.url", remote);
-	free(remote);
-
-	if (git_config_get_string(sb.buf, &remoteurl))
-		/* the repository is its own authoritative upstream */
-		remoteurl = xgetcwd();
-
-	if (argc == 3)
-		up_path = argv[2];
-
-	res = relative_url(remoteurl, url, up_path);
-	puts(res);
-	free(res);
-	free(remoteurl);
-	return 0;
-}
-
-static int resolve_relative_url_test(int argc, const char **argv, const char *prefix)
-{
-	char *remoteurl, *res;
-	const char *up_path, *url;
-
-	if (argc != 4)
-		die("resolve-relative-url-test only accepts three arguments: <up_path> <remoteurl> <url>");
-
-	up_path = argv[1];
-	remoteurl = xstrdup(argv[2]);
-	url = argv[3];
-
-	if (!strcmp(up_path, "(null)"))
-		up_path = NULL;
-
-	res = relative_url(remoteurl, url, up_path);
-	puts(res);
-	free(res);
-	free(remoteurl);
-	return 0;
-}
-
-/* the result should be freed by the caller. */
-static char *get_submodule_displaypath(const char *path, const char *prefix)
-{
-	const char *super_prefix = get_super_prefix();
-
-	if (prefix && super_prefix) {
-		BUG("cannot have prefix '%s' and superprefix '%s'",
-		    prefix, super_prefix);
-	} else if (prefix) {
-		struct strbuf sb = STRBUF_INIT;
-		char *displaypath = xstrdup(relative_path(path, prefix, &sb));
-		strbuf_release(&sb);
-		return displaypath;
-	} else if (super_prefix) {
-		return xstrfmt("%s%s", super_prefix, path);
-	} else {
-		return xstrdup(path);
-	}
-}
-
-static char *compute_rev_name(const char *sub_path, const char* object_id)
-{
-	struct strbuf sb = STRBUF_INIT;
-	const char ***d;
-
-	static const char *describe_bare[] = { NULL };
-
-	static const char *describe_tags[] = { "--tags", NULL };
-
-	static const char *describe_contains[] = { "--contains", NULL };
-
-	static const char *describe_all_always[] = { "--all", "--always", NULL };
-
-	static const char **describe_argv[] = { describe_bare, describe_tags,
-						describe_contains,
-						describe_all_always, NULL };
-
-	for (d = describe_argv; *d; d++) {
-		struct child_process cp = CHILD_PROCESS_INIT;
-		prepare_submodule_repo_env(&cp.env_array);
-		cp.dir = sub_path;
-		cp.git_cmd = 1;
-		cp.no_stderr = 1;
-
-		strvec_push(&cp.args, "describe");
-		strvec_pushv(&cp.args, *d);
-		strvec_push(&cp.args, object_id);
-
-		if (!capture_command(&cp, &sb, 0)) {
-			strbuf_strip_suffix(&sb, "\n");
-			return strbuf_detach(&sb, NULL);
-		}
-	}
-
-	strbuf_release(&sb);
-	return NULL;
-}
-
-struct module_list {
-	const struct cache_entry **entries;
-	int alloc, nr;
-};
-#define MODULE_LIST_INIT { NULL, 0, 0 }
-
-static int module_list_compute(int argc, const char **argv,
-			       const char *prefix,
-			       struct pathspec *pathspec,
-			       struct module_list *list)
-{
-	int i, result = 0;
-	char *ps_matched = NULL;
-	parse_pathspec(pathspec, 0,
-		       PATHSPEC_PREFER_FULL,
-		       prefix, argv);
-
-	if (pathspec->nr)
-		ps_matched = xcalloc(pathspec->nr, 1);
-
-	if (read_cache() < 0)
-		die(_("index file corrupt"));
-
-	for (i = 0; i < active_nr; i++) {
-		const struct cache_entry *ce = active_cache[i];
-
-		if (!match_pathspec(&the_index, pathspec, ce->name, ce_namelen(ce),
-				    0, ps_matched, 1) ||
-		    !S_ISGITLINK(ce->ce_mode))
-			continue;
-
-		ALLOC_GROW(list->entries, list->nr + 1, list->alloc);
-		list->entries[list->nr++] = ce;
-		while (i + 1 < active_nr &&
-		       !strcmp(ce->name, active_cache[i + 1]->name))
-			/*
-			 * Skip entries with the same name in different stages
-			 * to make sure an entry is returned only once.
-			 */
-			i++;
-	}
-
-	if (ps_matched && report_path_error(ps_matched, pathspec))
-		result = -1;
-
-	free(ps_matched);
-
-	return result;
-}
-
-static void module_list_active(struct module_list *list)
-{
-	int i;
-	struct module_list active_modules = MODULE_LIST_INIT;
-
-	for (i = 0; i < list->nr; i++) {
-		const struct cache_entry *ce = list->entries[i];
-
-		if (!is_submodule_active(the_repository, ce->name))
-			continue;
-
-		ALLOC_GROW(active_modules.entries,
-			   active_modules.nr + 1,
-			   active_modules.alloc);
-		active_modules.entries[active_modules.nr++] = ce;
-	}
-
-	free(list->entries);
-	*list = active_modules;
-}
-
-static char *get_up_path(const char *path)
-{
-	int i;
-	struct strbuf sb = STRBUF_INIT;
-
-	for (i = count_slashes(path); i; i--)
-		strbuf_addstr(&sb, "../");
-
-	/*
-	 * Check if 'path' ends with slash or not
-	 * for having the same output for dir/sub_dir
-	 * and dir/sub_dir/
-	 */
-	if (!is_dir_sep(path[strlen(path) - 1]))
-		strbuf_addstr(&sb, "../");
-
-	return strbuf_detach(&sb, NULL);
-}
-
-static int module_list(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	struct pathspec pathspec;
-	struct module_list list = MODULE_LIST_INIT;
-
-	struct option module_list_options[] = {
-		OPT_STRING(0, "prefix", &prefix,
-			   N_("path"),
-			   N_("alternative anchor for relative paths")),
-		OPT_END()
-	};
-
-	const char *const git_submodule_helper_usage[] = {
-		N_("git submodule--helper list [--prefix=<path>] [<path>...]"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, module_list_options,
-			     git_submodule_helper_usage, 0);
-
-	if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
-		return 1;
-
-	for (i = 0; i < list.nr; i++) {
-		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));
-		else
-			printf("%06o %s %d\t", ce->ce_mode,
-			       oid_to_hex(&ce->oid), ce_stage(ce));
-
-		fprintf(stdout, "%s\n", ce->name);
-	}
-	return 0;
-}
-
-static void for_each_listed_submodule(const struct module_list *list,
-				      each_submodule_fn fn, void *cb_data)
-{
-	int i;
-	for (i = 0; i < list->nr; i++)
-		fn(list->entries[i], cb_data);
-}
-
-struct foreach_cb {
-	int argc;
-	const char **argv;
-	const char *prefix;
-	int quiet;
-	int recursive;
-};
-#define FOREACH_CB_INIT { 0 }
-
-static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
-				       void *cb_data)
-{
-	struct foreach_cb *info = cb_data;
-	const char *path = list_item->name;
-	const struct object_id *ce_oid = &list_item->oid;
-
-	const struct submodule *sub;
-	struct child_process cp = CHILD_PROCESS_INIT;
-	char *displaypath;
-
-	displaypath = get_submodule_displaypath(path, info->prefix);
-
-	sub = submodule_from_path(the_repository, &null_oid, path);
-
-	if (!sub)
-		die(_("No url found for submodule path '%s' in .gitmodules"),
-			displaypath);
-
-	if (!is_submodule_populated_gently(path, NULL))
-		goto cleanup;
-
-	prepare_submodule_repo_env(&cp.env_array);
-
-	/*
-	 * For the purpose of executing <command> in the submodule,
-	 * separate shell is used for the purpose of running the
-	 * child process.
-	 */
-	cp.use_shell = 1;
-	cp.dir = path;
-
-	/*
-	 * NEEDSWORK: the command currently has access to the variables $name,
-	 * $sm_path, $displaypath, $sha1 and $toplevel only when the command
-	 * contains a single argument. This is done for maintaining a faithful
-	 * translation from shell script.
-	 */
-	if (info->argc == 1) {
-		char *toplevel = xgetcwd();
-		struct strbuf sb = STRBUF_INIT;
-
-		strvec_pushf(&cp.env_array, "name=%s", sub->name);
-		strvec_pushf(&cp.env_array, "sm_path=%s", path);
-		strvec_pushf(&cp.env_array, "displaypath=%s", displaypath);
-		strvec_pushf(&cp.env_array, "sha1=%s",
-			     oid_to_hex(ce_oid));
-		strvec_pushf(&cp.env_array, "toplevel=%s", toplevel);
-
-		/*
-		 * Since the path variable was accessible from the script
-		 * before porting, it is also made available after porting.
-		 * The environment variable "PATH" has a very special purpose
-		 * on windows. And since environment variables are
-		 * case-insensitive in windows, it interferes with the
-		 * existing PATH variable. Hence, to avoid that, we expose
-		 * path via the args strvec and not via env_array.
-		 */
-		sq_quote_buf(&sb, path);
-		strvec_pushf(&cp.args, "path=%s; %s",
-			     sb.buf, info->argv[0]);
-		strbuf_release(&sb);
-		free(toplevel);
-	} else {
-		strvec_pushv(&cp.args, info->argv);
-	}
-
-	if (!info->quiet)
-		printf(_("Entering '%s'\n"), displaypath);
-
-	if (info->argv[0] && run_command(&cp))
-		die(_("run_command returned non-zero status for %s\n."),
-			displaypath);
-
-	if (info->recursive) {
-		struct child_process cpr = CHILD_PROCESS_INIT;
-
-		cpr.git_cmd = 1;
-		cpr.dir = path;
-		prepare_submodule_repo_env(&cpr.env_array);
-
-		strvec_pushl(&cpr.args, "--super-prefix", NULL);
-		strvec_pushf(&cpr.args, "%s/", displaypath);
-		strvec_pushl(&cpr.args, "submodule--helper", "foreach", "--recursive",
-			     NULL);
-
-		if (info->quiet)
-			strvec_push(&cpr.args, "--quiet");
-
-		strvec_push(&cpr.args, "--");
-		strvec_pushv(&cpr.args, info->argv);
-
-		if (run_command(&cpr))
-			die(_("run_command returned non-zero status while "
-				"recursing in the nested submodules of %s\n."),
-				displaypath);
-	}
-
-cleanup:
-	free(displaypath);
-}
-
-static int module_foreach(int argc, const char **argv, const char *prefix)
-{
-	struct foreach_cb info = FOREACH_CB_INIT;
-	struct pathspec pathspec;
-	struct module_list list = MODULE_LIST_INIT;
-
-	struct option module_foreach_options[] = {
-		OPT__QUIET(&info.quiet, N_("Suppress output of entering each submodule command")),
-		OPT_BOOL(0, "recursive", &info.recursive,
-			 N_("Recurse into nested submodules")),
-		OPT_END()
-	};
-
-	const char *const git_submodule_helper_usage[] = {
-		N_("git submodule--helper foreach [--quiet] [--recursive] [--] <command>"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, module_foreach_options,
-			     git_submodule_helper_usage, 0);
-
-	if (module_list_compute(0, NULL, prefix, &pathspec, &list) < 0)
-		return 1;
-
-	info.argc = argc;
-	info.argv = argv;
-	info.prefix = prefix;
-
-	for_each_listed_submodule(&list, runcommand_in_submodule_cb, &info);
-
-	return 0;
-}
-
-static char *compute_submodule_clone_url(const char *rel_url)
-{
-	char *remoteurl, *relurl;
-	char *remote = get_default_remote();
-	struct strbuf remotesb = STRBUF_INIT;
-
-	strbuf_addf(&remotesb, "remote.%s.url", remote);
-	if (git_config_get_string(remotesb.buf, &remoteurl)) {
-		warning(_("could not look up configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
-		remoteurl = xgetcwd();
-	}
-	relurl = relative_url(remoteurl, rel_url, NULL);
-
-	free(remote);
-	free(remoteurl);
-	strbuf_release(&remotesb);
-
-	return relurl;
-}
-
-struct init_cb {
-	const char *prefix;
-	unsigned int flags;
-};
-#define INIT_CB_INIT { NULL, 0 }
-
-static void init_submodule(const char *path, const char *prefix,
-			   unsigned int flags)
-{
-	const struct submodule *sub;
-	struct strbuf sb = STRBUF_INIT;
-	char *upd = NULL, *url = NULL, *displaypath;
-
-	displaypath = get_submodule_displaypath(path, prefix);
-
-	sub = submodule_from_path(the_repository, &null_oid, path);
-
-	if (!sub)
-		die(_("No url found for submodule path '%s' in .gitmodules"),
-			displaypath);
-
-	/*
-	 * NEEDSWORK: In a multi-working-tree world, this needs to be
-	 * set in the per-worktree config.
-	 *
-	 * Set active flag for the submodule being initialized
-	 */
-	if (!is_submodule_active(the_repository, path)) {
-		strbuf_addf(&sb, "submodule.%s.active", sub->name);
-		git_config_set_gently(sb.buf, "true");
-		strbuf_reset(&sb);
-	}
-
-	/*
-	 * Copy url setting when it is not set yet.
-	 * To look up the url in .git/config, we must not fall back to
-	 * .gitmodules, so look it up directly.
-	 */
-	strbuf_addf(&sb, "submodule.%s.url", sub->name);
-	if (git_config_get_string(sb.buf, &url)) {
-		if (!sub->url)
-			die(_("No url found for submodule path '%s' in .gitmodules"),
-				displaypath);
-
-		url = xstrdup(sub->url);
-
-		/* Possibly a url relative to parent */
-		if (starts_with_dot_dot_slash(url) ||
-		    starts_with_dot_slash(url)) {
-			char *oldurl = url;
-			url = compute_submodule_clone_url(oldurl);
-			free(oldurl);
-		}
-
-		if (git_config_set_gently(sb.buf, url))
-			die(_("Failed to register url for submodule path '%s'"),
-			    displaypath);
-		if (!(flags & OPT_QUIET))
-			fprintf(stderr,
-				_("Submodule '%s' (%s) registered for path '%s'\n"),
-				sub->name, url, displaypath);
-	}
-	strbuf_reset(&sb);
-
-	/* Copy "update" setting when it is not set yet */
-	strbuf_addf(&sb, "submodule.%s.update", sub->name);
-	if (git_config_get_string(sb.buf, &upd) &&
-	    sub->update_strategy.type != SM_UPDATE_UNSPECIFIED) {
-		if (sub->update_strategy.type == SM_UPDATE_COMMAND) {
-			fprintf(stderr, _("warning: command update mode suggested for submodule '%s'\n"),
-				sub->name);
-			upd = xstrdup("none");
-		} else
-			upd = xstrdup(submodule_strategy_to_string(&sub->update_strategy));
-
-		if (git_config_set_gently(sb.buf, upd))
-			die(_("Failed to register update mode for submodule path '%s'"), displaypath);
-	}
-	strbuf_release(&sb);
-	free(displaypath);
-	free(url);
-	free(upd);
-}
-
-static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data)
-{
-	struct init_cb *info = cb_data;
-	init_submodule(list_item->name, info->prefix, info->flags);
-}
-
-static int module_init(int argc, const char **argv, const char *prefix)
-{
-	struct init_cb info = INIT_CB_INIT;
-	struct pathspec pathspec;
-	struct module_list list = MODULE_LIST_INIT;
-	int quiet = 0;
-
-	struct option module_init_options[] = {
-		OPT__QUIET(&quiet, N_("Suppress output for initializing a submodule")),
-		OPT_END()
-	};
-
-	const char *const git_submodule_helper_usage[] = {
-		N_("git submodule--helper init [<options>] [<path>]"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, module_init_options,
-			     git_submodule_helper_usage, 0);
-
-	if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
-		return 1;
-
-	/*
-	 * If there are no path args and submodule.active is set then,
-	 * by default, only initialize 'active' modules.
-	 */
-	if (!argc && git_config_get_value_multi("submodule.active"))
-		module_list_active(&list);
-
-	info.prefix = prefix;
-	if (quiet)
-		info.flags |= OPT_QUIET;
-
-	for_each_listed_submodule(&list, init_submodule_cb, &info);
-
-	return 0;
-}
-
-struct status_cb {
-	const char *prefix;
-	unsigned int flags;
-};
-#define STATUS_CB_INIT { NULL, 0 }
-
-static void print_status(unsigned int flags, char state, const char *path,
-			 const struct object_id *oid, const char *displaypath)
-{
-	if (flags & OPT_QUIET)
-		return;
-
-	printf("%c%s %s", state, oid_to_hex(oid), displaypath);
-
-	if (state == ' ' || state == '+') {
-		const char *name = compute_rev_name(path, oid_to_hex(oid));
-
-		if (name)
-			printf(" (%s)", name);
-	}
-
-	printf("\n");
-}
-
-static int handle_submodule_head_ref(const char *refname,
-				     const struct object_id *oid, int flags,
-				     void *cb_data)
-{
-	struct object_id *output = cb_data;
-	if (oid)
-		oidcpy(output, oid);
-
-	return 0;
-}
-
-static void status_submodule(const char *path, const struct object_id *ce_oid,
-			     unsigned int ce_flags, const char *prefix,
-			     unsigned int flags)
-{
-	char *displaypath;
-	struct strvec diff_files_args = STRVEC_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'"),
-		      path);
-
-	displaypath = get_submodule_displaypath(path, prefix);
-
-	if ((CE_STAGEMASK & ce_flags) >> CE_STAGESHIFT) {
-		print_status(flags, 'U', path, &null_oid, displaypath);
-		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)) {
-		print_status(flags, '-', path, ce_oid, displaypath);
-		strbuf_release(&buf);
-		goto cleanup;
-	}
-	strbuf_release(&buf);
-
-	strvec_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);
-	rev.abbrev = 0;
-	diff_files_args.nr = setup_revisions(diff_files_args.nr,
-					     diff_files_args.v,
-					     &rev, NULL);
-	diff_files_result = run_diff_files(&rev, 0);
-
-	if (!diff_result_code(&rev.diffopt, diff_files_result)) {
-		print_status(flags, ' ', path, ce_oid,
-			     displaypath);
-	} else if (!(flags & OPT_CACHED)) {
-		struct object_id oid;
-		struct ref_store *refs = get_submodule_ref_store(path);
-
-		if (!refs) {
-			print_status(flags, '-', path, ce_oid, displaypath);
-			goto cleanup;
-		}
-		if (refs_head_ref(refs, handle_submodule_head_ref, &oid))
-			die(_("could not resolve HEAD ref inside the "
-			      "submodule '%s'"), path);
-
-		print_status(flags, '+', path, &oid, displaypath);
-	} else {
-		print_status(flags, '+', path, ce_oid, displaypath);
-	}
-
-	if (flags & OPT_RECURSIVE) {
-		struct child_process cpr = CHILD_PROCESS_INIT;
-
-		cpr.git_cmd = 1;
-		cpr.dir = path;
-		prepare_submodule_repo_env(&cpr.env_array);
-
-		strvec_push(&cpr.args, "--super-prefix");
-		strvec_pushf(&cpr.args, "%s/", displaypath);
-		strvec_pushl(&cpr.args, "submodule--helper", "status",
-			     "--recursive", NULL);
-
-		if (flags & OPT_CACHED)
-			strvec_push(&cpr.args, "--cached");
-
-		if (flags & OPT_QUIET)
-			strvec_push(&cpr.args, "--quiet");
-
-		if (run_command(&cpr))
-			die(_("failed to recurse into submodule '%s'"), path);
-	}
-
-cleanup:
-	strvec_clear(&diff_files_args);
-	free(displaypath);
-}
-
-static void status_submodule_cb(const struct cache_entry *list_item,
-				void *cb_data)
-{
-	struct status_cb *info = cb_data;
-	status_submodule(list_item->name, &list_item->oid, list_item->ce_flags,
-			 info->prefix, info->flags);
-}
-
-static int module_status(int argc, const char **argv, const char *prefix)
-{
-	struct status_cb info = STATUS_CB_INIT;
-	struct pathspec pathspec;
-	struct module_list list = MODULE_LIST_INIT;
-	int quiet = 0;
-
-	struct option module_status_options[] = {
-		OPT__QUIET(&quiet, N_("Suppress submodule status output")),
-		OPT_BIT(0, "cached", &info.flags, N_("Use commit stored in the index instead of the one stored in the submodule HEAD"), OPT_CACHED),
-		OPT_BIT(0, "recursive", &info.flags, N_("recurse into nested submodules"), OPT_RECURSIVE),
-		OPT_END()
-	};
-
-	const char *const git_submodule_helper_usage[] = {
-		N_("git submodule status [--quiet] [--cached] [--recursive] [<path>...]"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, module_status_options,
-			     git_submodule_helper_usage, 0);
-
-	if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
-		return 1;
-
-	info.prefix = prefix;
-	if (quiet)
-		info.flags |= OPT_QUIET;
-
-	for_each_listed_submodule(&list, status_submodule_cb, &info);
-
-	return 0;
-}
-
-static int module_name(int argc, const char **argv, const char *prefix)
-{
-	const struct submodule *sub;
-
-	if (argc != 2)
-		usage(_("git submodule--helper name <path>"));
-
-	sub = submodule_from_path(the_repository, &null_oid, argv[1]);
-
-	if (!sub)
-		die(_("no submodule mapping found in .gitmodules for path '%s'"),
-		    argv[1]);
-
-	printf("%s\n", sub->name);
-
-	return 0;
-}
-
-struct module_cb {
-	unsigned int mod_src;
-	unsigned int mod_dst;
-	struct object_id oid_src;
-	struct object_id oid_dst;
-	char status;
-	const char *sm_path;
-};
-#define MODULE_CB_INIT { 0, 0, NULL, NULL, '\0', NULL }
-
-struct module_cb_list {
-	struct module_cb **entries;
-	int alloc, nr;
-};
-#define MODULE_CB_LIST_INIT { NULL, 0, 0 }
-
-struct summary_cb {
-	int argc;
-	const char **argv;
-	const char *prefix;
-	unsigned int cached: 1;
-	unsigned int for_status: 1;
-	unsigned int files: 1;
-	int summary_limit;
-};
-#define SUMMARY_CB_INIT { 0, NULL, NULL, 0, 0, 0, 0 }
-
-enum diff_cmd {
-	DIFF_INDEX,
-	DIFF_FILES
-};
-
-static char *verify_submodule_committish(const char *sm_path,
-					 const char *committish)
-{
-	struct child_process cp_rev_parse = CHILD_PROCESS_INIT;
-	struct strbuf result = STRBUF_INIT;
-
-	cp_rev_parse.git_cmd = 1;
-	cp_rev_parse.dir = sm_path;
-	prepare_submodule_repo_env(&cp_rev_parse.env_array);
-	strvec_pushl(&cp_rev_parse.args, "rev-parse", "-q", "--short", NULL);
-	strvec_pushf(&cp_rev_parse.args, "%s^0", committish);
-	strvec_push(&cp_rev_parse.args, "--");
-
-	if (capture_command(&cp_rev_parse, &result, 0))
-		return NULL;
-
-	strbuf_trim_trailing_newline(&result);
-	return strbuf_detach(&result, NULL);
-}
-
-static void print_submodule_summary(struct summary_cb *info, char *errmsg,
-				    int total_commits, const char *displaypath,
-				    const char *src_abbrev, const char *dst_abbrev,
-				    struct module_cb *p)
-{
-	if (p->status == 'T') {
-		if (S_ISGITLINK(p->mod_dst))
-			printf(_("* %s %s(blob)->%s(submodule)"),
-				 displaypath, src_abbrev, dst_abbrev);
-		else
-			printf(_("* %s %s(submodule)->%s(blob)"),
-				 displaypath, src_abbrev, dst_abbrev);
-	} else {
-		printf("* %s %s...%s",
-			displaypath, src_abbrev, dst_abbrev);
-	}
-
-	if (total_commits < 0)
-		printf(":\n");
-	else
-		printf(" (%d):\n", total_commits);
-
-	if (errmsg) {
-		printf(_("%s"), errmsg);
-	} else if (total_commits > 0) {
-		struct child_process cp_log = CHILD_PROCESS_INIT;
-
-		cp_log.git_cmd = 1;
-		cp_log.dir = p->sm_path;
-		prepare_submodule_repo_env(&cp_log.env_array);
-		strvec_pushl(&cp_log.args, "log", NULL);
-
-		if (S_ISGITLINK(p->mod_src) && S_ISGITLINK(p->mod_dst)) {
-			if (info->summary_limit > 0)
-				strvec_pushf(&cp_log.args, "-%d",
-					     info->summary_limit);
-
-			strvec_pushl(&cp_log.args, "--pretty=  %m %s",
-				     "--first-parent", NULL);
-			strvec_pushf(&cp_log.args, "%s...%s",
-				     src_abbrev, dst_abbrev);
-		} else if (S_ISGITLINK(p->mod_dst)) {
-			strvec_pushl(&cp_log.args, "--pretty=  > %s",
-				     "-1", dst_abbrev, NULL);
-		} else {
-			strvec_pushl(&cp_log.args, "--pretty=  < %s",
-				     "-1", src_abbrev, NULL);
-		}
-		run_command(&cp_log);
-	}
-	printf("\n");
-}
-
-static void generate_submodule_summary(struct summary_cb *info,
-				       struct module_cb *p)
-{
-	char *displaypath, *src_abbrev = NULL, *dst_abbrev;
-	int missing_src = 0, missing_dst = 0;
-	char *errmsg = NULL;
-	int total_commits = -1;
-
-	if (!info->cached && oideq(&p->oid_dst, &null_oid)) {
-		if (S_ISGITLINK(p->mod_dst)) {
-			struct ref_store *refs = get_submodule_ref_store(p->sm_path);
-			if (refs)
-				refs_head_ref(refs, handle_submodule_head_ref, &p->oid_dst);
-		} else if (S_ISLNK(p->mod_dst) || S_ISREG(p->mod_dst)) {
-			struct stat st;
-			int fd = open(p->sm_path, O_RDONLY);
-
-			if (fd < 0 || fstat(fd, &st) < 0 ||
-			    index_fd(&the_index, &p->oid_dst, fd, &st, OBJ_BLOB,
-				     p->sm_path, 0))
-				error(_("couldn't hash object from '%s'"), p->sm_path);
-		} else {
-			/* for a submodule removal (mode:0000000), don't warn */
-			if (p->mod_dst)
-				warning(_("unexpected mode %o\n"), p->mod_dst);
-		}
-	}
-
-	if (S_ISGITLINK(p->mod_src)) {
-		if (p->status != 'D')
-			src_abbrev = verify_submodule_committish(p->sm_path,
-								 oid_to_hex(&p->oid_src));
-		if (!src_abbrev) {
-			missing_src = 1;
-			/*
-			 * As `rev-parse` failed, we fallback to getting
-			 * the abbreviated hash using oid_src. We do
-			 * this as we might still need the abbreviated
-			 * hash in cases like a submodule type change, etc.
-			 */
-			src_abbrev = xstrndup(oid_to_hex(&p->oid_src), 7);
-		}
-	} else {
-		/*
-		 * The source does not point to a submodule.
-		 * So, we fallback to getting the abbreviation using
-		 * oid_src as we might still need the abbreviated
-		 * hash in cases like submodule add, etc.
-		 */
-		src_abbrev = xstrndup(oid_to_hex(&p->oid_src), 7);
-	}
-
-	if (S_ISGITLINK(p->mod_dst)) {
-		dst_abbrev = verify_submodule_committish(p->sm_path,
-							 oid_to_hex(&p->oid_dst));
-		if (!dst_abbrev) {
-			missing_dst = 1;
-			/*
-			 * As `rev-parse` failed, we fallback to getting
-			 * the abbreviated hash using oid_dst. We do
-			 * this as we might still need the abbreviated
-			 * hash in cases like a submodule type change, etc.
-			 */
-			dst_abbrev = xstrndup(oid_to_hex(&p->oid_dst), 7);
-		}
-	} else {
-		/*
-		 * The destination does not point to a submodule.
-		 * So, we fallback to getting the abbreviation using
-		 * oid_dst as we might still need the abbreviated
-		 * hash in cases like a submodule removal, etc.
-		 */
-		dst_abbrev = xstrndup(oid_to_hex(&p->oid_dst), 7);
-	}
-
-	displaypath = get_submodule_displaypath(p->sm_path, info->prefix);
-
-	if (!missing_src && !missing_dst) {
-		struct child_process cp_rev_list = CHILD_PROCESS_INIT;
-		struct strbuf sb_rev_list = STRBUF_INIT;
-
-		strvec_pushl(&cp_rev_list.args, "rev-list",
-			     "--first-parent", "--count", NULL);
-		if (S_ISGITLINK(p->mod_src) && S_ISGITLINK(p->mod_dst))
-			strvec_pushf(&cp_rev_list.args, "%s...%s",
-				     src_abbrev, dst_abbrev);
-		else
-			strvec_push(&cp_rev_list.args, S_ISGITLINK(p->mod_src) ?
-				    src_abbrev : dst_abbrev);
-		strvec_push(&cp_rev_list.args, "--");
-
-		cp_rev_list.git_cmd = 1;
-		cp_rev_list.dir = p->sm_path;
-		prepare_submodule_repo_env(&cp_rev_list.env_array);
-
-		if (!capture_command(&cp_rev_list, &sb_rev_list, 0))
-			total_commits = atoi(sb_rev_list.buf);
-
-		strbuf_release(&sb_rev_list);
-	} else {
-		/*
-		 * Don't give error msg for modification whose dst is not
-		 * submodule, i.e., deleted or changed to blob
-		 */
-		if (S_ISGITLINK(p->mod_dst)) {
-			struct strbuf errmsg_str = STRBUF_INIT;
-			if (missing_src && missing_dst) {
-				strbuf_addf(&errmsg_str, "  Warn: %s doesn't contain commits %s and %s\n",
-					    displaypath, oid_to_hex(&p->oid_src),
-					    oid_to_hex(&p->oid_dst));
-			} else {
-				strbuf_addf(&errmsg_str, "  Warn: %s doesn't contain commit %s\n",
-					    displaypath, missing_src ?
-					    oid_to_hex(&p->oid_src) :
-					    oid_to_hex(&p->oid_dst));
-			}
-			errmsg = strbuf_detach(&errmsg_str, NULL);
-		}
-	}
-
-	print_submodule_summary(info, errmsg, total_commits,
-				displaypath, src_abbrev,
-				dst_abbrev, p);
-
-	free(displaypath);
-	free(src_abbrev);
-	free(dst_abbrev);
-}
-
-static void prepare_submodule_summary(struct summary_cb *info,
-				      struct module_cb_list *list)
-{
-	int i;
-	for (i = 0; i < list->nr; i++) {
-		const struct submodule *sub;
-		struct module_cb *p = list->entries[i];
-		struct strbuf sm_gitdir = STRBUF_INIT;
-
-		if (p->status == 'D' || p->status == 'T') {
-			generate_submodule_summary(info, p);
-			continue;
-		}
-
-		if (info->for_status && p->status != 'A' &&
-		    (sub = submodule_from_path(the_repository,
-					       &null_oid, p->sm_path))) {
-			char *config_key = NULL;
-			const char *value;
-			int ignore_all = 0;
-
-			config_key = xstrfmt("submodule.%s.ignore",
-					     sub->name);
-			if (!git_config_get_string_tmp(config_key, &value))
-				ignore_all = !strcmp(value, "all");
-			else if (sub->ignore)
-				ignore_all = !strcmp(sub->ignore, "all");
-
-			free(config_key);
-			if (ignore_all)
-				continue;
-		}
-
-		/* Also show added or modified modules which are checked out */
-		strbuf_addstr(&sm_gitdir, p->sm_path);
-		if (is_nonbare_repository_dir(&sm_gitdir))
-			generate_submodule_summary(info, p);
-		strbuf_release(&sm_gitdir);
-	}
-}
-
-static void submodule_summary_callback(struct diff_queue_struct *q,
-				       struct diff_options *options,
-				       void *data)
-{
-	int i;
-	struct module_cb_list *list = data;
-	for (i = 0; i < q->nr; i++) {
-		struct diff_filepair *p = q->queue[i];
-		struct module_cb *temp;
-
-		if (!S_ISGITLINK(p->one->mode) && !S_ISGITLINK(p->two->mode))
-			continue;
-		temp = (struct module_cb*)malloc(sizeof(struct module_cb));
-		temp->mod_src = p->one->mode;
-		temp->mod_dst = p->two->mode;
-		temp->oid_src = p->one->oid;
-		temp->oid_dst = p->two->oid;
-		temp->status = p->status;
-		temp->sm_path = xstrdup(p->one->path);
-
-		ALLOC_GROW(list->entries, list->nr + 1, list->alloc);
-		list->entries[list->nr++] = temp;
-	}
-}
-
-static const char *get_diff_cmd(enum diff_cmd diff_cmd)
-{
-	switch (diff_cmd) {
-	case DIFF_INDEX: return "diff-index";
-	case DIFF_FILES: return "diff-files";
-	default: BUG("bad diff_cmd value %d", diff_cmd);
-	}
-}
-
-static int compute_summary_module_list(struct object_id *head_oid,
-				       struct summary_cb *info,
-				       enum diff_cmd diff_cmd)
-{
-	struct strvec diff_args = STRVEC_INIT;
-	struct rev_info rev;
-	struct module_cb_list list = MODULE_CB_LIST_INIT;
-
-	strvec_push(&diff_args, get_diff_cmd(diff_cmd));
-	if (info->cached)
-		strvec_push(&diff_args, "--cached");
-	strvec_pushl(&diff_args, "--ignore-submodules=dirty", "--raw", NULL);
-	if (head_oid)
-		strvec_push(&diff_args, oid_to_hex(head_oid));
-	strvec_push(&diff_args, "--");
-	if (info->argc)
-		strvec_pushv(&diff_args, info->argv);
-
-	git_config(git_diff_basic_config, NULL);
-	init_revisions(&rev, info->prefix);
-	rev.abbrev = 0;
-	precompose_argv(diff_args.nr, diff_args.v);
-	setup_revisions(diff_args.nr, diff_args.v, &rev, NULL);
-	rev.diffopt.output_format = DIFF_FORMAT_NO_OUTPUT | DIFF_FORMAT_CALLBACK;
-	rev.diffopt.format_callback = submodule_summary_callback;
-	rev.diffopt.format_callback_data = &list;
-
-	if (!info->cached) {
-		if (diff_cmd == DIFF_INDEX)
-			setup_work_tree();
-		if (read_cache_preload(&rev.diffopt.pathspec) < 0) {
-			perror("read_cache_preload");
-			return -1;
-		}
-	} else if (read_cache() < 0) {
-		perror("read_cache");
-		return -1;
-	}
-
-	if (diff_cmd == DIFF_INDEX)
-		run_diff_index(&rev, info->cached);
-	else
-		run_diff_files(&rev, 0);
-	prepare_submodule_summary(info, &list);
-	strvec_clear(&diff_args);
-	return 0;
-}
-
-static int module_summary(int argc, const char **argv, const char *prefix)
-{
-	struct summary_cb info = SUMMARY_CB_INIT;
-	int cached = 0;
-	int for_status = 0;
-	int files = 0;
-	int summary_limit = -1;
-	enum diff_cmd diff_cmd = DIFF_INDEX;
-	struct object_id head_oid;
-	int ret;
-
-	struct option module_summary_options[] = {
-		OPT_BOOL(0, "cached", &cached,
-			 N_("use the commit stored in the index instead of the submodule HEAD")),
-		OPT_BOOL(0, "files", &files,
-			 N_("to compare the commit in the index with that in the submodule HEAD")),
-		OPT_BOOL(0, "for-status", &for_status,
-			 N_("skip submodules with 'ignore_config' value set to 'all'")),
-		OPT_INTEGER('n', "summary-limit", &summary_limit,
-			     N_("limit the summary size")),
-		OPT_END()
-	};
-
-	const char *const git_submodule_helper_usage[] = {
-		N_("git submodule--helper summary [<options>] [<commit>] [--] [<path>]"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, module_summary_options,
-			     git_submodule_helper_usage, 0);
-
-	if (!summary_limit)
-		return 0;
-
-	if (!get_oid(argc ? argv[0] : "HEAD", &head_oid)) {
-		if (argc) {
-			argv++;
-			argc--;
-		}
-	} else if (!argc || !strcmp(argv[0], "HEAD")) {
-		/* before the first commit: compare with an empty tree */
-		oidcpy(&head_oid, the_hash_algo->empty_tree);
-		if (argc) {
-			argv++;
-			argc--;
-		}
-	} else {
-		if (get_oid("HEAD", &head_oid))
-			die(_("could not fetch a revision for HEAD"));
-	}
-
-	if (files) {
-		if (cached)
-			die(_("--cached and --files are mutually exclusive"));
-		diff_cmd = DIFF_FILES;
-	}
-
-	info.argc = argc;
-	info.argv = argv;
-	info.prefix = prefix;
-	info.cached = !!cached;
-	info.files = !!files;
-	info.for_status = !!for_status;
-	info.summary_limit = summary_limit;
-
-	ret = compute_summary_module_list((diff_cmd == DIFF_INDEX) ? &head_oid : NULL,
-					  &info, diff_cmd);
-	return ret;
-}
-
-struct sync_cb {
-	const char *prefix;
-	unsigned int flags;
-};
-#define SYNC_CB_INIT { NULL, 0 }
-
-static void sync_submodule(const char *path, const char *prefix,
-			   unsigned int flags)
-{
-	const struct submodule *sub;
-	char *remote_key = NULL;
-	char *sub_origin_url, *super_config_url, *displaypath;
-	struct strbuf sb = STRBUF_INIT;
-	struct child_process cp = CHILD_PROCESS_INIT;
-	char *sub_config_path = NULL;
-
-	if (!is_submodule_active(the_repository, path))
-		return;
-
-	sub = submodule_from_path(the_repository, &null_oid, path);
-
-	if (sub && sub->url) {
-		if (starts_with_dot_dot_slash(sub->url) ||
-		    starts_with_dot_slash(sub->url)) {
-			char *remote_url, *up_path;
-			char *remote = get_default_remote();
-			strbuf_addf(&sb, "remote.%s.url", remote);
-
-			if (git_config_get_string(sb.buf, &remote_url))
-				remote_url = xgetcwd();
-
-			up_path = get_up_path(path);
-			sub_origin_url = relative_url(remote_url, sub->url, up_path);
-			super_config_url = relative_url(remote_url, sub->url, NULL);
-
-			free(remote);
-			free(up_path);
-			free(remote_url);
-		} else {
-			sub_origin_url = xstrdup(sub->url);
-			super_config_url = xstrdup(sub->url);
-		}
-	} else {
-		sub_origin_url = xstrdup("");
-		super_config_url = xstrdup("");
-	}
-
-	displaypath = get_submodule_displaypath(path, prefix);
-
-	if (!(flags & OPT_QUIET))
-		printf(_("Synchronizing submodule url for '%s'\n"),
-			 displaypath);
-
-	strbuf_reset(&sb);
-	strbuf_addf(&sb, "submodule.%s.url", sub->name);
-	if (git_config_set_gently(sb.buf, super_config_url))
-		die(_("failed to register url for submodule path '%s'"),
-		      displaypath);
-
-	if (!is_submodule_populated_gently(path, NULL))
-		goto cleanup;
-
-	prepare_submodule_repo_env(&cp.env_array);
-	cp.git_cmd = 1;
-	cp.dir = path;
-	strvec_pushl(&cp.args, "submodule--helper",
-		     "print-default-remote", NULL);
-
-	strbuf_reset(&sb);
-	if (capture_command(&cp, &sb, 0))
-		die(_("failed to get the default remote for submodule '%s'"),
-		      path);
-
-	strbuf_strip_suffix(&sb, "\n");
-	remote_key = xstrfmt("remote.%s.url", sb.buf);
-
-	strbuf_reset(&sb);
-	submodule_to_gitdir(&sb, path);
-	strbuf_addstr(&sb, "/config");
-
-	if (git_config_set_in_file_gently(sb.buf, remote_key, sub_origin_url))
-		die(_("failed to update remote for submodule '%s'"),
-		      path);
-
-	if (flags & OPT_RECURSIVE) {
-		struct child_process cpr = CHILD_PROCESS_INIT;
-
-		cpr.git_cmd = 1;
-		cpr.dir = path;
-		prepare_submodule_repo_env(&cpr.env_array);
-
-		strvec_push(&cpr.args, "--super-prefix");
-		strvec_pushf(&cpr.args, "%s/", displaypath);
-		strvec_pushl(&cpr.args, "submodule--helper", "sync",
-			     "--recursive", NULL);
-
-		if (flags & OPT_QUIET)
-			strvec_push(&cpr.args, "--quiet");
-
-		if (run_command(&cpr))
-			die(_("failed to recurse into submodule '%s'"),
-			      path);
-	}
-
-cleanup:
-	free(super_config_url);
-	free(sub_origin_url);
-	strbuf_release(&sb);
-	free(remote_key);
-	free(displaypath);
-	free(sub_config_path);
-}
-
-static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data)
-{
-	struct sync_cb *info = cb_data;
-	sync_submodule(list_item->name, info->prefix, info->flags);
-}
-
-static int module_sync(int argc, const char **argv, const char *prefix)
-{
-	struct sync_cb info = SYNC_CB_INIT;
-	struct pathspec pathspec;
-	struct module_list list = MODULE_LIST_INIT;
-	int quiet = 0;
-	int recursive = 0;
-
-	struct option module_sync_options[] = {
-		OPT__QUIET(&quiet, N_("Suppress output of synchronizing submodule url")),
-		OPT_BOOL(0, "recursive", &recursive,
-			N_("Recurse into nested submodules")),
-		OPT_END()
-	};
-
-	const char *const git_submodule_helper_usage[] = {
-		N_("git submodule--helper sync [--quiet] [--recursive] [<path>]"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, module_sync_options,
-			     git_submodule_helper_usage, 0);
-
-	if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
-		return 1;
-
-	info.prefix = prefix;
-	if (quiet)
-		info.flags |= OPT_QUIET;
-	if (recursive)
-		info.flags |= OPT_RECURSIVE;
-
-	for_each_listed_submodule(&list, sync_submodule_cb, &info);
-
-	return 0;
-}
-
-struct deinit_cb {
-	const char *prefix;
-	unsigned int flags;
-};
-#define DEINIT_CB_INIT { NULL, 0 }
-
-static void deinit_submodule(const char *path, const char *prefix,
-			     unsigned int flags)
-{
-	const struct submodule *sub;
-	char *displaypath = NULL;
-	struct child_process cp_config = CHILD_PROCESS_INIT;
-	struct strbuf sb_config = STRBUF_INIT;
-	char *sub_git_dir = xstrfmt("%s/.git", path);
-
-	sub = submodule_from_path(the_repository, &null_oid, path);
-
-	if (!sub || !sub->name)
-		goto cleanup;
-
-	displaypath = get_submodule_displaypath(path, prefix);
-
-	/* remove the submodule work tree (unless the user already did it) */
-	if (is_directory(path)) {
-		struct strbuf sb_rm = STRBUF_INIT;
-		const char *format;
-
-		/*
-		 * protect submodules containing a .git directory
-		 * NEEDSWORK: instead of dying, automatically call
-		 * absorbgitdirs and (possibly) warn.
-		 */
-		if (is_directory(sub_git_dir))
-			die(_("Submodule work tree '%s' contains a .git "
-			      "directory (use 'rm -rf' if you really want "
-			      "to remove it including all of its history)"),
-			    displaypath);
-
-		if (!(flags & OPT_FORCE)) {
-			struct child_process cp_rm = CHILD_PROCESS_INIT;
-			cp_rm.git_cmd = 1;
-			strvec_pushl(&cp_rm.args, "rm", "-qn",
-				     path, NULL);
-
-			if (run_command(&cp_rm))
-				die(_("Submodule work tree '%s' contains local "
-				      "modifications; use '-f' to discard them"),
-				      displaypath);
-		}
-
-		strbuf_addstr(&sb_rm, path);
-
-		if (!remove_dir_recursively(&sb_rm, 0))
-			format = _("Cleared directory '%s'\n");
-		else
-			format = _("Could not remove submodule work tree '%s'\n");
-
-		if (!(flags & OPT_QUIET))
-			printf(format, displaypath);
-
-		submodule_unset_core_worktree(sub);
-
-		strbuf_release(&sb_rm);
-	}
-
-	if (mkdir(path, 0777))
-		printf(_("could not create empty submodule directory %s"),
-		      displaypath);
-
-	cp_config.git_cmd = 1;
-	strvec_pushl(&cp_config.args, "config", "--get-regexp", NULL);
-	strvec_pushf(&cp_config.args, "submodule.%s\\.", sub->name);
-
-	/* remove the .git/config entries (unless the user already did it) */
-	if (!capture_command(&cp_config, &sb_config, 0) && sb_config.len) {
-		char *sub_key = xstrfmt("submodule.%s", sub->name);
-		/*
-		 * remove the whole section so we have a clean state when
-		 * the user later decides to init this submodule again
-		 */
-		git_config_rename_section_in_file(NULL, sub_key, NULL);
-		if (!(flags & OPT_QUIET))
-			printf(_("Submodule '%s' (%s) unregistered for path '%s'\n"),
-				 sub->name, sub->url, displaypath);
-		free(sub_key);
-	}
-
-cleanup:
-	free(displaypath);
-	free(sub_git_dir);
-	strbuf_release(&sb_config);
-}
-
-static void deinit_submodule_cb(const struct cache_entry *list_item,
-				void *cb_data)
-{
-	struct deinit_cb *info = cb_data;
-	deinit_submodule(list_item->name, info->prefix, info->flags);
-}
-
-static int module_deinit(int argc, const char **argv, const char *prefix)
-{
-	struct deinit_cb info = DEINIT_CB_INIT;
-	struct pathspec pathspec;
-	struct module_list list = MODULE_LIST_INIT;
-	int quiet = 0;
-	int force = 0;
-	int all = 0;
-
-	struct option module_deinit_options[] = {
-		OPT__QUIET(&quiet, N_("Suppress submodule status output")),
-		OPT__FORCE(&force, N_("Remove submodule working trees even if they contain local changes"), 0),
-		OPT_BOOL(0, "all", &all, N_("Unregister all submodules")),
-		OPT_END()
-	};
-
-	const char *const git_submodule_helper_usage[] = {
-		N_("git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, module_deinit_options,
-			     git_submodule_helper_usage, 0);
-
-	if (all && argc) {
-		error("pathspec and --all are incompatible");
-		usage_with_options(git_submodule_helper_usage,
-				   module_deinit_options);
-	}
-
-	if (!argc && !all)
-		die(_("Use '--all' if you really want to deinitialize all submodules"));
-
-	if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
-		return 1;
-
-	info.prefix = prefix;
-	if (quiet)
-		info.flags |= OPT_QUIET;
-	if (force)
-		info.flags |= OPT_FORCE;
-
-	for_each_listed_submodule(&list, deinit_submodule_cb, &info);
-
-	return 0;
-}
-
-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)
-{
-	struct child_process cp = CHILD_PROCESS_INIT;
-
-	strvec_push(&cp.args, "clone");
-	strvec_push(&cp.args, "--no-checkout");
-	if (quiet)
-		strvec_push(&cp.args, "--quiet");
-	if (progress)
-		strvec_push(&cp.args, "--progress");
-	if (depth && *depth)
-		strvec_pushl(&cp.args, "--depth", depth, NULL);
-	if (reference->nr) {
-		struct string_list_item *item;
-		for_each_string_list_item(item, reference)
-			strvec_pushl(&cp.args, "--reference",
-				     item->string, NULL);
-	}
-	if (dissociate)
-		strvec_push(&cp.args, "--dissociate");
-	if (gitdir && *gitdir)
-		strvec_pushl(&cp.args, "--separate-git-dir", gitdir, NULL);
-	if (single_branch >= 0)
-		strvec_push(&cp.args, single_branch ?
-					  "--single-branch" :
-					  "--no-single-branch");
-
-	strvec_push(&cp.args, "--");
-	strvec_push(&cp.args, url);
-	strvec_push(&cp.args, path);
-
-	cp.git_cmd = 1;
-	prepare_submodule_repo_env(&cp.env_array);
-	cp.no_stdin = 1;
-
-	return run_command(&cp);
-}
-
-struct submodule_alternate_setup {
-	const char *submodule_name;
-	enum SUBMODULE_ALTERNATE_ERROR_MODE {
-		SUBMODULE_ALTERNATE_ERROR_DIE,
-		SUBMODULE_ALTERNATE_ERROR_INFO,
-		SUBMODULE_ALTERNATE_ERROR_IGNORE
-	} error_mode;
-	struct string_list *reference;
-};
-#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)
-{
-	struct submodule_alternate_setup *sas = sas_cb;
-	size_t len;
-
-	/*
-	 * If the alternate object store is another repository, try the
-	 * standard layout with .git/(modules/<name>)+/objects
-	 */
-	if (strip_suffix(odb->path, "/objects", &len)) {
-		char *sm_alternate;
-		struct strbuf sb = STRBUF_INIT;
-		struct strbuf err = STRBUF_INIT;
-		strbuf_add(&sb, odb->path, len);
-
-		/*
-		 * We need to end the new path with '/' to mark it as a dir,
-		 * otherwise a submodule name containing '/' will be broken
-		 * as the last part of a missing submodule reference would
-		 * be taken as a file name.
-		 */
-		strbuf_addf(&sb, "/modules/%s/", sas->submodule_name);
-
-		sm_alternate = compute_alternate_path(sb.buf, &err);
-		if (sm_alternate) {
-			string_list_append(sas->reference, xstrdup(sb.buf));
-			free(sm_alternate);
-		} 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:
-				fprintf_ln(stderr, _("submodule '%s' cannot add alternate: %s"),
-					sas->submodule_name, err.buf);
-			case SUBMODULE_ALTERNATE_ERROR_IGNORE:
-				; /* nothing */
-			}
-		}
-		strbuf_release(&sb);
-	}
-
-	return 0;
-}
-
-static void prepare_possible_alternates(const char *sm_name,
-		struct string_list *reference)
-{
-	char *sm_alternate = NULL, *error_strategy = NULL;
-	struct submodule_alternate_setup sas = SUBMODULE_ALTERNATE_SETUP_INIT;
-
-	git_config_get_string("submodule.alternateLocation", &sm_alternate);
-	if (!sm_alternate)
-		return;
-
-	git_config_get_string("submodule.alternateErrorStrategy", &error_strategy);
-
-	if (!error_strategy)
-		error_strategy = xstrdup("die");
-
-	sas.submodule_name = sm_name;
-	sas.reference = reference;
-	if (!strcmp(error_strategy, "die"))
-		sas.error_mode = SUBMODULE_ALTERNATE_ERROR_DIE;
-	else if (!strcmp(error_strategy, "info"))
-		sas.error_mode = SUBMODULE_ALTERNATE_ERROR_INFO;
-	else if (!strcmp(error_strategy, "ignore"))
-		sas.error_mode = SUBMODULE_ALTERNATE_ERROR_IGNORE;
-	else
-		die(_("Value '%s' for submodule.alternateErrorStrategy is not recognized"), error_strategy);
-
-	if (!strcmp(sm_alternate, "superproject"))
-		foreach_alt_odb(add_possible_reference_from_superproject, &sas);
-	else if (!strcmp(sm_alternate, "no"))
-		; /* do nothing */
-	else
-		die(_("Value '%s' for submodule.alternateLocation is not recognized"), sm_alternate);
-
-	free(sm_alternate);
-	free(error_strategy);
-}
-
-static int module_clone(int argc, const char **argv, const char *prefix)
-{
-	const char *name = NULL, *url = NULL, *depth = NULL;
-	int quiet = 0;
-	int progress = 0;
-	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;
-	char *sm_alternate = NULL, *error_strategy = NULL;
-	int single_branch = -1;
-
-	struct option module_clone_options[] = {
-		OPT_STRING(0, "prefix", &prefix,
-			   N_("path"),
-			   N_("alternative anchor for relative paths")),
-		OPT_STRING(0, "path", &path,
-			   N_("path"),
-			   N_("where the new submodule will be cloned to")),
-		OPT_STRING(0, "name", &name,
-			   N_("string"),
-			   N_("name of the new submodule")),
-		OPT_STRING(0, "url", &url,
-			   N_("string"),
-			   N_("url where to clone the submodule from")),
-		OPT_STRING_LIST(0, "reference", &reference,
-			   N_("repo"),
-			   N_("reference repository")),
-		OPT_BOOL(0, "dissociate", &dissociate,
-			   N_("use --reference only while cloning")),
-		OPT_STRING(0, "depth", &depth,
-			   N_("string"),
-			   N_("depth for shallow clones")),
-		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
-	};
-
-	argc = parse_options(argc, argv, prefix, module_clone_options,
-			     git_submodule_helper_usage, 0);
-
-	if (argc || !url || !path || !*path)
-		usage_with_options(git_submodule_helper_usage,
-				   module_clone_options);
-
-	strbuf_addf(&sb, "%s/modules/%s", get_git_dir(), name);
-	sm_gitdir = absolute_pathdup(sb.buf);
-	strbuf_reset(&sb);
-
-	if (!is_absolute_path(path)) {
-		strbuf_addf(&sb, "%s/%s", get_git_work_tree(), path);
-		path = strbuf_detach(&sb, NULL);
-	} 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);
-
-		prepare_possible_alternates(name, &reference);
-
-		if (clone_submodule(path, sm_gitdir, url, depth, &reference, dissociate,
-				    quiet, progress, single_branch))
-			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);
-		unlink_or_warn(sb.buf);
-		strbuf_reset(&sb);
-	}
-
-	connect_work_tree_and_git_dir(path, sm_gitdir, 0);
-
-	p = git_pathdup_submodule(path, "config");
-	if (!p)
-		die(_("could not get submodule directory for '%s'"), path);
-
-	/* setup alternateLocation and alternateErrorStrategy in the cloned submodule if needed */
-	git_config_get_string("submodule.alternateLocation", &sm_alternate);
-	if (sm_alternate)
-		git_config_set_in_file(p, "submodule.alternateLocation",
-					   sm_alternate);
-	git_config_get_string("submodule.alternateErrorStrategy", &error_strategy);
-	if (error_strategy)
-		git_config_set_in_file(p, "submodule.alternateErrorStrategy",
-					   error_strategy);
-
-	free(sm_alternate);
-	free(error_strategy);
-
-	strbuf_release(&sb);
-	free(sm_gitdir);
-	free(path);
-	free(p);
-	return 0;
-}
-
-static void determine_submodule_update_strategy(struct repository *r,
-						int just_cloned,
-						const char *path,
-						const char *update,
-						struct submodule_update_strategy *out)
-{
-	const struct submodule *sub = submodule_from_path(r, &null_oid, path);
-	char *key;
-	const char *val;
-
-	key = xstrfmt("submodule.%s.update", sub->name);
-
-	if (update) {
-		if (parse_submodule_update_strategy(update, out) < 0)
-			die(_("Invalid update mode '%s' for submodule path '%s'"),
-				update, path);
-	} else if (!repo_config_get_string_tmp(r, key, &val)) {
-		if (parse_submodule_update_strategy(val, out) < 0)
-			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
-		out->type = SM_UPDATE_CHECKOUT;
-
-	if (just_cloned &&
-	    (out->type == SM_UPDATE_MERGE ||
-	     out->type == SM_UPDATE_REBASE ||
-	     out->type == SM_UPDATE_NONE))
-		out->type = SM_UPDATE_CHECKOUT;
-
-	free(key);
-}
-
-static int module_update_module_mode(int argc, const char **argv, const char *prefix)
-{
-	const char *path, *update = NULL;
-	int just_cloned;
-	struct submodule_update_strategy update_strategy = { .type = SM_UPDATE_CHECKOUT };
-
-	if (argc < 3 || argc > 4)
-		die("submodule--helper update-module-clone expects <just-cloned> <path> [<update>]");
-
-	just_cloned = git_config_int("just_cloned", argv[1]);
-	path = argv[2];
-
-	if (argc == 4)
-		update = argv[3];
-
-	determine_submodule_update_strategy(the_repository,
-					    just_cloned, path, update,
-					    &update_strategy);
-	fputs(submodule_strategy_to_string(&update_strategy), stdout);
-
-	return 0;
-}
-
-struct update_clone_data {
-	const struct submodule *sub;
-	struct object_id oid;
-	unsigned just_cloned;
-};
-
-struct submodule_update_clone {
-	/* index into 'list', the list of submodules to look into for cloning */
-	int current;
-	struct module_list list;
-	unsigned warn_if_uninitialized : 1;
-
-	/* update parameter passed via commandline */
-	struct submodule_update_strategy update;
-
-	/* configuration parameters which are passed on to the children */
-	int progress;
-	int quiet;
-	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;
-	int update_clone_nr; int update_clone_alloc;
-
-	/* If we want to stop as fast as possible and return an error */
-	unsigned quickstop : 1;
-
-	/* failed clones to be retried again */
-	const struct cache_entry **failed_clones;
-	int failed_clones_nr, failed_clones_alloc;
-
-	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, \
-}
-
-
-static void next_submodule_warn_missing(struct submodule_update_clone *suc,
-		struct strbuf *out, const char *displaypath)
-{
-	/*
-	 * Only mention uninitialized submodules when their
-	 * paths have been specified.
-	 */
-	if (suc->warn_if_uninitialized) {
-		strbuf_addf(out,
-			_("Submodule path '%s' not initialized"),
-			displaypath);
-		strbuf_addch(out, '\n');
-		strbuf_addstr(out,
-			_("Maybe you want to use 'update --init'?"));
-		strbuf_addch(out, '\n');
-	}
-}
-
-/**
- * Determine whether 'ce' needs to be cloned. If so, prepare the 'child' to
- * run the clone. Returns 1 if 'ce' needs to be cloned, 0 otherwise.
- */
-static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
-					   struct child_process *child,
-					   struct submodule_update_clone *suc,
-					   struct strbuf *out)
-{
-	const struct submodule *sub = NULL;
-	const char *url = NULL;
-	const char *update_string;
-	enum submodule_update_type update_type;
-	char *key;
-	struct strbuf displaypath_sb = STRBUF_INIT;
-	struct strbuf sb = STRBUF_INIT;
-	const char *displaypath = NULL;
-	int needs_cloning = 0;
-	int need_free_url = 0;
-
-	if (ce_stage(ce)) {
-		if (suc->recursive_prefix)
-			strbuf_addf(&sb, "%s/%s", suc->recursive_prefix, ce->name);
-		else
-			strbuf_addstr(&sb, ce->name);
-		strbuf_addf(out, _("Skipping unmerged submodule %s"), sb.buf);
-		strbuf_addch(out, '\n');
-		goto cleanup;
-	}
-
-	sub = submodule_from_path(the_repository, &null_oid, ce->name);
-
-	if (suc->recursive_prefix)
-		displaypath = relative_path(suc->recursive_prefix,
-					    ce->name, &displaypath_sb);
-	else
-		displaypath = ce->name;
-
-	if (!sub) {
-		next_submodule_warn_missing(suc, out, displaypath);
-		goto cleanup;
-	}
-
-	key = xstrfmt("submodule.%s.update", sub->name);
-	if (!repo_config_get_string_tmp(the_repository, key, &update_string)) {
-		update_type = parse_submodule_update_type(update_string);
-	} else {
-		update_type = sub->update_strategy.type;
-	}
-	free(key);
-
-	if (suc->update.type == SM_UPDATE_NONE
-	    || (suc->update.type == SM_UPDATE_UNSPECIFIED
-		&& update_type == SM_UPDATE_NONE)) {
-		strbuf_addf(out, _("Skipping submodule '%s'"), displaypath);
-		strbuf_addch(out, '\n');
-		goto cleanup;
-	}
-
-	/* Check if the submodule has been initialized. */
-	if (!is_submodule_active(the_repository, ce->name)) {
-		next_submodule_warn_missing(suc, out, displaypath);
-		goto cleanup;
-	}
-
-	strbuf_reset(&sb);
-	strbuf_addf(&sb, "submodule.%s.url", sub->name);
-	if (repo_config_get_string_tmp(the_repository, sb.buf, &url)) {
-		if (starts_with_dot_slash(sub->url) ||
-		    starts_with_dot_dot_slash(sub->url)) {
-			url = compute_submodule_clone_url(sub->url);
-			need_free_url = 1;
-		} else
-			url = sub->url;
-	}
-
-	strbuf_reset(&sb);
-	strbuf_addf(&sb, "%s/.git", ce->name);
-	needs_cloning = !file_exists(sb.buf);
-
-	ALLOC_GROW(suc->update_clone, suc->update_clone_nr + 1,
-		   suc->update_clone_alloc);
-	oidcpy(&suc->update_clone[suc->update_clone_nr].oid, &ce->oid);
-	suc->update_clone[suc->update_clone_nr].just_cloned = needs_cloning;
-	suc->update_clone[suc->update_clone_nr].sub = sub;
-	suc->update_clone_nr++;
-
-	if (!needs_cloning)
-		goto cleanup;
-
-	child->git_cmd = 1;
-	child->no_stdin = 1;
-	child->stdout_to_stderr = 1;
-	child->err = -1;
-	strvec_push(&child->args, "submodule--helper");
-	strvec_push(&child->args, "clone");
-	if (suc->progress)
-		strvec_push(&child->args, "--progress");
-	if (suc->quiet)
-		strvec_push(&child->args, "--quiet");
-	if (suc->prefix)
-		strvec_pushl(&child->args, "--prefix", suc->prefix, NULL);
-	if (suc->recommend_shallow && sub->recommend_shallow == 1)
-		strvec_push(&child->args, "--depth=1");
-	if (suc->require_init)
-		strvec_push(&child->args, "--require-init");
-	strvec_pushl(&child->args, "--path", sub->path, NULL);
-	strvec_pushl(&child->args, "--name", sub->name, NULL);
-	strvec_pushl(&child->args, "--url", url, NULL);
-	if (suc->references.nr) {
-		struct string_list_item *item;
-		for_each_string_list_item(item, &suc->references)
-			strvec_pushl(&child->args, "--reference", item->string, NULL);
-	}
-	if (suc->dissociate)
-		strvec_push(&child->args, "--dissociate");
-	if (suc->depth)
-		strvec_push(&child->args, suc->depth);
-	if (suc->single_branch >= 0)
-		strvec_push(&child->args, suc->single_branch ?
-					      "--single-branch" :
-					      "--no-single-branch");
-
-cleanup:
-	strbuf_release(&displaypath_sb);
-	strbuf_release(&sb);
-	if (need_free_url)
-		free((void*)url);
-
-	return needs_cloning;
-}
-
-static int update_clone_get_next_task(struct child_process *child,
-				      struct strbuf *err,
-				      void *suc_cb,
-				      void **idx_task_cb)
-{
-	struct submodule_update_clone *suc = suc_cb;
-	const struct cache_entry *ce;
-	int index;
-
-	for (; suc->current < suc->list.nr; suc->current++) {
-		ce = suc->list.entries[suc->current];
-		if (prepare_to_clone_next_submodule(ce, child, suc, err)) {
-			int *p = xmalloc(sizeof(*p));
-			*p = suc->current;
-			*idx_task_cb = p;
-			suc->current++;
-			return 1;
-		}
-	}
-
-	/*
-	 * The loop above tried cloning each submodule once, now try the
-	 * stragglers again, which we can imagine as an extension of the
-	 * entry list.
-	 */
-	index = suc->current - suc->list.nr;
-	if (index < suc->failed_clones_nr) {
-		int *p;
-		ce = suc->failed_clones[index];
-		if (!prepare_to_clone_next_submodule(ce, child, suc, err)) {
-			suc->current ++;
-			strbuf_addstr(err, "BUG: submodule considered for "
-					   "cloning, doesn't need cloning "
-					   "any more?\n");
-			return 0;
-		}
-		p = xmalloc(sizeof(*p));
-		*p = suc->current;
-		*idx_task_cb = p;
-		suc->current ++;
-		return 1;
-	}
-
-	return 0;
-}
-
-static int update_clone_start_failure(struct strbuf *err,
-				      void *suc_cb,
-				      void *idx_task_cb)
-{
-	struct submodule_update_clone *suc = suc_cb;
-	suc->quickstop = 1;
-	return 1;
-}
-
-static int update_clone_task_finished(int result,
-				      struct strbuf *err,
-				      void *suc_cb,
-				      void *idx_task_cb)
-{
-	const struct cache_entry *ce;
-	struct submodule_update_clone *suc = suc_cb;
-
-	int *idxP = idx_task_cb;
-	int idx = *idxP;
-	free(idxP);
-
-	if (!result)
-		return 0;
-
-	if (idx < suc->list.nr) {
-		ce  = suc->list.entries[idx];
-		strbuf_addf(err, _("Failed to clone '%s'. Retry scheduled"),
-			    ce->name);
-		strbuf_addch(err, '\n');
-		ALLOC_GROW(suc->failed_clones,
-			   suc->failed_clones_nr + 1,
-			   suc->failed_clones_alloc);
-		suc->failed_clones[suc->failed_clones_nr++] = ce;
-		return 0;
-	} else {
-		idx -= suc->list.nr;
-		ce  = suc->failed_clones[idx];
-		strbuf_addf(err, _("Failed to clone '%s' a second time, aborting"),
-			    ce->name);
-		strbuf_addch(err, '\n');
-		suc->quickstop = 1;
-		return 1;
-	}
-
-	return 0;
-}
-
-static int git_update_clone_config(const char *var, const char *value,
-				   void *cb)
-{
-	int *max_jobs = cb;
-	if (!strcmp(var, "submodule.fetchjobs"))
-		*max_jobs = parse_submodule_fetchjobs(var, value);
-	return 0;
-}
-
-static void update_submodule(struct update_clone_data *ucd)
-{
-	fprintf(stdout, "dummy %s %d\t%s\n",
-		oid_to_hex(&ucd->oid),
-		ucd->just_cloned,
-		ucd->sub->path);
-}
-
-static int update_submodules(struct submodule_update_clone *suc)
-{
-	int i;
-
-	run_processes_parallel_tr2(suc->max_jobs, update_clone_get_next_task,
-				   update_clone_start_failure,
-				   update_clone_task_finished, suc, "submodule",
-				   "parallel/update");
-
-	/*
-	 * We saved the output and put it out all at once now.
-	 * That means:
-	 * - the listener does not have to interleave their (checkout)
-	 *   work with our fetching.  The writes involved in a
-	 *   checkout involve more straightforward sequential I/O.
-	 * - the listener can avoid doing any work if fetching failed.
-	 */
-	if (suc->quickstop)
-		return 1;
-
-	for (i = 0; i < suc->update_clone_nr; i++)
-		update_submodule(&suc->update_clone[i]);
-
-	return 0;
-}
-
-static int update_clone(int argc, const char **argv, const char *prefix)
-{
-	const char *update = NULL;
-	struct pathspec pathspec;
-	struct submodule_update_clone suc = SUBMODULE_UPDATE_CLONE_INIT;
-
-	struct option module_update_clone_options[] = {
-		OPT_STRING(0, "prefix", &prefix,
-			   N_("path"),
-			   N_("path into the working tree")),
-		OPT_STRING(0, "recursive-prefix", &suc.recursive_prefix,
-			   N_("path"),
-			   N_("path into the working tree, across nested "
-			      "submodule boundaries")),
-		OPT_STRING(0, "update", &update,
-			   N_("string"),
-			   N_("rebase, merge, checkout or none")),
-		OPT_STRING_LIST(0, "reference", &suc.references, N_("repo"),
-			   N_("reference repository")),
-		OPT_BOOL(0, "dissociate", &suc.dissociate,
-			   N_("use --reference only while cloning")),
-		OPT_STRING(0, "depth", &suc.depth, "<depth>",
-			   N_("Create a shallow clone truncated to the "
-			      "specified number of revisions")),
-		OPT_INTEGER('j', "jobs", &suc.max_jobs,
-			    N_("parallel jobs")),
-		OPT_BOOL(0, "recommend-shallow", &suc.recommend_shallow,
-			    N_("whether the initial clone should follow the shallow recommendation")),
-		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>...]"),
-		NULL
-	};
-	suc.prefix = prefix;
-
-	update_clone_config_from_gitmodules(&suc.max_jobs);
-	git_config(git_update_clone_config, &suc.max_jobs);
-
-	argc = parse_options(argc, argv, prefix, module_update_clone_options,
-			     git_submodule_helper_usage, 0);
-
-	if (update)
-		if (parse_submodule_update_strategy(update, &suc.update) < 0)
-			die(_("bad value for update parameter"));
-
-	if (module_list_compute(argc, argv, prefix, &pathspec, &suc.list) < 0)
-		return 1;
-
-	if (pathspec.nr)
-		suc.warn_if_uninitialized = 1;
-
-	return update_submodules(&suc);
-}
-
-static int resolve_relative_path(int argc, const char **argv, const char *prefix)
-{
-	struct strbuf sb = STRBUF_INIT;
-	if (argc != 3)
-		die("submodule--helper relative-path takes exactly 2 arguments, got %d", argc);
-
-	printf("%s", relative_path(argv[1], argv[2], &sb));
-	strbuf_release(&sb);
-	return 0;
-}
-
-static const char *remote_submodule_branch(const char *path)
-{
-	const struct submodule *sub;
-	const char *branch = NULL;
-	char *key;
-
-	sub = submodule_from_path(the_repository, &null_oid, path);
-	if (!sub)
-		return NULL;
-
-	key = xstrfmt("submodule.%s.branch", sub->name);
-	if (repo_config_get_string_tmp(the_repository, key, &branch))
-		branch = sub->branch;
-	free(key);
-
-	if (!branch)
-		return "HEAD";
-
-	if (!strcmp(branch, ".")) {
-		const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
-
-		if (!refname)
-			die(_("No such ref: %s"), "HEAD");
-
-		/* detached HEAD */
-		if (!strcmp(refname, "HEAD"))
-			die(_("Submodule (%s) branch configured to inherit "
-			      "branch from superproject, but the superproject "
-			      "is not on any branch"), sub->name);
-
-		if (!skip_prefix(refname, "refs/heads/", &refname))
-			die(_("Expecting a full ref name, got %s"), refname);
-		return refname;
-	}
-
-	return branch;
-}
-
-static int resolve_remote_submodule_branch(int argc, const char **argv,
-		const char *prefix)
-{
-	const char *ret;
-	struct strbuf sb = STRBUF_INIT;
-	if (argc != 2)
-		die("submodule--helper remote-branch takes exactly one arguments, got %d", argc);
-
-	ret = remote_submodule_branch(argv[1]);
-	if (!ret)
-		die("submodule %s doesn't exist", argv[1]);
-
-	printf("%s", ret);
-	strbuf_release(&sb);
-	return 0;
-}
-
-static int push_check(int argc, const char **argv, const char *prefix)
-{
-	struct remote *remote;
-	const char *superproject_head;
-	char *head;
-	int detached_head = 0;
-	struct object_id head_oid;
-
-	if (argc < 3)
-		die("submodule--helper push-check requires at least 2 arguments");
-
-	/*
-	 * superproject's resolved head ref.
-	 * if HEAD then the superproject is in a detached head state, otherwise
-	 * it will be the resolved head ref.
-	 */
-	superproject_head = argv[1];
-	argv++;
-	argc--;
-	/* Get the submodule's head ref and determine if it is detached */
-	head = resolve_refdup("HEAD", 0, &head_oid, NULL);
-	if (!head)
-		die(_("Failed to resolve HEAD as a valid ref."));
-	if (!strcmp(head, "HEAD"))
-		detached_head = 1;
-
-	/*
-	 * The remote must be configured.
-	 * This is to avoid pushing to the exact same URL as the parent.
-	 */
-	remote = pushremote_get(argv[1]);
-	if (!remote || remote->origin == REMOTE_UNCONFIGURED)
-		die("remote '%s' not configured", argv[1]);
-
-	/* Check the refspec */
-	if (argc > 2) {
-		int i;
-		struct ref *local_refs = get_local_heads();
-		struct refspec refspec = REFSPEC_INIT_PUSH;
-
-		refspec_appendn(&refspec, argv + 2, argc - 2);
-
-		for (i = 0; i < refspec.nr; i++) {
-			const struct refspec_item *rs = &refspec.items[i];
-
-			if (rs->pattern || rs->matching)
-				continue;
-
-			/* LHS must match a single ref */
-			switch (count_refspec_match(rs->src, local_refs, NULL)) {
-			case 1:
-				break;
-			case 0:
-				/*
-				 * If LHS matches 'HEAD' then we need to ensure
-				 * that it matches the same named branch
-				 * checked out in the superproject.
-				 */
-				if (!strcmp(rs->src, "HEAD")) {
-					if (!detached_head &&
-					    !strcmp(head, superproject_head))
-						break;
-					die("HEAD does not match the named branch in the superproject");
-				}
-				/* fallthrough */
-			default:
-				die("src refspec '%s' must name a ref",
-				    rs->src);
-			}
-		}
-		refspec_clear(&refspec);
-	}
-	free(head);
-
-	return 0;
-}
-
-static int ensure_core_worktree(int argc, const char **argv, const char *prefix)
-{
-	const struct submodule *sub;
-	const char *path;
-	const char *cw;
-	struct repository subrepo;
-
-	if (argc != 2)
-		BUG("submodule--helper ensure-core-worktree <path>");
-
-	path = argv[1];
-
-	sub = submodule_from_path(the_repository, &null_oid, path);
-	if (!sub)
-		BUG("We could get the submodule handle before?");
-
-	if (repo_submodule_init(&subrepo, the_repository, sub))
-		die(_("could not get a repository handle for submodule '%s'"), path);
-
-	if (!repo_config_get_string_tmp(&subrepo, "core.worktree", &cw)) {
-		char *cfg_file, *abs_path;
-		const char *rel_path;
-		struct strbuf sb = STRBUF_INIT;
-
-		cfg_file = repo_git_path(&subrepo, "config");
-
-		abs_path = absolute_pathdup(path);
-		rel_path = relative_path(abs_path, subrepo.gitdir, &sb);
-
-		git_config_set_in_file(cfg_file, "core.worktree", rel_path);
-
-		free(cfg_file);
-		free(abs_path);
-		strbuf_release(&sb);
-	}
-
-	return 0;
-}
-
-static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	struct pathspec pathspec;
-	struct module_list list = MODULE_LIST_INIT;
-	unsigned flags = ABSORB_GITDIR_RECURSE_SUBMODULES;
-
-	struct option embed_gitdir_options[] = {
-		OPT_STRING(0, "prefix", &prefix,
-			   N_("path"),
-			   N_("path into the working tree")),
-		OPT_BIT(0, "--recursive", &flags, N_("recurse into submodules"),
-			ABSORB_GITDIR_RECURSE_SUBMODULES),
-		OPT_END()
-	};
-
-	const char *const git_submodule_helper_usage[] = {
-		N_("git submodule--helper absorb-git-dirs [<options>] [<path>...]"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, embed_gitdir_options,
-			     git_submodule_helper_usage, 0);
-
-	if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
-		return 1;
-
-	for (i = 0; i < list.nr; i++)
-		absorb_git_dir_into_superproject(list.entries[i]->name, flags);
-
-	return 0;
-}
-
-static int is_active(int argc, const char **argv, const char *prefix)
-{
-	if (argc != 2)
-		die("submodule--helper is-active takes exactly 1 argument");
-
-	return !is_submodule_active(the_repository, argv[1]);
-}
-
-/*
- * Exit non-zero if any of the submodule names given on the command line is
- * invalid. If no names are given, filter stdin to print only valid names
- * (which is primarily intended for testing).
- */
-static int check_name(int argc, const char **argv, const char *prefix)
-{
-	if (argc > 1) {
-		while (*++argv) {
-			if (check_submodule_name(*argv) < 0)
-				return 1;
-		}
-	} else {
-		struct strbuf buf = STRBUF_INIT;
-		while (strbuf_getline(&buf, stdin) != EOF) {
-			if (!check_submodule_name(buf.buf))
-				printf("%s\n", buf.buf);
-		}
-		strbuf_release(&buf);
-	}
-	return 0;
-}
-
-static int module_config(int argc, const char **argv, const char *prefix)
-{
-	enum {
-		CHECK_WRITEABLE = 1,
-		DO_UNSET = 2
-	} command = 0;
-
-	struct option module_config_options[] = {
-		OPT_CMDMODE(0, "check-writeable", &command,
-			    N_("check if it is safe to write to the .gitmodules file"),
-			    CHECK_WRITEABLE),
-		OPT_CMDMODE(0, "unset", &command,
-			    N_("unset the config in the .gitmodules file"),
-			    DO_UNSET),
-		OPT_END()
-	};
-	const char *const git_submodule_helper_usage[] = {
-		N_("git submodule--helper config <name> [<value>]"),
-		N_("git submodule--helper config --unset <name>"),
-		N_("git submodule--helper config --check-writeable"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, module_config_options,
-			     git_submodule_helper_usage, PARSE_OPT_KEEP_ARGV0);
-
-	if (argc == 1 && command == CHECK_WRITEABLE)
-		return is_writing_gitmodules_ok() ? 0 : -1;
-
-	/* Equivalent to ACTION_GET in builtin/config.c */
-	if (argc == 2 && command != DO_UNSET)
-		return print_config_from_gitmodules(the_repository, argv[1]);
-
-	/* Equivalent to ACTION_SET in builtin/config.c */
-	if (argc == 3 || (argc == 2 && command == DO_UNSET)) {
-		const char *value = (argc == 3) ? argv[2] : NULL;
-
-		if (!is_writing_gitmodules_ok())
-			die(_("please make sure that the .gitmodules file is in the working tree"));
-
-		return config_set_in_gitmodules_file_gently(argv[1], value);
-	}
-
-	usage_with_options(git_submodule_helper_usage, module_config_options);
-}
-
-static int module_set_url(int argc, const char **argv, const char *prefix)
-{
-	int quiet = 0;
-	const char *newurl;
-	const char *path;
-	char *config_name;
-
-	struct option options[] = {
-		OPT__QUIET(&quiet, N_("Suppress output for setting url of a submodule")),
-		OPT_END()
-	};
-	const char *const usage[] = {
-		N_("git submodule--helper set-url [--quiet] <path> <newurl>"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-
-	if (argc != 2 || !(path = argv[0]) || !(newurl = argv[1]))
-		usage_with_options(usage, options);
-
-	config_name = xstrfmt("submodule.%s.url", path);
-
-	config_set_in_gitmodules_file_gently(config_name, newurl);
-	sync_submodule(path, prefix, quiet ? OPT_QUIET : 0);
-
-	free(config_name);
-
-	return 0;
-}
-
-static int module_set_branch(int argc, const char **argv, const char *prefix)
-{
-	int opt_default = 0, ret;
-	const char *opt_branch = NULL;
-	const char *path;
-	char *config_name;
-
-	/*
-	 * We accept the `quiet` option for uniformity across subcommands,
-	 * though there is nothing to make less verbose in this subcommand.
-	 */
-	struct option options[] = {
-		OPT_NOOP_NOARG('q', "quiet"),
-		OPT_BOOL('d', "default", &opt_default,
-			N_("set the default tracking branch to master")),
-		OPT_STRING('b', "branch", &opt_branch, N_("branch"),
-			N_("set the default tracking branch")),
-		OPT_END()
-	};
-	const char *const usage[] = {
-		N_("git submodule--helper set-branch [-q|--quiet] (-d|--default) <path>"),
-		N_("git submodule--helper set-branch [-q|--quiet] (-b|--branch) <branch> <path>"),
-		NULL
-	};
-
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
-
-	if (!opt_branch && !opt_default)
-		die(_("--branch or --default required"));
-
-	if (opt_branch && opt_default)
-		die(_("--branch and --default are mutually exclusive"));
-
-	if (argc != 1 || !(path = argv[0]))
-		usage_with_options(usage, options);
-
-	config_name = xstrfmt("submodule.%s.branch", path);
-	ret = config_set_in_gitmodules_file_gently(config_name, opt_branch);
-
-	free(config_name);
-	return !!ret;
-}
-
-#define SUPPORT_SUPER_PREFIX (1<<0)
-
-struct cmd_struct {
-	const char *cmd;
-	int (*fn)(int, const char **, const char *);
-	unsigned option;
-};
-
-static struct cmd_struct commands[] = {
-	{"list", module_list, 0},
-	{"name", module_name, 0},
-	{"clone", module_clone, 0},
-	{"update-module-mode", module_update_module_mode, 0},
-	{"update-clone", update_clone, 0},
-	{"ensure-core-worktree", ensure_core_worktree, 0},
-	{"relative-path", resolve_relative_path, 0},
-	{"resolve-relative-url", resolve_relative_url, 0},
-	{"resolve-relative-url-test", resolve_relative_url_test, 0},
-	{"foreach", module_foreach, SUPPORT_SUPER_PREFIX},
-	{"init", module_init, SUPPORT_SUPER_PREFIX},
-	{"status", module_status, SUPPORT_SUPER_PREFIX},
-	{"print-default-remote", print_default_remote, 0},
-	{"sync", module_sync, SUPPORT_SUPER_PREFIX},
-	{"deinit", module_deinit, 0},
-	{"summary", module_summary, SUPPORT_SUPER_PREFIX},
-	{"remote-branch", resolve_remote_submodule_branch, 0},
-	{"push-check", push_check, 0},
-	{"absorb-git-dirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
-	{"is-active", is_active, 0},
-	{"check-name", check_name, 0},
-	{"config", module_config, 0},
-	{"set-url", module_set_url, 0},
-	{"set-branch", module_set_branch, 0},
-};
-
-int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	if (argc < 2 || !strcmp(argv[1], "-h"))
-		usage("git submodule--helper <command>");
-
-	for (i = 0; i < ARRAY_SIZE(commands); i++) {
-		if (!strcmp(argv[1], commands[i].cmd)) {
-			if (get_super_prefix() &&
-			    !(commands[i].option & SUPPORT_SUPER_PREFIX))
-				die(_("%s doesn't support --super-prefix"),
-				    commands[i].cmd);
-			return commands[i].fn(argc - 1, argv + 1, prefix);
-		}
-	}
-
-	die(_("'%s' is not a valid submodule--helper "
-	      "subcommand"), argv[1]);
-}
diff --git a/third_party/git/builtin/symbolic-ref.c b/third_party/git/builtin/symbolic-ref.c
deleted file mode 100644
index 80237f0df10f..000000000000
--- a/third_party/git/builtin/symbolic-ref.c
+++ /dev/null
@@ -1,78 +0,0 @@
-#include "builtin.h"
-#include "config.h"
-#include "cache.h"
-#include "refs.h"
-#include "parse-options.h"
-
-static const char * const git_symbolic_ref_usage[] = {
-	N_("git symbolic-ref [<options>] <name> [<ref>]"),
-	N_("git symbolic-ref -d [-q] <name>"),
-	NULL
-};
-
-static int check_symref(const char *HEAD, int quiet, int shorten, int print)
-{
-	int flag;
-	const char *refname = resolve_ref_unsafe(HEAD, 0, NULL, &flag);
-
-	if (!refname)
-		die("No such ref: %s", HEAD);
-	else if (!(flag & REF_ISSYMREF)) {
-		if (!quiet)
-			die("ref %s is not a symbolic ref", HEAD);
-		else
-			return 1;
-	}
-	if (print) {
-		if (shorten)
-			refname = shorten_unambiguous_ref(refname, 0);
-		puts(refname);
-	}
-	return 0;
-}
-
-int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
-{
-	int quiet = 0, delete = 0, shorten = 0, ret = 0;
-	const char *msg = NULL;
-	struct option options[] = {
-		OPT__QUIET(&quiet,
-			N_("suppress error message for non-symbolic (detached) refs")),
-		OPT_BOOL('d', "delete", &delete, N_("delete symbolic ref")),
-		OPT_BOOL(0, "short", &shorten, N_("shorten ref output")),
-		OPT_STRING('m', NULL, &msg, N_("reason"), N_("reason of the update")),
-		OPT_END(),
-	};
-
-	git_config(git_default_config, NULL);
-	argc = parse_options(argc, argv, prefix, options,
-			     git_symbolic_ref_usage, 0);
-	if (msg && !*msg)
-		die("Refusing to perform update with empty message");
-
-	if (delete) {
-		if (argc != 1)
-			usage_with_options(git_symbolic_ref_usage, options);
-		ret = check_symref(argv[0], 1, 0, 0);
-		if (ret)
-			die("Cannot delete %s, not a symbolic ref", argv[0]);
-		if (!strcmp(argv[0], "HEAD"))
-			die("deleting '%s' is not allowed", argv[0]);
-		return delete_ref(NULL, argv[0], NULL, REF_NO_DEREF);
-	}
-
-	switch (argc) {
-	case 1:
-		ret = check_symref(argv[0], quiet, shorten, 1);
-		break;
-	case 2:
-		if (!strcmp(argv[0], "HEAD") &&
-		    !starts_with(argv[1], "refs/"))
-			die("Refusing to point HEAD outside of refs/");
-		ret = !!create_symref(argv[0], argv[1], msg);
-		break;
-	default:
-		usage_with_options(git_symbolic_ref_usage, options);
-	}
-	return ret;
-}
diff --git a/third_party/git/builtin/tag.c b/third_party/git/builtin/tag.c
deleted file mode 100644
index ecf011776dc0..000000000000
--- a/third_party/git/builtin/tag.c
+++ /dev/null
@@ -1,594 +0,0 @@
-/*
- * Builtin "git tag"
- *
- * Copyright (c) 2007 Kristian Hรธgsberg <krh@redhat.com>,
- *                    Carlos Rica <jasampler@gmail.com>
- * Based on git-tag.sh and mktag.c by Linus Torvalds.
- */
-
-#include "cache.h"
-#include "config.h"
-#include "builtin.h"
-#include "refs.h"
-#include "object-store.h"
-#include "tag.h"
-#include "run-command.h"
-#include "parse-options.h"
-#include "diff.h"
-#include "revision.h"
-#include "gpg-interface.h"
-#include "oid-array.h"
-#include "column.h"
-#include "ref-filter.h"
-
-static const char * const git_tag_usage[] = {
-	N_("git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]\n"
-		"\t\t<tagname> [<head>]"),
-	N_("git tag -d <tagname>..."),
-	N_("git tag -l [-n[<num>]] [--contains <commit>] [--no-contains <commit>] [--points-at <object>]\n"
-		"\t\t[--format=<format>] [--merged <commit>] [--no-merged <commit>] [<pattern>...]"),
-	N_("git tag -v [--format=<format>] <tagname>..."),
-	NULL
-};
-
-static unsigned int colopts;
-static int force_sign_annotate;
-static int config_sign_tag = -1; /* unspecified */
-
-static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting,
-		     struct ref_format *format)
-{
-	struct ref_array array;
-	char *to_free = NULL;
-	int i;
-
-	memset(&array, 0, sizeof(array));
-
-	if (filter->lines == -1)
-		filter->lines = 0;
-
-	if (!format->format) {
-		if (filter->lines) {
-			to_free = xstrfmt("%s %%(contents:lines=%d)",
-					  "%(align:15)%(refname:lstrip=2)%(end)",
-					  filter->lines);
-			format->format = to_free;
-		} else
-			format->format = "%(refname:lstrip=2)";
-	}
-
-	if (verify_ref_format(format))
-		die(_("unable to parse format string"));
-	filter->with_commit_tag_algo = 1;
-	filter_refs(&array, filter, FILTER_REFS_TAGS);
-	ref_array_sort(sorting, &array);
-
-	for (i = 0; i < array.nr; i++)
-		show_ref_array_item(array.items[i], format);
-	ref_array_clear(&array);
-	free(to_free);
-
-	return 0;
-}
-
-typedef int (*each_tag_name_fn)(const char *name, const char *ref,
-				const struct object_id *oid, const void *cb_data);
-
-static int for_each_tag_name(const char **argv, each_tag_name_fn fn,
-			     const void *cb_data)
-{
-	const char **p;
-	struct strbuf ref = STRBUF_INIT;
-	int had_error = 0;
-	struct object_id oid;
-
-	for (p = argv; *p; p++) {
-		strbuf_reset(&ref);
-		strbuf_addf(&ref, "refs/tags/%s", *p);
-		if (read_ref(ref.buf, &oid)) {
-			error(_("tag '%s' not found."), *p);
-			had_error = 1;
-			continue;
-		}
-		if (fn(*p, ref.buf, &oid, cb_data))
-			had_error = 1;
-	}
-	strbuf_release(&ref);
-	return had_error;
-}
-
-static int delete_tag(const char *name, const char *ref,
-		      const struct object_id *oid, const void *cb_data)
-{
-	if (delete_ref(NULL, ref, oid, 0))
-		return 1;
-	printf(_("Deleted tag '%s' (was %s)\n"), name,
-	       find_unique_abbrev(oid, DEFAULT_ABBREV));
-	return 0;
-}
-
-static int verify_tag(const char *name, const char *ref,
-		      const struct object_id *oid, const void *cb_data)
-{
-	int flags;
-	const struct ref_format *format = cb_data;
-	flags = GPG_VERIFY_VERBOSE;
-
-	if (format->format)
-		flags = GPG_VERIFY_OMIT_STATUS;
-
-	if (gpg_verify_tag(oid, name, flags))
-		return -1;
-
-	if (format->format)
-		pretty_print_ref(name, oid, format);
-
-	return 0;
-}
-
-static int do_sign(struct strbuf *buffer)
-{
-	return sign_buffer(buffer, buffer, get_signing_key());
-}
-
-static const char tag_template[] =
-	N_("\nWrite a message for tag:\n  %s\n"
-	"Lines starting with '%c' will be ignored.\n");
-
-static const char tag_template_nocleanup[] =
-	N_("\nWrite a message for tag:\n  %s\n"
-	"Lines starting with '%c' will be kept; you may remove them"
-	" yourself if you want to.\n");
-
-static int git_tag_config(const char *var, const char *value, void *cb)
-{
-	int status;
-	struct ref_sorting **sorting_tail = (struct ref_sorting **)cb;
-
-	if (!strcmp(var, "tag.gpgsign")) {
-		config_sign_tag = git_config_bool(var, value);
-		return 0;
-	}
-
-	if (!strcmp(var, "tag.sort")) {
-		if (!value)
-			return config_error_nonbool(var);
-		parse_ref_sorting(sorting_tail, value);
-		return 0;
-	}
-
-	status = git_gpg_config(var, value, cb);
-	if (status)
-		return status;
-	if (!strcmp(var, "tag.forcesignannotated")) {
-		force_sign_annotate = git_config_bool(var, value);
-		return 0;
-	}
-
-	if (starts_with(var, "column."))
-		return git_column_config(var, value, "tag", &colopts);
-	return git_color_default_config(var, value, cb);
-}
-
-static void write_tag_body(int fd, const struct object_id *oid)
-{
-	unsigned long size;
-	enum object_type type;
-	char *buf, *sp;
-
-	buf = read_object_file(oid, &type, &size);
-	if (!buf)
-		return;
-	/* skip header */
-	sp = strstr(buf, "\n\n");
-
-	if (!sp || !size || type != OBJ_TAG) {
-		free(buf);
-		return;
-	}
-	sp += 2; /* skip the 2 LFs */
-	write_or_die(fd, sp, parse_signature(sp, buf + size - sp));
-
-	free(buf);
-}
-
-static int build_tag_object(struct strbuf *buf, int sign, struct object_id *result)
-{
-	if (sign && do_sign(buf) < 0)
-		return error(_("unable to sign the tag"));
-	if (write_object_file(buf->buf, buf->len, tag_type, result) < 0)
-		return error(_("unable to write tag file"));
-	return 0;
-}
-
-struct create_tag_options {
-	unsigned int message_given:1;
-	unsigned int use_editor:1;
-	unsigned int sign;
-	enum {
-		CLEANUP_NONE,
-		CLEANUP_SPACE,
-		CLEANUP_ALL
-	} cleanup_mode;
-};
-
-static const char message_advice_nested_tag[] =
-	N_("You have created a nested tag. The object referred to by your new tag is\n"
-	   "already a tag. If you meant to tag the object that it points to, use:\n"
-	   "\n"
-	   "\tgit tag -f %s %s^{}");
-
-static void create_tag(const struct object_id *object, const char *object_ref,
-		       const char *tag,
-		       struct strbuf *buf, struct create_tag_options *opt,
-		       struct object_id *prev, struct object_id *result)
-{
-	enum object_type type;
-	struct strbuf header = STRBUF_INIT;
-	char *path = NULL;
-
-	type = oid_object_info(the_repository, object, NULL);
-	if (type <= OBJ_NONE)
-		die(_("bad object type."));
-
-	if (type == OBJ_TAG)
-		advise_if_enabled(ADVICE_NESTED_TAG, _(message_advice_nested_tag),
-				  tag, object_ref);
-
-	strbuf_addf(&header,
-		    "object %s\n"
-		    "type %s\n"
-		    "tag %s\n"
-		    "tagger %s\n\n",
-		    oid_to_hex(object),
-		    type_name(type),
-		    tag,
-		    git_committer_info(IDENT_STRICT));
-
-	if (!opt->message_given || opt->use_editor) {
-		int fd;
-
-		/* write the template message before editing: */
-		path = git_pathdup("TAG_EDITMSG");
-		fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
-		if (fd < 0)
-			die_errno(_("could not create file '%s'"), path);
-
-		if (opt->message_given) {
-			write_or_die(fd, buf->buf, buf->len);
-			strbuf_reset(buf);
-		} else if (!is_null_oid(prev)) {
-			write_tag_body(fd, prev);
-		} else {
-			struct strbuf buf = STRBUF_INIT;
-			strbuf_addch(&buf, '\n');
-			if (opt->cleanup_mode == CLEANUP_ALL)
-				strbuf_commented_addf(&buf, _(tag_template), tag, comment_line_char);
-			else
-				strbuf_commented_addf(&buf, _(tag_template_nocleanup), tag, comment_line_char);
-			write_or_die(fd, buf.buf, buf.len);
-			strbuf_release(&buf);
-		}
-		close(fd);
-
-		if (launch_editor(path, buf, NULL)) {
-			fprintf(stderr,
-			_("Please supply the message using either -m or -F option.\n"));
-			exit(1);
-		}
-	}
-
-	if (opt->cleanup_mode != CLEANUP_NONE)
-		strbuf_stripspace(buf, opt->cleanup_mode == CLEANUP_ALL);
-
-	if (!opt->message_given && !buf->len)
-		die(_("no tag message?"));
-
-	strbuf_insert(buf, 0, header.buf, header.len);
-	strbuf_release(&header);
-
-	if (build_tag_object(buf, opt->sign, result) < 0) {
-		if (path)
-			fprintf(stderr, _("The tag message has been left in %s\n"),
-				path);
-		exit(128);
-	}
-	if (path) {
-		unlink_or_warn(path);
-		free(path);
-	}
-}
-
-static void create_reflog_msg(const struct object_id *oid, struct strbuf *sb)
-{
-	enum object_type type;
-	struct commit *c;
-	char *buf;
-	unsigned long size;
-	int subject_len = 0;
-	const char *subject_start;
-
-	char *rla = getenv("GIT_REFLOG_ACTION");
-	if (rla) {
-		strbuf_addstr(sb, rla);
-	} else {
-		strbuf_addstr(sb, "tag: tagging ");
-		strbuf_add_unique_abbrev(sb, oid, DEFAULT_ABBREV);
-	}
-
-	strbuf_addstr(sb, " (");
-	type = oid_object_info(the_repository, oid, NULL);
-	switch (type) {
-	default:
-		strbuf_addstr(sb, "object of unknown type");
-		break;
-	case OBJ_COMMIT:
-		if ((buf = read_object_file(oid, &type, &size)) != NULL) {
-			subject_len = find_commit_subject(buf, &subject_start);
-			strbuf_insert(sb, sb->len, subject_start, subject_len);
-		} else {
-			strbuf_addstr(sb, "commit object");
-		}
-		free(buf);
-
-		if ((c = lookup_commit_reference(the_repository, oid)) != NULL)
-			strbuf_addf(sb, ", %s", show_date(c->date, 0, DATE_MODE(SHORT)));
-		break;
-	case OBJ_TREE:
-		strbuf_addstr(sb, "tree object");
-		break;
-	case OBJ_BLOB:
-		strbuf_addstr(sb, "blob object");
-		break;
-	case OBJ_TAG:
-		strbuf_addstr(sb, "other tag object");
-		break;
-	}
-	strbuf_addch(sb, ')');
-}
-
-struct msg_arg {
-	int given;
-	struct strbuf buf;
-};
-
-static int parse_msg_arg(const struct option *opt, const char *arg, int unset)
-{
-	struct msg_arg *msg = opt->value;
-
-	BUG_ON_OPT_NEG(unset);
-
-	if (!arg)
-		return -1;
-	if (msg->buf.len)
-		strbuf_addstr(&(msg->buf), "\n\n");
-	strbuf_addstr(&(msg->buf), arg);
-	msg->given = 1;
-	return 0;
-}
-
-static int strbuf_check_tag_ref(struct strbuf *sb, const char *name)
-{
-	if (name[0] == '-')
-		return -1;
-
-	strbuf_reset(sb);
-	strbuf_addf(sb, "refs/tags/%s", name);
-
-	return check_refname_format(sb->buf, 0);
-}
-
-int cmd_tag(int argc, const char **argv, const char *prefix)
-{
-	struct strbuf buf = STRBUF_INIT;
-	struct strbuf ref = STRBUF_INIT;
-	struct strbuf reflog_msg = STRBUF_INIT;
-	struct object_id object, prev;
-	const char *object_ref, *tag;
-	struct create_tag_options opt;
-	char *cleanup_arg = NULL;
-	int create_reflog = 0;
-	int annotate = 0, force = 0;
-	int cmdmode = 0, create_tag_object = 0;
-	const char *msgfile = NULL, *keyid = NULL;
-	struct msg_arg msg = { 0, STRBUF_INIT };
-	struct ref_transaction *transaction;
-	struct strbuf err = STRBUF_INIT;
-	struct ref_filter filter;
-	static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
-	struct ref_format format = REF_FORMAT_INIT;
-	int icase = 0;
-	int edit_flag = 0;
-	struct option options[] = {
-		OPT_CMDMODE('l', "list", &cmdmode, N_("list tag names"), 'l'),
-		{ OPTION_INTEGER, 'n', NULL, &filter.lines, N_("n"),
-				N_("print <n> lines of each tag message"),
-				PARSE_OPT_OPTARG, NULL, 1 },
-		OPT_CMDMODE('d', "delete", &cmdmode, N_("delete tags"), 'd'),
-		OPT_CMDMODE('v', "verify", &cmdmode, N_("verify tags"), 'v'),
-
-		OPT_GROUP(N_("Tag creation options")),
-		OPT_BOOL('a', "annotate", &annotate,
-					N_("annotated tag, needs a message")),
-		OPT_CALLBACK_F('m', "message", &msg, N_("message"),
-			       N_("tag message"), PARSE_OPT_NONEG, parse_msg_arg),
-		OPT_FILENAME('F', "file", &msgfile, N_("read message from file")),
-		OPT_BOOL('e', "edit", &edit_flag, N_("force edit of tag message")),
-		OPT_BOOL('s', "sign", &opt.sign, N_("annotated and GPG-signed tag")),
-		OPT_CLEANUP(&cleanup_arg),
-		OPT_STRING('u', "local-user", &keyid, N_("key-id"),
-					N_("use another key to sign the tag")),
-		OPT__FORCE(&force, N_("replace the tag if exists"), 0),
-		OPT_BOOL(0, "create-reflog", &create_reflog, N_("create a reflog")),
-
-		OPT_GROUP(N_("Tag listing options")),
-		OPT_COLUMN(0, "column", &colopts, N_("show tag list in columns")),
-		OPT_CONTAINS(&filter.with_commit, N_("print only tags that contain the commit")),
-		OPT_NO_CONTAINS(&filter.no_commit, N_("print only tags that don't contain the commit")),
-		OPT_WITH(&filter.with_commit, N_("print only tags that contain the commit")),
-		OPT_WITHOUT(&filter.no_commit, N_("print only tags that don't contain the commit")),
-		OPT_MERGED(&filter, N_("print only tags that are merged")),
-		OPT_NO_MERGED(&filter, N_("print only tags that are not merged")),
-		OPT_REF_SORT(sorting_tail),
-		{
-			OPTION_CALLBACK, 0, "points-at", &filter.points_at, N_("object"),
-			N_("print only tags of the object"), PARSE_OPT_LASTARG_DEFAULT,
-			parse_opt_object_name, (intptr_t) "HEAD"
-		},
-		OPT_STRING(  0 , "format", &format.format, N_("format"),
-			   N_("format to use for the output")),
-		OPT__COLOR(&format.use_color, N_("respect format colors")),
-		OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
-		OPT_END()
-	};
-
-	setup_ref_filter_porcelain_msg();
-
-	git_config(git_tag_config, sorting_tail);
-
-	memset(&opt, 0, sizeof(opt));
-	memset(&filter, 0, sizeof(filter));
-	filter.lines = -1;
-	opt.sign = -1;
-
-	argc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);
-
-	if (!cmdmode) {
-		if (argc == 0)
-			cmdmode = 'l';
-		else if (filter.with_commit || filter.no_commit ||
-			 filter.reachable_from || filter.unreachable_from ||
-			 filter.points_at.nr || filter.lines != -1)
-			cmdmode = 'l';
-	}
-
-	if (cmdmode == 'l')
-		setup_auto_pager("tag", 1);
-
-	if (opt.sign == -1)
-		opt.sign = cmdmode ? 0 : config_sign_tag > 0;
-
-	if (keyid) {
-		opt.sign = 1;
-		set_signing_key(keyid);
-	}
-	create_tag_object = (opt.sign || annotate || msg.given || msgfile);
-
-	if ((create_tag_object || force) && (cmdmode != 0))
-		usage_with_options(git_tag_usage, options);
-
-	finalize_colopts(&colopts, -1);
-	if (cmdmode == 'l' && filter.lines != -1) {
-		if (explicitly_enable_column(colopts))
-			die(_("--column and -n are incompatible"));
-		colopts = 0;
-	}
-	if (!sorting)
-		sorting = ref_default_sorting();
-	ref_sorting_icase_all(sorting, icase);
-	filter.ignore_case = icase;
-	if (cmdmode == 'l') {
-		int ret;
-		if (column_active(colopts)) {
-			struct column_options copts;
-			memset(&copts, 0, sizeof(copts));
-			copts.padding = 2;
-			run_column_filter(colopts, &copts);
-		}
-		filter.name_patterns = argv;
-		ret = list_tags(&filter, sorting, &format);
-		if (column_active(colopts))
-			stop_column_filter();
-		return ret;
-	}
-	if (filter.lines != -1)
-		die(_("-n option is only allowed in list mode"));
-	if (filter.with_commit)
-		die(_("--contains option is only allowed in list mode"));
-	if (filter.no_commit)
-		die(_("--no-contains option is only allowed in list mode"));
-	if (filter.points_at.nr)
-		die(_("--points-at option is only allowed in list mode"));
-	if (filter.reachable_from || filter.unreachable_from)
-		die(_("--merged and --no-merged options are only allowed in list mode"));
-	if (cmdmode == 'd')
-		return for_each_tag_name(argv, delete_tag, NULL);
-	if (cmdmode == 'v') {
-		if (format.format && verify_ref_format(&format))
-			usage_with_options(git_tag_usage, options);
-		return for_each_tag_name(argv, verify_tag, &format);
-	}
-
-	if (msg.given || msgfile) {
-		if (msg.given && msgfile)
-			die(_("only one -F or -m option is allowed."));
-		if (msg.given)
-			strbuf_addbuf(&buf, &(msg.buf));
-		else {
-			if (!strcmp(msgfile, "-")) {
-				if (strbuf_read(&buf, 0, 1024) < 0)
-					die_errno(_("cannot read '%s'"), msgfile);
-			} else {
-				if (strbuf_read_file(&buf, msgfile, 1024) < 0)
-					die_errno(_("could not open or read '%s'"),
-						msgfile);
-			}
-		}
-	}
-
-	tag = argv[0];
-
-	object_ref = argc == 2 ? argv[1] : "HEAD";
-	if (argc > 2)
-		die(_("too many params"));
-
-	if (get_oid(object_ref, &object))
-		die(_("Failed to resolve '%s' as a valid ref."), object_ref);
-
-	if (strbuf_check_tag_ref(&ref, tag))
-		die(_("'%s' is not a valid tag name."), tag);
-
-	if (read_ref(ref.buf, &prev))
-		oidclr(&prev);
-	else if (!force)
-		die(_("tag '%s' already exists"), tag);
-
-	opt.message_given = msg.given || msgfile;
-	opt.use_editor = edit_flag;
-
-	if (!cleanup_arg || !strcmp(cleanup_arg, "strip"))
-		opt.cleanup_mode = CLEANUP_ALL;
-	else if (!strcmp(cleanup_arg, "verbatim"))
-		opt.cleanup_mode = CLEANUP_NONE;
-	else if (!strcmp(cleanup_arg, "whitespace"))
-		opt.cleanup_mode = CLEANUP_SPACE;
-	else
-		die(_("Invalid cleanup mode %s"), cleanup_arg);
-
-	create_reflog_msg(&object, &reflog_msg);
-
-	if (create_tag_object) {
-		if (force_sign_annotate && !annotate)
-			opt.sign = 1;
-		create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object);
-	}
-
-	transaction = ref_transaction_begin(&err);
-	if (!transaction ||
-	    ref_transaction_update(transaction, ref.buf, &object, &prev,
-				   create_reflog ? REF_FORCE_CREATE_REFLOG : 0,
-				   reflog_msg.buf, &err) ||
-	    ref_transaction_commit(transaction, &err))
-		die("%s", err.buf);
-	ref_transaction_free(transaction);
-	if (force && !is_null_oid(&prev) && !oideq(&prev, &object))
-		printf(_("Updated tag '%s' (was %s)\n"), tag,
-		       find_unique_abbrev(&prev, DEFAULT_ABBREV));
-
-	UNLEAK(buf);
-	UNLEAK(ref);
-	UNLEAK(reflog_msg);
-	UNLEAK(msg);
-	UNLEAK(err);
-	return 0;
-}
diff --git a/third_party/git/builtin/unpack-file.c b/third_party/git/builtin/unpack-file.c
deleted file mode 100644
index 58652229f273..000000000000
--- a/third_party/git/builtin/unpack-file.c
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "builtin.h"
-#include "config.h"
-#include "object-store.h"
-
-static char *create_temp_file(struct object_id *oid)
-{
-	static char path[50];
-	void *buf;
-	enum object_type type;
-	unsigned long size;
-	int fd;
-
-	buf = read_object_file(oid, &type, &size);
-	if (!buf || type != OBJ_BLOB)
-		die("unable to read blob object %s", oid_to_hex(oid));
-
-	xsnprintf(path, sizeof(path), ".merge_file_XXXXXX");
-	fd = xmkstemp(path);
-	if (write_in_full(fd, buf, size) < 0)
-		die_errno("unable to write temp-file");
-	close(fd);
-	return path;
-}
-
-int cmd_unpack_file(int argc, const char **argv, const char *prefix)
-{
-	struct object_id oid;
-
-	if (argc != 2 || !strcmp(argv[1], "-h"))
-		usage("git unpack-file <sha1>");
-	if (get_oid(argv[1], &oid))
-		die("Not a valid object name %s", argv[1]);
-
-	git_config(git_default_config, NULL);
-
-	puts(create_temp_file(&oid));
-	return 0;
-}
diff --git a/third_party/git/builtin/unpack-objects.c b/third_party/git/builtin/unpack-objects.c
deleted file mode 100644
index dd4a75e030d2..000000000000
--- a/third_party/git/builtin/unpack-objects.c
+++ /dev/null
@@ -1,599 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "object-store.h"
-#include "object.h"
-#include "delta.h"
-#include "pack.h"
-#include "blob.h"
-#include "commit.h"
-#include "tag.h"
-#include "tree.h"
-#include "tree-walk.h"
-#include "progress.h"
-#include "decorate.h"
-#include "fsck.h"
-
-static int dry_run, quiet, recover, has_errors, strict;
-static const char unpack_usage[] = "git unpack-objects [-n] [-q] [-r] [--strict]";
-
-/* We always read in 4kB chunks. */
-static unsigned char buffer[4096];
-static unsigned int offset, len;
-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
- * suspect are kept in core without getting written in the object
- * store.
- */
-struct obj_buffer {
-	char *buffer;
-	unsigned long size;
-};
-
-static struct decoration obj_decorate;
-
-static struct obj_buffer *lookup_object_buffer(struct object *base)
-{
-	return lookup_decoration(&obj_decorate, base);
-}
-
-static void add_object_buffer(struct object *object, char *buffer, unsigned long size)
-{
-	struct obj_buffer *obj;
-	obj = xcalloc(1, sizeof(struct obj_buffer));
-	obj->buffer = buffer;
-	obj->size = size;
-	if (add_decoration(&obj_decorate, object, obj))
-		die("object %s tried to add buffer twice!", oid_to_hex(&object->oid));
-}
-
-/*
- * Make sure at least "min" bytes are available in the buffer, and
- * return the pointer to the buffer.
- */
-static void *fill(int min)
-{
-	if (min <= len)
-		return buffer + offset;
-	if (min > sizeof(buffer))
-		die("cannot fill %d bytes", min);
-	if (offset) {
-		the_hash_algo->update_fn(&ctx, buffer, offset);
-		memmove(buffer, buffer + offset, len);
-		offset = 0;
-	}
-	do {
-		ssize_t ret = xread(0, buffer + len, sizeof(buffer) - len);
-		if (ret <= 0) {
-			if (!ret)
-				die("early EOF");
-			die_errno("read error on input");
-		}
-		len += ret;
-	} while (len < min);
-	return buffer;
-}
-
-static void use(int bytes)
-{
-	if (bytes > len)
-		die("used more bytes than were available");
-	len -= bytes;
-	offset += bytes;
-
-	/* make sure off_t is sufficiently large not to wrap */
-	if (signed_add_overflows(consumed_bytes, bytes))
-		die("pack too large for current definition of off_t");
-	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)
-{
-	git_zstream stream;
-	void *buf = xmallocz(size);
-
-	memset(&stream, 0, sizeof(stream));
-
-	stream.next_out = buf;
-	stream.avail_out = size;
-	stream.next_in = fill(1);
-	stream.avail_in = len;
-	git_inflate_init(&stream);
-
-	for (;;) {
-		int ret = git_inflate(&stream, 0);
-		use(len - stream.avail_in);
-		if (stream.total_out == size && ret == Z_STREAM_END)
-			break;
-		if (ret != Z_OK) {
-			error("inflate returned %d", ret);
-			FREE_AND_NULL(buf);
-			if (!recover)
-				exit(1);
-			has_errors = 1;
-			break;
-		}
-		stream.next_in = fill(1);
-		stream.avail_in = len;
-	}
-	git_inflate_end(&stream);
-	return buf;
-}
-
-struct delta_info {
-	struct object_id base_oid;
-	unsigned nr;
-	off_t base_offset;
-	unsigned long size;
-	void *delta;
-	struct delta_info *next;
-};
-
-static struct delta_info *delta_list;
-
-static void add_delta_to_list(unsigned nr, const struct object_id *base_oid,
-			      off_t base_offset,
-			      void *delta, unsigned long size)
-{
-	struct delta_info *info = xmalloc(sizeof(*info));
-
-	oidcpy(&info->base_oid, base_oid);
-	info->base_offset = base_offset;
-	info->size = size;
-	info->delta = delta;
-	info->nr = nr;
-	info->next = delta_list;
-	delta_list = info;
-}
-
-struct obj_info {
-	off_t offset;
-	struct object_id oid;
-	struct object *obj;
-};
-
-/* Remember to update object flag allocation in object.h */
-#define FLAG_OPEN (1u<<20)
-#define FLAG_WRITTEN (1u<<21)
-
-static struct obj_info *obj_list;
-static unsigned nr_objects;
-
-/*
- * Called only from check_object() after it verified this object
- * is Ok.
- */
-static void write_cached_object(struct object *obj, struct obj_buffer *obj_buf)
-{
-	struct object_id oid;
-
-	if (write_object_file(obj_buf->buffer, obj_buf->size,
-			      type_name(obj->type), &oid) < 0)
-		die("failed to write object %s", oid_to_hex(&obj->oid));
-	obj->flags |= FLAG_WRITTEN;
-}
-
-/*
- * At the very end of the processing, write_rest() scans the objects
- * that have reachability requirements and calls this function.
- * Verify its reachability and validity recursively and write it out.
- */
-static int check_object(struct object *obj, int type, void *data, struct fsck_options *options)
-{
-	struct obj_buffer *obj_buf;
-
-	if (!obj)
-		return 1;
-
-	if (obj->flags & FLAG_WRITTEN)
-		return 0;
-
-	if (type != OBJ_ANY && obj->type != type)
-		die("object type mismatch");
-
-	if (!(obj->flags & FLAG_OPEN)) {
-		unsigned long size;
-		int type = oid_object_info(the_repository, &obj->oid, &size);
-		if (type != obj->type || type <= 0)
-			die("object of unexpected type");
-		obj->flags |= FLAG_WRITTEN;
-		return 0;
-	}
-
-	obj_buf = lookup_object_buffer(obj);
-	if (!obj_buf)
-		die("Whoops! Cannot find object '%s'", oid_to_hex(&obj->oid));
-	if (fsck_object(obj, obj_buf->buffer, obj_buf->size, &fsck_options))
-		die("fsck error in packed object");
-	fsck_options.walk = check_object;
-	if (fsck_walk(obj, NULL, &fsck_options))
-		die("Error on reachable objects of %s", oid_to_hex(&obj->oid));
-	write_cached_object(obj, obj_buf);
-	return 0;
-}
-
-static void write_rest(void)
-{
-	unsigned i;
-	for (i = 0; i < nr_objects; i++) {
-		if (obj_list[i].obj)
-			check_object(obj_list[i].obj, OBJ_ANY, NULL, NULL);
-	}
-}
-
-static void added_object(unsigned nr, enum object_type type,
-			 void *data, unsigned long size);
-
-/*
- * Write out nr-th object from the list, now we know the contents
- * of it.  Under --strict, this buffers structured objects in-core,
- * to be checked at the end.
- */
-static void write_object(unsigned nr, enum object_type type,
-			 void *buf, unsigned long size)
-{
-	if (!strict) {
-		if (write_object_file(buf, size, type_name(type),
-				      &obj_list[nr].oid) < 0)
-			die("failed to write object");
-		added_object(nr, type, buf, size);
-		free(buf);
-		obj_list[nr].obj = NULL;
-	} else if (type == OBJ_BLOB) {
-		struct blob *blob;
-		if (write_object_file(buf, size, type_name(type),
-				      &obj_list[nr].oid) < 0)
-			die("failed to write object");
-		added_object(nr, type, buf, size);
-		free(buf);
-
-		blob = lookup_blob(the_repository, &obj_list[nr].oid);
-		if (blob)
-			blob->object.flags |= FLAG_WRITTEN;
-		else
-			die("invalid blob object");
-		obj_list[nr].obj = NULL;
-	} else {
-		struct object *obj;
-		int eaten;
-		hash_object_file(the_hash_algo, 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,
-					  &eaten);
-		if (!obj)
-			die("invalid %s", type_name(type));
-		add_object_buffer(obj, buf, size);
-		obj->flags |= FLAG_OPEN;
-		obj_list[nr].obj = obj;
-	}
-}
-
-static void resolve_delta(unsigned nr, enum object_type type,
-			  void *base, unsigned long base_size,
-			  void *delta, unsigned long delta_size)
-{
-	void *result;
-	unsigned long result_size;
-
-	result = patch_delta(base, base_size,
-			     delta, delta_size,
-			     &result_size);
-	if (!result)
-		die("failed to apply delta");
-	free(delta);
-	write_object(nr, type, result, result_size);
-}
-
-/*
- * We now know the contents of an object (which is nr-th in the pack);
- * resolve all the deltified objects that are based on it.
- */
-static void added_object(unsigned nr, enum object_type type,
-			 void *data, unsigned long size)
-{
-	struct delta_info **p = &delta_list;
-	struct delta_info *info;
-
-	while ((info = *p) != NULL) {
-		if (oideq(&info->base_oid, &obj_list[nr].oid) ||
-		    info->base_offset == obj_list[nr].offset) {
-			*p = info->next;
-			p = &delta_list;
-			resolve_delta(info->nr, type, data, size,
-				      info->delta, info->size);
-			free(info);
-			continue;
-		}
-		p = &info->next;
-	}
-}
-
-static void unpack_non_delta_entry(enum object_type type, unsigned long size,
-				   unsigned nr)
-{
-	void *buf = get_data(size);
-
-	if (!dry_run && buf)
-		write_object(nr, type, buf, size);
-	else
-		free(buf);
-}
-
-static int resolve_against_held(unsigned nr, const struct object_id *base,
-				void *delta_data, unsigned long delta_size)
-{
-	struct object *obj;
-	struct obj_buffer *obj_buffer;
-	obj = lookup_object(the_repository, base);
-	if (!obj)
-		return 0;
-	obj_buffer = lookup_object_buffer(obj);
-	if (!obj_buffer)
-		return 0;
-	resolve_delta(nr, obj->type, obj_buffer->buffer,
-		      obj_buffer->size, delta_data, delta_size);
-	return 1;
-}
-
-static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
-			       unsigned nr)
-{
-	void *delta_data, *base;
-	unsigned long base_size;
-	struct object_id base_oid;
-
-	if (type == OBJ_REF_DELTA) {
-		hashcpy(base_oid.hash, fill(the_hash_algo->rawsz));
-		use(the_hash_algo->rawsz);
-		delta_data = get_data(delta_size);
-		if (dry_run || !delta_data) {
-			free(delta_data);
-			return;
-		}
-		if (has_object_file(&base_oid))
-			; /* Ok we have this one */
-		else if (resolve_against_held(nr, &base_oid,
-					      delta_data, delta_size))
-			return; /* we are done */
-		else {
-			/* cannot resolve yet --- queue it */
-			oidclr(&obj_list[nr].oid);
-			add_delta_to_list(nr, &base_oid, 0, delta_data, delta_size);
-			return;
-		}
-	} else {
-		unsigned base_found = 0;
-		unsigned char *pack, c;
-		off_t base_offset;
-		unsigned lo, mid, hi;
-
-		pack = fill(1);
-		c = *pack;
-		use(1);
-		base_offset = c & 127;
-		while (c & 128) {
-			base_offset += 1;
-			if (!base_offset || MSB(base_offset, 7))
-				die("offset value overflow for delta base object");
-			pack = fill(1);
-			c = *pack;
-			use(1);
-			base_offset = (base_offset << 7) + (c & 127);
-		}
-		base_offset = obj_list[nr].offset - base_offset;
-		if (base_offset <= 0 || base_offset >= obj_list[nr].offset)
-			die("offset value out of bound for delta base object");
-
-		delta_data = get_data(delta_size);
-		if (dry_run || !delta_data) {
-			free(delta_data);
-			return;
-		}
-		lo = 0;
-		hi = nr;
-		while (lo < hi) {
-			mid = lo + (hi - lo) / 2;
-			if (base_offset < obj_list[mid].offset) {
-				hi = mid;
-			} else if (base_offset > obj_list[mid].offset) {
-				lo = mid + 1;
-			} else {
-				oidcpy(&base_oid, &obj_list[mid].oid);
-				base_found = !is_null_oid(&base_oid);
-				break;
-			}
-		}
-		if (!base_found) {
-			/*
-			 * The delta base object is itself a delta that
-			 * has not been resolved yet.
-			 */
-			oidclr(&obj_list[nr].oid);
-			add_delta_to_list(nr, &null_oid, base_offset, delta_data, delta_size);
-			return;
-		}
-	}
-
-	if (resolve_against_held(nr, &base_oid, delta_data, delta_size))
-		return;
-
-	base = read_object_file(&base_oid, &type, &base_size);
-	if (!base) {
-		error("failed to read delta-pack base object %s",
-		      oid_to_hex(&base_oid));
-		if (!recover)
-			exit(1);
-		has_errors = 1;
-		return;
-	}
-	resolve_delta(nr, type, base, base_size, delta_data, delta_size);
-	free(base);
-}
-
-static void unpack_one(unsigned nr)
-{
-	unsigned shift;
-	unsigned char *pack;
-	unsigned long size, c;
-	enum object_type type;
-
-	obj_list[nr].offset = consumed_bytes;
-
-	pack = fill(1);
-	c = *pack;
-	use(1);
-	type = (c >> 4) & 7;
-	size = (c & 15);
-	shift = 4;
-	while (c & 0x80) {
-		pack = fill(1);
-		c = *pack;
-		use(1);
-		size += (c & 0x7f) << shift;
-		shift += 7;
-	}
-
-	switch (type) {
-	case OBJ_COMMIT:
-	case OBJ_TREE:
-	case OBJ_BLOB:
-	case OBJ_TAG:
-		unpack_non_delta_entry(type, size, nr);
-		return;
-	case OBJ_REF_DELTA:
-	case OBJ_OFS_DELTA:
-		unpack_delta_entry(type, size, nr);
-		return;
-	default:
-		error("bad object type %d", type);
-		has_errors = 1;
-		if (recover)
-			return;
-		exit(1);
-	}
-}
-
-static void unpack_all(void)
-{
-	int i;
-	struct pack_header *hdr = fill(sizeof(struct pack_header));
-
-	nr_objects = ntohl(hdr->hdr_entries);
-
-	if (ntohl(hdr->hdr_signature) != PACK_SIGNATURE)
-		die("bad pack file");
-	if (!pack_version_ok(hdr->hdr_version))
-		die("unknown pack file version %"PRIu32,
-			ntohl(hdr->hdr_version));
-	use(sizeof(struct pack_header));
-
-	if (!quiet)
-		progress = start_progress(_("Unpacking objects"), nr_objects);
-	obj_list = xcalloc(nr_objects, sizeof(*obj_list));
-	for (i = 0; i < nr_objects; i++) {
-		unpack_one(i);
-		display_progress(progress, i + 1);
-	}
-	stop_progress(&progress);
-
-	if (delta_list)
-		die("unresolved deltas left after unpacking");
-}
-
-int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
-{
-	int i;
-	struct object_id oid;
-
-	read_replace_refs = 0;
-
-	git_config(git_default_config, NULL);
-
-	quiet = !isatty(2);
-
-	for (i = 1 ; i < argc; i++) {
-		const char *arg = argv[i];
-
-		if (*arg == '-') {
-			if (!strcmp(arg, "-n")) {
-				dry_run = 1;
-				continue;
-			}
-			if (!strcmp(arg, "-q")) {
-				quiet = 1;
-				continue;
-			}
-			if (!strcmp(arg, "-r")) {
-				recover = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--strict")) {
-				strict = 1;
-				continue;
-			}
-			if (skip_prefix(arg, "--strict=", &arg)) {
-				strict = 1;
-				fsck_set_msg_types(&fsck_options, arg);
-				continue;
-			}
-			if (starts_with(arg, "--pack_header=")) {
-				struct pack_header *hdr;
-				char *c;
-
-				hdr = (struct pack_header *)buffer;
-				hdr->hdr_signature = htonl(PACK_SIGNATURE);
-				hdr->hdr_version = htonl(strtoul(arg + 14, &c, 10));
-				if (*c != ',')
-					die("bad %s", arg);
-				hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10));
-				if (*c)
-					die("bad %s", arg);
-				len = sizeof(*hdr);
-				continue;
-			}
-			if (skip_prefix(arg, "--max-input-size=", &arg)) {
-				max_input_size = strtoumax(arg, NULL, 10);
-				continue;
-			}
-			usage(unpack_usage);
-		}
-
-		/* We don't take any non-flag arguments now.. Maybe some day */
-		usage(unpack_usage);
-	}
-	the_hash_algo->init_fn(&ctx);
-	unpack_all();
-	the_hash_algo->update_fn(&ctx, buffer, offset);
-	the_hash_algo->final_fn(oid.hash, &ctx);
-	if (strict) {
-		write_rest();
-		if (fsck_finish(&fsck_options))
-			die(_("fsck error in pack objects"));
-	}
-	if (!hasheq(fill(the_hash_algo->rawsz), oid.hash))
-		die("final sha1 did not match");
-	use(the_hash_algo->rawsz);
-
-	/* Write the last part of the buffer to stdout */
-	while (len) {
-		int ret = xwrite(1, buffer + offset, len);
-		if (ret <= 0)
-			break;
-		len -= ret;
-		offset += ret;
-	}
-
-	/* All done */
-	return has_errors;
-}
diff --git a/third_party/git/builtin/update-index.c b/third_party/git/builtin/update-index.c
deleted file mode 100644
index 79087bccea4b..000000000000
--- a/third_party/git/builtin/update-index.c
+++ /dev/null
@@ -1,1245 +0,0 @@
-/*
- * GIT - The information manager from hell
- *
- * Copyright (C) Linus Torvalds, 2005
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "cache.h"
-#include "config.h"
-#include "lockfile.h"
-#include "quote.h"
-#include "cache-tree.h"
-#include "tree-walk.h"
-#include "builtin.h"
-#include "refs.h"
-#include "resolve-undo.h"
-#include "parse-options.h"
-#include "pathspec.h"
-#include "dir.h"
-#include "split-index.h"
-#include "fsmonitor.h"
-
-/*
- * Default to not allowing changes to the list of files. The
- * tool doesn't actually care, but this makes it harder to add
- * files to the revision control by mistake by doing something
- * like "git update-index *" and suddenly having all the object
- * files be revision controlled.
- */
-static int allow_add;
-static int allow_remove;
-static int allow_replace;
-static int info_only;
-static int force_remove;
-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;
-
-/* Untracked cache mode */
-enum uc_mode {
-	UC_UNSPECIFIED = -1,
-	UC_DISABLE = 0,
-	UC_ENABLE,
-	UC_TEST,
-	UC_FORCE
-};
-
-__attribute__((format (printf, 1, 2)))
-static void report(const char *fmt, ...)
-{
-	va_list vp;
-
-	if (!verbose)
-		return;
-
-	va_start(vp, fmt);
-	vprintf(fmt, vp);
-	putchar('\n');
-	va_end(vp);
-}
-
-static void remove_test_directory(void)
-{
-	if (mtime_dir.len)
-		remove_dir_recursively(&mtime_dir, 0);
-}
-
-static const char *get_mtime_path(const char *path)
-{
-	static struct strbuf sb = STRBUF_INIT;
-	strbuf_reset(&sb);
-	strbuf_addf(&sb, "%s/%s", mtime_dir.buf, path);
-	return sb.buf;
-}
-
-static void xmkdir(const char *path)
-{
-	path = get_mtime_path(path);
-	if (mkdir(path, 0700))
-		die_errno(_("failed to create directory %s"), path);
-}
-
-static int xstat_mtime_dir(struct stat *st)
-{
-	if (stat(mtime_dir.buf, st))
-		die_errno(_("failed to stat %s"), mtime_dir.buf);
-	return 0;
-}
-
-static int create_file(const char *path)
-{
-	int fd;
-	path = get_mtime_path(path);
-	fd = open(path, O_CREAT | O_RDWR, 0644);
-	if (fd < 0)
-		die_errno(_("failed to create file %s"), path);
-	return fd;
-}
-
-static void xunlink(const char *path)
-{
-	path = get_mtime_path(path);
-	if (unlink(path))
-		die_errno(_("failed to delete file %s"), path);
-}
-
-static void xrmdir(const char *path)
-{
-	path = get_mtime_path(path);
-	if (rmdir(path))
-		die_errno(_("failed to delete directory %s"), path);
-}
-
-static void avoid_racy(void)
-{
-	/*
-	 * not use if we could usleep(10) if USE_NSEC is defined. The
-	 * field nsec could be there, but the OS could choose to
-	 * ignore it?
-	 */
-	sleep(1);
-}
-
-static int test_if_untracked_cache_is_supported(void)
-{
-	struct stat st;
-	struct stat_data base;
-	int fd, ret = 0;
-	char *cwd;
-
-	strbuf_addstr(&mtime_dir, "mtime-test-XXXXXX");
-	if (!mkdtemp(mtime_dir.buf))
-		die_errno("Could not make temporary directory");
-
-	cwd = xgetcwd();
-	fprintf(stderr, _("Testing mtime in '%s' "), cwd);
-	free(cwd);
-
-	atexit(remove_test_directory);
-	xstat_mtime_dir(&st);
-	fill_stat_data(&base, &st);
-	fputc('.', stderr);
-
-	avoid_racy();
-	fd = create_file("newfile");
-	xstat_mtime_dir(&st);
-	if (!match_stat_data(&base, &st)) {
-		close(fd);
-		fputc('\n', stderr);
-		fprintf_ln(stderr,_("directory stat info does not "
-				    "change after adding a new file"));
-		goto done;
-	}
-	fill_stat_data(&base, &st);
-	fputc('.', stderr);
-
-	avoid_racy();
-	xmkdir("new-dir");
-	xstat_mtime_dir(&st);
-	if (!match_stat_data(&base, &st)) {
-		close(fd);
-		fputc('\n', stderr);
-		fprintf_ln(stderr, _("directory stat info does not change "
-				     "after adding a new directory"));
-		goto done;
-	}
-	fill_stat_data(&base, &st);
-	fputc('.', stderr);
-
-	avoid_racy();
-	write_or_die(fd, "data", 4);
-	close(fd);
-	xstat_mtime_dir(&st);
-	if (match_stat_data(&base, &st)) {
-		fputc('\n', stderr);
-		fprintf_ln(stderr, _("directory stat info changes "
-				     "after updating a file"));
-		goto done;
-	}
-	fputc('.', stderr);
-
-	avoid_racy();
-	close(create_file("new-dir/new"));
-	xstat_mtime_dir(&st);
-	if (match_stat_data(&base, &st)) {
-		fputc('\n', stderr);
-		fprintf_ln(stderr, _("directory stat info changes after "
-				     "adding a file inside subdirectory"));
-		goto done;
-	}
-	fputc('.', stderr);
-
-	avoid_racy();
-	xunlink("newfile");
-	xstat_mtime_dir(&st);
-	if (!match_stat_data(&base, &st)) {
-		fputc('\n', stderr);
-		fprintf_ln(stderr, _("directory stat info does not "
-				     "change after deleting a file"));
-		goto done;
-	}
-	fill_stat_data(&base, &st);
-	fputc('.', stderr);
-
-	avoid_racy();
-	xunlink("new-dir/new");
-	xrmdir("new-dir");
-	xstat_mtime_dir(&st);
-	if (!match_stat_data(&base, &st)) {
-		fputc('\n', stderr);
-		fprintf_ln(stderr, _("directory stat info does not "
-				     "change after deleting a directory"));
-		goto done;
-	}
-
-	if (rmdir(mtime_dir.buf))
-		die_errno(_("failed to delete directory %s"), mtime_dir.buf);
-	fprintf_ln(stderr, _(" OK"));
-	ret = 1;
-
-done:
-	strbuf_release(&mtime_dir);
-	return ret;
-}
-
-static int mark_ce_flags(const char *path, int flag, int mark)
-{
-	int namelen = strlen(path);
-	int pos = cache_name_pos(path, namelen);
-	if (0 <= pos) {
-		mark_fsmonitor_invalid(&the_index, active_cache[pos]);
-		if (mark)
-			active_cache[pos]->ce_flags |= flag;
-		else
-			active_cache[pos]->ce_flags &= ~flag;
-		active_cache[pos]->ce_flags |= CE_UPDATE_IN_BASE;
-		cache_tree_invalidate_path(&the_index, path);
-		active_cache_changed |= CE_ENTRY_CHANGED;
-		return 0;
-	}
-	return -1;
-}
-
-static int remove_one_path(const char *path)
-{
-	if (!allow_remove)
-		return error("%s: does not exist and --remove not passed", path);
-	if (remove_file_from_cache(path))
-		return error("%s: cannot remove from the index", path);
-	return 0;
-}
-
-/*
- * Handle a path that couldn't be lstat'ed. It's either:
- *  - missing file (ENOENT or ENOTDIR). That's ok if we're
- *    supposed to be removing it and the removal actually
- *    succeeds.
- *  - permission error. That's never ok.
- */
-static int process_lstat_error(const char *path, int err)
-{
-	if (is_missing_file_error(err))
-		return remove_one_path(path);
-	return error("lstat(\"%s\"): %s", path, strerror(err));
-}
-
-static int add_one_path(const struct cache_entry *old, const char *path, int len, struct stat *st)
-{
-	int option;
-	struct cache_entry *ce;
-
-	/* Was the old index entry already up-to-date? */
-	if (old && !ce_stage(old) && !ce_match_stat(old, st, 0))
-		return 0;
-
-	ce = make_empty_cache_entry(&the_index, len);
-	memcpy(ce->name, path, len);
-	ce->ce_flags = create_ce_flags(0);
-	ce->ce_namelen = len;
-	fill_stat_cache_info(&the_index, ce, st);
-	ce->ce_mode = ce_mode_from_stat(old, st->st_mode);
-
-	if (index_path(&the_index, &ce->oid, path, st,
-		       info_only ? 0 : HASH_WRITE_OBJECT)) {
-		discard_cache_entry(ce);
-		return -1;
-	}
-	option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
-	option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
-	if (add_cache_entry(ce, option)) {
-		discard_cache_entry(ce);
-		return error("%s: cannot add to the index - missing --add option?", path);
-	}
-	return 0;
-}
-
-/*
- * Handle a path that was a directory. Four cases:
- *
- *  - it's already a gitlink in the index, and we keep it that
- *    way, and update it if we can (if we cannot find the HEAD,
- *    we're going to keep it unchanged in the index!)
- *
- *  - it's a *file* in the index, in which case it should be
- *    removed as a file if removal is allowed, since it doesn't
- *    exist as such any more. If removal isn't allowed, it's
- *    an error.
- *
- *    (NOTE! This is old and arguably fairly strange behaviour.
- *    We might want to make this an error unconditionally, and
- *    use "--force-remove" if you actually want to force removal).
- *
- *  - it used to exist as a subdirectory (ie multiple files with
- *    this particular prefix) in the index, in which case it's wrong
- *    to try to update it as a directory.
- *
- *  - it doesn't exist at all in the index, but it is a valid
- *    git directory, and it should be *added* as a gitlink.
- */
-static int process_directory(const char *path, int len, struct stat *st)
-{
-	struct object_id oid;
-	int pos = cache_name_pos(path, len);
-
-	/* Exact match: file or existing gitlink */
-	if (pos >= 0) {
-		const struct cache_entry *ce = active_cache[pos];
-		if (S_ISGITLINK(ce->ce_mode)) {
-
-			/* Do nothing to the index if there is no HEAD! */
-			if (resolve_gitlink_ref(path, "HEAD", &oid) < 0)
-				return 0;
-
-			return add_one_path(ce, path, len, st);
-		}
-		/* Should this be an unconditional error? */
-		return remove_one_path(path);
-	}
-
-	/* Inexact match: is there perhaps a subdirectory match? */
-	pos = -pos-1;
-	while (pos < active_nr) {
-		const struct cache_entry *ce = active_cache[pos++];
-
-		if (strncmp(ce->name, path, len))
-			break;
-		if (ce->name[len] > '/')
-			break;
-		if (ce->name[len] < '/')
-			continue;
-
-		/* Subdirectory match - error out */
-		return error("%s: is a directory - add individual files instead", path);
-	}
-
-	/* No match - should we add it as a gitlink? */
-	if (!resolve_gitlink_ref(path, "HEAD", &oid))
-		return add_one_path(NULL, path, len, st);
-
-	/* Error out. */
-	return error("%s: is a directory - add files inside instead", path);
-}
-
-static int process_path(const char *path, struct stat *st, int stat_errno)
-{
-	int pos, len;
-	const struct cache_entry *ce;
-
-	len = strlen(path);
-	if (has_symlink_leading_path(path, len))
-		return error("'%s' is beyond a symbolic link", path);
-
-	pos = cache_name_pos(path, len);
-	ce = pos < 0 ? NULL : active_cache[pos];
-	if (ce && ce_skip_worktree(ce)) {
-		/*
-		 * working directory version is assumed "good"
-		 * 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))
-			return error("%s: cannot remove from the index", path);
-		return 0;
-	}
-
-	/*
-	 * First things first: get the stat information, to decide
-	 * what to do about the pathname!
-	 */
-	if (stat_errno)
-		return process_lstat_error(path, stat_errno);
-
-	if (S_ISDIR(st->st_mode))
-		return process_directory(path, len, st);
-
-	return add_one_path(ce, path, len, st);
-}
-
-static int add_cacheinfo(unsigned int mode, const struct object_id *oid,
-			 const char *path, int stage)
-{
-	int len, option;
-	struct cache_entry *ce;
-
-	if (!verify_path(path, mode))
-		return error("Invalid path '%s'", path);
-
-	len = strlen(path);
-	ce = make_empty_cache_entry(&the_index, len);
-
-	oidcpy(&ce->oid, oid);
-	memcpy(ce->name, path, len);
-	ce->ce_flags = create_ce_flags(stage);
-	ce->ce_namelen = len;
-	ce->ce_mode = create_ce_mode(mode);
-	if (assume_unchanged)
-		ce->ce_flags |= CE_VALID;
-	option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
-	option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
-	if (add_cache_entry(ce, option))
-		return error("%s: cannot add to the index - missing --add option?",
-			     path);
-	report("add '%s'", path);
-	return 0;
-}
-
-static void chmod_path(char flip, const char *path)
-{
-	int pos;
-	struct cache_entry *ce;
-
-	pos = cache_name_pos(path, strlen(path));
-	if (pos < 0)
-		goto fail;
-	ce = active_cache[pos];
-	if (chmod_cache_entry(ce, flip) < 0)
-		goto fail;
-
-	report("chmod %cx '%s'", flip, path);
-	return;
- fail:
-	die("git update-index: cannot chmod %cx '%s'", flip, path);
-}
-
-static void update_one(const char *path)
-{
-	int stat_errno = 0;
-	struct stat st;
-
-	if (mark_valid_only || mark_skip_worktree_only || force_remove ||
-	    mark_fsmonitor_only)
-		st.st_mode = 0;
-	else if (lstat(path, &st) < 0) {
-		st.st_mode = 0;
-		stat_errno = errno;
-	} /* else stat is valid */
-
-	if (!verify_path(path, st.st_mode)) {
-		fprintf(stderr, "Ignoring path %s\n", path);
-		return;
-	}
-	if (mark_valid_only) {
-		if (mark_ce_flags(path, CE_VALID, mark_valid_only == MARK_FLAG))
-			die("Unable to mark file %s", path);
-		return;
-	}
-	if (mark_skip_worktree_only) {
-		if (mark_ce_flags(path, CE_SKIP_WORKTREE, mark_skip_worktree_only == MARK_FLAG))
-			die("Unable to mark file %s", path);
-		return;
-	}
-	if (mark_fsmonitor_only) {
-		if (mark_ce_flags(path, CE_FSMONITOR_VALID, mark_fsmonitor_only == MARK_FLAG))
-			die("Unable to mark file %s", path);
-		return;
-	}
-
-	if (force_remove) {
-		if (remove_file_from_cache(path))
-			die("git update-index: unable to remove %s", path);
-		report("remove '%s'", path);
-		return;
-	}
-	if (process_path(path, &st, stat_errno))
-		die("Unable to process path %s", path);
-	report("add '%s'", path);
-}
-
-static void read_index_info(int nul_term_line)
-{
-	const int hexsz = the_hash_algo->hexsz;
-	struct strbuf buf = STRBUF_INIT;
-	struct strbuf uq = STRBUF_INIT;
-	strbuf_getline_fn getline_fn;
-
-	getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
-	while (getline_fn(&buf, stdin) != EOF) {
-		char *ptr, *tab;
-		char *path_name;
-		struct object_id oid;
-		unsigned int mode;
-		unsigned long ul;
-		int stage;
-
-		/* This reads lines formatted in one of three formats:
-		 *
-		 * (1) mode         SP sha1          TAB path
-		 * The first format is what "git apply --index-info"
-		 * reports, and used to reconstruct a partial tree
-		 * that is used for phony merge base tree when falling
-		 * back on 3-way merge.
-		 *
-		 * (2) mode SP type SP sha1          TAB path
-		 * The second format is to stuff "git ls-tree" output
-		 * into the index file.
-		 *
-		 * (3) mode         SP sha1 SP stage TAB path
-		 * This format is to put higher order stages into the
-		 * index file and matches "git ls-files --stage" output.
-		 */
-		errno = 0;
-		ul = strtoul(buf.buf, &ptr, 8);
-		if (ptr == buf.buf || *ptr != ' '
-		    || errno || (unsigned int) ul != ul)
-			goto bad_line;
-		mode = ul;
-
-		tab = strchr(ptr, '\t');
-		if (!tab || tab - ptr < hexsz + 1)
-			goto bad_line;
-
-		if (tab[-2] == ' ' && '0' <= tab[-1] && tab[-1] <= '3') {
-			stage = tab[-1] - '0';
-			ptr = tab + 1; /* point at the head of path */
-			tab = tab - 2; /* point at tail of sha1 */
-		}
-		else {
-			stage = 0;
-			ptr = tab + 1; /* point at the head of path */
-		}
-
-		if (get_oid_hex(tab - hexsz, &oid) ||
-			tab[-(hexsz + 1)] != ' ')
-			goto bad_line;
-
-		path_name = ptr;
-		if (!nul_term_line && path_name[0] == '"') {
-			strbuf_reset(&uq);
-			if (unquote_c_style(&uq, path_name, NULL)) {
-				die("git update-index: bad quoting of path name");
-			}
-			path_name = uq.buf;
-		}
-
-		if (!verify_path(path_name, mode)) {
-			fprintf(stderr, "Ignoring path %s\n", path_name);
-			continue;
-		}
-
-		if (!mode) {
-			/* mode == 0 means there is no such path -- remove */
-			if (remove_file_from_cache(path_name))
-				die("git update-index: unable to remove %s",
-				    ptr);
-		}
-		else {
-			/* mode ' ' sha1 '\t' name
-			 * ptr[-1] points at tab,
-			 * ptr[-41] is at the beginning of sha1
-			 */
-			ptr[-(hexsz + 2)] = ptr[-1] = 0;
-			if (add_cacheinfo(mode, &oid, path_name, stage))
-				die("git update-index: unable to update %s",
-				    path_name);
-		}
-		continue;
-
-	bad_line:
-		die("malformed index info %s", buf.buf);
-	}
-	strbuf_release(&buf);
-	strbuf_release(&uq);
-}
-
-static const char * const update_index_usage[] = {
-	N_("git update-index [<options>] [--] [<file>...]"),
-	NULL
-};
-
-static struct object_id head_oid;
-static struct object_id merge_head_oid;
-
-static struct cache_entry *read_one_ent(const char *which,
-					struct object_id *ent, const char *path,
-					int namelen, int stage)
-{
-	unsigned short mode;
-	struct object_id oid;
-	struct cache_entry *ce;
-
-	if (get_tree_entry(the_repository, ent, path, &oid, &mode)) {
-		if (which)
-			error("%s: not in %s branch.", path, which);
-		return NULL;
-	}
-	if (mode == S_IFDIR) {
-		if (which)
-			error("%s: not a blob in %s branch.", path, which);
-		return NULL;
-	}
-	ce = make_empty_cache_entry(&the_index, namelen);
-
-	oidcpy(&ce->oid, &oid);
-	memcpy(ce->name, path, namelen);
-	ce->ce_flags = create_ce_flags(stage);
-	ce->ce_namelen = namelen;
-	ce->ce_mode = create_ce_mode(mode);
-	return ce;
-}
-
-static int unresolve_one(const char *path)
-{
-	int namelen = strlen(path);
-	int pos;
-	int ret = 0;
-	struct cache_entry *ce_2 = NULL, *ce_3 = NULL;
-
-	/* See if there is such entry in the index. */
-	pos = cache_name_pos(path, namelen);
-	if (0 <= pos) {
-		/* already merged */
-		pos = unmerge_cache_entry_at(pos);
-		if (pos < active_nr) {
-			const struct cache_entry *ce = active_cache[pos];
-			if (ce_stage(ce) &&
-			    ce_namelen(ce) == namelen &&
-			    !memcmp(ce->name, path, namelen))
-				return 0;
-		}
-		/* no resolve-undo information; fall back */
-	} else {
-		/* If there isn't, either it is unmerged, or
-		 * resolved as "removed" by mistake.  We do not
-		 * want to do anything in the former case.
-		 */
-		pos = -pos-1;
-		if (pos < active_nr) {
-			const struct cache_entry *ce = active_cache[pos];
-			if (ce_namelen(ce) == namelen &&
-			    !memcmp(ce->name, path, namelen)) {
-				fprintf(stderr,
-					"%s: skipping still unmerged path.\n",
-					path);
-				goto free_return;
-			}
-		}
-	}
-
-	/* Grab blobs from given path from HEAD and MERGE_HEAD,
-	 * stuff HEAD version in stage #2,
-	 * stuff MERGE_HEAD version in stage #3.
-	 */
-	ce_2 = read_one_ent("our", &head_oid, path, namelen, 2);
-	ce_3 = read_one_ent("their", &merge_head_oid, path, namelen, 3);
-
-	if (!ce_2 || !ce_3) {
-		ret = -1;
-		goto free_return;
-	}
-	if (oideq(&ce_2->oid, &ce_3->oid) &&
-	    ce_2->ce_mode == ce_3->ce_mode) {
-		fprintf(stderr, "%s: identical in both, skipping.\n",
-			path);
-		goto free_return;
-	}
-
-	remove_file_from_cache(path);
-	if (add_cache_entry(ce_2, ADD_CACHE_OK_TO_ADD)) {
-		error("%s: cannot add our version to the index.", path);
-		ret = -1;
-		goto free_return;
-	}
-	if (!add_cache_entry(ce_3, ADD_CACHE_OK_TO_ADD))
-		return 0;
-	error("%s: cannot add their version to the index.", path);
-	ret = -1;
- free_return:
-	discard_cache_entry(ce_2);
-	discard_cache_entry(ce_3);
-	return ret;
-}
-
-static void read_head_pointers(void)
-{
-	if (read_ref("HEAD", &head_oid))
-		die("No HEAD -- no initial commit yet?");
-	if (read_ref("MERGE_HEAD", &merge_head_oid)) {
-		fprintf(stderr, "Not in the middle of a merge.\n");
-		exit(0);
-	}
-}
-
-static int do_unresolve(int ac, const char **av,
-			const char *prefix, int prefix_length)
-{
-	int i;
-	int err = 0;
-
-	/* Read HEAD and MERGE_HEAD; if MERGE_HEAD does not exist, we
-	 * are not doing a merge, so exit with success status.
-	 */
-	read_head_pointers();
-
-	for (i = 1; i < ac; i++) {
-		const char *arg = av[i];
-		char *p = prefix_path(prefix, prefix_length, arg);
-		err |= unresolve_one(p);
-		free(p);
-	}
-	return err;
-}
-
-static int do_reupdate(int ac, const char **av,
-		       const char *prefix)
-{
-	/* Read HEAD and run update-index on paths that are
-	 * merged and already different between index and HEAD.
-	 */
-	int pos;
-	int has_head = 1;
-	struct pathspec pathspec;
-
-	parse_pathspec(&pathspec, 0,
-		       PATHSPEC_PREFER_CWD,
-		       prefix, av + 1);
-
-	if (read_ref("HEAD", &head_oid))
-		/* If there is no HEAD, that means it is an initial
-		 * commit.  Update everything in the index.
-		 */
-		has_head = 0;
- redo:
-	for (pos = 0; pos < active_nr; pos++) {
-		const struct cache_entry *ce = active_cache[pos];
-		struct cache_entry *old = NULL;
-		int save_nr;
-		char *path;
-
-		if (ce_stage(ce) || !ce_path_match(&the_index, ce, &pathspec, NULL))
-			continue;
-		if (has_head)
-			old = read_one_ent(NULL, &head_oid,
-					   ce->name, ce_namelen(ce), 0);
-		if (old && ce->ce_mode == old->ce_mode &&
-		    oideq(&ce->oid, &old->oid)) {
-			discard_cache_entry(old);
-			continue; /* unchanged */
-		}
-		/* Be careful.  The working tree may not have the
-		 * path anymore, in which case, under 'allow_remove',
-		 * or worse yet 'allow_replace', active_nr may decrease.
-		 */
-		save_nr = active_nr;
-		path = xstrdup(ce->name);
-		update_one(path);
-		free(path);
-		discard_cache_entry(old);
-		if (save_nr != active_nr)
-			goto redo;
-	}
-	clear_pathspec(&pathspec);
-	return 0;
-}
-
-struct refresh_params {
-	unsigned int flags;
-	int *has_errors;
-};
-
-static int refresh(struct refresh_params *o, unsigned int flag)
-{
-	setup_work_tree();
-	read_cache();
-	*o->has_errors |= refresh_cache(o->flags | flag);
-	return 0;
-}
-
-static int refresh_callback(const struct option *opt,
-				const char *arg, int unset)
-{
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-	return refresh(opt->value, 0);
-}
-
-static int really_refresh_callback(const struct option *opt,
-				const char *arg, int unset)
-{
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-	return refresh(opt->value, REFRESH_REALLY);
-}
-
-static int chmod_callback(const struct option *opt,
-				const char *arg, int unset)
-{
-	char *flip = opt->value;
-	BUG_ON_OPT_NEG(unset);
-	if ((arg[0] != '-' && arg[0] != '+') || arg[1] != 'x' || arg[2])
-		return error("option 'chmod' expects \"+x\" or \"-x\"");
-	*flip = arg[0];
-	return 0;
-}
-
-static int resolve_undo_clear_callback(const struct option *opt,
-				const char *arg, int unset)
-{
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-	resolve_undo_clear();
-	return 0;
-}
-
-static int parse_new_style_cacheinfo(const char *arg,
-				     unsigned int *mode,
-				     struct object_id *oid,
-				     const char **path)
-{
-	unsigned long ul;
-	char *endp;
-	const char *p;
-
-	if (!arg)
-		return -1;
-
-	errno = 0;
-	ul = strtoul(arg, &endp, 8);
-	if (errno || endp == arg || *endp != ',' || (unsigned int) ul != ul)
-		return -1; /* not a new-style cacheinfo */
-	*mode = ul;
-	endp++;
-	if (parse_oid_hex(endp, oid, &p) || *p != ',')
-		return -1;
-	*path = p + 1;
-	return 0;
-}
-
-static enum parse_opt_result cacheinfo_callback(
-	struct parse_opt_ctx_t *ctx, const struct option *opt,
-	const char *arg, int unset)
-{
-	struct object_id oid;
-	unsigned int mode;
-	const char *path;
-
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-
-	if (!parse_new_style_cacheinfo(ctx->argv[1], &mode, &oid, &path)) {
-		if (add_cacheinfo(mode, &oid, path, 0))
-			die("git update-index: --cacheinfo cannot add %s", path);
-		ctx->argv++;
-		ctx->argc--;
-		return 0;
-	}
-	if (ctx->argc <= 3)
-		return error("option 'cacheinfo' expects <mode>,<sha1>,<path>");
-	if (strtoul_ui(*++ctx->argv, 8, &mode) ||
-	    get_oid_hex(*++ctx->argv, &oid) ||
-	    add_cacheinfo(mode, &oid, *++ctx->argv, 0))
-		die("git update-index: --cacheinfo cannot add %s", *ctx->argv);
-	ctx->argc -= 3;
-	return 0;
-}
-
-static enum parse_opt_result stdin_cacheinfo_callback(
-	struct parse_opt_ctx_t *ctx, const struct option *opt,
-	const char *arg, int unset)
-{
-	int *nul_term_line = opt->value;
-
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-
-	if (ctx->argc != 1)
-		return error("option '%s' must be the last argument", opt->long_name);
-	allow_add = allow_replace = allow_remove = 1;
-	read_index_info(*nul_term_line);
-	return 0;
-}
-
-static enum parse_opt_result stdin_callback(
-	struct parse_opt_ctx_t *ctx, const struct option *opt,
-	const char *arg, int unset)
-{
-	int *read_from_stdin = opt->value;
-
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-
-	if (ctx->argc != 1)
-		return error("option '%s' must be the last argument", opt->long_name);
-	*read_from_stdin = 1;
-	return 0;
-}
-
-static enum parse_opt_result unresolve_callback(
-	struct parse_opt_ctx_t *ctx, const struct option *opt,
-	const char *arg, int unset)
-{
-	int *has_errors = opt->value;
-	const char *prefix = startup_info->prefix;
-
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-
-	/* consume remaining arguments. */
-	*has_errors = do_unresolve(ctx->argc, ctx->argv,
-				prefix, prefix ? strlen(prefix) : 0);
-	if (*has_errors)
-		active_cache_changed = 0;
-
-	ctx->argv += ctx->argc - 1;
-	ctx->argc = 1;
-	return 0;
-}
-
-static enum parse_opt_result reupdate_callback(
-	struct parse_opt_ctx_t *ctx, const struct option *opt,
-	const char *arg, int unset)
-{
-	int *has_errors = opt->value;
-	const char *prefix = startup_info->prefix;
-
-	BUG_ON_OPT_NEG(unset);
-	BUG_ON_OPT_ARG(arg);
-
-	/* consume remaining arguments. */
-	setup_work_tree();
-	*has_errors = do_reupdate(ctx->argc, ctx->argv, prefix);
-	if (*has_errors)
-		active_cache_changed = 0;
-
-	ctx->argv += ctx->argc - 1;
-	ctx->argc = 1;
-	return 0;
-}
-
-int cmd_update_index(int argc, const char **argv, const char *prefix)
-{
-	int newfd, entries, has_errors = 0, nul_term_line = 0;
-	enum uc_mode untracked_cache = UC_UNSPECIFIED;
-	int read_from_stdin = 0;
-	int prefix_length = prefix ? strlen(prefix) : 0;
-	int preferred_index_format = 0;
-	char set_executable_bit = 0;
-	struct refresh_params refresh_args = {0, &has_errors};
-	int lock_error = 0;
-	int split_index = -1;
-	int force_write = 0;
-	int fsmonitor = -1;
-	struct lock_file lock_file = LOCK_INIT;
-	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"),
-			REFRESH_QUIET),
-		OPT_BIT(0, "ignore-submodules", &refresh_args.flags,
-			N_("refresh: ignore submodules"),
-			REFRESH_IGNORE_SUBMODULES),
-		OPT_SET_INT(0, "add", &allow_add,
-			N_("do not ignore new files"), 1),
-		OPT_SET_INT(0, "replace", &allow_replace,
-			N_("let files replace directories and vice-versa"), 1),
-		OPT_SET_INT(0, "remove", &allow_remove,
-			N_("notice files missing from worktree"), 1),
-		OPT_BIT(0, "unmerged", &refresh_args.flags,
-			N_("refresh even if index contains unmerged entries"),
-			REFRESH_UNMERGED),
-		OPT_CALLBACK_F(0, "refresh", &refresh_args, NULL,
-			N_("refresh stat information"),
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG,
-			refresh_callback),
-		OPT_CALLBACK_F(0, "really-refresh", &refresh_args, NULL,
-			N_("like --refresh, but ignore assume-unchanged setting"),
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG,
-			really_refresh_callback),
-		{OPTION_LOWLEVEL_CALLBACK, 0, "cacheinfo", NULL,
-			N_("<mode>,<object>,<path>"),
-			N_("add the specified entry to the index"),
-			PARSE_OPT_NOARG | /* disallow --cacheinfo=<mode> form */
-			PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
-			NULL, 0,
-			cacheinfo_callback},
-		OPT_CALLBACK_F(0, "chmod", &set_executable_bit, "(+|-)x",
-			N_("override the executable bit of the listed files"),
-			PARSE_OPT_NONEG,
-			chmod_callback),
-		{OPTION_SET_INT, 0, "assume-unchanged", &mark_valid_only, NULL,
-			N_("mark files as \"not changing\""),
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG},
-		{OPTION_SET_INT, 0, "no-assume-unchanged", &mark_valid_only, NULL,
-			N_("clear assumed-unchanged bit"),
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
-		{OPTION_SET_INT, 0, "skip-worktree", &mark_skip_worktree_only, NULL,
-			N_("mark files as \"index-only\""),
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG},
-		{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,
-			N_("remove named paths even if present in worktree"), 1),
-		OPT_BOOL('z', NULL, &nul_term_line,
-			 N_("with --stdin: input lines are terminated by null bytes")),
-		{OPTION_LOWLEVEL_CALLBACK, 0, "stdin", &read_from_stdin, NULL,
-			N_("read list of paths to be updated from standard input"),
-			PARSE_OPT_NONEG | PARSE_OPT_NOARG,
-			NULL, 0, stdin_callback},
-		{OPTION_LOWLEVEL_CALLBACK, 0, "index-info", &nul_term_line, NULL,
-			N_("add entries from standard input to the index"),
-			PARSE_OPT_NONEG | PARSE_OPT_NOARG,
-			NULL, 0, stdin_cacheinfo_callback},
-		{OPTION_LOWLEVEL_CALLBACK, 0, "unresolve", &has_errors, NULL,
-			N_("repopulate stages #2 and #3 for the listed paths"),
-			PARSE_OPT_NONEG | PARSE_OPT_NOARG,
-			NULL, 0, unresolve_callback},
-		{OPTION_LOWLEVEL_CALLBACK, 'g', "again", &has_errors, NULL,
-			N_("only update entries that differ from HEAD"),
-			PARSE_OPT_NONEG | PARSE_OPT_NOARG,
-			NULL, 0, reupdate_callback},
-		OPT_BIT(0, "ignore-missing", &refresh_args.flags,
-			N_("ignore files missing from worktree"),
-			REFRESH_IGNORE_MISSING),
-		OPT_SET_INT(0, "verbose", &verbose,
-			N_("report actions to standard output"), 1),
-		OPT_CALLBACK_F(0, "clear-resolve-undo", NULL, NULL,
-			N_("(for porcelains) forget saved unresolved conflicts"),
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG,
-			resolve_undo_clear_callback),
-		OPT_INTEGER(0, "index-version", &preferred_index_format,
-			N_("write index in this format")),
-		OPT_BOOL(0, "split-index", &split_index,
-			N_("enable or disable split index")),
-		OPT_BOOL(0, "untracked-cache", &untracked_cache,
-			N_("enable/disable untracked cache")),
-		OPT_SET_INT(0, "test-untracked-cache", &untracked_cache,
-			    N_("test if the filesystem supports untracked cache"), UC_TEST),
-		OPT_SET_INT(0, "force-untracked-cache", &untracked_cache,
-			    N_("enable untracked cache without testing the filesystem"), UC_FORCE),
-		OPT_SET_INT(0, "force-write-index", &force_write,
-			N_("write out the index even if is not flagged as changed"), 1),
-		OPT_BOOL(0, "fsmonitor", &fsmonitor,
-			N_("enable or disable file system monitor")),
-		{OPTION_SET_INT, 0, "fsmonitor-valid", &mark_fsmonitor_only, NULL,
-			N_("mark files as fsmonitor valid"),
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG},
-		{OPTION_SET_INT, 0, "no-fsmonitor-valid", &mark_fsmonitor_only, NULL,
-			N_("clear fsmonitor valid bit"),
-			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
-		OPT_END()
-	};
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage_with_options(update_index_usage, options);
-
-	git_config(git_default_config, NULL);
-
-	/* we will diagnose later if it turns out that we need to update it */
-	newfd = hold_locked_index(&lock_file, 0);
-	if (newfd < 0)
-		lock_error = errno;
-
-	entries = read_cache();
-	if (entries < 0)
-		die("cache corrupted");
-
-	the_index.updated_skipworktree = 1;
-
-	/*
-	 * Custom copy of parse_options() because we want to handle
-	 * filename arguments as they come.
-	 */
-	parse_options_start(&ctx, argc, argv, prefix,
-			    options, PARSE_OPT_STOP_AT_NON_OPTION);
-	while (ctx.argc) {
-		if (parseopt_state != PARSE_OPT_DONE)
-			parseopt_state = parse_options_step(&ctx, options,
-							    update_index_usage);
-		if (!ctx.argc)
-			break;
-		switch (parseopt_state) {
-		case PARSE_OPT_HELP:
-		case PARSE_OPT_ERROR:
-			exit(129);
-		case PARSE_OPT_COMPLETE:
-			exit(0);
-		case PARSE_OPT_NON_OPTION:
-		case PARSE_OPT_DONE:
-		{
-			const char *path = ctx.argv[0];
-			char *p;
-
-			setup_work_tree();
-			p = prefix_path(prefix, prefix_length, path);
-			update_one(p);
-			if (set_executable_bit)
-				chmod_path(set_executable_bit, p);
-			free(p);
-			ctx.argc--;
-			ctx.argv++;
-			break;
-		}
-		case PARSE_OPT_UNKNOWN:
-			if (ctx.argv[0][1] == '-')
-				error("unknown option '%s'", ctx.argv[0] + 2);
-			else
-				error("unknown switch '%c'", *ctx.opt);
-			usage_with_options(update_index_usage, options);
-		}
-	}
-	argc = parse_options_end(&ctx);
-
-	getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
-	if (preferred_index_format) {
-		if (preferred_index_format < INDEX_FORMAT_LB ||
-		    INDEX_FORMAT_UB < preferred_index_format)
-			die("index-version %d not in range: %d..%d",
-			    preferred_index_format,
-			    INDEX_FORMAT_LB, INDEX_FORMAT_UB);
-
-		if (the_index.version != preferred_index_format)
-			active_cache_changed |= SOMETHING_CHANGED;
-		the_index.version = preferred_index_format;
-	}
-
-	if (read_from_stdin) {
-		struct strbuf buf = STRBUF_INIT;
-		struct strbuf unquoted = STRBUF_INIT;
-
-		setup_work_tree();
-		while (getline_fn(&buf, stdin) != EOF) {
-			char *p;
-			if (!nul_term_line && buf.buf[0] == '"') {
-				strbuf_reset(&unquoted);
-				if (unquote_c_style(&unquoted, buf.buf, NULL))
-					die("line is badly quoted");
-				strbuf_swap(&buf, &unquoted);
-			}
-			p = prefix_path(prefix, prefix_length, buf.buf);
-			update_one(p);
-			if (set_executable_bit)
-				chmod_path(set_executable_bit, p);
-			free(p);
-		}
-		strbuf_release(&unquoted);
-		strbuf_release(&buf);
-	}
-
-	if (split_index > 0) {
-		if (git_config_get_split_index() == 0)
-			warning(_("core.splitIndex is set to false; "
-				  "remove or change it, if you really want to "
-				  "enable split index"));
-		if (the_index.split_index)
-			the_index.cache_changed |= SPLIT_INDEX_ORDERED;
-		else
-			add_split_index(&the_index);
-	} else if (!split_index) {
-		if (git_config_get_split_index() == 1)
-			warning(_("core.splitIndex is set to true; "
-				  "remove or change it, if you really want to "
-				  "disable split index"));
-		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)
-			warning(_("core.untrackedCache is set to true; "
-				  "remove or change it, if you really want to "
-				  "disable the untracked cache"));
-		remove_untracked_cache(&the_index);
-		report(_("Untracked cache disabled"));
-		break;
-	case UC_TEST:
-		setup_work_tree();
-		return !test_if_untracked_cache_is_supported();
-	case UC_ENABLE:
-	case UC_FORCE:
-		if (r->settings.core_untracked_cache == UNTRACKED_CACHE_REMOVE)
-			warning(_("core.untrackedCache is set to false; "
-				  "remove or change it, if you really want to "
-				  "enable the untracked cache"));
-		add_untracked_cache(&the_index);
-		report(_("Untracked cache enabled for '%s'"), get_git_work_tree());
-		break;
-	default:
-		BUG("bad untracked_cache value: %d", untracked_cache);
-	}
-
-	if (fsmonitor > 0) {
-		if (git_config_get_fsmonitor() == 0)
-			warning(_("core.fsmonitor is unset; "
-				"set it if you really want to "
-				"enable fsmonitor"));
-		add_fsmonitor(&the_index);
-		report(_("fsmonitor enabled"));
-	} else if (!fsmonitor) {
-		if (git_config_get_fsmonitor() == 1)
-			warning(_("core.fsmonitor is set; "
-				"remove it if you really want to "
-				"disable fsmonitor"));
-		remove_fsmonitor(&the_index);
-		report(_("fsmonitor disabled"));
-	}
-
-	if (active_cache_changed || force_write) {
-		if (newfd < 0) {
-			if (refresh_args.flags & REFRESH_QUIET)
-				exit(128);
-			unable_to_lock_die(get_index_file(), lock_error);
-		}
-		if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
-			die("Unable to write new index file");
-	}
-
-	rollback_lock_file(&lock_file);
-
-	return has_errors ? 1 : 0;
-}
diff --git a/third_party/git/builtin/update-ref.c b/third_party/git/builtin/update-ref.c
deleted file mode 100644
index 8a2df4459c66..000000000000
--- a/third_party/git/builtin/update-ref.c
+++ /dev/null
@@ -1,560 +0,0 @@
-#include "cache.h"
-#include "config.h"
-#include "refs.h"
-#include "builtin.h"
-#include "parse-options.h"
-#include "quote.h"
-#include "strvec.h"
-
-static const char * const git_update_ref_usage[] = {
-	N_("git update-ref [<options>] -d <refname> [<old-val>]"),
-	N_("git update-ref [<options>]    <refname> <new-val> [<old-val>]"),
-	N_("git update-ref [<options>] --stdin [-z]"),
-	NULL
-};
-
-static char line_termination = '\n';
-static unsigned int update_flags;
-static unsigned int default_flags;
-static unsigned create_reflog_flag;
-static const char *msg;
-
-/*
- * Parse one whitespace- or NUL-terminated, possibly C-quoted argument
- * and append the result to arg.  Return a pointer to the terminator.
- * Die if there is an error in how the argument is C-quoted.  This
- * function is only used if not -z.
- */
-static const char *parse_arg(const char *next, struct strbuf *arg)
-{
-	if (*next == '"') {
-		const char *orig = next;
-
-		if (unquote_c_style(arg, next, &next))
-			die("badly quoted argument: %s", orig);
-		if (*next && !isspace(*next))
-			die("unexpected character after quoted argument: %s", orig);
-	} else {
-		while (*next && !isspace(*next))
-			strbuf_addch(arg, *next++);
-	}
-
-	return next;
-}
-
-/*
- * Parse the reference name immediately after "command SP".  If not
- * -z, then handle C-quoting.  Return a pointer to a newly allocated
- * string containing the name of the reference, or NULL if there was
- * an error.  Update *next to point at the character that terminates
- * the argument.  Die if C-quoting is malformed or the reference name
- * is invalid.
- */
-static char *parse_refname(const char **next)
-{
-	struct strbuf ref = STRBUF_INIT;
-
-	if (line_termination) {
-		/* Without -z, use the next argument */
-		*next = parse_arg(*next, &ref);
-	} else {
-		/* With -z, use everything up to the next NUL */
-		strbuf_addstr(&ref, *next);
-		*next += ref.len;
-	}
-
-	if (!ref.len) {
-		strbuf_release(&ref);
-		return NULL;
-	}
-
-	if (check_refname_format(ref.buf, REFNAME_ALLOW_ONELEVEL))
-		die("invalid ref format: %s", ref.buf);
-
-	return strbuf_detach(&ref, NULL);
-}
-
-/*
- * The value being parsed is <oldvalue> (as opposed to <newvalue>; the
- * difference affects which error messages are generated):
- */
-#define PARSE_SHA1_OLD 0x01
-
-/*
- * For backwards compatibility, accept an empty string for update's
- * <newvalue> in binary mode to be equivalent to specifying zeros.
- */
-#define PARSE_SHA1_ALLOW_EMPTY 0x02
-
-/*
- * Parse an argument separator followed by the next argument, if any.
- * If there is an argument, convert it to a SHA-1, write it to sha1,
- * set *next to point at the character terminating the argument, and
- * return 0.  If there is no argument at all (not even the empty
- * string), return 1 and leave *next unchanged.  If the value is
- * provided but cannot be converted to a SHA-1, die.  flags can
- * include PARSE_SHA1_OLD and/or PARSE_SHA1_ALLOW_EMPTY.
- */
-static int parse_next_oid(const char **next, const char *end,
-			  struct object_id *oid,
-			  const char *command, const char *refname,
-			  int flags)
-{
-	struct strbuf arg = STRBUF_INIT;
-	int ret = 0;
-
-	if (*next == end)
-		goto eof;
-
-	if (line_termination) {
-		/* Without -z, consume SP and use next argument */
-		if (!**next || **next == line_termination)
-			return 1;
-		if (**next != ' ')
-			die("%s %s: expected SP but got: %s",
-			    command, refname, *next);
-		(*next)++;
-		*next = parse_arg(*next, &arg);
-		if (arg.len) {
-			if (get_oid(arg.buf, oid))
-				goto invalid;
-		} else {
-			/* Without -z, an empty value means all zeros: */
-			oidclr(oid);
-		}
-	} else {
-		/* With -z, read the next NUL-terminated line */
-		if (**next)
-			die("%s %s: expected NUL but got: %s",
-			    command, refname, *next);
-		(*next)++;
-		if (*next == end)
-			goto eof;
-		strbuf_addstr(&arg, *next);
-		*next += arg.len;
-
-		if (arg.len) {
-			if (get_oid(arg.buf, oid))
-				goto invalid;
-		} else if (flags & PARSE_SHA1_ALLOW_EMPTY) {
-			/* With -z, treat an empty value as all zeros: */
-			warning("%s %s: missing <newvalue>, treating as zero",
-				command, refname);
-			oidclr(oid);
-		} else {
-			/*
-			 * With -z, an empty non-required value means
-			 * unspecified:
-			 */
-			ret = 1;
-		}
-	}
-
-	strbuf_release(&arg);
-
-	return ret;
-
- invalid:
-	die(flags & PARSE_SHA1_OLD ?
-	    "%s %s: invalid <oldvalue>: %s" :
-	    "%s %s: invalid <newvalue>: %s",
-	    command, refname, arg.buf);
-
- eof:
-	die(flags & PARSE_SHA1_OLD ?
-	    "%s %s: unexpected end of input when reading <oldvalue>" :
-	    "%s %s: unexpected end of input when reading <newvalue>",
-	    command, refname);
-}
-
-
-/*
- * The following five parse_cmd_*() functions parse the corresponding
- * command.  In each case, next points at the character following the
- * command name and the following space.  They each return a pointer
- * to the character terminating the command, and die with an
- * explanatory message if there are any parsing problems.  All of
- * these functions handle either text or binary format input,
- * depending on how line_termination is set.
- */
-
-static void parse_cmd_update(struct ref_transaction *transaction,
-			     const char *next, const char *end)
-{
-	struct strbuf err = STRBUF_INIT;
-	char *refname;
-	struct object_id new_oid, old_oid;
-	int have_old;
-
-	refname = parse_refname(&next);
-	if (!refname)
-		die("update: missing <ref>");
-
-	if (parse_next_oid(&next, end, &new_oid, "update", refname,
-			   PARSE_SHA1_ALLOW_EMPTY))
-		die("update %s: missing <newvalue>", refname);
-
-	have_old = !parse_next_oid(&next, end, &old_oid, "update", refname,
-				   PARSE_SHA1_OLD);
-
-	if (*next != line_termination)
-		die("update %s: extra input: %s", refname, next);
-
-	if (ref_transaction_update(transaction, refname,
-				   &new_oid, have_old ? &old_oid : NULL,
-				   update_flags | create_reflog_flag,
-				   msg, &err))
-		die("%s", err.buf);
-
-	update_flags = default_flags;
-	free(refname);
-	strbuf_release(&err);
-}
-
-static void parse_cmd_create(struct ref_transaction *transaction,
-			     const char *next, const char *end)
-{
-	struct strbuf err = STRBUF_INIT;
-	char *refname;
-	struct object_id new_oid;
-
-	refname = parse_refname(&next);
-	if (!refname)
-		die("create: missing <ref>");
-
-	if (parse_next_oid(&next, end, &new_oid, "create", refname, 0))
-		die("create %s: missing <newvalue>", refname);
-
-	if (is_null_oid(&new_oid))
-		die("create %s: zero <newvalue>", refname);
-
-	if (*next != line_termination)
-		die("create %s: extra input: %s", refname, next);
-
-	if (ref_transaction_create(transaction, refname, &new_oid,
-				   update_flags | create_reflog_flag,
-				   msg, &err))
-		die("%s", err.buf);
-
-	update_flags = default_flags;
-	free(refname);
-	strbuf_release(&err);
-}
-
-static void parse_cmd_delete(struct ref_transaction *transaction,
-			     const char *next, const char *end)
-{
-	struct strbuf err = STRBUF_INIT;
-	char *refname;
-	struct object_id old_oid;
-	int have_old;
-
-	refname = parse_refname(&next);
-	if (!refname)
-		die("delete: missing <ref>");
-
-	if (parse_next_oid(&next, end, &old_oid, "delete", refname,
-			   PARSE_SHA1_OLD)) {
-		have_old = 0;
-	} else {
-		if (is_null_oid(&old_oid))
-			die("delete %s: zero <oldvalue>", refname);
-		have_old = 1;
-	}
-
-	if (*next != line_termination)
-		die("delete %s: extra input: %s", refname, next);
-
-	if (ref_transaction_delete(transaction, refname,
-				   have_old ? &old_oid : NULL,
-				   update_flags, msg, &err))
-		die("%s", err.buf);
-
-	update_flags = default_flags;
-	free(refname);
-	strbuf_release(&err);
-}
-
-static void parse_cmd_verify(struct ref_transaction *transaction,
-			     const char *next, const char *end)
-{
-	struct strbuf err = STRBUF_INIT;
-	char *refname;
-	struct object_id old_oid;
-
-	refname = parse_refname(&next);
-	if (!refname)
-		die("verify: missing <ref>");
-
-	if (parse_next_oid(&next, end, &old_oid, "verify", refname,
-			   PARSE_SHA1_OLD))
-		oidclr(&old_oid);
-
-	if (*next != line_termination)
-		die("verify %s: extra input: %s", refname, next);
-
-	if (ref_transaction_verify(transaction, refname, &old_oid,
-				   update_flags, &err))
-		die("%s", err.buf);
-
-	update_flags = default_flags;
-	free(refname);
-	strbuf_release(&err);
-}
-
-static void parse_cmd_option(struct ref_transaction *transaction,
-			     const char *next, const char *end)
-{
-	const char *rest;
-	if (skip_prefix(next, "no-deref", &rest) && *rest == line_termination)
-		update_flags |= REF_NO_DEREF;
-	else
-		die("option unknown: %s", next);
-}
-
-static void parse_cmd_start(struct ref_transaction *transaction,
-			    const char *next, const char *end)
-{
-	if (*next != line_termination)
-		die("start: extra input: %s", next);
-	puts("start: ok");
-}
-
-static void parse_cmd_prepare(struct ref_transaction *transaction,
-			      const char *next, const char *end)
-{
-	struct strbuf error = STRBUF_INIT;
-	if (*next != line_termination)
-		die("prepare: extra input: %s", next);
-	if (ref_transaction_prepare(transaction, &error))
-		die("prepare: %s", error.buf);
-	puts("prepare: ok");
-}
-
-static void parse_cmd_abort(struct ref_transaction *transaction,
-			    const char *next, const char *end)
-{
-	struct strbuf error = STRBUF_INIT;
-	if (*next != line_termination)
-		die("abort: extra input: %s", next);
-	if (ref_transaction_abort(transaction, &error))
-		die("abort: %s", error.buf);
-	puts("abort: ok");
-}
-
-static void parse_cmd_commit(struct ref_transaction *transaction,
-			     const char *next, const char *end)
-{
-	struct strbuf error = STRBUF_INIT;
-	if (*next != line_termination)
-		die("commit: extra input: %s", next);
-	if (ref_transaction_commit(transaction, &error))
-		die("commit: %s", error.buf);
-	puts("commit: ok");
-	ref_transaction_free(transaction);
-}
-
-enum update_refs_state {
-	/* Non-transactional state open for updates. */
-	UPDATE_REFS_OPEN,
-	/* A transaction has been started. */
-	UPDATE_REFS_STARTED,
-	/* References are locked and ready for commit */
-	UPDATE_REFS_PREPARED,
-	/* Transaction has been committed or closed. */
-	UPDATE_REFS_CLOSED,
-};
-
-static const struct parse_cmd {
-	const char *prefix;
-	void (*fn)(struct ref_transaction *, const char *, const char *);
-	unsigned args;
-	enum update_refs_state state;
-} command[] = {
-	{ "update",  parse_cmd_update,  3, UPDATE_REFS_OPEN },
-	{ "create",  parse_cmd_create,  2, UPDATE_REFS_OPEN },
-	{ "delete",  parse_cmd_delete,  2, UPDATE_REFS_OPEN },
-	{ "verify",  parse_cmd_verify,  2, UPDATE_REFS_OPEN },
-	{ "option",  parse_cmd_option,  1, UPDATE_REFS_OPEN },
-	{ "start",   parse_cmd_start,   0, UPDATE_REFS_STARTED },
-	{ "prepare", parse_cmd_prepare, 0, UPDATE_REFS_PREPARED },
-	{ "abort",   parse_cmd_abort,   0, UPDATE_REFS_CLOSED },
-	{ "commit",  parse_cmd_commit,  0, UPDATE_REFS_CLOSED },
-};
-
-static void update_refs_stdin(void)
-{
-	struct strbuf input = STRBUF_INIT, err = STRBUF_INIT;
-	enum update_refs_state state = UPDATE_REFS_OPEN;
-	struct ref_transaction *transaction;
-	int i, j;
-
-	transaction = ref_transaction_begin(&err);
-	if (!transaction)
-		die("%s", err.buf);
-
-	/* Read each line dispatch its command */
-	while (!strbuf_getwholeline(&input, stdin, line_termination)) {
-		const struct parse_cmd *cmd = NULL;
-
-		if (*input.buf == line_termination)
-			die("empty command in input");
-		else if (isspace(*input.buf))
-			die("whitespace before command: %s", input.buf);
-
-		for (i = 0; i < ARRAY_SIZE(command); i++) {
-			const char *prefix = command[i].prefix;
-			char c;
-
-			if (!starts_with(input.buf, prefix))
-				continue;
-
-			/*
-			 * If the command has arguments, verify that it's
-			 * followed by a space. Otherwise, it shall be followed
-			 * by a line terminator.
-			 */
-			c = command[i].args ? ' ' : line_termination;
-			if (input.buf[strlen(prefix)] != c)
-				continue;
-
-			cmd = &command[i];
-			break;
-		}
-		if (!cmd)
-			die("unknown command: %s", input.buf);
-
-		/*
-		 * Read additional arguments if NUL-terminated. Do not raise an
-		 * error in case there is an early EOF to let the command
-		 * handle missing arguments with a proper error message.
-		 */
-		for (j = 1; line_termination == '\0' && j < cmd->args; j++)
-			if (strbuf_appendwholeline(&input, stdin, line_termination))
-				break;
-
-		switch (state) {
-		case UPDATE_REFS_OPEN:
-		case UPDATE_REFS_STARTED:
-			/* Do not downgrade a transaction to a non-transaction. */
-			if (cmd->state >= state)
-				state = cmd->state;
-			break;
-		case UPDATE_REFS_PREPARED:
-			if (cmd->state != UPDATE_REFS_CLOSED)
-				die("prepared transactions can only be closed");
-			state = cmd->state;
-			break;
-		case UPDATE_REFS_CLOSED:
-			die("transaction is closed");
-			break;
-		}
-
-		cmd->fn(transaction, input.buf + strlen(cmd->prefix) + !!cmd->args,
-			input.buf + input.len);
-	}
-
-	switch (state) {
-	case UPDATE_REFS_OPEN:
-		/* Commit by default if no transaction was requested. */
-		if (ref_transaction_commit(transaction, &err))
-			die("%s", err.buf);
-		ref_transaction_free(transaction);
-		break;
-	case UPDATE_REFS_STARTED:
-	case UPDATE_REFS_PREPARED:
-		/* If using a transaction, we want to abort it. */
-		if (ref_transaction_abort(transaction, &err))
-			die("%s", err.buf);
-		break;
-	case UPDATE_REFS_CLOSED:
-		/* Otherwise no need to do anything, the transaction was closed already. */
-		break;
-	}
-
-	strbuf_release(&err);
-	strbuf_release(&input);
-}
-
-int cmd_update_ref(int argc, const char **argv, const char *prefix)
-{
-	const char *refname, *oldval;
-	struct object_id oid, oldoid;
-	int delete = 0, no_deref = 0, read_stdin = 0, end_null = 0;
-	int create_reflog = 0;
-	struct option options[] = {
-		OPT_STRING( 'm', NULL, &msg, N_("reason"), N_("reason of the update")),
-		OPT_BOOL('d', NULL, &delete, N_("delete the reference")),
-		OPT_BOOL( 0 , "no-deref", &no_deref,
-					N_("update <refname> not the one it points to")),
-		OPT_BOOL('z', NULL, &end_null, N_("stdin has NUL-terminated arguments")),
-		OPT_BOOL( 0 , "stdin", &read_stdin, N_("read updates from stdin")),
-		OPT_BOOL( 0 , "create-reflog", &create_reflog, N_("create a reflog")),
-		OPT_END(),
-	};
-
-	git_config(git_default_config, NULL);
-	argc = parse_options(argc, argv, prefix, options, git_update_ref_usage,
-			     0);
-	if (msg && !*msg)
-		die("Refusing to perform update with empty message.");
-
-	create_reflog_flag = create_reflog ? REF_FORCE_CREATE_REFLOG : 0;
-
-	if (no_deref) {
-		default_flags = REF_NO_DEREF;
-		update_flags = default_flags;
-	}
-
-	if (read_stdin) {
-		if (delete || argc > 0)
-			usage_with_options(git_update_ref_usage, options);
-		if (end_null)
-			line_termination = '\0';
-		update_refs_stdin();
-		return 0;
-	}
-
-	if (end_null)
-		usage_with_options(git_update_ref_usage, options);
-
-	if (delete) {
-		if (argc < 1 || argc > 2)
-			usage_with_options(git_update_ref_usage, options);
-		refname = argv[0];
-		oldval = argv[1];
-	} else {
-		const char *value;
-		if (argc < 2 || argc > 3)
-			usage_with_options(git_update_ref_usage, options);
-		refname = argv[0];
-		value = argv[1];
-		oldval = argv[2];
-		if (get_oid(value, &oid))
-			die("%s: not a valid SHA1", value);
-	}
-
-	if (oldval) {
-		if (!*oldval)
-			/*
-			 * The empty string implies that the reference
-			 * must not already exist:
-			 */
-			oidclr(&oldoid);
-		else if (get_oid(oldval, &oldoid))
-			die("%s: not a valid old SHA1", oldval);
-	}
-
-	if (delete)
-		/*
-		 * For purposes of backwards compatibility, we treat
-		 * NULL_SHA1 as "don't care" here:
-		 */
-		return delete_ref(msg, refname,
-				  (oldval && !is_null_oid(&oldoid)) ? &oldoid : NULL,
-				  default_flags);
-	else
-		return update_ref(msg, refname, &oid, oldval ? &oldoid : NULL,
-				  default_flags | create_reflog_flag,
-				  UPDATE_REFS_DIE_ON_ERR);
-}
diff --git a/third_party/git/builtin/update-server-info.c b/third_party/git/builtin/update-server-info.c
deleted file mode 100644
index 4321a344567e..000000000000
--- a/third_party/git/builtin/update-server-info.c
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "cache.h"
-#include "config.h"
-#include "builtin.h"
-#include "parse-options.h"
-
-static const char * const update_server_info_usage[] = {
-	N_("git update-server-info [--force]"),
-	NULL
-};
-
-int cmd_update_server_info(int argc, const char **argv, const char *prefix)
-{
-	int force = 0;
-	struct option options[] = {
-		OPT__FORCE(&force, N_("update the info files from scratch"), 0),
-		OPT_END()
-	};
-
-	git_config(git_default_config, NULL);
-	argc = parse_options(argc, argv, prefix, options,
-			     update_server_info_usage, 0);
-	if (argc > 0)
-		usage_with_options(update_server_info_usage, options);
-
-	return !!update_server_info(force);
-}
diff --git a/third_party/git/builtin/upload-archive.c b/third_party/git/builtin/upload-archive.c
deleted file mode 100644
index 24654b4c9bf0..000000000000
--- a/third_party/git/builtin/upload-archive.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2006 Franck Bui-Huu
- */
-#include "cache.h"
-#include "builtin.h"
-#include "archive.h"
-#include "pkt-line.h"
-#include "sideband.h"
-#include "run-command.h"
-#include "strvec.h"
-
-static const char upload_archive_usage[] =
-	"git upload-archive <repo>";
-
-static const char deadchild[] =
-"git upload-archive: archiver died with error";
-
-#define MAX_ARGS (64)
-
-int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix)
-{
-	struct strvec sent_argv = STRVEC_INIT;
-	const char *arg_cmd = "argument ";
-
-	if (argc != 2 || !strcmp(argv[1], "-h"))
-		usage(upload_archive_usage);
-
-	if (!enter_repo(argv[1], 0))
-		die("'%s' does not appear to be a git repository", argv[1]);
-
-	init_archivers();
-
-	/* put received options in sent_argv[] */
-	strvec_push(&sent_argv, "git-upload-archive");
-	for (;;) {
-		char *buf = packet_read_line(0, NULL);
-		if (!buf)
-			break;	/* got a flush */
-		if (sent_argv.nr > MAX_ARGS)
-			die("Too many options (>%d)", MAX_ARGS - 1);
-
-		if (!starts_with(buf, arg_cmd))
-			die("'argument' token or flush expected");
-		strvec_push(&sent_argv, buf + strlen(arg_cmd));
-	}
-
-	/* parse all options sent by the client */
-	return write_archive(sent_argv.nr, sent_argv.v, prefix,
-			     the_repository, NULL, 1);
-}
-
-__attribute__((format (printf, 1, 2)))
-static void error_clnt(const char *fmt, ...)
-{
-	struct strbuf buf = STRBUF_INIT;
-	va_list params;
-
-	va_start(params, fmt);
-	strbuf_vaddf(&buf, fmt, params);
-	va_end(params);
-	send_sideband(1, 3, buf.buf, buf.len, LARGE_PACKET_MAX);
-	die("sent error to the client: %s", buf.buf);
-}
-
-static ssize_t process_input(int child_fd, int band)
-{
-	char buf[16384];
-	ssize_t sz = read(child_fd, buf, sizeof(buf));
-	if (sz < 0) {
-		if (errno != EAGAIN && errno != EINTR)
-			error_clnt("read error: %s\n", strerror(errno));
-		return sz;
-	}
-	send_sideband(1, band, buf, sz, LARGE_PACKET_MAX);
-	return sz;
-}
-
-int cmd_upload_archive(int argc, const char **argv, const char *prefix)
-{
-	struct child_process writer = { argv };
-
-	if (argc == 2 && !strcmp(argv[1], "-h"))
-		usage(upload_archive_usage);
-
-	/*
-	 * Set up sideband subprocess.
-	 *
-	 * We (parent) monitor and read from child, sending its fd#1 and fd#2
-	 * multiplexed out to our fd#1.  If the child dies, we tell the other
-	 * end over channel #3.
-	 */
-	argv[0] = "upload-archive--writer";
-	writer.out = writer.err = -1;
-	writer.git_cmd = 1;
-	if (start_command(&writer)) {
-		int err = errno;
-		packet_write_fmt(1, "NACK unable to spawn subprocess\n");
-		die("upload-archive: %s", strerror(err));
-	}
-
-	packet_write_fmt(1, "ACK\n");
-	packet_flush(1);
-
-	while (1) {
-		struct pollfd pfd[2];
-
-		pfd[0].fd = writer.out;
-		pfd[0].events = POLLIN;
-		pfd[1].fd = writer.err;
-		pfd[1].events = POLLIN;
-		if (poll(pfd, 2, -1) < 0) {
-			if (errno != EINTR) {
-				error_errno("poll failed resuming");
-				sleep(1);
-			}
-			continue;
-		}
-		if (pfd[1].revents & POLLIN)
-			/* Status stream ready */
-			if (process_input(pfd[1].fd, 2))
-				continue;
-		if (pfd[0].revents & POLLIN)
-			/* Data stream ready */
-			if (process_input(pfd[0].fd, 1))
-				continue;
-
-		if (finish_command(&writer))
-			error_clnt("%s", deadchild);
-		packet_flush(1);
-		break;
-	}
-	return 0;
-}
diff --git a/third_party/git/builtin/upload-pack.c b/third_party/git/builtin/upload-pack.c
deleted file mode 100644
index 6da8fa2607c6..000000000000
--- a/third_party/git/builtin/upload-pack.c
+++ /dev/null
@@ -1,74 +0,0 @@
-#include "cache.h"
-#include "builtin.h"
-#include "exec-cmd.h"
-#include "pkt-line.h"
-#include "parse-options.h"
-#include "protocol.h"
-#include "upload-pack.h"
-#include "serve.h"
-
-static const char * const upload_pack_usage[] = {
-	N_("git upload-pack [<options>] <dir>"),
-	NULL
-};
-
-int cmd_upload_pack(int argc, const char **argv, const char *prefix)
-{
-	const char *dir;
-	int strict = 0;
-	struct upload_pack_options opts = { 0 };
-	struct serve_options serve_opts = SERVE_OPTIONS_INIT;
-	struct option options[] = {
-		OPT_BOOL(0, "stateless-rpc", &opts.stateless_rpc,
-			 N_("quit after a single request/response exchange")),
-		OPT_BOOL(0, "advertise-refs", &opts.advertise_refs,
-			 N_("exit immediately after initial ref advertisement")),
-		OPT_BOOL(0, "strict", &strict,
-			 N_("do not try <directory>/.git/ if <directory> is no Git directory")),
-		OPT_INTEGER(0, "timeout", &opts.timeout,
-			    N_("interrupt transfer after <n> seconds of inactivity")),
-		OPT_END()
-	};
-
-	packet_trace_identity("upload-pack");
-	read_replace_refs = 0;
-
-	argc = parse_options(argc, argv, prefix, options, upload_pack_usage, 0);
-
-	if (argc != 1)
-		usage_with_options(upload_pack_usage, options);
-
-	if (opts.timeout)
-		opts.daemon_mode = 1;
-
-	setup_path();
-
-	dir = argv[0];
-
-	if (!enter_repo(dir, strict))
-		die("'%s' does not appear to be a git repository", dir);
-
-	switch (determine_protocol_version_server()) {
-	case protocol_v2:
-		serve_opts.advertise_capabilities = opts.advertise_refs;
-		serve_opts.stateless_rpc = opts.stateless_rpc;
-		serve(&serve_opts);
-		break;
-	case protocol_v1:
-		/*
-		 * v1 is just the original protocol with a version string,
-		 * so just fall through after writing the version string.
-		 */
-		if (opts.advertise_refs || !opts.stateless_rpc)
-			packet_write_fmt(1, "version 1\n");
-
-		/* fallthrough */
-	case protocol_v0:
-		upload_pack(&opts);
-		break;
-	case protocol_unknown_version:
-		BUG("unknown protocol version");
-	}
-
-	return 0;
-}
diff --git a/third_party/git/builtin/var.c b/third_party/git/builtin/var.c
deleted file mode 100644
index 6c6f46b4aeaf..000000000000
--- a/third_party/git/builtin/var.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * GIT - The information manager from hell
- *
- * Copyright (C) Eric Biederman, 2005
- */
-#include "builtin.h"
-#include "config.h"
-
-static const char var_usage[] = "git var (-l | <variable>)";
-
-static const char *editor(int flag)
-{
-	const char *pgm = git_editor();
-
-	if (!pgm && flag & IDENT_STRICT)
-		die("Terminal is dumb, but EDITOR unset");
-
-	return pgm;
-}
-
-static const char *pager(int flag)
-{
-	const char *pgm = git_pager(1);
-
-	if (!pgm)
-		pgm = "cat";
-	return pgm;
-}
-
-struct git_var {
-	const char *name;
-	const char *(*read)(int);
-};
-static struct git_var git_vars[] = {
-	{ "GIT_COMMITTER_IDENT", git_committer_info },
-	{ "GIT_AUTHOR_IDENT",   git_author_info },
-	{ "GIT_EDITOR", editor },
-	{ "GIT_PAGER", pager },
-	{ "", NULL },
-};
-
-static void list_vars(void)
-{
-	struct git_var *ptr;
-	const char *val;
-
-	for (ptr = git_vars; ptr->read; ptr++)
-		if ((val = ptr->read(0)))
-			printf("%s=%s\n", ptr->name, val);
-}
-
-static const char *read_var(const char *var)
-{
-	struct git_var *ptr;
-	const char *val;
-	val = NULL;
-	for (ptr = git_vars; ptr->read; ptr++) {
-		if (strcmp(var, ptr->name) == 0) {
-			val = ptr->read(IDENT_STRICT);
-			break;
-		}
-	}
-	return val;
-}
-
-static int show_config(const char *var, const char *value, void *cb)
-{
-	if (value)
-		printf("%s=%s\n", var, value);
-	else
-		printf("%s\n", var);
-	return git_default_config(var, value, cb);
-}
-
-int cmd_var(int argc, const char **argv, const char *prefix)
-{
-	const char *val = NULL;
-	if (argc != 2)
-		usage(var_usage);
-
-	if (strcmp(argv[1], "-l") == 0) {
-		git_config(show_config, NULL);
-		list_vars();
-		return 0;
-	}
-	git_config(git_default_config, NULL);
-	val = read_var(argv[1]);
-	if (!val)
-		usage(var_usage);
-
-	printf("%s\n", val);
-
-	return 0;
-}
diff --git a/third_party/git/builtin/verify-commit.c b/third_party/git/builtin/verify-commit.c
deleted file mode 100644
index 40c69a0bedde..000000000000
--- a/third_party/git/builtin/verify-commit.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Builtin "git commit-commit"
- *
- * Copyright (c) 2014 Michael J Gruber <git@drmicha.warpmail.net>
- *
- * Based on git-verify-tag
- */
-#include "cache.h"
-#include "config.h"
-#include "builtin.h"
-#include "object-store.h"
-#include "repository.h"
-#include "commit.h"
-#include "run-command.h"
-#include "parse-options.h"
-#include "gpg-interface.h"
-
-static const char * const verify_commit_usage[] = {
-		N_("git verify-commit [-v | --verbose] <commit>..."),
-		NULL
-};
-
-static int run_gpg_verify(struct commit *commit, unsigned flags)
-{
-	struct signature_check signature_check;
-	int ret;
-
-	memset(&signature_check, 0, sizeof(signature_check));
-
-	ret = check_commit_signature(commit, &signature_check);
-	print_signature_buffer(&signature_check, flags);
-
-	signature_check_clear(&signature_check);
-	return ret;
-}
-
-static int verify_commit(const char *name, unsigned flags)
-{
-	struct object_id oid;
-	struct object *obj;
-
-	if (get_oid(name, &oid))
-		return error("commit '%s' not found.", name);
-
-	obj = parse_object(the_repository, &oid);
-	if (!obj)
-		return error("%s: unable to read file.", name);
-	if (obj->type != OBJ_COMMIT)
-		return error("%s: cannot verify a non-commit object of type %s.",
-				name, type_name(obj->type));
-
-	return run_gpg_verify((struct commit *)obj, flags);
-}
-
-static int git_verify_commit_config(const char *var, const char *value, void *cb)
-{
-	int status = git_gpg_config(var, value, cb);
-	if (status)
-		return status;
-	return git_default_config(var, value, cb);
-}
-
-int cmd_verify_commit(int argc, const char **argv, const char *prefix)
-{
-	int i = 1, verbose = 0, had_error = 0;
-	unsigned flags = 0;
-	const struct option verify_commit_options[] = {
-		OPT__VERBOSE(&verbose, N_("print commit contents")),
-		OPT_BIT(0, "raw", &flags, N_("print raw gpg status output"), GPG_VERIFY_RAW),
-		OPT_END()
-	};
-
-	git_config(git_verify_commit_config, NULL);
-
-	argc = parse_options(argc, argv, prefix, verify_commit_options,
-			     verify_commit_usage, PARSE_OPT_KEEP_ARGV0);
-	if (argc <= i)
-		usage_with_options(verify_commit_usage, verify_commit_options);
-
-	if (verbose)
-		flags |= GPG_VERIFY_VERBOSE;
-
-	/* sometimes the program was terminated because this signal
-	 * was received in the process of writing the gpg input: */
-	signal(SIGPIPE, SIG_IGN);
-	while (i < argc)
-		if (verify_commit(argv[i++], flags))
-			had_error = 1;
-	return had_error;
-}
diff --git a/third_party/git/builtin/verify-pack.c b/third_party/git/builtin/verify-pack.c
deleted file mode 100644
index 05c52135946b..000000000000
--- a/third_party/git/builtin/verify-pack.c
+++ /dev/null
@@ -1,90 +0,0 @@
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "run-command.h"
-#include "parse-options.h"
-
-#define VERIFY_PACK_VERBOSE 01
-#define VERIFY_PACK_STAT_ONLY 02
-
-static int verify_one_pack(const char *path, unsigned int flags, const char *hash_algo)
-{
-	struct child_process index_pack = CHILD_PROCESS_INIT;
-	struct strvec *argv = &index_pack.args;
-	struct strbuf arg = STRBUF_INIT;
-	int verbose = flags & VERIFY_PACK_VERBOSE;
-	int stat_only = flags & VERIFY_PACK_STAT_ONLY;
-	int err;
-
-	strvec_push(argv, "index-pack");
-
-	if (stat_only)
-		strvec_push(argv, "--verify-stat-only");
-	else if (verbose)
-		strvec_push(argv, "--verify-stat");
-	else
-		strvec_push(argv, "--verify");
-
-	if (hash_algo)
-		strvec_pushf(argv, "--object-format=%s", hash_algo);
-
-	/*
-	 * In addition to "foo.pack" we accept "foo.idx" and "foo";
-	 * normalize these forms to "foo.pack" for "index-pack --verify".
-	 */
-	strbuf_addstr(&arg, path);
-	if (strbuf_strip_suffix(&arg, ".idx") ||
-	    !ends_with(arg.buf, ".pack"))
-		strbuf_addstr(&arg, ".pack");
-	strvec_push(argv, arg.buf);
-
-	index_pack.git_cmd = 1;
-
-	err = run_command(&index_pack);
-
-	if (verbose || stat_only) {
-		if (err)
-			printf("%s: bad\n", arg.buf);
-		else {
-			if (!stat_only)
-				printf("%s: ok\n", arg.buf);
-		}
-	}
-	strbuf_release(&arg);
-
-	return err;
-}
-
-static const char * const verify_pack_usage[] = {
-	N_("git verify-pack [-v | --verbose] [-s | --stat-only] <pack>..."),
-	NULL
-};
-
-int cmd_verify_pack(int argc, const char **argv, const char *prefix)
-{
-	int err = 0;
-	unsigned int flags = 0;
-	const char *object_format = NULL;
-	int i;
-	const struct option verify_pack_options[] = {
-		OPT_BIT('v', "verbose", &flags, N_("verbose"),
-			VERIFY_PACK_VERBOSE),
-		OPT_BIT('s', "stat-only", &flags, N_("show statistics only"),
-			VERIFY_PACK_STAT_ONLY),
-		OPT_STRING(0, "object-format", &object_format, N_("hash"),
-			   N_("specify the hash algorithm to use")),
-		OPT_END()
-	};
-
-	git_config(git_default_config, NULL);
-	argc = parse_options(argc, argv, prefix, verify_pack_options,
-			     verify_pack_usage, 0);
-	if (argc < 1)
-		usage_with_options(verify_pack_usage, verify_pack_options);
-	for (i = 0; i < argc; i++) {
-		if (verify_one_pack(argv[i], flags, object_format))
-			err = 1;
-	}
-
-	return err;
-}
diff --git a/third_party/git/builtin/verify-tag.c b/third_party/git/builtin/verify-tag.c
deleted file mode 100644
index f45136a06ba7..000000000000
--- a/third_party/git/builtin/verify-tag.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Builtin "git verify-tag"
- *
- * Copyright (c) 2007 Carlos Rica <jasampler@gmail.com>
- *
- * Based on git-verify-tag.sh
- */
-#include "cache.h"
-#include "config.h"
-#include "builtin.h"
-#include "tag.h"
-#include "run-command.h"
-#include "parse-options.h"
-#include "gpg-interface.h"
-#include "ref-filter.h"
-
-static const char * const verify_tag_usage[] = {
-		N_("git verify-tag [-v | --verbose] [--format=<format>] <tag>..."),
-		NULL
-};
-
-static int git_verify_tag_config(const char *var, const char *value, void *cb)
-{
-	int status = git_gpg_config(var, value, cb);
-	if (status)
-		return status;
-	return git_default_config(var, value, cb);
-}
-
-int cmd_verify_tag(int argc, const char **argv, const char *prefix)
-{
-	int i = 1, verbose = 0, had_error = 0;
-	unsigned flags = 0;
-	struct ref_format format = REF_FORMAT_INIT;
-	const struct option verify_tag_options[] = {
-		OPT__VERBOSE(&verbose, N_("print tag contents")),
-		OPT_BIT(0, "raw", &flags, N_("print raw gpg status output"), GPG_VERIFY_RAW),
-		OPT_STRING(0, "format", &format.format, N_("format"), N_("format to use for the output")),
-		OPT_END()
-	};
-
-	git_config(git_verify_tag_config, NULL);
-
-	argc = parse_options(argc, argv, prefix, verify_tag_options,
-			     verify_tag_usage, PARSE_OPT_KEEP_ARGV0);
-	if (argc <= i)
-		usage_with_options(verify_tag_usage, verify_tag_options);
-
-	if (verbose)
-		flags |= GPG_VERIFY_VERBOSE;
-
-	if (format.format) {
-		if (verify_ref_format(&format))
-			usage_with_options(verify_tag_usage,
-					   verify_tag_options);
-		flags |= GPG_VERIFY_OMIT_STATUS;
-	}
-
-	while (i < argc) {
-		struct object_id oid;
-		const char *name = argv[i++];
-
-		if (get_oid(name, &oid)) {
-			had_error = !!error("tag '%s' not found.", name);
-			continue;
-		}
-
-		if (gpg_verify_tag(&oid, name, flags)) {
-			had_error = 1;
-			continue;
-		}
-
-		if (format.format)
-			pretty_print_ref(name, &oid, &format);
-	}
-	return had_error;
-}
diff --git a/third_party/git/builtin/worktree.c b/third_party/git/builtin/worktree.c
deleted file mode 100644
index 99abaeec6c6e..000000000000
--- a/third_party/git/builtin/worktree.c
+++ /dev/null
@@ -1,1088 +0,0 @@
-#include "cache.h"
-#include "checkout.h"
-#include "config.h"
-#include "builtin.h"
-#include "dir.h"
-#include "parse-options.h"
-#include "strvec.h"
-#include "branch.h"
-#include "refs.h"
-#include "run-command.h"
-#include "sigchain.h"
-#include "submodule.h"
-#include "utf8.h"
-#include "worktree.h"
-
-static const char * const worktree_usage[] = {
-	N_("git worktree add [<options>] <path> [<commit-ish>]"),
-	N_("git worktree list [<options>]"),
-	N_("git worktree lock [<options>] <path>"),
-	N_("git worktree move <worktree> <new-path>"),
-	N_("git worktree prune [<options>]"),
-	N_("git worktree remove [<options>] <worktree>"),
-	N_("git worktree unlock <path>"),
-	NULL
-};
-
-struct add_opts {
-	int force;
-	int detach;
-	int quiet;
-	int checkout;
-	int keep_locked;
-};
-
-static int show_only;
-static int verbose;
-static int guess_remote;
-static timestamp_t expire;
-
-static int git_worktree_config(const char *var, const char *value, void *cb)
-{
-	if (!strcmp(var, "worktree.guessremote")) {
-		guess_remote = git_config_bool(var, value);
-		return 0;
-	}
-
-	return git_default_config(var, value, cb);
-}
-
-static int delete_git_dir(const char *id)
-{
-	struct strbuf sb = STRBUF_INIT;
-	int ret;
-
-	strbuf_addstr(&sb, git_common_path("worktrees/%s", id));
-	ret = remove_dir_recursively(&sb, 0);
-	if (ret < 0 && errno == ENOTDIR)
-		ret = unlink(sb.buf);
-	if (ret)
-		error_errno(_("failed to delete '%s'"), sb.buf);
-	strbuf_release(&sb);
-	return ret;
-}
-
-static void delete_worktrees_dir_if_empty(void)
-{
-	rmdir(git_path("worktrees")); /* ignore failed removal */
-}
-
-/*
- * Return true if worktree entry should be pruned, along with the reason for
- * pruning. Otherwise, return false and the worktree's path, or NULL if it
- * cannot be determined. Caller is responsible for freeing returned path.
- */
-static int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath)
-{
-	struct stat st;
-	char *path;
-	int fd;
-	size_t len;
-	ssize_t read_result;
-
-	*wtpath = NULL;
-	if (!is_directory(git_path("worktrees/%s", id))) {
-		strbuf_addstr(reason, _("not a valid directory"));
-		return 1;
-	}
-	if (file_exists(git_path("worktrees/%s/locked", id)))
-		return 0;
-	if (stat(git_path("worktrees/%s/gitdir", id), &st)) {
-		strbuf_addstr(reason, _("gitdir file does not exist"));
-		return 1;
-	}
-	fd = open(git_path("worktrees/%s/gitdir", id), O_RDONLY);
-	if (fd < 0) {
-		strbuf_addf(reason, _("unable to read gitdir file (%s)"),
-			    strerror(errno));
-		return 1;
-	}
-	len = xsize_t(st.st_size);
-	path = xmallocz(len);
-
-	read_result = read_in_full(fd, path, len);
-	if (read_result < 0) {
-		strbuf_addf(reason, _("unable to read gitdir file (%s)"),
-			    strerror(errno));
-		close(fd);
-		free(path);
-		return 1;
-	}
-	close(fd);
-
-	if (read_result != len) {
-		strbuf_addf(reason,
-			    _("short read (expected %"PRIuMAX" bytes, read %"PRIuMAX")"),
-			    (uintmax_t)len, (uintmax_t)read_result);
-		free(path);
-		return 1;
-	}
-	while (len && (path[len - 1] == '\n' || path[len - 1] == '\r'))
-		len--;
-	if (!len) {
-		strbuf_addstr(reason, _("invalid gitdir file"));
-		free(path);
-		return 1;
-	}
-	path[len] = '\0';
-	if (!file_exists(path)) {
-		if (stat(git_path("worktrees/%s/index", id), &st) ||
-		    st.st_mtime <= expire) {
-			strbuf_addstr(reason, _("gitdir file points to non-existent location"));
-			free(path);
-			return 1;
-		} else {
-			*wtpath = path;
-			return 0;
-		}
-	}
-	*wtpath = path;
-	return 0;
-}
-
-static void prune_worktree(const char *id, const char *reason)
-{
-	if (show_only || verbose)
-		printf_ln(_("Removing %s/%s: %s"), "worktrees", id, reason);
-	if (!show_only)
-		delete_git_dir(id);
-}
-
-static int prune_cmp(const void *a, const void *b)
-{
-	const struct string_list_item *x = a;
-	const struct string_list_item *y = b;
-	int c;
-
-	if ((c = fspathcmp(x->string, y->string)))
-	    return c;
-	/*
-	 * paths same; prune_dupes() removes all but the first worktree entry
-	 * having the same path, so sort main worktree ('util' is NULL) above
-	 * linked worktrees ('util' not NULL) since main worktree can't be
-	 * removed
-	 */
-	if (!x->util)
-		return -1;
-	if (!y->util)
-		return 1;
-	/* paths same; sort by .git/worktrees/<id> */
-	return strcmp(x->util, y->util);
-}
-
-static void prune_dups(struct string_list *l)
-{
-	int i;
-
-	QSORT(l->items, l->nr, prune_cmp);
-	for (i = 1; i < l->nr; i++) {
-		if (!fspathcmp(l->items[i].string, l->items[i - 1].string))
-			prune_worktree(l->items[i].util, "duplicate entry");
-	}
-}
-
-static void prune_worktrees(void)
-{
-	struct strbuf reason = STRBUF_INIT;
-	struct strbuf main_path = STRBUF_INIT;
-	struct string_list kept = STRING_LIST_INIT_NODUP;
-	DIR *dir = opendir(git_path("worktrees"));
-	struct dirent *d;
-	if (!dir)
-		return;
-	while ((d = readdir(dir)) != NULL) {
-		char *path;
-		if (is_dot_or_dotdot(d->d_name))
-			continue;
-		strbuf_reset(&reason);
-		if (should_prune_worktree(d->d_name, &reason, &path))
-			prune_worktree(d->d_name, reason.buf);
-		else if (path)
-			string_list_append(&kept, path)->util = xstrdup(d->d_name);
-	}
-	closedir(dir);
-
-	strbuf_add_absolute_path(&main_path, get_git_common_dir());
-	/* massage main worktree absolute path to match 'gitdir' content */
-	strbuf_strip_suffix(&main_path, "/.");
-	string_list_append(&kept, strbuf_detach(&main_path, NULL));
-	prune_dups(&kept);
-	string_list_clear(&kept, 1);
-
-	if (!show_only)
-		delete_worktrees_dir_if_empty();
-	strbuf_release(&reason);
-}
-
-static int prune(int ac, const char **av, const char *prefix)
-{
-	struct option options[] = {
-		OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
-		OPT__VERBOSE(&verbose, N_("report pruned working trees")),
-		OPT_EXPIRY_DATE(0, "expire", &expire,
-				N_("expire working trees older than <time>")),
-		OPT_END()
-	};
-
-	expire = TIME_MAX;
-	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
-	if (ac)
-		usage_with_options(worktree_usage, options);
-	prune_worktrees();
-	return 0;
-}
-
-static char *junk_work_tree;
-static char *junk_git_dir;
-static int is_junk;
-static pid_t junk_pid;
-
-static void remove_junk(void)
-{
-	struct strbuf sb = STRBUF_INIT;
-	if (!is_junk || getpid() != junk_pid)
-		return;
-	if (junk_git_dir) {
-		strbuf_addstr(&sb, junk_git_dir);
-		remove_dir_recursively(&sb, 0);
-		strbuf_reset(&sb);
-	}
-	if (junk_work_tree) {
-		strbuf_addstr(&sb, junk_work_tree);
-		remove_dir_recursively(&sb, 0);
-	}
-	strbuf_release(&sb);
-}
-
-static void remove_junk_on_signal(int signo)
-{
-	remove_junk();
-	sigchain_pop(signo);
-	raise(signo);
-}
-
-static const char *worktree_basename(const char *path, int *olen)
-{
-	const char *name;
-	int len;
-
-	len = strlen(path);
-	while (len && is_dir_sep(path[len - 1]))
-		len--;
-
-	for (name = path + len - 1; name > path; name--)
-		if (is_dir_sep(*name)) {
-			name++;
-			break;
-		}
-
-	*olen = len;
-	return name;
-}
-
-/* check that path is viable location for worktree */
-static void check_candidate_path(const char *path,
-				 int force,
-				 struct worktree **worktrees,
-				 const char *cmd)
-{
-	struct worktree *wt;
-	int locked;
-
-	if (file_exists(path) && !is_empty_dir(path))
-		die(_("'%s' already exists"), path);
-
-	wt = find_worktree_by_path(worktrees, path);
-	if (!wt)
-		return;
-
-	locked = !!worktree_lock_reason(wt);
-	if ((!locked && force) || (locked && force > 1)) {
-		if (delete_git_dir(wt->id))
-		    die(_("unusable worktree destination '%s'"), path);
-		return;
-	}
-
-	if (locked)
-		die(_("'%s' is a missing but locked worktree;\nuse '%s -f -f' to override, or 'unlock' and 'prune' or 'remove' to clear"), cmd, path);
-	else
-		die(_("'%s' is a missing but already registered worktree;\nuse '%s -f' to override, or 'prune' or 'remove' to clear"), cmd, path);
-}
-
-static int add_worktree(const char *path, const char *refname,
-			const struct add_opts *opts)
-{
-	struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT;
-	struct strbuf sb = STRBUF_INIT, realpath = STRBUF_INIT;
-	const char *name;
-	struct child_process cp = CHILD_PROCESS_INIT;
-	struct strvec child_env = STRVEC_INIT;
-	unsigned int counter = 0;
-	int len, ret;
-	struct strbuf symref = STRBUF_INIT;
-	struct commit *commit = NULL;
-	int is_branch = 0;
-	struct strbuf sb_name = STRBUF_INIT;
-	struct worktree **worktrees;
-
-	worktrees = get_worktrees();
-	check_candidate_path(path, opts->force, worktrees, "add");
-	free_worktrees(worktrees);
-	worktrees = NULL;
-
-	/* is 'refname' a branch or commit? */
-	if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) &&
-	    ref_exists(symref.buf)) {
-		is_branch = 1;
-		if (!opts->force)
-			die_if_checked_out(symref.buf, 0);
-	}
-	commit = lookup_commit_reference_by_name(refname);
-	if (!commit)
-		die(_("invalid reference: %s"), refname);
-
-	name = worktree_basename(path, &len);
-	strbuf_add(&sb, name, path + len - name);
-	sanitize_refname_component(sb.buf, &sb_name);
-	if (!sb_name.len)
-		BUG("How come '%s' becomes empty after sanitization?", sb.buf);
-	strbuf_reset(&sb);
-	name = sb_name.buf;
-	git_path_buf(&sb_repo, "worktrees/%s", name);
-	len = sb_repo.len;
-	if (safe_create_leading_directories_const(sb_repo.buf))
-		die_errno(_("could not create leading directories of '%s'"),
-			  sb_repo.buf);
-
-	while (mkdir(sb_repo.buf, 0777)) {
-		counter++;
-		if ((errno != EEXIST) || !counter /* overflow */)
-			die_errno(_("could not create directory of '%s'"),
-				  sb_repo.buf);
-		strbuf_setlen(&sb_repo, len);
-		strbuf_addf(&sb_repo, "%d", counter);
-	}
-	name = strrchr(sb_repo.buf, '/') + 1;
-
-	junk_pid = getpid();
-	atexit(remove_junk);
-	sigchain_push_common(remove_junk_on_signal);
-
-	junk_git_dir = xstrdup(sb_repo.buf);
-	is_junk = 1;
-
-	/*
-	 * lock the incomplete repo so prune won't delete it, unlock
-	 * after the preparation is over.
-	 */
-	strbuf_addf(&sb, "%s/locked", sb_repo.buf);
-	if (!opts->keep_locked)
-		write_file(sb.buf, "initializing");
-	else
-		write_file(sb.buf, "added with --lock");
-
-	strbuf_addf(&sb_git, "%s/.git", path);
-	if (safe_create_leading_directories_const(sb_git.buf))
-		die_errno(_("could not create leading directories of '%s'"),
-			  sb_git.buf);
-	junk_work_tree = xstrdup(path);
-
-	strbuf_reset(&sb);
-	strbuf_addf(&sb, "%s/gitdir", sb_repo.buf);
-	strbuf_realpath(&realpath, sb_git.buf, 1);
-	write_file(sb.buf, "%s", realpath.buf);
-	strbuf_realpath(&realpath, get_git_common_dir(), 1);
-	write_file(sb_git.buf, "gitdir: %s/worktrees/%s",
-		   realpath.buf, name);
-	/*
-	 * This is to keep resolve_ref() happy. We need a valid HEAD
-	 * or is_git_directory() will reject the directory. Any value which
-	 * looks like an object ID will do since it will be immediately
-	 * replaced by the symbolic-ref or update-ref invocation in the new
-	 * worktree.
-	 */
-	strbuf_reset(&sb);
-	strbuf_addf(&sb, "%s/HEAD", sb_repo.buf);
-	write_file(sb.buf, "%s", oid_to_hex(&null_oid));
-	strbuf_reset(&sb);
-	strbuf_addf(&sb, "%s/commondir", sb_repo.buf);
-	write_file(sb.buf, "../..");
-
-	strvec_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf);
-	strvec_pushf(&child_env, "%s=%s", GIT_WORK_TREE_ENVIRONMENT, path);
-	cp.git_cmd = 1;
-
-	if (!is_branch)
-		strvec_pushl(&cp.args, "update-ref", "HEAD",
-			     oid_to_hex(&commit->object.oid), NULL);
-	else {
-		strvec_pushl(&cp.args, "symbolic-ref", "HEAD",
-			     symref.buf, NULL);
-		if (opts->quiet)
-			strvec_push(&cp.args, "--quiet");
-	}
-
-	cp.env = child_env.v;
-	ret = run_command(&cp);
-	if (ret)
-		goto done;
-
-	if (opts->checkout) {
-		cp.argv = NULL;
-		strvec_clear(&cp.args);
-		strvec_pushl(&cp.args, "reset", "--hard", "--no-recurse-submodules", NULL);
-		if (opts->quiet)
-			strvec_push(&cp.args, "--quiet");
-		cp.env = child_env.v;
-		ret = run_command(&cp);
-		if (ret)
-			goto done;
-	}
-
-	is_junk = 0;
-	FREE_AND_NULL(junk_work_tree);
-	FREE_AND_NULL(junk_git_dir);
-
-done:
-	if (ret || !opts->keep_locked) {
-		strbuf_reset(&sb);
-		strbuf_addf(&sb, "%s/locked", sb_repo.buf);
-		unlink_or_warn(sb.buf);
-	}
-
-	/*
-	 * Hook failure does not warrant worktree deletion, so run hook after
-	 * is_junk is cleared, but do return appropriate code when hook fails.
-	 */
-	if (!ret && opts->checkout) {
-		const char *hook = find_hook("post-checkout");
-		if (hook) {
-			const char *env[] = { "GIT_DIR", "GIT_WORK_TREE", NULL };
-			cp.git_cmd = 0;
-			cp.no_stdin = 1;
-			cp.stdout_to_stderr = 1;
-			cp.dir = path;
-			cp.env = env;
-			cp.argv = NULL;
-			cp.trace2_hook_name = "post-checkout";
-			strvec_pushl(&cp.args, absolute_path(hook),
-				     oid_to_hex(&null_oid),
-				     oid_to_hex(&commit->object.oid),
-				     "1", NULL);
-			ret = run_command(&cp);
-		}
-	}
-
-	strvec_clear(&child_env);
-	strbuf_release(&sb);
-	strbuf_release(&symref);
-	strbuf_release(&sb_repo);
-	strbuf_release(&sb_git);
-	strbuf_release(&sb_name);
-	strbuf_release(&realpath);
-	return ret;
-}
-
-static void print_preparing_worktree_line(int detach,
-					  const char *branch,
-					  const char *new_branch,
-					  int force_new_branch)
-{
-	if (force_new_branch) {
-		struct commit *commit = lookup_commit_reference_by_name(new_branch);
-		if (!commit)
-			printf_ln(_("Preparing worktree (new branch '%s')"), new_branch);
-		else
-			printf_ln(_("Preparing worktree (resetting branch '%s'; was at %s)"),
-				  new_branch,
-				  find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV));
-	} else if (new_branch) {
-		printf_ln(_("Preparing worktree (new branch '%s')"), new_branch);
-	} else {
-		struct strbuf s = STRBUF_INIT;
-		if (!detach && !strbuf_check_branch_ref(&s, branch) &&
-		    ref_exists(s.buf))
-			printf_ln(_("Preparing worktree (checking out '%s')"),
-				  branch);
-		else {
-			struct commit *commit = lookup_commit_reference_by_name(branch);
-			if (!commit)
-				die(_("invalid reference: %s"), branch);
-			printf_ln(_("Preparing worktree (detached HEAD %s)"),
-				  find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV));
-		}
-		strbuf_release(&s);
-	}
-}
-
-static const char *dwim_branch(const char *path, const char **new_branch)
-{
-	int n;
-	const char *s = worktree_basename(path, &n);
-	const char *branchname = xstrndup(s, n);
-	struct strbuf ref = STRBUF_INIT;
-
-	UNLEAK(branchname);
-	if (!strbuf_check_branch_ref(&ref, branchname) &&
-	    ref_exists(ref.buf)) {
-		strbuf_release(&ref);
-		return branchname;
-	}
-
-	*new_branch = branchname;
-	if (guess_remote) {
-		struct object_id oid;
-		const char *remote =
-			unique_tracking_name(*new_branch, &oid, NULL);
-		return remote;
-	}
-	return NULL;
-}
-
-static int add(int ac, const char **av, const char *prefix)
-{
-	struct add_opts opts;
-	const char *new_branch_force = NULL;
-	char *path;
-	const char *branch;
-	const char *new_branch = NULL;
-	const char *opt_track = NULL;
-	struct option options[] = {
-		OPT__FORCE(&opts.force,
-			   N_("checkout <branch> even if already checked out in other worktree"),
-			   PARSE_OPT_NOCOMPLETE),
-		OPT_STRING('b', NULL, &new_branch, N_("branch"),
-			   N_("create a new branch")),
-		OPT_STRING('B', NULL, &new_branch_force, N_("branch"),
-			   N_("create or reset a branch")),
-		OPT_BOOL('d', "detach", &opts.detach, N_("detach HEAD at named commit")),
-		OPT_BOOL(0, "checkout", &opts.checkout, N_("populate the new working tree")),
-		OPT_BOOL(0, "lock", &opts.keep_locked, N_("keep the new working tree locked")),
-		OPT__QUIET(&opts.quiet, N_("suppress progress reporting")),
-		OPT_PASSTHRU(0, "track", &opt_track, NULL,
-			     N_("set up tracking mode (see git-branch(1))"),
-			     PARSE_OPT_NOARG | PARSE_OPT_OPTARG),
-		OPT_BOOL(0, "guess-remote", &guess_remote,
-			 N_("try to match the new branch name with a remote-tracking branch")),
-		OPT_END()
-	};
-
-	memset(&opts, 0, sizeof(opts));
-	opts.checkout = 1;
-	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
-	if (!!opts.detach + !!new_branch + !!new_branch_force > 1)
-		die(_("-b, -B, and --detach are mutually exclusive"));
-	if (ac < 1 || ac > 2)
-		usage_with_options(worktree_usage, options);
-
-	path = prefix_filename(prefix, av[0]);
-	branch = ac < 2 ? "HEAD" : av[1];
-
-	if (!strcmp(branch, "-"))
-		branch = "@{-1}";
-
-	if (new_branch_force) {
-		struct strbuf symref = STRBUF_INIT;
-
-		new_branch = new_branch_force;
-
-		if (!opts.force &&
-		    !strbuf_check_branch_ref(&symref, new_branch) &&
-		    ref_exists(symref.buf))
-			die_if_checked_out(symref.buf, 0);
-		strbuf_release(&symref);
-	}
-
-	if (ac < 2 && !new_branch && !opts.detach) {
-		const char *s = dwim_branch(path, &new_branch);
-		if (s)
-			branch = s;
-	}
-
-	if (ac == 2 && !new_branch && !opts.detach) {
-		struct object_id oid;
-		struct commit *commit;
-		const char *remote;
-
-		commit = lookup_commit_reference_by_name(branch);
-		if (!commit) {
-			remote = unique_tracking_name(branch, &oid, NULL);
-			if (remote) {
-				new_branch = branch;
-				branch = remote;
-			}
-		}
-	}
-	if (!opts.quiet)
-		print_preparing_worktree_line(opts.detach, branch, new_branch, !!new_branch_force);
-
-	if (new_branch) {
-		struct child_process cp = CHILD_PROCESS_INIT;
-		cp.git_cmd = 1;
-		strvec_push(&cp.args, "branch");
-		if (new_branch_force)
-			strvec_push(&cp.args, "--force");
-		if (opts.quiet)
-			strvec_push(&cp.args, "--quiet");
-		strvec_push(&cp.args, new_branch);
-		strvec_push(&cp.args, branch);
-		if (opt_track)
-			strvec_push(&cp.args, opt_track);
-		if (run_command(&cp))
-			return -1;
-		branch = new_branch;
-	} else if (opt_track) {
-		die(_("--[no-]track can only be used if a new branch is created"));
-	}
-
-	UNLEAK(path);
-	UNLEAK(opts);
-	return add_worktree(path, branch, &opts);
-}
-
-static void show_worktree_porcelain(struct worktree *wt)
-{
-	printf("worktree %s\n", wt->path);
-	if (wt->is_bare)
-		printf("bare\n");
-	else {
-		printf("HEAD %s\n", oid_to_hex(&wt->head_oid));
-		if (wt->is_detached)
-			printf("detached\n");
-		else if (wt->head_ref)
-			printf("branch %s\n", wt->head_ref);
-	}
-	printf("\n");
-}
-
-static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len)
-{
-	struct strbuf sb = STRBUF_INIT;
-	int cur_path_len = strlen(wt->path);
-	int path_adj = cur_path_len - utf8_strwidth(wt->path);
-
-	strbuf_addf(&sb, "%-*s ", 1 + path_maxlen + path_adj, wt->path);
-	if (wt->is_bare)
-		strbuf_addstr(&sb, "(bare)");
-	else {
-		strbuf_addf(&sb, "%-*s ", abbrev_len,
-				find_unique_abbrev(&wt->head_oid, DEFAULT_ABBREV));
-		if (wt->is_detached)
-			strbuf_addstr(&sb, "(detached HEAD)");
-		else if (wt->head_ref) {
-			char *ref = shorten_unambiguous_ref(wt->head_ref, 0);
-			strbuf_addf(&sb, "[%s]", ref);
-			free(ref);
-		} else
-			strbuf_addstr(&sb, "(error)");
-	}
-	printf("%s\n", sb.buf);
-
-	strbuf_release(&sb);
-}
-
-static void measure_widths(struct worktree **wt, int *abbrev, int *maxlen)
-{
-	int i;
-
-	for (i = 0; wt[i]; i++) {
-		int sha1_len;
-		int path_len = strlen(wt[i]->path);
-
-		if (path_len > *maxlen)
-			*maxlen = path_len;
-		sha1_len = strlen(find_unique_abbrev(&wt[i]->head_oid, *abbrev));
-		if (sha1_len > *abbrev)
-			*abbrev = sha1_len;
-	}
-}
-
-static int pathcmp(const void *a_, const void *b_)
-{
-	const struct worktree *const *a = a_;
-	const struct worktree *const *b = b_;
-	return fspathcmp((*a)->path, (*b)->path);
-}
-
-static void pathsort(struct worktree **wt)
-{
-	int n = 0;
-	struct worktree **p = wt;
-
-	while (*p++)
-		n++;
-	QSORT(wt, n, pathcmp);
-}
-
-static int list(int ac, const char **av, const char *prefix)
-{
-	int porcelain = 0;
-
-	struct option options[] = {
-		OPT_BOOL(0, "porcelain", &porcelain, N_("machine-readable output")),
-		OPT_END()
-	};
-
-	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
-	if (ac)
-		usage_with_options(worktree_usage, options);
-	else {
-		struct worktree **worktrees = get_worktrees();
-		int path_maxlen = 0, abbrev = DEFAULT_ABBREV, i;
-
-		/* sort worktrees by path but keep main worktree at top */
-		pathsort(worktrees + 1);
-
-		if (!porcelain)
-			measure_widths(worktrees, &abbrev, &path_maxlen);
-
-		for (i = 0; worktrees[i]; i++) {
-			if (porcelain)
-				show_worktree_porcelain(worktrees[i]);
-			else
-				show_worktree(worktrees[i], path_maxlen, abbrev);
-		}
-		free_worktrees(worktrees);
-	}
-	return 0;
-}
-
-static int lock_worktree(int ac, const char **av, const char *prefix)
-{
-	const char *reason = "", *old_reason;
-	struct option options[] = {
-		OPT_STRING(0, "reason", &reason, N_("string"),
-			   N_("reason for locking")),
-		OPT_END()
-	};
-	struct worktree **worktrees, *wt;
-
-	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
-	if (ac != 1)
-		usage_with_options(worktree_usage, options);
-
-	worktrees = get_worktrees();
-	wt = find_worktree(worktrees, prefix, av[0]);
-	if (!wt)
-		die(_("'%s' is not a working tree"), av[0]);
-	if (is_main_worktree(wt))
-		die(_("The main working tree cannot be locked or unlocked"));
-
-	old_reason = worktree_lock_reason(wt);
-	if (old_reason) {
-		if (*old_reason)
-			die(_("'%s' is already locked, reason: %s"),
-			    av[0], old_reason);
-		die(_("'%s' is already locked"), av[0]);
-	}
-
-	write_file(git_common_path("worktrees/%s/locked", wt->id),
-		   "%s", reason);
-	free_worktrees(worktrees);
-	return 0;
-}
-
-static int unlock_worktree(int ac, const char **av, const char *prefix)
-{
-	struct option options[] = {
-		OPT_END()
-	};
-	struct worktree **worktrees, *wt;
-	int ret;
-
-	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
-	if (ac != 1)
-		usage_with_options(worktree_usage, options);
-
-	worktrees = get_worktrees();
-	wt = find_worktree(worktrees, prefix, av[0]);
-	if (!wt)
-		die(_("'%s' is not a working tree"), av[0]);
-	if (is_main_worktree(wt))
-		die(_("The main working tree cannot be locked or unlocked"));
-	if (!worktree_lock_reason(wt))
-		die(_("'%s' is not locked"), av[0]);
-	ret = unlink_or_warn(git_common_path("worktrees/%s/locked", wt->id));
-	free_worktrees(worktrees);
-	return ret;
-}
-
-static void validate_no_submodules(const struct worktree *wt)
-{
-	struct index_state istate = { NULL };
-	struct strbuf path = STRBUF_INIT;
-	int i, found_submodules = 0;
-
-	if (is_directory(worktree_git_path(wt, "modules"))) {
-		/*
-		 * There could be false positives, e.g. the "modules"
-		 * directory exists but is empty. But it's a rare case and
-		 * this simpler check is probably good enough for now.
-		 */
-		found_submodules = 1;
-	} else if (read_index_from(&istate, worktree_git_path(wt, "index"),
-				   get_worktree_git_dir(wt)) > 0) {
-		for (i = 0; i < istate.cache_nr; i++) {
-			struct cache_entry *ce = istate.cache[i];
-			int err;
-
-			if (!S_ISGITLINK(ce->ce_mode))
-				continue;
-
-			strbuf_reset(&path);
-			strbuf_addf(&path, "%s/%s", wt->path, ce->name);
-			if (!is_submodule_populated_gently(path.buf, &err))
-				continue;
-
-			found_submodules = 1;
-			break;
-		}
-	}
-	discard_index(&istate);
-	strbuf_release(&path);
-
-	if (found_submodules)
-		die(_("working trees containing submodules cannot be moved or removed"));
-}
-
-static int move_worktree(int ac, const char **av, const char *prefix)
-{
-	int force = 0;
-	struct option options[] = {
-		OPT__FORCE(&force,
-			 N_("force move even if worktree is dirty or locked"),
-			 PARSE_OPT_NOCOMPLETE),
-		OPT_END()
-	};
-	struct worktree **worktrees, *wt;
-	struct strbuf dst = STRBUF_INIT;
-	struct strbuf errmsg = STRBUF_INIT;
-	const char *reason = NULL;
-	char *path;
-
-	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
-	if (ac != 2)
-		usage_with_options(worktree_usage, options);
-
-	path = prefix_filename(prefix, av[1]);
-	strbuf_addstr(&dst, path);
-	free(path);
-
-	worktrees = get_worktrees();
-	wt = find_worktree(worktrees, prefix, av[0]);
-	if (!wt)
-		die(_("'%s' is not a working tree"), av[0]);
-	if (is_main_worktree(wt))
-		die(_("'%s' is a main working tree"), av[0]);
-	if (is_directory(dst.buf)) {
-		const char *sep = find_last_dir_sep(wt->path);
-
-		if (!sep)
-			die(_("could not figure out destination name from '%s'"),
-			    wt->path);
-		strbuf_trim_trailing_dir_sep(&dst);
-		strbuf_addstr(&dst, sep);
-	}
-	check_candidate_path(dst.buf, force, worktrees, "move");
-
-	validate_no_submodules(wt);
-
-	if (force < 2)
-		reason = worktree_lock_reason(wt);
-	if (reason) {
-		if (*reason)
-			die(_("cannot move a locked working tree, lock reason: %s\nuse 'move -f -f' to override or unlock first"),
-			    reason);
-		die(_("cannot move a locked working tree;\nuse 'move -f -f' to override or unlock first"));
-	}
-	if (validate_worktree(wt, &errmsg, 0))
-		die(_("validation failed, cannot move working tree: %s"),
-		    errmsg.buf);
-	strbuf_release(&errmsg);
-
-	if (rename(wt->path, dst.buf) == -1)
-		die_errno(_("failed to move '%s' to '%s'"), wt->path, dst.buf);
-
-	update_worktree_location(wt, dst.buf);
-
-	strbuf_release(&dst);
-	free_worktrees(worktrees);
-	return 0;
-}
-
-/*
- * Note, "git status --porcelain" is used to determine if it's safe to
- * delete a whole worktree. "git status" does not ignore user
- * configuration, so if a normal "git status" shows "clean" for the
- * user, then it's ok to remove it.
- *
- * This assumption may be a bad one. We may want to ignore
- * (potentially bad) user settings and only delete a worktree when
- * it's absolutely safe to do so from _our_ point of view because we
- * know better.
- */
-static void check_clean_worktree(struct worktree *wt,
-				 const char *original_path)
-{
-	struct child_process cp;
-	char buf[1];
-	int ret;
-
-	/*
-	 * Until we sort this out, all submodules are "dirty" and
-	 * will abort this function.
-	 */
-	validate_no_submodules(wt);
-
-	child_process_init(&cp);
-	strvec_pushf(&cp.env_array, "%s=%s/.git",
-		     GIT_DIR_ENVIRONMENT, wt->path);
-	strvec_pushf(&cp.env_array, "%s=%s",
-		     GIT_WORK_TREE_ENVIRONMENT, wt->path);
-	strvec_pushl(&cp.args, "status",
-		     "--porcelain", "--ignore-submodules=none",
-		     NULL);
-	cp.git_cmd = 1;
-	cp.dir = wt->path;
-	cp.out = -1;
-	ret = start_command(&cp);
-	if (ret)
-		die_errno(_("failed to run 'git status' on '%s'"),
-			  original_path);
-	ret = xread(cp.out, buf, sizeof(buf));
-	if (ret)
-		die(_("'%s' contains modified or untracked files, use --force to delete it"),
-		    original_path);
-	close(cp.out);
-	ret = finish_command(&cp);
-	if (ret)
-		die_errno(_("failed to run 'git status' on '%s', code %d"),
-			  original_path, ret);
-}
-
-static int delete_git_work_tree(struct worktree *wt)
-{
-	struct strbuf sb = STRBUF_INIT;
-	int ret = 0;
-
-	strbuf_addstr(&sb, wt->path);
-	if (remove_dir_recursively(&sb, 0)) {
-		error_errno(_("failed to delete '%s'"), sb.buf);
-		ret = -1;
-	}
-	strbuf_release(&sb);
-	return ret;
-}
-
-static int remove_worktree(int ac, const char **av, const char *prefix)
-{
-	int force = 0;
-	struct option options[] = {
-		OPT__FORCE(&force,
-			 N_("force removal even if worktree is dirty or locked"),
-			 PARSE_OPT_NOCOMPLETE),
-		OPT_END()
-	};
-	struct worktree **worktrees, *wt;
-	struct strbuf errmsg = STRBUF_INIT;
-	const char *reason = NULL;
-	int ret = 0;
-
-	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
-	if (ac != 1)
-		usage_with_options(worktree_usage, options);
-
-	worktrees = get_worktrees();
-	wt = find_worktree(worktrees, prefix, av[0]);
-	if (!wt)
-		die(_("'%s' is not a working tree"), av[0]);
-	if (is_main_worktree(wt))
-		die(_("'%s' is a main working tree"), av[0]);
-	if (force < 2)
-		reason = worktree_lock_reason(wt);
-	if (reason) {
-		if (*reason)
-			die(_("cannot remove a locked working tree, lock reason: %s\nuse 'remove -f -f' to override or unlock first"),
-			    reason);
-		die(_("cannot remove a locked working tree;\nuse 'remove -f -f' to override or unlock first"));
-	}
-	if (validate_worktree(wt, &errmsg, WT_VALIDATE_WORKTREE_MISSING_OK))
-		die(_("validation failed, cannot remove working tree: %s"),
-		    errmsg.buf);
-	strbuf_release(&errmsg);
-
-	if (file_exists(wt->path)) {
-		if (!force)
-			check_clean_worktree(wt, av[0]);
-
-		ret |= delete_git_work_tree(wt);
-	}
-	/*
-	 * continue on even if ret is non-zero, there's no going back
-	 * from here.
-	 */
-	ret |= delete_git_dir(wt->id);
-	delete_worktrees_dir_if_empty();
-
-	free_worktrees(worktrees);
-	return ret;
-}
-
-static void report_repair(int iserr, const char *path, const char *msg, void *cb_data)
-{
-	if (!iserr) {
-		printf_ln(_("repair: %s: %s"), msg, path);
-	} else {
-		int *exit_status = (int *)cb_data;
-		fprintf_ln(stderr, _("error: %s: %s"), msg, path);
-		*exit_status = 1;
-	}
-}
-
-static int repair(int ac, const char **av, const char *prefix)
-{
-	const char **p;
-	const char *self[] = { ".", NULL };
-	struct option options[] = {
-		OPT_END()
-	};
-	int rc = 0;
-
-	ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
-	repair_worktrees(report_repair, &rc);
-	p = ac > 0 ? av : self;
-	for (; *p; p++)
-		repair_worktree_at_path(*p, report_repair, &rc);
-	return rc;
-}
-
-int cmd_worktree(int ac, const char **av, const char *prefix)
-{
-	struct option options[] = {
-		OPT_END()
-	};
-
-	git_config(git_worktree_config, NULL);
-
-	if (ac < 2)
-		usage_with_options(worktree_usage, options);
-	if (!prefix)
-		prefix = "";
-	if (!strcmp(av[1], "add"))
-		return add(ac - 1, av + 1, prefix);
-	if (!strcmp(av[1], "prune"))
-		return prune(ac - 1, av + 1, prefix);
-	if (!strcmp(av[1], "list"))
-		return list(ac - 1, av + 1, prefix);
-	if (!strcmp(av[1], "lock"))
-		return lock_worktree(ac - 1, av + 1, prefix);
-	if (!strcmp(av[1], "unlock"))
-		return unlock_worktree(ac - 1, av + 1, prefix);
-	if (!strcmp(av[1], "move"))
-		return move_worktree(ac - 1, av + 1, prefix);
-	if (!strcmp(av[1], "remove"))
-		return remove_worktree(ac - 1, av + 1, prefix);
-	if (!strcmp(av[1], "repair"))
-		return repair(ac - 1, av + 1, prefix);
-	usage_with_options(worktree_usage, options);
-}
diff --git a/third_party/git/builtin/write-tree.c b/third_party/git/builtin/write-tree.c
deleted file mode 100644
index 45d61707e7d1..000000000000
--- a/third_party/git/builtin/write-tree.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * GIT - The information manager from hell
- *
- * Copyright (C) Linus Torvalds, 2005
- */
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
-#include "builtin.h"
-#include "cache.h"
-#include "config.h"
-#include "tree.h"
-#include "cache-tree.h"
-#include "parse-options.h"
-
-static const char * const write_tree_usage[] = {
-	N_("git write-tree [--missing-ok] [--prefix=<prefix>/]"),
-	NULL
-};
-
-int cmd_write_tree(int argc, const char **argv, const char *cmd_prefix)
-{
-	int flags = 0, ret;
-	const char *tree_prefix = NULL;
-	struct object_id oid;
-	const char *me = "git-write-tree";
-	struct option write_tree_options[] = {
-		OPT_BIT(0, "missing-ok", &flags, N_("allow missing objects"),
-			WRITE_TREE_MISSING_OK),
-		OPT_STRING(0, "prefix", &tree_prefix, N_("<prefix>/"),
-			   N_("write tree object for a subdirectory <prefix>")),
-		{ OPTION_BIT, 0, "ignore-cache-tree", &flags, NULL,
-		  N_("only useful for debugging"),
-		  PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, NULL,
-		  WRITE_TREE_IGNORE_CACHE_TREE },
-		OPT_END()
-	};
-
-	git_config(git_default_config, NULL);
-	argc = parse_options(argc, argv, cmd_prefix, write_tree_options,
-			     write_tree_usage, 0);
-
-	ret = write_cache_as_tree(&oid, flags, tree_prefix);
-	switch (ret) {
-	case 0:
-		printf("%s\n", oid_to_hex(&oid));
-		break;
-	case WRITE_TREE_UNREADABLE_INDEX:
-		die("%s: error reading the index", me);
-		break;
-	case WRITE_TREE_UNMERGED_INDEX:
-		die("%s: error building trees", me);
-		break;
-	case WRITE_TREE_PREFIX_ERROR:
-		die("%s: prefix %s not found", me, tree_prefix);
-		break;
-	}
-	return ret;
-}