I was trying to get the 1Password CLI to hand over my GitHub token to the gh
command, and configure Git to use the gh
command as a credential helper. But I was running into an issue when I would run gh auth git-credential
from the command line and it would produce the correct credentials, but when I had the following in ~/.gitignore
a git clone
would still prompt me for my username and password:
[credential "https://github.com"]
helper = /usr/bin/gh auth git-credential
To do some debugging, I first enabled trace logging in Git by setting the GIT_TRACE
environment variable to true
:
GIT_TRACE=true git clone https://github.com/wheelerlaw/some-private-repo
which would yield output that looked like this:
$ GIT_TRACE=true git clone https://github.com/Kong/khcp.git
15:19:00.344373 git.c:460 trace: built-in: git clone https://github.com/Kong/khcp.git
Cloning into 'khcp'...
15:19:00.347803 run-command.c:655 trace: run_command: git remote-https origin https://github.com/Kong/khcp.git
15:19:00.349893 git.c:750 trace: exec: git-remote-https origin https://github.com/Kong/khcp.git
15:19:00.349939 run-command.c:655 trace: run_command: git-remote-https origin https://github.com/Kong/khcp.git
15:19:00.625485 run-command.c:655 trace: run_command: '/usr/bin/gh auth git-credential get'
However, it wouldn't show any debugging output of the data passed to/from the credential helper. To do this, I wrote a small Python script that acted as a wrapper around the credential helper:
#!/usr/bin/env python3
import sys
import subprocess
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
def etrace(str):
eprint("[TRACE] ", str)
args = ['/usr/bin/gh', 'auth', 'git-credential'] + sys.argv[1:]
process = subprocess.Popen(args,
stdout=subprocess.PIPE,
stderr=sys.stderr,
stdin=subprocess.PIPE,
universal_newlines=True)
etrace(args)
for input in sys.stdin:
etrace(input.strip())
process.stdin.write(input)
process.stdin.close()
etrace("Done sending input...")
for output in process.stdout.readlines():
etrace("Printing output...")
etrace(output.strip())
print(output.strip())
etrace("Done receiving output...")
return_code = process.poll()
etrace("Return code: " + str(return_code))
exit(return_code)
Then, I modified my ~/.gitconfig
file to call the Python script as the credential helper:
[credential "https://github.com"]
helper = /home/wheeler/wrapper.py
Now when I do the same git clone
command with the trace debugging enabled, I can see how git
and gh auth git-credential
are talking to each other:
$ GIT_TRACE=true git clone https://github.com/Kong/khcp.git
15:54:33.973855 git.c:460 trace: built-in: git clone https://github.com/Kong/khcp.git
Cloning into 'khcp'...
15:54:33.987155 run-command.c:655 trace: run_command: git remote-https origin https://github.com/Kong/khcp.git
15:54:33.989509 git.c:750 trace: exec: git-remote-https origin https://github.com/Kong/khcp.git
15:54:33.989539 run-command.c:655 trace: run_command: git-remote-https origin https://github.com/Kong/khcp.git
15:54:34.191478 run-command.c:655 trace: run_command: '/home/wheeler/test.py get'
[TRACE] ['/usr/bin/gh', 'auth', 'git-credential', 'get']
[TRACE] protocol=https
[TRACE] host=github.com
[TRACE] Done sending input...
[TRACE] Done receiving output...
[TRACE] Return code: 1
This helped me realize that I needed to set my helper
line to the following to allow the gh
command to get the token from 1Password:
[credential "https://github.com"]
helper = /usr/bin/op plugin run -- gh auth git-credential
Hope this helps