SYNOPSIS
--------
[verse]
+'git config list' [<file-option>] [<display-option>] [--includes]
'git config' [<file-option>] [--type=<type>] [--comment=<message>] [--fixed-value] [--show-origin] [--show-scope] [-z|--null] <name> [<value> [<value-pattern>]]
'git config' [<file-option>] [--type=<type>] [--comment=<message>] --add <name> <value>
'git config' [<file-option>] [--type=<type>] [--comment=<message>] [--fixed-value] --replace-all <name> <value> [<value-pattern>]
'git config' [<file-option>] [--fixed-value] --unset-all <name> [<value-pattern>]
'git config' [<file-option>] --rename-section <old-name> <new-name>
'git config' [<file-option>] --remove-section <name>
-'git config' [<file-option>] [--show-origin] [--show-scope] [-z|--null] [--name-only] -l | --list
'git config' [<file-option>] --get-color <name> [<default>]
'git config' [<file-option>] --get-colorbool <name> [<stdout-is-tty>]
'git config' [<file-option>] -e | --edit
A list of all available configuration variables can be obtained using the
`git help --config` command.
+COMMANDS
+--------
+
+list::
+ List all variables set in config file, along with their values.
+
[[OPTIONS]]
OPTIONS
-------
--unset-all::
Remove all lines matching the key from config file.
--l::
---list::
- List all variables set in config file, along with their values.
-
--fixed-value::
When used with the `value-pattern` argument, treat `value-pattern` as
an exact string instead of a regular expression. This will restrict
contain line breaks.
--name-only::
- Output only the names of config variables for `--list` or
+ Output only the names of config variables for `list` or
`--get-regexp`.
--show-origin::
When using `--get`, and the requested variable is not found, behave as if
<value> were the value assigned to that variable.
+DEPRECATED MODES
+----------------
+
+The following modes have been deprecated in favor of subcommands. It is
+recommended to migrate to the new syntax.
+
+-l::
+--list::
+ Replaced by `git config list`.
+
CONFIGURATION
-------------
`pager.config` is only respected when listing configuration, i.e., when
-using `--list` or any of the `--get-*` which may return multiple results.
+using `list` or any of the `--get-*` which may return multiple results.
The default is to use a pager.
[[FILES]]
#include "worktree.h"
static const char *const builtin_config_usage[] = {
+ N_("git config list [<file-option>] [<display-option>] [--includes]"),
N_("git config [<options>]"),
NULL
};
+static const char *const builtin_config_list_usage[] = {
+ N_("git config list [<file-option>] [<display-option>] [--includes]"),
+ NULL
+};
+
static char *key;
static regex_t *key_regexp;
static const char *value_pattern;
static char key_delim = ' ';
static char term = '\n';
+static parse_opt_subcommand_fn *subcommand;
static int use_global_config, use_system_config, use_local_config;
static int use_worktree_config;
static struct git_config_source given_config_source;
}
}
+#define CONFIG_LOCATION_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"))
+
+#define CONFIG_DISPLAY_OPTIONS \
+ OPT_GROUP(N_("Display options")), \
+ 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, "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)"))
+
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")),
+ CONFIG_LOCATION_OPTIONS,
OPT_GROUP(N_("Action")),
OPT_CMDMODE(0, "get", &actions, N_("get value: name [<value-pattern>]"), ACTION_GET),
OPT_CMDMODE(0, "get-all", &actions, N_("get all values: key [<value-pattern>]"), ACTION_GET_ALL),
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),
+ CONFIG_DISPLAY_OPTIONS,
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_STRING(0, "comment", &comment_arg, N_("value"), N_("human-readable comment string (# will be prepended as needed)")),
OPT_BOOL(0, "fixed-value", &fixed_value, N_("use string equality when comparing values to 'value-pattern'")),
+ OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
OPT_END(),
};
usage_with_options(builtin_config_usage, builtin_config_options);
}
+static int cmd_config_list(int argc, const char **argv, const char *prefix)
+{
+ struct option opts[] = {
+ CONFIG_LOCATION_OPTIONS,
+ CONFIG_DISPLAY_OPTIONS,
+ OPT_GROUP(N_("Other")),
+ OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
+ OPT_END(),
+ };
+
+ argc = parse_options(argc, argv, prefix, opts, builtin_config_list_usage, 0);
+ check_argc(argc, 0, 0);
+
+ handle_config_location(prefix);
+ handle_nul();
+
+ setup_auto_pager("config", 1);
+
+ 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 struct option builtin_subcommand_options[] = {
+ OPT_SUBCOMMAND("list", &subcommand, cmd_config_list),
+ OPT_END(),
+};
+
int cmd_config(int argc, const char **argv, const char *prefix)
{
char *value = NULL, *comment = NULL;
given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));
+ /*
+ * This is somewhat hacky: we first parse the command line while
+ * keeping all args intact in order to determine whether a subcommand
+ * has been specified. If so, we re-parse it a second time, but this
+ * time we drop KEEP_ARGV0. This is so that we don't munge the command
+ * line in case no subcommand was given, which would otherwise confuse
+ * us when parsing the legacy-style modes that don't use subcommands.
+ */
+ argc = parse_options(argc, argv, prefix, builtin_subcommand_options, builtin_config_usage,
+ PARSE_OPT_SUBCOMMAND_OPTIONAL|PARSE_OPT_NO_INTERNAL_HELP|PARSE_OPT_KEEP_ARGV0|PARSE_OPT_KEEP_UNKNOWN_OPT);
+ if (subcommand) {
+ argc = parse_options(argc, argv, prefix, builtin_subcommand_options, builtin_config_usage,
+ PARSE_OPT_SUBCOMMAND_OPTIONAL|PARSE_OPT_NO_INTERNAL_HELP|PARSE_OPT_KEEP_UNKNOWN_OPT);
+ return subcommand(argc, argv, prefix);
+ }
+
argc = parse_options(argc, argv, prefix, builtin_config_options,
builtin_config_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
+for mode in legacy subcommands
+do
+
+case "$mode" in
+legacy)
+ mode_prefix="--"
+ ;;
+subcommands)
+ mode_prefix=""
+ ;;
+*)
+ BUG "unknown mode $mode";;
+esac
+
test_expect_success 'setup whitespace config' '
sed -e "s/^|//" \
-e "s/[$]$//" \
EOF
test_expect_success 'working --list' '
- git config --list > output &&
+ git config ${mode_prefix}list > output &&
test_cmp expect output
'
test_expect_success '--list without repo produces empty output' '
- git --git-dir=nonexistent config --list >output &&
+ git --git-dir=nonexistent config ${mode_prefix}list >output &&
test_must_be_empty output
'
EOF
test_expect_success '--name-only --list' '
- git config --name-only --list >output &&
+ git config ${mode_prefix}list --name-only >output &&
test_cmp expect output
'
EOF
test_expect_success 'alternative GIT_CONFIG' '
- GIT_CONFIG=other-config git config --list >output &&
+ GIT_CONFIG=other-config git config ${mode_prefix}list >output &&
test_cmp expect output
'
test_expect_success 'alternative GIT_CONFIG (--file)' '
- git config --file other-config --list >output &&
+ git config ${mode_prefix}list --file other-config >output &&
test_cmp expect output
'
test_expect_success 'alternative GIT_CONFIG (--file=-)' '
- git config --file - --list <other-config >output &&
+ git config ${mode_prefix}list --file - <other-config >output &&
test_cmp expect output
'
'
test_expect_success 'refer config from subdirectory' '
+ test_when_finished "rm -r x" &&
mkdir x &&
test_cmp_config -C x strasse --file=../other-config --get ein.bahn
'
'
test_expect_success 'invalid stdin config' '
- echo "[broken" | test_must_fail git config --list --file - >output 2>&1 &&
+ echo "[broken" | test_must_fail git config ${mode_prefix}list --file - >output 2>&1 &&
test_grep "bad config line 1 in standard input" output
'
EOF
test_expect_success 'value continued on next line' '
- git config --list > result &&
+ git config ${mode_prefix}list > result &&
test_cmp expect result
'
Qsection.sub=section.val5Q
EOF
test_expect_success '--null --list' '
- git config --null --list >result.raw &&
+ git config ${mode_prefix}list --null >result.raw &&
nul_to_q <result.raw >result &&
echo >>result &&
test_cmp expect result
'
test_expect_success SYMLINKS 'symlinked configuration' '
+ test_when_finished "rm myconfig" &&
ln -s notyet myconfig &&
git config --file=myconfig test.frotz nitfol &&
test -h myconfig &&
'
test_expect_success SYMLINKS 'symlink to nonexistent configuration' '
+ test_when_finished "rm linktonada linktolinktonada" &&
ln -s doesnotexist linktonada &&
ln -s linktonada linktolinktonada &&
- test_must_fail git config --file=linktonada --list &&
- test_must_fail git config --file=linktolinktonada --list
+ test_must_fail git config ${mode_prefix}list --file=linktonada &&
+ test_must_fail git config ${mode_prefix}list --file=linktolinktonada
'
test_expect_success 'check split_cmdline return' '
done
test_expect_success 'git -c is not confused by empty environment' '
- GIT_CONFIG_PARAMETERS="" git -c x.one=1 config --list
+ GIT_CONFIG_PARAMETERS="" git -c x.one=1 config ${mode_prefix}list
'
test_expect_success 'GIT_CONFIG_PARAMETERS handles old-style entries' '
'
test_expect_success 'git config fails with invalid count' '
- test_must_fail env GIT_CONFIG_COUNT=10a git config --list 2>error &&
+ test_must_fail env GIT_CONFIG_COUNT=10a git config ${mode_prefix}list 2>error &&
test_grep "bogus count" error &&
- test_must_fail env GIT_CONFIG_COUNT=9999999999999999 git config --list 2>error &&
+ test_must_fail env GIT_CONFIG_COUNT=9999999999999999 git config ${mode_prefix}list 2>error &&
test_grep "too many entries" error
'
test_expect_success 'git config fails with missing config key' '
test_must_fail env GIT_CONFIG_COUNT=1 GIT_CONFIG_VALUE_0="value" \
- git config --list 2>error &&
+ git config ${mode_prefix}list 2>error &&
test_grep "missing config key" error
'
test_expect_success 'git config fails with missing config value' '
test_must_fail env GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0="pair.one" \
- git config --list 2>error &&
+ git config ${mode_prefix}list 2>error &&
test_grep "missing config value" error
'
test_expect_success 'git config fails with invalid config pair key' '
test_must_fail env GIT_CONFIG_COUNT=1 \
GIT_CONFIG_KEY_0= GIT_CONFIG_VALUE_0=value \
- git config --list &&
+ git config ${mode_prefix}list &&
test_must_fail env GIT_CONFIG_COUNT=1 \
GIT_CONFIG_KEY_0=missing-section GIT_CONFIG_VALUE_0=value \
- git config --list
+ git config ${mode_prefix}list
'
test_expect_success 'environment overrides config file' '
git config -f tmp test.value no &&
echo test.value=yes >expect &&
GIT_EDITOR="echo [test]value=yes >" git config -f tmp --edit &&
- git config -f tmp --list >actual &&
+ git config ${mode_prefix}list -f tmp >actual &&
test_cmp expect actual
'
echo test.value=yes >expect &&
test_config core.editor "echo [test]value=yes >" &&
git config -f tmp --edit &&
- git config -f tmp --list >actual &&
+ git config ${mode_prefix}list -f tmp >actual &&
test_cmp expect actual
'
command line: user.cmdline=true
EOF
GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=user.environ GIT_CONFIG_VALUE_0=true\
- git -c user.cmdline=true config --list --show-origin >output &&
+ git -c user.cmdline=true config ${mode_prefix}list --show-origin >output &&
test_cmp expect output
'
includeQcommand line:Quser.cmdline
trueQ
EOF
- git -c user.cmdline=true config --null --list --show-origin >output.raw &&
+ git -c user.cmdline=true config ${mode_prefix}list --null --show-origin >output.raw &&
nul_to_q <output.raw >output &&
# The here-doc above adds a newline that the --null output would not
# include. Add it here to make the two comparable.
file:.git/config user.override=local
file:.git/config include.path=../include/relative.include
EOF
- git config --local --list --show-origin >output &&
+ git config ${mode_prefix}list --local --show-origin >output &&
test_cmp expect output
'
cat >expect <<-\EOF &&
file:"file\" (dq) and spaces.conf" user.custom=true
EOF
- git config --file "$WEIRDLY_NAMED_FILE" --show-origin --list >output &&
+ git config ${mode_prefix}list --file "$WEIRDLY_NAMED_FILE" --show-origin >output &&
test_cmp expect output
'
cat >expect <<-\EOF &&
standard input: user.custom=true
EOF
- git config --file - --show-origin --list <"$CUSTOM_CONFIG_FILE" >output &&
+ git config ${mode_prefix}list --file - --show-origin <"$CUSTOM_CONFIG_FILE" >output &&
test_cmp expect output
'
cat >expect <<-EOF &&
blob:$blob user.custom=true
EOF
- git config --blob=$blob --show-origin --list >output &&
+ git config ${mode_prefix}list --blob=$blob --show-origin >output &&
test_cmp expect output
)
'
cp "$CUSTOM_CONFIG_FILE" custom.conf &&
git add custom.conf &&
git commit -m "new config file" &&
- git config --blob=main:custom.conf --show-origin --list >output &&
+ git config ${mode_prefix}list --blob=main:custom.conf --show-origin >output &&
test_cmp expect output
)
'
worktree user.worktree=true
command user.cmdline=true
EOF
+ test_when_finished "git worktree remove wt1" &&
git worktree add wt1 &&
# We need these to test for worktree scope, but outside of this
# test, this is just noise
test_config core.repositoryformatversion 1 &&
test_config extensions.worktreeConfig true &&
git config --worktree user.worktree true &&
- git -c user.cmdline=true config --list --show-scope >output &&
+ git -c user.cmdline=true config ${mode_prefix}list --show-scope >output &&
test_cmp expect output
'
cat >expect <<-EOF &&
command user.custom=true
EOF
- git config --blob=$blob --show-scope --list >output &&
+ git config ${mode_prefix}list --blob=$blob --show-scope >output &&
test_cmp expect output
'
local user.override=local
local include.path=../include/relative.include
EOF
- git config --local --list --show-scope >output &&
+ git config ${mode_prefix}list --local --show-scope >output &&
test_cmp expect output
'
local file:.git/../include/relative.include user.relative=include
command command line: user.cmdline=true
EOF
- git -c user.cmdline=true config --list --show-origin --show-scope >output &&
+ git -c user.cmdline=true config ${mode_prefix}list --show-origin --show-scope >output &&
test_cmp expect output
'
global home.config=true
local local.config=true
EOF
- git config --show-scope --list >output &&
+ git config ${mode_prefix}list --show-scope >output &&
test_cmp expect output &&
cat >expect <<-EOF &&
local local.config=true
EOF
GIT_CONFIG_NOSYSTEM=false GIT_CONFIG_SYSTEM=custom-system-config GIT_CONFIG_GLOBAL=custom-global-config \
- git config --show-scope --list >output &&
+ git config ${mode_prefix}list --show-scope >output &&
test_cmp expect output &&
cat >expect <<-EOF &&
local local.config=true
EOF
GIT_CONFIG_NOSYSTEM=false GIT_CONFIG_SYSTEM=/dev/null GIT_CONFIG_GLOBAL=/dev/null \
- git config --show-scope --list >output &&
+ git config ${mode_prefix}list --show-scope >output &&
test_cmp expect output
'
test_expect_success 'override global and system config with missing file' '
- test_must_fail env GIT_CONFIG_GLOBAL=does-not-exist GIT_CONFIG_SYSTEM=/dev/null git config --global --list &&
- test_must_fail env GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=does-not-exist git config --system --list &&
+ test_must_fail env GIT_CONFIG_GLOBAL=does-not-exist GIT_CONFIG_SYSTEM=/dev/null git config ${mode_prefix}list --global &&
+ test_must_fail env GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=does-not-exist git config ${mode_prefix}list --system &&
GIT_CONFIG_GLOBAL=does-not-exist GIT_CONFIG_SYSTEM=does-not-exist git version
'
# no match => add new entry
cp initial config &&
git config --file=config abc.key two a+ &&
- git config --file=config --list >actual &&
+ git config ${mode_prefix}list --file=config >actual &&
cat >expect <<-\EOF &&
abc.key=one
abc.key=two
# multiple values, no match => add
git config --file=config abc.key three a+ &&
- git config --file=config --list >actual &&
+ git config ${mode_prefix}list --file=config >actual &&
cat >expect <<-\EOF &&
abc.key=one
abc.key=two
# single match => replace
git config --file=config abc.key four h+ &&
- git config --file=config --list >actual &&
+ git config ${mode_prefix}list --file=config >actual &&
cat >expect <<-\EOF &&
abc.key=one
abc.key=two
git config --file=config --add abc.key two &&
git config --file=config --add abc.key three &&
git config --file=config --replace-all abc.key four "o+" &&
- git config --file=config --list >actual &&
+ git config ${mode_prefix}list --file=config >actual &&
cat >expect <<-\EOF &&
abc.key=four
abc.key=three
test_must_fail git config --file=config --fixed-value --get-urlmatch dev.null bogus &&
test_must_fail git config --file=config --fixed-value --rename-section dev null &&
test_must_fail git config --file=config --fixed-value --remove-section dev &&
- test_must_fail git config --file=config --fixed-value --list &&
+ test_must_fail git config ${mode_prefix}list --file=config --fixed-value &&
test_must_fail git config --file=config --fixed-value --get-color dev.null &&
test_must_fail git config --file=config --fixed-value --get-colorbool dev.null &&
cp initial config &&
git config --file=config fixed.test bogus "$META" &&
- git config --file=config --list >actual &&
+ git config ${mode_prefix}list --file=config >actual &&
cat >expect <<-EOF &&
fixed.test=$META
fixed.test=bogus
cp initial config &&
git config --file=config --fixed-value fixed.test bogus "$META" &&
- git config --file=config --list >actual &&
+ git config ${mode_prefix}list --file=config >actual &&
cat >expect <<-\EOF &&
fixed.test=bogus
EOF
cp initial config &&
git config --file=config --replace-all fixed.test bogus "$META" &&
- git config --file=config --list >actual &&
+ git config ${mode_prefix}list --file=config >actual &&
cat >expect <<-EOF &&
fixed.test=$META
fixed.test=bogus
test_cmp expect actual &&
git config --file=config --fixed-value --replace-all fixed.test bogus "$META" &&
- git config --file=config --list >actual &&
+ git config ${mode_prefix}list --file=config >actual &&
cat >expect <<-EOF &&
fixed.test=bogus
fixed.test=bogus
test_cmp expect err
'
+done
+
test_done