Message ID | 766ffe31a6f14c55d1b58a8f53edbb7f731b1b24.1607514692.git.ps@pks.im (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | config: allow specifying config entries via env | expand |
On Wed, Dec 09 2020, Patrick Steinhardt wrote: > While it's already possible to pass runtime configuration via `git -c > <key>=<value>`, it may be undesirable to use when the value contains > sensitive information. E.g. if one wants to set `http.extraHeader` to > contain an authentication token, doing so via `-c` would trivially leak > those credentials via e.g. ps(1), which typically also shows command > arguments. > > To enable this usecase without leaking credentials, this commit > introduces a new switch `--config-env=<key>=<envvar>`. Instead of > directly passing a value for the given key, it instead allows the user > to specify the name of an environment variable. The value of that > variable will then be used as value of the key. > [...] > +--config-env=<name>=<envvar>:: > + Pass a configuration parameter to the command. The <envvar> > + given will be replaced with the contents of the environment > + variable of that name. In contrast to `-c`, an envvar must > + always be given and exist in the environment. Passing an > + environment variable with empty value will set <name> to the > + empty string which `git config --type=bool` will convert to > + `false`. Okey, because "-c foo.bar" (true) "-c foo.bar=" is the empty string, but that doesn't make sene with "--config-env". Also the whole part about --type=bool is just confusing, because it's referring to `-c`'s magic behavior when it comes to `bool` which we don't have here. I think it's also worth describing what this is for & what the limitations are. Maybe: --config-env=<name>=<envvar> Like `-c <name>=<var>` except the value is the name of an environment variable from which to retrieve the value. Unlike `-c` there is no shortcut for directly setting the value to an empty string, instead the environment variable itself must be set to the empty strin. Errors if the `<envvar>` does not exist in the environment. This is useful for cases where you want to pass transitory configuration options to git, but are doing so on OS's where other processes might be able to read your cmdline (e.g. `/proc/self/cmdline`), but not your environ (e.g. `/proc/self/environ`). That behavior is the default on Linux, but may not be on your system. Note that this might add security for variables such as `http.extraHeader` where the sensitive information is part of the value, but not e.g. `url.<base.insteadOf` where the sensitive information can be part of the key. > +void git_config_push_env(const char *spec) > +{ > + struct strbuf buf = STRBUF_INIT; > + const char *env_name; > + const char *env_value; > + > + env_name = strrchr(spec, '='); > + if (!env_name) > + die("invalid config format: %s", spec); > + env_name++; Not something new, and maybe not something for this series, but I wish -c and --config-env would document this limitation that we support "=" in keys in config, but not via those parameters.
On Wed, Dec 09, 2020 at 12:52:26PM +0100, Patrick Steinhardt wrote: > Co-authored-by: Jeff King <peff@peff.net> > Signed-off-by: Patrick Steinhardt <ps@pks.im> In case we want it, this is also: Signed-off-by: Jeff King <peff@peff.net> > +--config-env=<name>=<envvar>:: > + Pass a configuration parameter to the command. The <envvar> > + given will be replaced with the contents of the environment > + variable of that name. In contrast to `-c`, an envvar must > + always be given and exist in the environment. Passing an > + environment variable with empty value will set <name> to the > + empty string which `git config --type=bool` will convert to > + `false`. I agree with Ævar that we probably should keep an empty variable as the empty string. I think some options use an empty string to clear a list (e.g., push.pushOption), and I'm not sure how they'd react to a bool instead. It would be nice to also have a way to do the implicit-bool thing, but I don't think it's strictly necessary (it's always correct to put the string "true" into the variable instead). I think we should also document that <envvar> can't contain an "=" sign. Of course using strrchr() here doesn't help much with just this patch, because we flatten the string before stuffing it into $GIT_CONFIG_PARAMETERS, so the reading side would mis-parse it. But here's a fix for that. I built it on top of your whole series, since you touched some of the related functions, but it could easily be rebased onto just this part. [1/3]: quote: make sq_dequote_step() a public function [2/3]: config: parse more robust format in GIT_CONFIG_PARAMETERS [3/3]: config: store "git -c" variables using more robust format config.c | 118 +++++++++++++++++++++++++++++++++++++--------- quote.c | 15 ++++-- quote.h | 18 ++++++- t/t1300-config.sh | 60 +++++++++++++++++++++++ 4 files changed, 183 insertions(+), 28 deletions(-) -Peff
On Wed, Dec 09, 2020 at 03:40:17PM +0100, Ævar Arnfjörð Bjarmason wrote: > > +--config-env=<name>=<envvar>:: > > + Pass a configuration parameter to the command. The <envvar> > > + given will be replaced with the contents of the environment > > + variable of that name. In contrast to `-c`, an envvar must > > + always be given and exist in the environment. Passing an > > + environment variable with empty value will set <name> to the > > + empty string which `git config --type=bool` will convert to > > + `false`. > > Okey, because "-c foo.bar" (true) "-c foo.bar=" is the empty string, but > that doesn't make sene with "--config-env". Also the whole part about > --type=bool is just confusing, because it's referring to `-c`'s magic > behavior when it comes to `bool` which we don't have here. Yeah, I agree. > I think it's also worth describing what this is for & what the > limitations are. Maybe: Agreed, and the text you gave looks reasonable. Another reason to use it is that it will (if we add the patches I just sent on top) avoid the key/value ambiguity with equals in the section name. > Not something new, and maybe not something for this series, but I wish > -c and --config-env would document this limitation that we support "=" > in keys in config, but not via those parameters. Yeah. If we add in my patches, then the limitation is gone here (but we should mention the limitation on the environment variable name). I stopped short of adding a variant of "-c" that avoids the ambiguity. I'm certainly not opposed to one if somebody wants to do it, but I think documenting the current limitation makes sense in the meantime (and we should do it in this series while we're thinking about it). -Peff
Jeff King <peff@peff.net> writes: > On Wed, Dec 09, 2020 at 12:52:26PM +0100, Patrick Steinhardt wrote: > >> Co-authored-by: Jeff King <peff@peff.net> >> Signed-off-by: Patrick Steinhardt <ps@pks.im> > > In case we want it, this is also: > > Signed-off-by: Jeff King <peff@peff.net> > >> +--config-env=<name>=<envvar>:: >> + Pass a configuration parameter to the command. The <envvar> >> + given will be replaced with the contents of the environment >> + variable of that name. In contrast to `-c`, an envvar must >> + always be given and exist in the environment. Passing an >> + environment variable with empty value will set <name> to the >> + empty string which `git config --type=bool` will convert to >> + `false`. > > I agree with Ævar that we probably should keep an empty variable as the > empty string. I think some options use an empty string to clear a list > (e.g., push.pushOption), and I'm not sure how they'd react to a bool > instead. It would be nice to also have a way to do the implicit-bool > thing, but I don't think it's strictly necessary (it's always correct to > put the string "true" into the variable instead). > > I think we should also document that <envvar> can't contain an "=" sign. > Of course using strrchr() here doesn't help much with just this patch, > because we flatten the string before stuffing it into > $GIT_CONFIG_PARAMETERS, so the reading side would mis-parse it. > > But here's a fix for that. I built it on top of your whole series, since > you touched some of the related functions, but it could easily be > rebased onto just this part. Hmph, so (1) Patrick's 1 & 2 are about adding --config-env, (2) These three patches can come on top to make it more robust to pass key=value with GIT_CONFIG_PARAMETERS (including what is added via the --config-env=name=envvar), and (3) The remainder of Patrick's 6-patch series is to further add the pairs of environment variables to pass keys and values? I am still not sure if we want the last part, but whether we take (1) or (3) or neither or both, (2) sounds like a good thing to do. And (2) would not shine without (1). In the traditional use of -c, we do not know which = from the end user separates key and value, but when (1) places a = to separate the <name> and the value in the environment variable, we know where that = is and can quote accordingly. But these three patches are done on top of (1) and (3), at least for now. The above is my understanding of the state of these patches. Am I getting it right? Thanks. > [1/3]: quote: make sq_dequote_step() a public function > [2/3]: config: parse more robust format in GIT_CONFIG_PARAMETERS > [3/3]: config: store "git -c" variables using more robust format > > config.c | 118 +++++++++++++++++++++++++++++++++++++--------- > quote.c | 15 ++++-- > quote.h | 18 ++++++- > t/t1300-config.sh | 60 +++++++++++++++++++++++ > 4 files changed, 183 insertions(+), 28 deletions(-) > > -Peff
On Wed, Dec 09, 2020 at 04:00:08PM -0800, Junio C Hamano wrote: > > I think we should also document that <envvar> can't contain an "=" sign. > > Of course using strrchr() here doesn't help much with just this patch, > > because we flatten the string before stuffing it into > > $GIT_CONFIG_PARAMETERS, so the reading side would mis-parse it. > > > > But here's a fix for that. I built it on top of your whole series, since > > you touched some of the related functions, but it could easily be > > rebased onto just this part. > > Hmph, so > > (1) Patrick's 1 & 2 are about adding --config-env, > > (2) These three patches can come on top to make it more robust to > pass key=value with GIT_CONFIG_PARAMETERS (including what is > added via the --config-env=name=envvar), and Yep, exactly. > (3) The remainder of Patrick's 6-patch series is to further add the > pairs of environment variables to pass keys and values? More or less. I did use the config_parse_pair() helper from patch 4, and there's some textual dependency on his patch 5 (but it would be easy to rebase). > I am still not sure if we want the last part, but whether we take > (1) or (3) or neither or both, (2) sounds like a good thing to do. > And (2) would not shine without (1). In the traditional use of -c, > we do not know which = from the end user separates key and value, > but when (1) places a = to separate the <name> and the value in the > environment variable, we know where that = is and can quote > accordingly. Exactly. Without (1), then (2) is not nearly as exciting. We could also implement a non-ambiguous version of "-c", like: git --config key.with=equals.foo some-value ... which would also benefit from (2). But I think Patrick's main goal was to get secret values off the command-line, so he'd want either (1) or (3) for that. > But these three patches are done on top of (1) and (3), at least for > now. Yes. I'd be happy to rebase them if we're not going to do the GIT_CONFIG_{KEY,VALUE}_<n> parts. > The above is my understanding of the state of these patches. Am I > getting it right? Yep. -Peff
Jeff King <peff@peff.net> writes: > Yes. I'd be happy to rebase them if we're not going to do the > GIT_CONFIG_{KEY,VALUE}_<n> parts. > >> The above is my understanding of the state of these patches. Am I >> getting it right? > > Yep. Thanks. I have no strong feeling for or against the env-pair feature, so the way these three parts are structured (i.e. more robust parsing of '=' comes at the end) is fine by me.
On Wed, Dec 09, 2020 at 11:24:03AM -0500, Jeff King wrote: > On Wed, Dec 09, 2020 at 03:40:17PM +0100, Ævar Arnfjörð Bjarmason wrote: > > > > +--config-env=<name>=<envvar>:: > > > + Pass a configuration parameter to the command. The <envvar> > > > + given will be replaced with the contents of the environment > > > + variable of that name. In contrast to `-c`, an envvar must > > > + always be given and exist in the environment. Passing an > > > + environment variable with empty value will set <name> to the > > > + empty string which `git config --type=bool` will convert to > > > + `false`. > > > > Okey, because "-c foo.bar" (true) "-c foo.bar=" is the empty string, but > > that doesn't make sene with "--config-env". Also the whole part about > > --type=bool is just confusing, because it's referring to `-c`'s magic > > behavior when it comes to `bool` which we don't have here. > > Yeah, I agree. > > > I think it's also worth describing what this is for & what the > > limitations are. Maybe: > > Agreed, and the text you gave looks reasonable. Another reason to use it > is that it will (if we add the patches I just sent on top) avoid the > key/value ambiguity with equals in the section name. Yeah, I'll pick up the explanation by Ævar, it's a lot better compared to what I had. Thanks! > > Not something new, and maybe not something for this series, but I wish > > -c and --config-env would document this limitation that we support "=" > > in keys in config, but not via those parameters. > > Yeah. If we add in my patches, then the limitation is gone here (but we > should mention the limitation on the environment variable name). > > I stopped short of adding a variant of "-c" that avoids the ambiguity. > I'm certainly not opposed to one if somebody wants to do it, but I think > documenting the current limitation makes sense in the meantime (and we > should do it in this series while we're thinking about it). > > -Peff Do you want me to adopt your patches as part of this series? Patrick
On Wed, Dec 09, 2020 at 11:10:04AM -0500, Jeff King wrote: > On Wed, Dec 09, 2020 at 12:52:26PM +0100, Patrick Steinhardt wrote: > > > Co-authored-by: Jeff King <peff@peff.net> > > Signed-off-by: Patrick Steinhardt <ps@pks.im> > > In case we want it, this is also: > > Signed-off-by: Jeff King <peff@peff.net> > > > +--config-env=<name>=<envvar>:: > > + Pass a configuration parameter to the command. The <envvar> > > + given will be replaced with the contents of the environment > > + variable of that name. In contrast to `-c`, an envvar must > > + always be given and exist in the environment. Passing an > > + environment variable with empty value will set <name> to the > > + empty string which `git config --type=bool` will convert to > > + `false`. > > I agree with Ævar that we probably should keep an empty variable as the > empty string. I think some options use an empty string to clear a list > (e.g., push.pushOption), and I'm not sure how they'd react to a bool > instead. It would be nice to also have a way to do the implicit-bool > thing, but I don't think it's strictly necessary (it's always correct to > put the string "true" into the variable instead). I think this is just weirdly worded in the `-c` case, which I mostly copied. We _do_ keep the empty string, which effectively means that `git config --type=bool` will return `false`. Or do you mean that we should allow `--config-env=foo.bar=`? > I think we should also document that <envvar> can't contain an "=" sign. > Of course using strrchr() here doesn't help much with just this patch, > because we flatten the string before stuffing it into > $GIT_CONFIG_PARAMETERS, so the reading side would mis-parse it. Makes sense. Patrick > But here's a fix for that. I built it on top of your whole series, since > you touched some of the related functions, but it could easily be > rebased onto just this part. > > [1/3]: quote: make sq_dequote_step() a public function > [2/3]: config: parse more robust format in GIT_CONFIG_PARAMETERS > [3/3]: config: store "git -c" variables using more robust format > > config.c | 118 +++++++++++++++++++++++++++++++++++++--------- > quote.c | 15 ++++-- > quote.h | 18 ++++++- > t/t1300-config.sh | 60 +++++++++++++++++++++++ > 4 files changed, 183 insertions(+), 28 deletions(-) > > -Peff
On Fri, Dec 11, 2020 at 02:24:35PM +0100, Patrick Steinhardt wrote: > > > +--config-env=<name>=<envvar>:: > > > + Pass a configuration parameter to the command. The <envvar> > > > + given will be replaced with the contents of the environment > > > + variable of that name. In contrast to `-c`, an envvar must > > > + always be given and exist in the environment. Passing an > > > + environment variable with empty value will set <name> to the > > > + empty string which `git config --type=bool` will convert to > > > + `false`. > > > > I agree with Ævar that we probably should keep an empty variable as the > > empty string. I think some options use an empty string to clear a list > > (e.g., push.pushOption), and I'm not sure how they'd react to a bool > > instead. It would be nice to also have a way to do the implicit-bool > > thing, but I don't think it's strictly necessary (it's always correct to > > put the string "true" into the variable instead). > > I think this is just weirdly worded in the `-c` case, which I mostly > copied. We _do_ keep the empty string, which effectively means that `git > config --type=bool` will return `false`. Oh indeed, I misread what you wrote in the documentation. I think it is doing the right thing, then. IMHO it is not worth even calling out specially, since there is no matching implicit-bool form. I.e., I'd probably just cut the final sentence. > Or do you mean that we should allow `--config-env=foo.bar=`? Hmm, yeah, that would work as an "implicit bool". But it's sufficiently ugly and non-intuitive (and weirdly overlapping with "-c") that I'm not sure it is worth supporting. -Peff
On Fri, Dec 11, 2020 at 02:24:33PM +0100, Patrick Steinhardt wrote:
> Do you want me to adopt your patches as part of this series?
Yeah, if you're willing to. I don't mind spinning it off into its own
series if you don't want to (the tricky part is that we're touching a
couple of the same spots, though, so if you're willing to pick them up,
I think that makes coordination easier).
-Peff
On Fri, Dec 11, 2020 at 09:21:38AM -0500, Jeff King wrote: > On Fri, Dec 11, 2020 at 02:24:33PM +0100, Patrick Steinhardt wrote: > > > Do you want me to adopt your patches as part of this series? > > Yeah, if you're willing to. I don't mind spinning it off into its own > series if you don't want to (the tricky part is that we're touching a > couple of the same spots, though, so if you're willing to pick them up, > I think that makes coordination easier). > > -Peff I can do so. The only question that I have is whether I should rebase it on top of 6/6 or on top of 2/6. It's hard for me to gauge whether 6/6 is going to make it in or not due to the conflicting opinions on it. It currently seems to me like we tend towards a "no", which is also what the "What's cooking" report said. But there were also some opinions in favor of it, which made me wonder. If this is a definitive "no", then I'm happy to stop bothering with them to make the patch series easier to manage. Patrick
On Fri, Dec 11, 2020 at 03:54:03PM +0100, Patrick Steinhardt wrote: > > Yeah, if you're willing to. I don't mind spinning it off into its own > > series if you don't want to (the tricky part is that we're touching a > > couple of the same spots, though, so if you're willing to pick them up, > > I think that makes coordination easier). > > > > I can do so. The only question that I have is whether I should rebase it > on top of 6/6 or on top of 2/6. It's hard for me to gauge whether 6/6 is > going to make it in or not due to the conflicting opinions on it. It > currently seems to me like we tend towards a "no", which is also what > the "What's cooking" report said. But there were also some opinions in > favor of it, which made me wonder. If this is a definitive "no", then > I'm happy to stop bothering with them to make the patch series easier to > manage. I'd probably do it on top of 2/6 (well, perhaps shuffling 4/6 forward is needed, then, I think). And then that punts the decision. As for the general idea of 6/6, I think I'm a soft "no" there. Normally my opinion for things I wouldn't use myself is "hey, go to town, if you're willing to write the patch and it won't hurt anybody else". My only reservation is that it's a public-facing interface, so we'll have to support it forever. And I don't love the interface. That's not a reflection on how you did the series, btw. I think you've done a very good job of trying to address everyone's concerns, and balance them with having a way to get data through the environment that doesn't require error-prone quoting and parsing. But at the end, I think we are left with a fundamental tradeoff: an interface that is clunky because of the counted variables, or one if that is clunky because of the quoting. (And by "soft no", I just mean that I wouldn't pursue it further in your shoes, but I'm not going to strenuously object if you and others want to go forward). -Peff
diff --git a/Documentation/git.txt b/Documentation/git.txt index c463b937a8..9061c54792 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -13,7 +13,7 @@ SYNOPSIS [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path] [-p|--paginate|-P|--no-pager] [--no-replace-objects] [--bare] [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>] - [--super-prefix=<path>] + [--super-prefix=<path>] [--config-env <name>=<envvar>] <command> [<args>] DESCRIPTION @@ -80,6 +80,15 @@ config file). Including the equals but with an empty value (like `git -c foo.bar= ...`) sets `foo.bar` to the empty string which `git config --type=bool` will convert to `false`. +--config-env=<name>=<envvar>:: + Pass a configuration parameter to the command. The <envvar> + given will be replaced with the contents of the environment + variable of that name. In contrast to `-c`, an envvar must + always be given and exist in the environment. Passing an + environment variable with empty value will set <name> to the + empty string which `git config --type=bool` will convert to + `false`. + --exec-path[=<path>]:: Path to wherever your core Git programs are installed. This can also be controlled by setting the GIT_EXEC_PATH diff --git a/config.c b/config.c index 1137bd73af..cde3511110 100644 --- a/config.c +++ b/config.c @@ -345,6 +345,27 @@ void git_config_push_parameter(const char *text) strbuf_release(&env); } +void git_config_push_env(const char *spec) +{ + struct strbuf buf = STRBUF_INIT; + const char *env_name; + const char *env_value; + + env_name = strrchr(spec, '='); + if (!env_name) + die("invalid config format: %s", spec); + env_name++; + + env_value = getenv(env_name); + if (!env_value) + die("config variable missing for '%s'", env_name); + + strbuf_add(&buf, spec, env_name - spec); + strbuf_addstr(&buf, env_value); + git_config_push_parameter(buf.buf); + strbuf_release(&buf); +} + static inline int iskeychar(int c) { return isalnum(c) || c == '-'; diff --git a/config.h b/config.h index c1449bb790..19a9adbaa9 100644 --- a/config.h +++ b/config.h @@ -138,6 +138,7 @@ int git_config_from_mem(config_fn_t fn, int git_config_from_blob_oid(config_fn_t fn, const char *name, const struct object_id *oid, void *data); void git_config_push_parameter(const char *text); +void git_config_push_env(const char *spec); int git_config_from_parameters(config_fn_t fn, void *data); void read_early_config(config_fn_t cb, void *data); void read_very_early_config(config_fn_t cb, void *data); diff --git a/git.c b/git.c index 5a8ff12f87..b5f63d346b 100644 --- a/git.c +++ b/git.c @@ -29,7 +29,7 @@ const char git_usage_string[] = " [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" " [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]\n" " [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" - " [--super-prefix=<path>]\n" + " [--super-prefix=<path>] [--config-env=<name>=<envvar>]\n" " <command> [<args>]"); const char git_more_info_string[] = @@ -255,6 +255,8 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) git_config_push_parameter((*argv)[1]); (*argv)++; (*argc)--; + } else if (skip_prefix(cmd, "--config-env=", &cmd)) { + git_config_push_env(cmd); } else if (!strcmp(cmd, "--literal-pathspecs")) { setenv(GIT_LITERAL_PATHSPECS_ENVIRONMENT, "1", 1); if (envchanged) diff --git a/t/t1300-config.sh b/t/t1300-config.sh index 97a04c6cc2..46a94814d5 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -1316,6 +1316,51 @@ test_expect_success 'detect bogus GIT_CONFIG_PARAMETERS' ' git config --get-regexp "env.*" ' +test_expect_success 'git --config-env=key=envvar support' ' + cat >expect <<-\EOF && + value + value + false + EOF + { + env ENVVAR=value git --config-env=core.name=ENVVAR config core.name && + env ENVVAR=value git --config-env=foo.CamelCase=ENVVAR config foo.camelcase && + env ENVVAR= git --config-env=foo.flag=ENVVAR config --bool foo.flag + } >actual && + test_cmp expect actual +' + +test_expect_success 'git --config-env fails with invalid parameters' ' + test_must_fail git --config-env=foo.flag config --bool foo.flag 2>error && + test_i18ngrep "invalid config format" error && + test_must_fail git --config-env=foo.flag=NONEXISTENT config --bool foo.flag 2>error && + test_i18ngrep "config variable missing" error +' + +test_expect_success 'git -c and --config-env work together' ' + cat >expect <<-\EOF && + bar.cmd cmd-value + bar.env env-value + EOF + env ENVVAR=env-value git \ + -c bar.cmd=cmd-value \ + --config-env=bar.env=ENVVAR \ + config --get-regexp "^bar.*" >actual && + test_cmp expect actual +' + +test_expect_success 'git -c and --config-env override each other' ' + cat >expect <<-\EOF && + env + cmd + EOF + { + env ENVVAR=env git -c bar.bar=cmd --config-env=bar.bar=ENVVAR config bar.bar && + env ENVVAR=env git --config-env=bar.bar=ENVVAR -c bar.bar=cmd config bar.bar + } >actual && + test_cmp expect actual +' + test_expect_success 'git config --edit works' ' git config -f tmp test.value no && echo test.value=yes >expect &&
While it's already possible to pass runtime configuration via `git -c <key>=<value>`, it may be undesirable to use when the value contains sensitive information. E.g. if one wants to set `http.extraHeader` to contain an authentication token, doing so via `-c` would trivially leak those credentials via e.g. ps(1), which typically also shows command arguments. To enable this usecase without leaking credentials, this commit introduces a new switch `--config-env=<key>=<envvar>`. Instead of directly passing a value for the given key, it instead allows the user to specify the name of an environment variable. The value of that variable will then be used as value of the key. Co-authored-by: Jeff King <peff@peff.net> Signed-off-by: Patrick Steinhardt <ps@pks.im> --- Documentation/git.txt | 11 ++++++++++- config.c | 21 ++++++++++++++++++++ config.h | 1 + git.c | 4 +++- t/t1300-config.sh | 45 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 80 insertions(+), 2 deletions(-)