mauvehed's dotfiles for personal and work environments
1# Git Usage and Best Practices
2
3This document outlines Git configuration, best practices for commit signing with GPG and 1Password, and useful Git commands relevant to this dotfiles setup.
4
5## Table of Contents
6
7- [Git Usage and Best Practices](#git-usage-and-best-practices)
8 - [Table of Contents](#table-of-contents)
9 - [Core Git Configuration](#core-git-configuration)
10 - [Commit Signing with GPG and 1Password](#commit-signing-with-gpg-and-1password)
11 - [1. Generating or Importing Your GPG Key](#1-generating-or-importing-your-gpg-key)
12 - [2. Adding Your GPG Key ID to 1Password](#2-adding-your-gpg-key-id-to-1password)
13 - [3. Configuring Git to Use the GPG Key (via `chezmoi` and 1Password)](#3-configuring-git-to-use-the-gpg-key-via-chezmoi-and-1password)
14 - [4. Adding GPG Public Key to GitHub](#4-adding-gpg-public-key-to-github)
15 - [5. GPG Agent Configuration](#5-gpg-agent-configuration)
16 - [6. Troubleshooting GPG Signing](#6-troubleshooting-gpg-signing)
17 - [GitHub CLI Authentication (`gh auth login`)](#github-cli-authentication-gh-auth-login)
18 - [Common Git Workflows and Useful Commands](#common-git-workflows-and-useful-commands)
19 - [Basic Workflow](#basic-workflow)
20 - [Branching](#branching)
21 - [Stashing Changes](#stashing-changes)
22 - [Viewing History](#viewing-history)
23 - [Squashing Commits](#squashing-commits)
24 - [Tags](#tags)
25 - [Resources](#resources)
26
27## Core Git Configuration
28
29Key Git settings are managed by `chezmoi` via the `dot_gitconfig.tmpl` template file, which generates `~/.gitconfig`.
30This configuration generally promotes trunk-based development and a linear Git history.
31
32Common global settings include:
33
34```ini
35# Example from dot_gitconfig.tmpl (values are templated)
36[user]
37 name = {{ .name | quote }}
38 email = {{ .email | quote }}
39 signingkey = {{ (onepasswordRead "op://Personal/Git GPG Key/key_id").stdout | trim | quote }} # Fetched from 1Password
40[commit]
41 gpgsign = true # Sign all commits by default
42[pull]
43 rebase = true # Prefer rebase over merge on pull
44[rebase]
45 autoStash = true # Automatically stash changes before rebase
46[push]
47 default = current # Push the current branch to a branch of the same name
48 followTags = true # Push tags that point to commits being pushed
49[branch]
50 autosetupmerge = false # Do not automatically set up merge configurations
51 autosetuprebase = always # Always rebase when pulling on new branches
52[core]
53 autocrlf = input # Handle line endings correctly
54 # ... other settings ...
55[remote "origin"]
56 prune = true # Remove remote-tracking branches that no longer exist on the remote
57```
58
59* The specific template is located at: `{{ .chezmoi.sourceDir }}/dot_gitconfig.tmpl`.
60* Refer to the [Git Reference documentation](https://git-scm.com/docs) for details on these settings.
61
62## Commit Signing with GPG and 1Password
63
64Signing Git commits cryptographically verifies the committer's identity. This setup uses GPG for signing, with the GPG key ID managed via 1Password.
65
66### 1. Generating or Importing Your GPG Key
67
68If you don't have a GPG key, generate one:
69
70```sh
71gpg --full-gen-key
72```
73Follow 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).
74
75If you have an existing GPG key, ensure it's in your GPG keyring.
76
77### 2. Adding Your GPG Key ID to 1Password
78
79Once you have a GPG key, get its Key ID:
80
81```sh
82gpg --list-secret-keys --keyid-format LONG "Your Name" # Or your email
83```
84Output will look like:
85```
86sec nistp256/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX YYYY-MM-DD [SCA]
87 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
88uid [ultimate] Your Name <your.email@example.com>
89ssb nistp256/YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY YYYY-MM-DD [E]
90```
91The long Key ID is `XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` (the 40-character string).
92
93Store 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.
94
95See `docs/1password-usage.md` for more on storing items in 1Password.
96
97### 3. Configuring Git to Use the GPG Key (via `chezmoi` and 1Password)
98
99As shown in the "Core Git Configuration" section, `dot_gitconfig.tmpl` is set up to fetch the `user.signingkey` from 1Password:
100
101```ini
102[user]
103 signingkey = {{ (onepasswordRead "op://Personal/Git GPG Key/key_id").stdout | trim | quote }}
104```
105Ensure 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.
106`chezmoi apply` will populate your `~/.gitconfig` with this signing key.
107
108### 4. Adding GPG Public Key to GitHub
109
110To have GitHub show your commits as "Verified":
111
1121. Export your GPG public key:
113 ```sh
114 gpg --armor --export XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # Use your Key ID
115 ```
1162. Copy the entire output (starting with `-----BEGIN PGP PUBLIC KEY BLOCK-----`).
1173. Go to [GitHub GPG keys settings](https://github.com/settings/keys) and add the new GPG key.
118
119### 5. GPG Agent Configuration
120
121To avoid entering your GPG passphrase for every commit, configure the `gpg-agent` to cache it. `chezmoi` manages `~/.gnupg/gpg-agent.conf`:
122
123```
124# Example content for gpg-agent.conf.tmpl
125# Managed by chezmoi
126
127pinentry-program {{ .pinentryProgram | quote }} # Path to pinentry, templated by chezmoi
128default-cache-ttl 10800 # Cache passphrase for 3 hours
129max-cache-ttl 10800 # Max cache time
130```
131`chezmoi` templates can determine the correct `pinentry-program` path based on your OS.
132After changes, you might need to restart the agent: `gpgconf --kill gpg-agent`.
133
134### 6. Troubleshooting GPG Signing
135
136* **Error: `gpg failed to sign the data` or `Inappropriate ioctl for device`**:
137 Ensure `export GPG_TTY=$(tty)` is in your shell configuration (e.g., `~/.exports` or `~/.zshrc`, managed by `chezmoi`). This allows GPG to prompt for a passphrase in the current terminal.
138 ```sh
139 # Ensure this line is in a chezmoi-managed shell startup file:
140 # export GPG_TTY=$(tty)
141 ```
142 Restart your shell or source the updated file.
143* **No Pinentry Program Found**: Ensure `pinentry` is installed (e.g., `brew install pinentry-mac` on macOS) and `gpg-agent.conf` points to the correct program.
144* **Secret Key Not Available**: Verify the key ID in `~/.gitconfig` matches a private key in your `gpg --list-secret-keys` output.
145
146## GitHub CLI Authentication (`gh auth login`)
147
148While Git uses SSH or HTTPS (often with a credential helper) for repository access, the GitHub CLI (`gh`) requires its own authentication.
149
150```sh
151gh auth login
152```
153Follow the prompts. Authenticating with a web browser (HTTPS) is often simplest.
154Refer to `docs/github-usage.md` for more on using `gh`.
155
156## Common Git Workflows and Useful Commands
157
158### Basic Workflow
159
160```sh
161git pull # Fetch and integrate changes from remote
162git add . # Stage all changes in the current directory
163# Or git add <file1> <file2> ... to stage specific files
164git commit -S -m "Your descriptive commit message" # Create a signed commit
165git push # Push changes to the remote repository
166```
167
168### Branching
169
170* Create a new branch and switch to it:
171 ```sh
172 git checkout -b new-feature-branch
173 ```
174* Switch to an existing branch:
175 ```sh
176 git checkout main
177 ```
178* Delete a local branch (after merging):
179 ```sh
180 git branch -d feature-branch # Safe delete (only if merged)
181 git branch -D feature-branch # Force delete
182 ```
183* Push a new local branch to remote and set up tracking:
184 ```sh
185 git push -u origin new-feature-branch
186 ```
187
188### Stashing Changes
189
190Temporarily save uncommitted changes:
191
192```sh
193git stash push -m "WIP: some changes for later"
194git stash list
195git stash apply stash@{0} # Apply a specific stash
196git stash pop # Apply the latest stash and remove it from the list
197git stash drop stash@{0} # Remove a specific stash
198```
199
200### Viewing History
201
202* Compact log view:
203 ```sh
204 git log --oneline --graph --decorate --all
205 ```
206 (Consider creating a Git alias like `git la` for this.)
207* View changes for a specific commit:
208 ```sh
209 git show <commit_hash>
210 ```
211* View changes for a specific file:
212 ```sh
213 git log -p -- <file_path>
214 ```
215
216### Squashing Commits
217
218Combine multiple commits into a single one, often done before merging a feature branch.
219
220* Interactively rebase onto `main` (or your target branch), squashing commits from your current feature branch:
221 ```sh
222 # Assuming you are on your feature branch that branched off main
223 git rebase -i main
224 ```
225 In the interactive editor, change `pick` to `s` (squash) or `f` (fixup) for commits you want to merge into the preceding one. Edit commit messages as needed.
226* Force push (with lease) if you've rewritten history on a shared branch (use with caution):
227 ```sh
228 git push --force-with-lease
229 ```
230
231Alternatively, the example from the previous version for squashing all commits on a branch into one based on `main`:
232```sh
233# git checkout your-feature-branch
234# git reset $(git merge-base main $(git branch --show-current))
235# git add .
236# git commit -S -m "New single commit message for the feature"
237# git push --force-with-lease origin your-feature-branch
238```
239
240### Tags
241
242Create lightweight or annotated tags for releases:
243
244```sh
245git tag v1.0.0 # Lightweight tag
246git tag -a v1.0.1 -m "Version 1.0.1 release" # Annotated tag (signed if gpgsign=true)
247git push origin v1.0.1 # Push a specific tag
248git push --tags # Push all tags
249```
250
251## Resources
252
253* **Pro Git Book**: [https://git-scm.com/book/en/v2](https://git-scm.com/book/en/v2) (Excellent, comprehensive guide)
254* **Git Reference Documentation**: [https://git-scm.com/docs](https://git-scm.com/docs)
255* **GitHub GPG Signing Documentation**: [https://docs.github.com/en/authentication/managing-commit-signature-verification](https://docs.github.com/en/authentication/managing-commit-signature-verification)
256* **1Password Documentation**: See `docs/1password-usage.md`
257* **GitHub CLI Documentation**: See `docs/github-usage.md`
258
259This guide covers key Git practices for this dotfiles setup. Consistent use of signed commits and a clean history are encouraged.