When used with `--verbose` print description for all recognized
        commands.
 
+-c::
+--config::
+       List all available configuration variables. This is a short
+       summary of the list in linkgit:git-config[1].
+
 -g::
 --guides::
        Prints a list of useful guides on the standard output. This
 
 #include "cache.h"
 #include "config.h"
 #include "color.h"
+#include "help.h"
 
 int advice_push_update_rejected = 1;
 int advice_push_non_ff_current = 1;
        return 0;
 }
 
+void list_config_advices(struct string_list *list, const char *prefix)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(advice_config); i++)
+               list_config_item(list, prefix, advice_config[i].name);
+}
+
 int error_resolve_conflict(const char *me)
 {
        if (!strcmp(me, "cherry-pick"))
 
 #include "wt-status.h"
 #include "ref-filter.h"
 #include "worktree.h"
+#include "help.h"
 
 static const char * const builtin_branch_usage[] = {
        N_("git branch [<options>] [-r | -a] [--merged | --no-merged]"),
 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;
 
 #include "column.h"
 #include "color.h"
 #include "pathspec.h"
+#include "help.h"
 
 static int force = -1; /* unset */
 static int interactive;
        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;
 
 #include "column.h"
 #include "sequencer.h"
 #include "mailmap.h"
+#include "help.h"
 
 static const char * const builtin_commit_usage[] = {
        N_("git commit [<options>] [--] <pathspec>..."),
        return commitable ? 0 : 1;
 }
 
+define_list_config_array_extra(color_status_slots, {"added"});
+
 static int parse_status_slot(const char *slot)
 {
        if (!strcasecmp(slot, "added"))
 
 
 static int show_all = 0;
 static int show_guides = 0;
+static int show_config;
 static int verbose;
 static unsigned int colopts;
 static enum help_format help_format = HELP_FORMAT_NONE;
        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('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),
                list_commands(colopts, &main_cmds, &other_cmds);
        }
 
+       if (show_config) {
+               setup_pager();
+               list_config_help();
+               printf("\n%s\n", _("'git help config' for more information"));
+               return 0;
+       }
+
        if (show_guides)
                list_common_guides_help();
 
 
 #include "argv-array.h"
 #include "graph.h"
 #include "packfile.h"
+#include "help.h"
 
 #ifdef NO_FAST_WORKING_DIRECTORY
 #define FAST_WORKING_DIRECTORY 0
        die(_("option '%s' requires a value"), option_name);
 }
 
+define_list_config_array_extra(color_diff_slots, {"plain"});
+
 static int parse_diff_color_slot(const char *var)
 {
        if (!strcasecmp(var, "plain"))
 
 #include "utf8.h"
 #include "sha1-array.h"
 #include "decorate.h"
+#include "help.h"
 
 #define FSCK_FATAL -1
 #define FSCK_INFO -2
        return -1;
 }
 
+void list_config_fsck_msg_ids(struct string_list *list, const char *prefix)
+{
+       int i;
+
+       prepare_msg_ids();
+
+       /* TODO: we can do better by producing camelCase names */
+       for (i = 0; i < FSCK_MSG_MAX; i++)
+               list_config_item(list, prefix, msg_id_info[i].downcased);
+}
+
 static int fsck_msg_type(enum fsck_msg_id msg_id,
        struct fsck_options *options)
 {
 
        echo "};"
 }
 
+print_config_list () {
+       cat <<EOF
+static const char *config_name_list[] = {
+EOF
+       grep '^[a-zA-Z].*\..*::$' Documentation/config.txt |
+       sed '/deprecated/d; s/::$//; s/,  */\n/g' |
+       sort |
+       while read line
+       do
+               echo "  \"$line\","
+       done
+       cat <<EOF
+       NULL,
+};
+EOF
+}
+
 echo "/* Automatically generated by generate-cmdlist.sh */
 struct cmdname_help {
        const char *name;
 define_category_names "$1"
 echo
 print_command_list "$1"
+echo
+print_config_list
 
 #include "diffcore.h"
 #include "commit.h"
 #include "quote.h"
+#include "help.h"
 
 static int grep_source_load(struct grep_source *gs);
 static int grep_source_is_binary(struct grep_source *gs);
        die("bad %s argument: %s", opt, arg);
 }
 
+define_list_config_array_extra(color_grep_slots, {"match"});
+
 /*
  * Read the configuration file once and store it in
  * the grep_defaults template.
 
        putchar('\n');
 }
 
+struct slot_expansion {
+       const char *prefix;
+       const char *placeholder;
+       void (*fn)(struct string_list *list, const char *prefix);
+       int found;
+};
+
+void list_config_help(void)
+{
+       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.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++)
+               puts(keys.items[i].string);
+       string_list_clear(&keys, 0);
+}
+
 void list_all_cmds_help(void)
 {
        print_cmd_by_category(main_categories);
 
 #ifndef HELP_H
 #define HELP_H
 
-struct string_list;
+#include "string-list.h"
+#include "strbuf.h"
 
 struct cmdnames {
        int alloc;
 extern void list_common_cmds_help(void);
 extern void list_all_cmds_help(void);
 extern void list_common_guides_help(void);
+extern void list_config_help(void);
 
 extern void list_all_main_cmds(struct string_list *list);
 extern void list_all_other_cmds(struct string_list *list);
  * ref to the command, to give suggested "correct" refs.
  */
 extern void help_unknown_ref(const char *ref, const char *cmd, const char *error);
+
+static inline void list_config_item(struct string_list *list,
+                                   const char *prefix,
+                                   const char *str)
+{
+       string_list_append_nodup(list, xstrfmt("%s.%s", prefix, str));
+}
+
+#define define_list_config_array(array)                                        \
+void list_config_##array(struct string_list *list, const char *prefix) \
+{                                                                      \
+       int i;                                                          \
+       for (i = 0; i < ARRAY_SIZE(array); i++)                         \
+               if (array[i])                                           \
+                       list_config_item(list, prefix, array[i]);       \
+}                                                                      \
+struct string_list
+
+#define define_list_config_array_extra(array, values)                  \
+void list_config_##array(struct string_list *list, const char *prefix) \
+{                                                                      \
+       int i;                                                          \
+       static const char *extra[] = values;                            \
+       for (i = 0; i < ARRAY_SIZE(extra); i++)                         \
+               list_config_item(list, prefix, extra[i]);               \
+       for (i = 0; i < ARRAY_SIZE(array); i++)                         \
+               if (array[i])                                           \
+                       list_config_item(list, prefix, array[i]);       \
+}                                                                      \
+struct string_list
+
+/* These are actually scattered over many C files */
+void list_config_advices(struct string_list *list, const char *prefix);
+void list_config_color_branch_slots(struct string_list *list, const char *prefix);
+void list_config_color_decorate_slots(struct string_list *list, const char *prefix);
+void list_config_color_diff_slots(struct string_list *list, const char *prefix);
+void list_config_color_grep_slots(struct string_list *list, const char *prefix);
+void list_config_color_interactive_slots(struct string_list *list, const char *prefix);
+void list_config_color_status_slots(struct string_list *list, const char *prefix);
+void list_config_fsck_msg_ids(struct string_list *list, const char *prefix);
+
 #endif /* HELP_H */
 
 #include "gpg-interface.h"
 #include "sequencer.h"
 #include "line-log.h"
+#include "help.h"
 
 static struct decoration name_decoration = { "object names" };
 static int decoration_loaded;
        return "";
 }
 
+define_list_config_array(color_decorate_slots);
+
 int parse_decorate_color_config(const char *var, const char *slot_name, const char *value)
 {
        int slot = LOOKUP_CONFIG(color_decorate_slots, slot_name);