Hacker News new | ask | show | jobs
by diggan 980 days ago
Different gitconfigs per path on disk, git automatically uses the right identity depending on where you are on disk. Allows you to separate all projects into different users and every repository within those directories will use the specified user.

Main/default config (~/.gitconfig):

  [user]
    email = git@victor.earth
    name = Victor Bjelkholm

  [includeIf "gitdir:/home/user/projects/user-a/"]
    path = /home/user/.gitconfig-user-a

  [includeIf "gitdir:/home/user/projects/user-b/"]
    path = /home/user/.gitconfig-user-b
Then in .gitconfig-user-{a,b}:

  [user]
    name = UserA
    email = UserA@DomainA.local

  [core]
    sshCommand = ssh -i /home/user/.ssh/user_a_id_ed25519
Or, even more separation, create separate users/accounts on the computers you use.
4 comments

You can also filter based on the remote URL! I find this much more useful than the location of the directory on disk.

  ; include only if a remote with the given URL exists (note
  ; that such a URL may be provided later in a file or in a
  ; file read after this file is read, as seen in this example)
  [includeIf "hasconfig:remote.*.url:https://example.com/\*"]
      path = foo.inc
  [remote "origin"]
      url = https://example.com/git*
Handy, didn't know about that, thanks for sharing!

The reason for doing it by location is probably because my directory structure for projects look something like this:

/home/user/projects/organization/project

so github.com/victorb/neat-project would go into /home/user/projects/victor/neat-project

So my solution is tailored to that structure I suppose :)

Also learning the power of includeIf

At home (I mean a personal box I for personal project and some other public contributions), my directory structure is like:

    ~/sources/forge/organisation/project
where `sources` has the same meaning as your `/home/user/projects` ; and your example will end up here to

    ~/sources/github.com/victorb/neat-project
The structure used has some great influence on solution adopted I think :)
Great tip!

But how could I also select the config for an initial clone of a repo based on the repository address?

Note that this doesn't work if you have a default IdentityKey specified in your ssh config, because `-i` is always unioned with the default IdentityKey in that case (which is a feature, not a bug, of how IdentityKey / `-i` work) and it's possible that that key will be sent to the server before the one you specified in `-i`

Say my IdentityKey that I use for regular ssh is also associated with GH user foo, and then I have the above gitconfig to use a different key associated with GH user bar under certain directories. It's still possible that ssh will try the IdentityKey before the `-i` key when I do git operations under those directories, which means GH will identify me as user foo anyway.

I'm not sure what order ssh uses to sort the union, if any, but at least in my case it seems to always use the IdentityKey before the `-i` key even though it prints them in the opposite order initially (according to `-vvvv`).

And no, `-o IdentitiesOnly=yes` doesn't affect this behavior.

Note that includeIf support can still be spotty in third-party tools/IDEs. Be sure to check that it works everywhere you need it to.
Last I looked, Xcode still doesn't support this. Having it present in the .gitconfig breaks SPM for initial clones and updates.
Does it work with subdirectories?
Yes, anything in /home/user/projects/user-b/ and deeper will use the configured git config for that path.
Awesome, it seems this is the way to go for me then!