Once more, I wanted to push a small change to a Git repository to which the owner gave me write access. This repo is currently the only one for me, for which I need to use https as transport protocol and therefore have to enter username and password for each and every push.

On the other hand, I keep all my valuable credentials in Pass: The Standard Unix Password Manager for a couple of years now. It stores them with strong GPG encryption on my disk, is nicely integrated into Firefox by a plugin and there is also a KDE plasma widget available, created by my fellow KDE developer Daniel Vrátil. So why can’t Git read (I was about to use pull here, but that might be confusing in the context of Git) the credentials from my password store? There must be a way!

Next, I started reading the documentation about git-credentials which seems to provide all that is needed. Just that pass was not on the list of helpers. Reading the specs, I expected it to be pretty easy to write a small wrapper that solves the issue. But: this sounds like a problem too obvious and to be solved already. So the search began.

Using all kinds of combinations of git-credentials, pass, password-store and some more I don’t remember, I always ended up on some general Git documentation, but no sign of what I was looking for. So maybe, it really does not exist (oh, I have not consulted the yellow pages) and I have to develop and provide it to the internet community myself.

Reading the specs more thoroughly – now that i need to understand the interface to such a wrapper – I came across the search pattern used by Git to find those credential helpers. I was tempted to name mine git-credential-pass since it is a helper for pass. But wait: one more trial using this name as pattern for the search engine of choice, et voilà: I found pass-git-helper, a nice python based script which does exactly what I looked for (and maybe a few more things).

It already exists for a couple of years, so I wondered if I can find it in my distro’s repo to save some time and get automatic updates. Bad news, it does not exist.

So it was a matter of git clone, manual installation and configuration to gain some more integration and automation.

% git clone https://github.com/languitar/pass-git-helper.git
% sudo python3 setup.py install
# test drive
% pass-git-helper get
protocol=https
host=git.example.com
^D
Unable to parse mapping file
% 

Ah, I needed that mapping file, it does not work without it. OK, let’s do it then.

% mkdir -p ~/.config/pass-git-helper
% cat > ~/.config/pass-git-helper/git-pass-mapping.ini
[*]
Target=${host}
^D
% pass-git-helper get
protocol=https
host=git.example.com
^D
password=git-password
username=login: git-username
%

Hmm, works, but the lead-in text login: for the username is not a good idea to be returned to Git. Problem: I have that in most of my pass records and the firefox plugin can cope with it pretty well. But that could be tweaked by an extension to the mapping.ini file based on my favorites: regular expressions.

 % cat > ~/.config/pass-git-helper/git-pass-mapping.ini
[DEFAULT]
username_extractor=regex_search
regex_username=^login: (.*)$

[*]
target=${host}
^D
% pass-git-helper get
protocol=https
host=git.example.com
^D
password=git-password
username=git-username

Looks good to me. Now on to Git:

% git credential fill
url=https://git.example.com
^D
# at this point, the normal 'enter username' dialog popped
# up, which I cancelled
error: unable to read askpass response from '/usr/lib/ssh/ssh-askpass'
Username for 'https://git.example.com': ^C

Now it was just a matter to configure Git to use the new helper. This is done by setting the Git credential.helper option, which can be achieved with the following command executed in the top directory of the project:

git config credential.helper '!pass-git-helper $@'
# test drive
% git credential fill
url=https://git.example.com
^D
protocol=https
host=git.example.com
username=git-username
password=git-password

Yeah! That’s it. Now I am prepared for the next git push to that repo.

The search engine btw, seems to have learned in the meantime: now when I enter my initial search arguments it presents pass-git-helper right away. Maybe other users benefit from this learning as well.

It’s just a matter of selecting the right search terms