DEV Community

Thomas H Jones II
Thomas H Jones II

Posted on • Originally published at thjones2.blogspot.com on

Implementing (Psuedo) Profiles in Git

I'm an automation consultant for an IT contracting company. Using git is a daily part of my work-life. Early on, things were easy: set up my (one) identity in GitHub, GitLab, BitBucket, etc. depending on the requirements of the customer. I always just used my personal, task-specific email address for each (makes reconstructing my contribution-life easier). Then things started shifting, a bit. Some customers wanted me to use my corporate email address as my ID. Annoying, but not an especially big deal, by itself. Then, some wanted me to use their privately-hosted repositories and wanted me to use identities issued by them.

Personally, I'm a fan of git-over-ssh. I also like to use signed-commits (whether my customers require them or not). Unfortunately, when you move to customer-prescribed or -issued(!) SSH and GPG keys, things get a bit more annoying.

While git has mechanisms for using per-project keys, it means abandoning the stuff you've set via git config --global …. If your customer only has one project they want you to contribute to, git config --local … is annoying but not especially cumbersome or prone to accidentally committing with the wrong signature (fortunately, you can't commit with the wrong SSH key, since you'll get a big, fat permission denied type of error if you try). However, most of my customers have multiple projects they want me to make commits to.

Having to remember to git config --local … for multiple projects introduces more opportunities to forget to do so. Which means it also introduces more opportunities to apply an incorrect signature to a commit. For many tools, I'd set up a new profile, virtual-environment, etc. Unfortuntately, git doesn't (directly) have that capability. That said, you can fake that capability by using the git client's includeif configuration directive (and, if you're like me, using ${HOME}/.ssh/config).

SSH Setup:

  1. Generate – or retrieve(!) – a project-specific SSH key
  2. Open your ${HOME}/.ssh/config file for editing
  3. Add a stanza similar to the following:
Host gitlab.<private.domain>
IdentityFile /home/<USERID>/.ssh/<PRIVATE_KEY_NAME>
AddKeysToAgent yes

Note: The AddKeysToAgent config-statement is iffy. While it injects the key into your keychain and relieves you of having to provide your key's password (you did set a password on the key, right?) every time you do an operation against the remote, the order the keychain presents it may not be adequately predictable. If you have a bunch of SSH keys (say, more than three) in your keychain, you may find that you start getting "too many authentication failures" errors from the remote's SSH authentication process.

Git Setup:

  1. Create a project-group git config file (say, "/home/<USERID>/.gitconfig-<PROJECT_GROUP>")
  2. Create a directory specific to the project-group (e.g., "/home/<USERID>/GIT/<PROJECT_GROUP>")
  3. Add the configuration-contents you'd normally place in "/home/<USERID>/.gitconfig" into this file: any competing directives in the include file will override the "/home/<USERID>/.gitconfig" file's contents.
  4. Tell git the conditions under which to use the project-group config file
$ git config --global includeIf."gitdir:/home/<USERID>/GIT/<PROJECT_GROUP>".path \
/home/<USERID>/.gitconfig-<PROJECT_GROUP>

The above is both ughly and not especially clearly-documented (literally tried a half-dozen iterations before finding the right command: hand-editing might be mo-easier

Profit:

Once the above is done, any git operations performed within the "/home/<USERID>/GIT/<PROJECT_GROUP>" directory should be governed by the directives in the "/home/<USERID>/.gitconfig-<PROJECT_GROUP>" file:

  • If you're using project-specific SSH keys, a git clone</font> will succeed
  • If you're using commit-signing, the signed commit will have the project-specific signature applied (use git log --show-signature to verify)

If neither of the preceeding is true, something's not set up correctly in your pseudo-profile.

Top comments (0)