Hacker News new | past | comments | ask | show | jobs | submit login

I found this user management strategy somewhere, and it's been working great for me:

  git config --global --unset user.name
  git config --global --unset user.email
  git config --global --unset user.signingkey

  git config --global user.useConfigOnly true

  git config --global user.<id>.name "<name>"
  git config --global user.<id>.email "<email>"

  git config --global alias.identity '! git config user.name "$(git config user.$1.name)"; git config user.email "$(git config user.$1.email)"; :'
So given that I have created two users, e.g. personal and work I run:

  git identity work
in repos that need the work name/e-mail, and

  git identity personal
in the ones that are private.



I find it much easier to use direnv and set GIT_AUTHOR_EMAIL in each of ~/work/.envrc and ~/personal/.envrc No need to reconfigure every repo this way.


Git has conditional includes based on path[1]. My configuration is like:

On ~/.gitconfig

  [user]
    name = personal
    email = personal@example.com

  [includeIF "gitdir:~/workspace/"]
    path = ~/work.gitconfig

Then on ~/work.gitconfig

  [user]
    name = workname
    email = work@example.com
[1] https://git-scm.com/docs/git-config#_conditional_includes


Just a note of caution, when this feature was added tools based on libgit2 did not understand it. I just checked now, libgit2 eventually added support (though it took 5 months since I filed the ticket). But if you're using any tools that have a 3-year-old version of libgit2 they might not understand it.


Woah, this is neat!


I do the same. Also remember the following keyword if you use nested .envrc files: source_up

If you don't use this in any nested envrc files, the settings don't carry over which means your git settings are not maintained. It is kind of an escape hatch as the parent files are not verified in the same way normal envrc files are, but I have found the trade off to be worth it


I also appreciate using `git whoami` to check the current identity settings:

    $ git whoami 
    GIT_COMMITTER_IDENT=Mel Smith <mel@example.org>
    GIT_AUTHOR_IDENT=Mel Smith <mel@example.org>
`whoami` can be implemented via a simple alias:

    git config --global alias.whoami = "! git var -l | grep '^GIT_.*_IDENT'"


Nice! I was thinking of something like this recently, but decided instead to completely divorce personal and work projects. It’s nice to close the work laptop and go open the personal laptop knowing it’s impossible to cross the streams, as well as for the ritual.


Good idea as it makes the trees "self describing".

But: does this edit a file that can appear in .gitignore or are you uploading this to affect all your collaborators?


It writes to `.git/config` in the local repo. (.git/ is ignored by default, obviously.)


> git config --global alias.identity '! git config user.name "$(git config user.$1.name)"; git config user.email "$(git config user.$1.email)"; :'

Why `; :` at the end?


I'm not entirely sure, but `:` means "true" in bash, and if I omit it, something like this happens:

  $ git config alias.foo '! echo "$1";'
  $ git foo bar
  bar
  echo "$1";: bar: command not found
Whereas if I end with `; :` then it works as expected:

  $ git config alias.foo '! echo "$1"; :'
  $ git foo bar
  bar
It seems to execute the last argument (`bar`) as a command without the `:` at the end, and I don't have a `bar` command on my PATH so it angrily fails with exit code 127. If it instead executes `:` however, that will make it happily exit with 0.

It seems to be a Git alias quirk, but I may be incorrect here.


Seems it's to allow implicit and explicit use of arguments passed to alias. Git does the following to the alias string[1]:

  argv_array_pushf(out, "%s \"$@\"", argv[0]);
So, you can have aliases like `!grep foobar` to automatically accept arguments or aliases like yours that use arguments explicitly.

I've done aliases like `!bash -c 'foo $1' sh` before, but on seeing yours, I see that it was unnecessary to re-wrap with bash.

[1] https://github.com/git/git/blob/e31aba42fb12bdeb0f850829e008...


Huh I had no idea $1/$2/etc worked as-is in an alias. The advice I learned years ago for dealing with any alias that needs to do something custom with parameters is to write it like

  git config alias.foo '!f() { actual command goes here }; f'
as that will pass all the args to the shell function. But if git is already setting it up so the args work then suffixing the alias with ";:" seems simpler.


> The advice I learned years ago

Being able to use $1/$2/etc directly might be a relatively new development.

EDIT: Or maybe not. This might have been doable since 2010:

https://github.com/git/git/commit/8dba1e634af1d973a47fca616a...


2010 is still “new development” to me


Interesting! Thanks for digging up the code.


I've been doing the same, this it's pretty good IMO.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: