* config-file includes
@ 2011-09-23 19:58 Jeff King
2011-09-26 10:45 ` Nguyen Thai Ngoc Duy
0 siblings, 1 reply; 8+ messages in thread
From: Jeff King @ 2011-09-23 19:58 UTC (permalink / raw)
To: git; +Cc: Michael Haggerty, Jay Soffian, Junio C Hamano, Jakub Narebski
On Fri, Sep 23, 2011 at 03:33:41PM -0400, Jeff King wrote:
> [1] I really wish we had an elegant way of versioning meta-information
> about a repository (like config, info/attributes, etc). I've hacked
> around this before by having a special meta-branch for each repo,
> checkout it out in an alternate directory, and then symlinking bits
> of it into .git. But that's kind of ugly, too.
>
> I'm not sure what a good solution would look like. There's a real
> can of worms with respect to picking and choosing local versus
> remote bits of meta-information, with some security implications.
Here's one solution I've given a little thought to. Comments welcome.
I've sometimes wanted an "include" mechanism in git config files.
Partially to just keep things tidier, partially to avoid
cutting-and-pasting between some repo-specific config, and partially
because I'd like a conditional inclusion mechanism[1]. I was thinking of
something that would be syntactically compatible but semantically
meaningless in current versions of git, like:
[include]
path = /some/file
path = /some/other/file
path = ~/some/file/in/your/homedir
You could extend this to look in refs, with something like:
[include]
ref = meta:config
which would resolve meta:config to a blob and examine it (i.e., it would
look at refs/heads/meta).
So the procedure for importing and updating config from a remote would
look like:
git clone project.git
cd project
# check that the upstream config looks good
git show origin/meta:config
# if so, use it
git branch meta origin/meta
git config --add include.ref meta:config
# later, check updates to upstream's config
git fetch
git diff meta origin/meta -- config
# looks ok, use it
git branch -f meta origin/meta
And obviously if you wanted to streamline that, you could make "meta"
and "config" well-known names and have clone and fetch interactively
show the config and say "do you want this [y/N]?" or something. Though I
think there is some value to doing it manually, as it gives projects the
flexibility to have different config profiles in their meta branch.
And if you really wanted to live dangerously, you could do:
git config --add include.ref origin/meta:config
That of course just covers "config". But I think you might be able to do
something similar with core.attributesfile (which could be included from
the config).
-Peff
[1] I want conditional inclusion because sometimes the rules for config
entries changes from version to version. For example, I have
pager.diff set to a script in my ~/.gitconfig. But older versions of
git don't understand non-boolean values and barf. I'd really like to
do something like:
[include-ifdef "has-pager-scripts"]
path = ~/.gitconfig-pager
where "has-pager-scripts" would be a magic flag compiled into git
versions that understand that config.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: config-file includes
2011-09-23 19:58 config-file includes Jeff King
@ 2011-09-26 10:45 ` Nguyen Thai Ngoc Duy
2011-09-26 12:36 ` Jeff King
2011-09-26 19:21 ` David Aguilar
0 siblings, 2 replies; 8+ messages in thread
From: Nguyen Thai Ngoc Duy @ 2011-09-26 10:45 UTC (permalink / raw)
To: Jeff King
Cc: git, Michael Haggerty, Jay Soffian, Junio C Hamano,
Jakub Narebski
On Sat, Sep 24, 2011 at 5:58 AM, Jeff King <peff@peff.net> wrote:
> Here's one solution I've given a little thought to. Comments welcome.
>
> I've sometimes wanted an "include" mechanism in git config files.
> Partially to just keep things tidier, partially to avoid
> cutting-and-pasting between some repo-specific config, and partially
> because I'd like a conditional inclusion mechanism[1]. I was thinking of
> something that would be syntactically compatible but semantically
> meaningless in current versions of git, like:
>
> [include]
> path = /some/file
> path = /some/other/file
> path = ~/some/file/in/your/homedir
>
> You could extend this to look in refs, with something like:
>
> [include]
> ref = meta:config
>
> which would resolve meta:config to a blob and examine it (i.e., it would
> look at refs/heads/meta).
I had something similar [1], although I disregarded worktree content
completely. One thing about this meta thing is fsck/prune must dig in
config file in order not to accidentally remove something config file
refers to.
Another thing is, what if I want to exclude certain part of the included config?
[1] http://thread.gmane.org/gmane.comp.version-control.git/163285/focus=163288
> [1] I want conditional inclusion because sometimes the rules for config
> entries changes from version to version. For example, I have
> pager.diff set to a script in my ~/.gitconfig. But older versions of
> git don't understand non-boolean values and barf. I'd really like to
> do something like:
>
> [include-ifdef "has-pager-scripts"]
> path = ~/.gitconfig-pager
>
> where "has-pager-scripts" would be a magic flag compiled into git
> versions that understand that config.
But how far would you go with conditional expressions?
--
Duy
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: config-file includes
2011-09-26 10:45 ` Nguyen Thai Ngoc Duy
@ 2011-09-26 12:36 ` Jeff King
2011-09-26 19:21 ` David Aguilar
1 sibling, 0 replies; 8+ messages in thread
From: Jeff King @ 2011-09-26 12:36 UTC (permalink / raw)
To: Nguyen Thai Ngoc Duy
Cc: git, Michael Haggerty, Jay Soffian, Junio C Hamano,
Jakub Narebski
On Mon, Sep 26, 2011 at 08:45:58PM +1000, Nguyen Thai Ngoc Duy wrote:
> > You could extend this to look in refs, with something like:
> >
> > [include]
> > ref = meta:config
> >
> > which would resolve meta:config to a blob and examine it (i.e., it would
> > look at refs/heads/meta).
>
> I had something similar [1], although I disregarded worktree content
> completely.
Thanks, I had totally missed that thread.
Maybe it wasn't clear from my proposal, but I intend to disregard the
worktree entirely, too. The include.path was about including stuff from
the local filesystem, not necessarily your worktree.
> One thing about this meta thing is fsck/prune must dig in
> config file in order not to accidentally remove something config file
> refers to.
It is only a connectivity problem if you put a raw sha1 in the config.
It seems much more sensible to me to use a real ref. That solves the
fsck issue, and it makes it easier to manipulate the contents using git.
> Another thing is, what if I want to exclude certain part of the included config?
git show origin/meta:config ;# review upstream
git checkout meta origin/meta
$EDITOR config
git commit -a -m 'tweak my config based on upstream'
git config include.ref meta:config
[weeks later]
git fetch ;# oh, new config from upstream
git log -p origin/meta@{1}...origin/meta ;# looks good to me
git checkout meta
git merge origin/meta
Junio raised a good point in the thread you referenced: why is this any
better than the project just shipping a "./setup-config" script that you
run (and re-run when there is an update). Two things I can think of:
1. Carrying it in the project tree (as opposed to a separate ref) is
annoying. It bloats your project tree, and any changes you make
get tangled up in the changes you're making to the project itself.
To me, they're logically separate entities.
You can still keep a separate "meta" ref that has the setup-config
script in it, though. That wouldn't need git support at all.
But...
2. Using a script to deploy the config makes it annoying to track
changes. If I make local tweaks to what upstream suggests for the
config, I would want those tracked by git. And when upstream makes
a change, I want to do a 3-way merge. So either my script must be
clever in deploying, or I must never touch the deployed .git/config
file, and instead edit the setup-config script. Even then, how does
it handle changes in .git/config that happen naturally (e.g.,
branch config written by git).
If we had even a mechanism to include regular files, you could do
something like:
# make our local tweaked version of config
git checkout meta
$EDITOR config
git commit -a -m 'tweak config based on upstream'
# now deploy it
cp config .git/tracked-config
# and reference it
git config include.path tracked-config
# Weeks later, update and redeploy. Don't touch tracked-config in
# the meantime, as your changes will be overwritten (or copy it
# back after checkout, commit changes, then pull)
git checkout meta
git pull
cp config .git/tracked-config
which is really quite similar to the "include.ref" I showed earlier,
except you can skip the annoying "deploy" step. Which is a minor
convenience if you are actually keeping your own local config branch,
and a slightly larger one if you want to do the dangerous "just look at
origin/meta for config" thing.
> > [1] I want conditional inclusion because sometimes the rules for config
> > entries changes from version to version. For example, I have
> > pager.diff set to a script in my ~/.gitconfig. But older versions of
> > git don't understand non-boolean values and barf. I'd really like to
> > do something like:
> >
> > [include-ifdef "has-pager-scripts"]
> > path = ~/.gitconfig-pager
> >
> > where "has-pager-scripts" would be a magic flag compiled into git
> > versions that understand that config.
>
> But how far would you go with conditional expressions?
I agree it could become hairy in the general case. That's why I called
it "include-ifdef" and not "include-if". That would serve my use case. I
have no desire to support
[include-if "2 + 2 >= 4"]
-Peff
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: config-file includes
2011-09-26 10:45 ` Nguyen Thai Ngoc Duy
2011-09-26 12:36 ` Jeff King
@ 2011-09-26 19:21 ` David Aguilar
2011-09-26 20:05 ` Jeff King
1 sibling, 1 reply; 8+ messages in thread
From: David Aguilar @ 2011-09-26 19:21 UTC (permalink / raw)
To: Nguyen Thai Ngoc Duy
Cc: Jeff King, git, Michael Haggerty, Jay Soffian, Junio C Hamano,
Jakub Narebski
On Mon, Sep 26, 2011 at 08:45:58PM +1000, Nguyen Thai Ngoc Duy wrote:
> On Sat, Sep 24, 2011 at 5:58 AM, Jeff King <peff@peff.net> wrote:
>
> Another thing is, what if I want to exclude certain part of the included config?
>
> [1] http://thread.gmane.org/gmane.comp.version-control.git/163285/focus=163288
>
> > [1] I want conditional inclusion because sometimes the rules for config
> > entries changes from version to version. For example, I have
> > pager.diff set to a script in my ~/.gitconfig. But older versions of
> > git don't understand non-boolean values and barf. I'd really like to
> > do something like:
> >
> > [include-ifdef "has-pager-scripts"]
> > path = ~/.gitconfig-pager
> >
> > where "has-pager-scripts" would be a magic flag compiled into git
> > versions that understand that config.
>
> But how far would you go with conditional expressions?
> --
> Duy
This syntax is simple yet would solve one problem I run into
often. It could be used for the case where some settings
(e.g. diff.tool, merge.tool) are different on OS X and Linux.
[include-ifdef "darwin"]
path = ~/.gitconfig-darwin
--
David
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: config-file includes
2011-09-26 19:21 ` David Aguilar
@ 2011-09-26 20:05 ` Jeff King
2011-09-26 21:12 ` Junio C Hamano
2011-09-27 2:13 ` Jay Soffian
0 siblings, 2 replies; 8+ messages in thread
From: Jeff King @ 2011-09-26 20:05 UTC (permalink / raw)
To: David Aguilar
Cc: Nguyen Thai Ngoc Duy, git, Michael Haggerty, Jay Soffian,
Junio C Hamano, Jakub Narebski
On Mon, Sep 26, 2011 at 09:21:27PM +0200, David Aguilar wrote:
> > > [include-ifdef "has-pager-scripts"]
> > > path = ~/.gitconfig-pager
> > >
> > > where "has-pager-scripts" would be a magic flag compiled into git
> > > versions that understand that config.
> >
> > But how far would you go with conditional expressions?
>
> This syntax is simple yet would solve one problem I run into
> often. It could be used for the case where some settings
> (e.g. diff.tool, merge.tool) are different on OS X and Linux.
>
> [include-ifdef "darwin"]
> path = ~/.gitconfig-darwin
Thanks for another concrete example.
I'm not sure how that would be implemented, though. I don't think git
knows that it is compiled for darwin. Would it just be running "uname
-s" behind the scenes? Should it happen at runtime, or as part of the
compile process?
We could allow arbitrary shell code like:
[include-if "test `uname -s` -eq Darwin"]
Very flexible, though it makes me think we are getting a little
overboard. And it's an extra shell invocation whenever we read the
config, which is ugly.
-Peff
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: config-file includes
2011-09-26 20:05 ` Jeff King
@ 2011-09-26 21:12 ` Junio C Hamano
2011-09-27 2:13 ` Jay Soffian
1 sibling, 0 replies; 8+ messages in thread
From: Junio C Hamano @ 2011-09-26 21:12 UTC (permalink / raw)
To: Jeff King
Cc: David Aguilar, Nguyen Thai Ngoc Duy, git, Michael Haggerty,
Jay Soffian, Jakub Narebski
Jeff King <peff@peff.net> writes:
> We could allow arbitrary shell code like:
>
> [include-if "test `uname -s` -eq Darwin"]
>
> Very flexible, though it makes me think we are getting a little
> overboard. And it's an extra shell invocation whenever we read the
> config, which is ugly.
Let's not go there. It is not even like we only ever call git_config()
once in the lifetime of a process.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: config-file includes
2011-09-26 20:05 ` Jeff King
2011-09-26 21:12 ` Junio C Hamano
@ 2011-09-27 2:13 ` Jay Soffian
2011-09-27 2:38 ` Jeff King
1 sibling, 1 reply; 8+ messages in thread
From: Jay Soffian @ 2011-09-27 2:13 UTC (permalink / raw)
To: Jeff King
Cc: David Aguilar, Nguyen Thai Ngoc Duy, git, Michael Haggerty,
Junio C Hamano, Jakub Narebski
On Mon, Sep 26, 2011 at 4:05 PM, Jeff King <peff@peff.net> wrote:
>> [include-ifdef "darwin"]
>> path = ~/.gitconfig-darwin
>
> Thanks for another concrete example.
>
> I'm not sure how that would be implemented, though. I don't think git
> knows that it is compiled for darwin. Would it just be running "uname
> -s" behind the scenes? Should it happen at runtime, or as part of the
> compile process?
>
> We could allow arbitrary shell code like:
>
> [include-if "test `uname -s` -eq Darwin"]
>
> Very flexible, though it makes me think we are getting a little
> overboard. And it's an extra shell invocation whenever we read the
> config, which is ugly.
I would think git could just learn a few useful defines at the time of
compile, such as e.g. OS_Darwin would be more than sufficient.
I can also give you another use use case. I keep all my work repos
under ~Work/ and I want my user.email on all those to be my work email
addy, and all other repos on my system I want to use my personal email
address. So my ~/.gitconfig has my personal email address and then 99%
of the time I forget to configure the repos under ~/Work correctly.
That said, I'm not sure how the config include would help this...
j.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: config-file includes
2011-09-27 2:13 ` Jay Soffian
@ 2011-09-27 2:38 ` Jeff King
0 siblings, 0 replies; 8+ messages in thread
From: Jeff King @ 2011-09-27 2:38 UTC (permalink / raw)
To: Jay Soffian
Cc: David Aguilar, Nguyen Thai Ngoc Duy, git, Michael Haggerty,
Junio C Hamano, Jakub Narebski
On Mon, Sep 26, 2011 at 10:13:44PM -0400, Jay Soffian wrote:
> > We could allow arbitrary shell code like:
> >
> > [include-if "test `uname -s` -eq Darwin"]
> >
> > Very flexible, though it makes me think we are getting a little
> > overboard. And it's an extra shell invocation whenever we read the
> > config, which is ugly.
>
> I would think git could just learn a few useful defines at the time of
> compile, such as e.g. OS_Darwin would be more than sufficient.
Yeah, I think that is probably more sane. We don't collect the
information now, but it probably wouldn't be that hard (at the very
worst, it would probably just involve running "uname" at build time).
> I can also give you another use use case. I keep all my work repos
> under ~Work/ and I want my user.email on all those to be my work email
> addy, and all other repos on my system I want to use my personal email
> address. So my ~/.gitconfig has my personal email address and then 99%
> of the time I forget to configure the repos under ~/Work correctly.
> That said, I'm not sure how the config include would help this...
You would need to provide git with some condition about which address
should be used. It sounds like the repo directory is the best bet. So
maybe something like:
[include-ifrepo "/home/jsoffian/Work/*"]
or something. Maybe that's too gross. I dunno.
FWIW, this hack would work even with current git:
cat >bin/git <<\EOF
#!/bin/sh
case "`git rev-parse --show-toplevel`" in
"$HOME/Work/*")
set -- -c user.email=whatever "$@"
;;
esac
exec /path/to/real/git "$@"
EOF
which would actually work with most of the conditionals that have been
mentioned in this thread. But it's kind of nasty.
-Peff
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2011-09-27 2:38 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-09-23 19:58 config-file includes Jeff King
2011-09-26 10:45 ` Nguyen Thai Ngoc Duy
2011-09-26 12:36 ` Jeff King
2011-09-26 19:21 ` David Aguilar
2011-09-26 20:05 ` Jeff King
2011-09-26 21:12 ` Junio C Hamano
2011-09-27 2:13 ` Jay Soffian
2011-09-27 2:38 ` Jeff King
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).