My git workflow

jacekpoz


published: 2023-11-12


last updated: 2024-05-23

time to read: 6:45 minutes


views:


# TL;DR

(if you use nixos)

git module (uses home-manager) and the config

ssh module and the config


Over the past few months I helped a few people learn how to setup git so I decided to put this together instead of explaining my workflow each time.

Hopefully this can serve as an inspiration to others or a reference to come back to if you forget something.

This is not meant to be a git guide (even though it partly was one before). If you're looking for that read the official git book.

After you initialize your git repository and add a remote without any other setup you might see an error akin to this:


    user@example.com: Permission denied (publickey).
    fatal: Could not read from remote repository.

    Please make sure you have the correct access rights
    and the repository exists.
  

which means you need to generate and setup an ssh key.


# SSH key

ssh-keygen -t ed25519 -f ~/.ssh/<keyfile> is what I usually do. Some people might recommend making a single key for all git forges, I keep them separate, you do you.

After running the above you'll be asked to enter a passphrase or leave it empty for no passphrase. I recommend always setting a strong passphrase (could be generated with KeePassXC) and adding it to a password manager like the aforementioned. Copying and pasting that passphrase isn't a big deal, having your unlocked key stolen is (if it is a big deal check out the SSH Agent section).

After doing that you'll have 2 files, ~/.ssh/<keyfile> (the private key) and ~/.ssh/<keyfile>.pub (the public key). As the name suggests, DO NOT share the first one with anyone, it must be kept secure. If that leaks and isn't protected by a password or the password is cracked, whoever has the file can modify the git history as you (and possibly more).

Now you want to add your public key to your preferred git forge. Here's how to do that on github, gitlab and codeberg (which should work for all forgejo instances). All of these instructions are pretty similar and you should be able to figure it out after the first time.

What we need to do now is tell git which ssh key to use when connecting to our preferred forge.


# Remotes

On my machine I alias all the remotes in my ssh config which both makes them shorter and allows me to add the ssh key to that forge. The nix config is at the top but if you don't use nix this is what you add for each remote to either /etc/ssh/ssh_config or (preferably) ~/.ssh/config:


    Host example
        HostName git.example.com
        User git
        IdentityFile /path/to/private_key
  

For example, this is what I'd do for codeberg:


    Host codeberg
        HostName codeberg.org
        User git
        IdentityFile ~/.ssh/codeberg
  

and change my git remote: git remote set-url origin codeberg:nickname/repo (if you added it already).

Now you should finally be able to push your changes! That wasn't so bad, was it? This workflow might not be ideal to you but it's simple and convenient enough for me and I think it should be alright for new users.

If all you want to do is push a few commits to a repo, this should be enough and you can stop reading. But, if you want to learn how to create an SSH Agent that will automatically supply the passwords for your keys or how to sign your commits with an SSH key, read on!


# SSH Agent

An SSH Agent is a program that keeps track of your keys' passphrases. There's plenty agents out there but this post is about my workflow - let's talk about KeepassXC again! If you have any issues here, make sure to consult the SSH Agent integration section of their FAQ.

First off, enable the actual SSH Agent. I use ssh-agent - the official one included with OpenSSH. The Arch Wiki has a great article on the topic. I recommend (and myself use) the systemd service.

When you're done with that, enable the KeepassXC integration under Settings -> SSH Agent -> Enable SSH Agent integration. I remember having some issues with that the first time - the FAQ should have all the answers.

Now you're ready to create some entries for your keys. I group all of them under an ssh directory, you do you. The entry should have some descriptive title and, of course, the passphrase to your key (if you followed the previous steps that entry is already created).

The next step is linking your key to that entry. There's two ways to go about this - either give KeepassXC the path to your private key or give it the whole file. This is the one exception to what I said earlier - it's safe to share your private key with KeepassXC, as long as you keep your database safe as well.

If you decide to use the key's path, the key will need to stay in ~/.ssh, which means if you have multiple machines, move to a different one or reinstall you must remember to move not only your KeepassXC database but also your ~/.ssh directory.

If you give KeepassXC the file, this means you can (probably) safely remove the private key and not worry about the ~/.ssh directory at all. I still keep them there though, better safe than sorry. To add the private key file to your entry, go into its settings (right click and Edit entry or Ctrl+E), go into the Advanced section and in the bottom Attachments pane click Add and find your private key file (the one without an extension).

Then, regardless of which method you picked, go into the entry's SSH Agent section. The 2 top options are in my opinion something most people will want, the next 2 are disabled in my database and less convenient. If you added the private key file to the current entry, in the Private key menu pick Attachment and choose (most likely) the only one there. Otherwise, choose External file and either manually type the path or click on Browse and find it.

Click on the Add to agent button and you should see the corresponding public key in the box below. If you picked the path option, you're done. You should now be able to freely use that ssh key only when the KeepassXC database is open. If you added the private key as an attachment and aren't using nix, write that public key down in some file and set the IdentityFile part of your alias to its path. If you are using nix, feel free to steal my module.


# Signing your commits

When you sign your commits with a GPG / SSH key you cryptographically verify that you were the one to create that commit. Git recently added the ability to sign commits with SSH keys. They're much simpler to create and manage than GPG keys and are not bound to an email address, which is why I use them - I won't explain how to sign commits with a GPG key.

First follow the above again to create a new SSH key and add it to an SSH Agent. Then configure the following git config variables: git config --global commit.gpgsign true and git config --global gpg.format ssh. --global will set these in your ~/.config/git/config instead of a single repository.

Set your signing key: git config --global user.signingkey "key::<key>", <key> being the public key. Now git will sign commits with that key but you still need to go to your forge and tell it that this key belongs to you. Without this you'll get a warning about your commits being unverified. To do that check your forge's documentation, the process should be similar (if not identical) to adding an ssh key for connections.


If you got stuck on some part, find this too hard or have any suggestions for this post, feel free to contact me. All my public contact information is on the main page, I'd be more than happy to help you out. :-)

(c) 2024 jacekpoz