Git Usage and Best Practices#
This document outlines Git configuration, best practices for commit signing with GPG and 1Password, and useful Git commands relevant to this dotfiles setup.
Table of Contents#
- Git Usage and Best Practices
Core Git Configuration#
Key Git settings are managed by chezmoi via the dot_gitconfig.tmpl template file, which generates ~/.gitconfig.
This configuration generally promotes trunk-based development and a linear Git history.
Common global settings include:
# Example from dot_gitconfig.tmpl (values are templated)
[user]
name = {{ .name | quote }}
email = {{ .email | quote }}
signingkey = {{ (onepasswordRead "op://Personal/Git GPG Key/key_id").stdout | trim | quote }} # Fetched from 1Password
[commit]
gpgsign = true # Sign all commits by default
[pull]
rebase = true # Prefer rebase over merge on pull
[rebase]
autoStash = true # Automatically stash changes before rebase
[push]
default = current # Push the current branch to a branch of the same name
followTags = true # Push tags that point to commits being pushed
[branch]
autosetupmerge = false # Do not automatically set up merge configurations
autosetuprebase = always # Always rebase when pulling on new branches
[core]
autocrlf = input # Handle line endings correctly
# ... other settings ...
[remote "origin"]
prune = true # Remove remote-tracking branches that no longer exist on the remote
- The specific template is located at:
{{ .chezmoi.sourceDir }}/dot_gitconfig.tmpl. - Refer to the Git Reference documentation for details on these settings.
Commit Signing with GPG and 1Password#
Signing Git commits cryptographically verifies the committer's identity. This setup uses GPG for signing, with the GPG key ID managed via 1Password.
1. Generating or Importing Your GPG Key#
If you don't have a GPG key, generate one:
gpg --full-gen-key
Follow the prompts. An ECDSA key with nistp256 curve is a good modern choice. Ensure you use a strong passphrase and store it securely (e.g., in 1Password).
If you have an existing GPG key, ensure it's in your GPG keyring.
2. Adding Your GPG Key ID to 1Password#
Once you have a GPG key, get its Key ID:
gpg --list-secret-keys --keyid-format LONG "Your Name" # Or your email
Output will look like:
sec nistp256/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX YYYY-MM-DD [SCA]
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
uid [ultimate] Your Name <your.email@example.com>
ssb nistp256/YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY YYYY-MM-DD [E]
The long Key ID is XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX (the 40-character string).
Store this Key ID in 1Password. For example, create a "Secure Note" or "Login" item named "Git GPG Key" and add a field/label (e.g., key_id) with your GPG Key ID as the value.
See docs/1password-usage.md for more on storing items in 1Password.
3. Configuring Git to Use the GPG Key (via chezmoi and 1Password)#
As shown in the "Core Git Configuration" section, dot_gitconfig.tmpl is set up to fetch the user.signingkey from 1Password:
[user]
signingkey = {{ (onepasswordRead "op://Personal/Git GPG Key/key_id").stdout | trim | quote }}
Ensure the 1Password item path (op://Personal/Git GPG Key/key_id) in your dot_gitconfig.tmpl matches where you stored the key ID in 1Password.
chezmoi apply will populate your ~/.gitconfig with this signing key.
4. Adding GPG Public Key to GitHub#
To have GitHub show your commits as "Verified":
- Export your GPG public key:
gpg --armor --export XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # Use your Key ID - Copy the entire output (starting with
-----BEGIN PGP PUBLIC KEY BLOCK-----). - Go to GitHub GPG keys settings and add the new GPG key.
5. GPG Agent Configuration#
To avoid entering your GPG passphrase for every commit, configure the gpg-agent to cache it. chezmoi manages ~/.gnupg/gpg-agent.conf:
# Example content for gpg-agent.conf.tmpl
# Managed by chezmoi
pinentry-program {{ .pinentryProgram | quote }} # Path to pinentry, templated by chezmoi
default-cache-ttl 10800 # Cache passphrase for 3 hours
max-cache-ttl 10800 # Max cache time
chezmoi templates can determine the correct pinentry-program path based on your OS.
After changes, you might need to restart the agent: gpgconf --kill gpg-agent.
6. Troubleshooting GPG Signing#
- Error:
gpg failed to sign the dataorInappropriate ioctl for device: Ensureexport GPG_TTY=$(tty)is in your shell configuration (e.g.,~/.exportsor~/.zshrc, managed bychezmoi). This allows GPG to prompt for a passphrase in the current terminal.
Restart your shell or source the updated file.# Ensure this line is in a chezmoi-managed shell startup file: # export GPG_TTY=$(tty) - No Pinentry Program Found: Ensure
pinentryis installed (e.g.,brew install pinentry-macon macOS) andgpg-agent.confpoints to the correct program. - Secret Key Not Available: Verify the key ID in
~/.gitconfigmatches a private key in yourgpg --list-secret-keysoutput.
GitHub CLI Authentication (gh auth login)#
While Git uses SSH or HTTPS (often with a credential helper) for repository access, the GitHub CLI (gh) requires its own authentication.
gh auth login
Follow the prompts. Authenticating with a web browser (HTTPS) is often simplest.
Refer to docs/github-usage.md for more on using gh.
Common Git Workflows and Useful Commands#
Basic Workflow#
git pull # Fetch and integrate changes from remote
git add . # Stage all changes in the current directory
# Or git add <file1> <file2> ... to stage specific files
git commit -S -m "Your descriptive commit message" # Create a signed commit
git push # Push changes to the remote repository
Branching#
- Create a new branch and switch to it:
git checkout -b new-feature-branch - Switch to an existing branch:
git checkout main - Delete a local branch (after merging):
git branch -d feature-branch # Safe delete (only if merged) git branch -D feature-branch # Force delete - Push a new local branch to remote and set up tracking:
git push -u origin new-feature-branch
Stashing Changes#
Temporarily save uncommitted changes:
git stash push -m "WIP: some changes for later"
git stash list
git stash apply stash@{0} # Apply a specific stash
git stash pop # Apply the latest stash and remove it from the list
git stash drop stash@{0} # Remove a specific stash
Viewing History#
- Compact log view:
(Consider creating a Git alias likegit log --oneline --graph --decorate --allgit lafor this.) - View changes for a specific commit:
git show <commit_hash> - View changes for a specific file:
git log -p -- <file_path>
Squashing Commits#
Combine multiple commits into a single one, often done before merging a feature branch.
- Interactively rebase onto
main(or your target branch), squashing commits from your current feature branch:
In the interactive editor, change# Assuming you are on your feature branch that branched off main git rebase -i mainpicktos(squash) orf(fixup) for commits you want to merge into the preceding one. Edit commit messages as needed. - Force push (with lease) if you've rewritten history on a shared branch (use with caution):
git push --force-with-lease
Alternatively, the example from the previous version for squashing all commits on a branch into one based on main:
# git checkout your-feature-branch
# git reset $(git merge-base main $(git branch --show-current))
# git add .
# git commit -S -m "New single commit message for the feature"
# git push --force-with-lease origin your-feature-branch
Tags#
Create lightweight or annotated tags for releases:
git tag v1.0.0 # Lightweight tag
git tag -a v1.0.1 -m "Version 1.0.1 release" # Annotated tag (signed if gpgsign=true)
git push origin v1.0.1 # Push a specific tag
git push --tags # Push all tags
Resources#
- Pro Git Book: https://git-scm.com/book/en/v2 (Excellent, comprehensive guide)
- Git Reference Documentation: https://git-scm.com/docs
- GitHub GPG Signing Documentation: https://docs.github.com/en/authentication/managing-commit-signature-verification
- 1Password Documentation: See
docs/1password-usage.md - GitHub CLI Documentation: See
docs/github-usage.md
This guide covers key Git practices for this dotfiles setup. Consistent use of signed commits and a clean history are encouraged.