diff --git a/builtin/config.c b/builtin/config.c
index 8a2d1a5de7..a6ab9b8204 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -44,6 +44,7 @@ static struct config_options config_options;
 static int show_origin;
 static int show_scope;
 static int fixed_value;
+static int config_flags;
 
 #define ACTION_GET (1<<0)
 #define ACTION_GET_ALL (1<<1)
@@ -622,6 +623,225 @@ static char *default_user_config(void)
 	return strbuf_detach(&buf, NULL);
 }
 
+static int cmd_config_list(int argc, const char **argv, const char *prefix)
+{
+	check_argc(argc, 0, 0);
+	if (config_with_options(show_all_config, NULL,
+				&given_config_source, the_repository,
+				&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)"));
+	}
+
+	return 0;
+}
+
+static int cmd_config_edit(int argc, const char **argv, const char *prefix)
+{
+	char *config_file;
+
+	check_argc(argc, 0, 0);
+	if (!given_config_source.file && !startup_info->have_repository)
+		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);
+
+	return 0;
+}
+
+static int cmd_config_set(int argc, const char **argv, const char *prefix)
+{
+	struct key_value_info default_kvi = KVI_INIT;
+	char *value = NULL;
+	int ret;
+
+	check_write();
+	check_argc(argc, 2, 2);
+	value = normalize_value(argv[0], argv[1], &default_kvi);
+	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]);
+
+	free(value);
+	return ret;
+}
+
+static int cmd_config_set_all(int argc, const char **argv, const char *prefix)
+{
+	struct key_value_info default_kvi = KVI_INIT;
+	char *value = NULL;
+	int ret;
+
+	check_write();
+	check_argc(argc, 2, 3);
+	value = normalize_value(argv[0], argv[1], &default_kvi);
+	ret = git_config_set_multivar_in_file_gently(given_config_source.file,
+						     argv[0], value, argv[2],
+						     config_flags);
+
+	free(value);
+	return ret;
+}
+
+static int cmd_config_add(int argc, const char **argv, const char *prefix)
+{
+	struct key_value_info default_kvi = KVI_INIT;
+	char *value = NULL;
+	int ret;
+
+	check_write();
+	check_argc(argc, 2, 2);
+	value = normalize_value(argv[0], argv[1], &default_kvi);
+	ret = git_config_set_multivar_in_file_gently(given_config_source.file,
+						     argv[0], value,
+						     CONFIG_REGEX_NONE,
+						     config_flags);
+
+	free(value);
+	return ret;
+}
+
+static int cmd_config_replace_all(int argc, const char **argv, const char *prefix)
+{
+	struct key_value_info default_kvi = KVI_INIT;
+	char *value = NULL;
+	int ret;
+
+	check_write();
+	check_argc(argc, 2, 3);
+	value = normalize_value(argv[0], argv[1], &default_kvi);
+	ret = git_config_set_multivar_in_file_gently(given_config_source.file,
+						     argv[0], value, argv[2],
+						     config_flags | CONFIG_FLAGS_MULTI_REPLACE);
+
+	free(value);
+	return ret;
+}
+
+static int cmd_config_get(int argc, const char **argv, const char *prefix)
+{
+	check_argc(argc, 1, 2);
+	return get_value(argv[0], argv[1], config_flags);
+}
+
+static int cmd_config_get_all(int argc, const char **argv, const char *prefix)
+{
+	do_all = 1;
+	check_argc(argc, 1, 2);
+	return get_value(argv[0], argv[1], config_flags);
+}
+
+static int cmd_config_get_regexp(int argc, const char **argv, const char *prefix)
+{
+	show_keys = 1;
+	use_key_regexp = 1;
+	do_all = 1;
+	check_argc(argc, 1, 2);
+	return get_value(argv[0], argv[1], config_flags);
+}
+
+static int cmd_config_get_urlmatch(int argc, const char **argv, const char *prefix)
+{
+	check_argc(argc, 2, 2);
+	return get_urlmatch(argv[0], argv[1]);
+}
+
+static int cmd_config_unset(int argc, const char **argv, const char *prefix)
+{
+	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],
+							      config_flags);
+	else
+		return git_config_set_in_file_gently(given_config_source.file,
+						     argv[0], NULL);
+}
+
+static int cmd_config_unset_all(int argc, const char **argv, const char *prefix)
+{
+	check_write();
+	check_argc(argc, 1, 2);
+	return git_config_set_multivar_in_file_gently(given_config_source.file,
+						      argv[0], NULL, argv[1],
+						      config_flags | CONFIG_FLAGS_MULTI_REPLACE);
+}
+
+static int cmd_config_rename_section(int argc, const char **argv, const char *prefix)
+{
+	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;
+	else if (!ret)
+		die(_("no such section: %s"), argv[0]);
+	else
+		ret = 0;
+
+	return ret;
+}
+
+static int cmd_config_remove_section(int argc, const char **argv, const char *prefix)
+{
+	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;
+	else if (!ret)
+		die(_("no such section: %s"), argv[0]);
+	else
+		ret = 0;
+
+	return ret;
+}
+
+static int cmd_config_get_color(int argc, const char **argv, const char *prefix)
+{
+	check_argc(argc, 1, 2);
+	get_color(argv[0], argv[1]);
+	return 0;
+}
+
+static int cmd_config_get_colorbool(int argc, const char **argv, const char *prefix)
+{
+	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);
+}
+
 static struct option builtin_config_options[] = {
 	OPT_GROUP(N_("Config file location")),
 	OPT_BOOL(0, "global", &use_global_config, N_("use global config file")),
@@ -671,12 +891,6 @@ static NORETURN void usage_builtin_config(void)
 
 int cmd_config(int argc, const char **argv, const char *prefix)
 {
-	int nongit = !startup_info->have_repository;
-	char *value = NULL;
-	int flags = 0;
-	int ret = 0;
-	struct key_value_info default_kvi = KVI_INIT;
-
 	given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));
 
 	argc = parse_options(argc, argv, prefix, builtin_config_options,
@@ -690,7 +904,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 		usage_builtin_config();
 	}
 
-	if (nongit) {
+	if (!startup_info->have_repository) {
 		if (use_local_config)
 			die(_("--local can only be used inside a git repository"));
 		if (given_config_source.blob)
@@ -751,7 +965,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 		config_options.respect_includes = !given_config_source.file;
 	else
 		config_options.respect_includes = respect_includes_opt;
-	if (!nongit) {
+	if (startup_info->have_repository) {
 		config_options.commondir = get_git_common_dir();
 		config_options.git_dir = get_git_dir();
 	}
@@ -826,159 +1040,45 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			usage_builtin_config();
 		}
 
-		flags |= CONFIG_FLAGS_FIXED_VALUE;
+		config_flags |= CONFIG_FLAGS_FIXED_VALUE;
 	}
 
 	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, the_repository,
-					&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)"));
-		}
+		return cmd_config_list(argc, argv, prefix);
+	} else if (actions == ACTION_EDIT) {
+		return cmd_config_edit(argc, argv, prefix);
+	} else if (actions == ACTION_SET) {
+		return cmd_config_set(argc, argv, prefix);
+	} else if (actions == ACTION_SET_ALL) {
+		return cmd_config_set_all(argc, argv, prefix);
+	} else if (actions == ACTION_ADD) {
+		return cmd_config_add(argc, argv, prefix);
+	} else if (actions == ACTION_REPLACE_ALL) {
+		return cmd_config_replace_all(argc, argv, prefix);
+	} else if (actions == ACTION_GET) {
+		return cmd_config_get(argc, argv, prefix);
+	} else if (actions == ACTION_GET_ALL) {
+		return cmd_config_get_all(argc, argv, prefix);
+	} else if (actions == ACTION_GET_REGEXP) {
+		return cmd_config_get_regexp(argc, argv, prefix);
+	} else if (actions == ACTION_GET_URLMATCH) {
+		return cmd_config_get_urlmatch(argc, argv, prefix);
+	} else if (actions == ACTION_UNSET) {
+		return cmd_config_unset(argc, argv, prefix);
+	} else if (actions == ACTION_UNSET_ALL) {
+		return cmd_config_unset_all(argc, argv, prefix);
+	} else if (actions == ACTION_RENAME_SECTION) {
+		return cmd_config_rename_section(argc, argv, prefix);
+	} else if (actions == ACTION_REMOVE_SECTION) {
+		return cmd_config_remove_section(argc, argv, prefix);
+	} else if (actions == ACTION_GET_COLOR) {
+		return cmd_config_get_color(argc, argv, prefix);
+	} else if (actions == ACTION_GET_COLORBOOL) {
+		return cmd_config_get_colorbool(argc, argv, prefix);
 	}
-	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) {
-		check_write();
-		check_argc(argc, 2, 2);
-		value = normalize_value(argv[0], argv[1], &default_kvi);
-		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]);
-	}
-	else if (actions == ACTION_SET_ALL) {
-		check_write();
-		check_argc(argc, 2, 3);
-		value = normalize_value(argv[0], argv[1], &default_kvi);
-		ret = git_config_set_multivar_in_file_gently(given_config_source.file,
-							     argv[0], value, argv[2],
-							     flags);
-	}
-	else if (actions == ACTION_ADD) {
-		check_write();
-		check_argc(argc, 2, 2);
-		value = normalize_value(argv[0], argv[1], &default_kvi);
-		ret = git_config_set_multivar_in_file_gently(given_config_source.file,
-							     argv[0], value,
-							     CONFIG_REGEX_NONE,
-							     flags);
-	}
-	else if (actions == ACTION_REPLACE_ALL) {
-		check_write();
-		check_argc(argc, 2, 3);
-		value = normalize_value(argv[0], argv[1], &default_kvi);
-		ret = git_config_set_multivar_in_file_gently(given_config_source.file,
-							     argv[0], value, argv[2],
-							     flags | CONFIG_FLAGS_MULTI_REPLACE);
-	}
-	else if (actions == ACTION_GET) {
-		check_argc(argc, 1, 2);
-		return get_value(argv[0], argv[1], flags);
-	}
-	else if (actions == ACTION_GET_ALL) {
-		do_all = 1;
-		check_argc(argc, 1, 2);
-		return get_value(argv[0], argv[1], flags);
-	}
-	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], flags);
-	}
-	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],
-								      flags);
-		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],
-							      flags | CONFIG_FLAGS_MULTI_REPLACE);
-	}
-	else if (actions == ACTION_RENAME_SECTION) {
-		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;
-		else if (!ret)
-			die(_("no such section: %s"), argv[0]);
-		else
-			ret = 0;
-	}
-	else if (actions == ACTION_REMOVE_SECTION) {
-		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;
-		else if (!ret)
-			die(_("no such section: %s"), argv[0]);
-		else
-			ret = 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);
-	}
-
-	free(value);
-	return ret;
+	BUG("invalid action");
 }
