GitHub CLI vs Git Credential Manager - Which is better as a credential manager?
2022-08-16

TL;DR

Git Credential Manager, also known as gcm, is the most popular, multi-platform credential helper. GitHub CLI, also known as the gh command, can also be used as a credential manager. These two are officially recommended by GitHub, but which one should I pick?

After some trials and errors, I decided to use gcm over gh as it’s more secure and straightforward. Note that you still have to run gh auth login to use gh, even if gcm is chosen as the credential helper for Git. And don’t get me wrong, gh is an awesome cli tool. My main focus in this article is about the credential management functionality.

1. Two tokens and osxkeychain

Before diving into the details, let’s talk about osxkeychain first.

On macOS, osxkeychain is set at the system level by default, in both default git and homebrew git.

Homebew Git

$ /opt/homebrew/bin/git config --list --show-origin | grep credential.helper
file:/opt/homebrew/etc/gitconfig	credential.helper=osxkeychain
file:/Users/sho/.gitconfig	credential.helper=!git-credential-manager-core
$ cat /opt/homebrew/etc/gitconfig
[credential]
	helper = osxkeychain

Xcode Git

$ /usr/bin/git config --list --show-origin | grep credential.helper
file:/Applications/Xcode.app/Contents/Developer/usr/share/git-core/gitconfig	credential.helper=osxkeychain
file:/Users/sho/.gitconfig	credential.helper=!git-credential-manager-core
$ cat /Applications/Xcode.app/Contents/Developer/usr/share/git-core/gitconfig
[credential]
	helper = osxkeychain

Due to this configuration, the first time you clone a repo after authenticating with gh or gcm, a new OAuth access token will be stored in the Keychain.app in addition to the one that’s already generated for the OAuth app.

gh

With gh, this is the reason why you can still clone a private repo after running gh auth logout -h github.com and can be really confusing. Also, with gh, the token in the ~/.config/gh/hosts.yml file and the token in the Keychain.app (Internet password for github.com) are different (unsure why).

gcm

With gcm, there’s no concept of logging out. To delete the authentication token you should manually remove it from the credential store. No confusion. Also, with gcm, these tokens (application password and the Internet password for github.com) are the same.

2. How to store credentials

gh

I’ve briefly covered this topic in the previous section - With gh, after authenticating using gh auth login, the credential will be stored in the configuration file ~/.config/gh/hosts.yml as a plain text format.

Note that this may change in the future, see feat: Support for storing OAuth token in encrypted keychain for more info.

gcm

On the other hand, gcm stores its credentials in the Keychain.app on macOS and Windows Credential Manager on Windows so it’s much more secure.

There’s no default credential store for Linux though. If your Linux machine is owned by you and there’s no other users, plaintext can be an option - See Credential stores for more details.

Do you want to use Keychain.app on macOS and plaintext on Linux? Use [include] directive in your ~/.gitconfig. With this, you can load environment specific configuration files e.g. ~/.gitconfig.local.

$ tail -n 2 ~/.gitconfig
[include]
    path = ~/.gitconfig.local

Then only on your Linux machine, add credentialStore = plaintext to ~/.gitconfig.local:

$ cat ~/.gitconfig.local
[credential]
	credentialStore = plaintext

If you choose plaintext, your credential will be stored in ~/.gcm/store/git/https/github.com/[username].credential.

3. The helper path

gh

Due to the reason explained in https://github.com/cli/cli/blob/v2.14.3/pkg/cmdutil/factory.go#L42-L57, gh auth setup-git will add the absolute path to the gh binary in your local ~/.gitconfig, for example:

[credential]
	helper = !/opt/homebrew/bin/gh auth git-credential

This can be a problem when you manage your dotfiles using GitHub and want to use a single .gitconfig across multiple environments.

Btw, the ! at the beginning is explained in Git - gitcredentials Documentation:

If the helper string begins with “!”, it is considered a shell snippet, and everything after the “!” becomes the command.

gcm

On the other hand, with gcm, the installation path is the same at least both on macOS and Linux. On macOS the git-credential-manager-core binary is installed in /usr/local/share/gcm-core and the symlink to the binary will be created in /usr/local/bin. On Linux the git-credential-manager-core binary is installed in /usr/local/bin, either using the tarball or the .deb package.

So your ~/.gitconfig should be simple, just set the absolute path to the binary as the helper:

[credential]
    helper = /usr/local/bin/git-credential-manager-core

Conclusion

As I said in the beginning, in my impression gcm is much more secure and straightforward as a credential store. Hope this helps!