Skip to content

Commit 635c8bd

Browse files
committed
docs: documentation page
1 parent 097d303 commit 635c8bd

9 files changed

Lines changed: 873 additions & 0 deletions

File tree

.github/workflows/docs.yml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: Docs
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- "docs/**"
8+
- "mkdocs.yml"
9+
pull_request:
10+
branches: [main]
11+
paths:
12+
- "docs/**"
13+
- "mkdocs.yml"
14+
workflow_dispatch:
15+
16+
permissions:
17+
contents: read
18+
pages: write
19+
id-token: write
20+
21+
# Only one deployment runs at a time; cancel in-progress if a new one is queued.
22+
concurrency:
23+
group: pages
24+
cancel-in-progress: false
25+
26+
jobs:
27+
build:
28+
name: Build docs
29+
runs-on: ubuntu-latest
30+
steps:
31+
- uses: actions/checkout@v4
32+
33+
- uses: actions/setup-python@v5
34+
with:
35+
python-version: "3.12"
36+
37+
- name: Install MkDocs Material
38+
run: pip install mkdocs-material
39+
40+
- name: Build site
41+
run: mkdocs build --strict
42+
43+
- name: Upload pages artifact
44+
if: github.ref == 'refs/heads/main'
45+
uses: actions/upload-pages-artifact@v3
46+
with:
47+
path: site/
48+
49+
deploy:
50+
name: Deploy to GitHub Pages
51+
if: github.ref == 'refs/heads/main'
52+
needs: build
53+
runs-on: ubuntu-latest
54+
environment:
55+
name: github-pages
56+
url: ${{ steps.deployment.outputs.page_url }}
57+
steps:
58+
- name: Deploy to GitHub Pages
59+
id: deployment
60+
uses: actions/deploy-pages@v4

docs/configuration.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Configuration
2+
3+
## Config file location
4+
5+
Profiles are stored at:
6+
7+
```text
8+
$XDG_CONFIG_HOME/git-profile/config.json
9+
```
10+
11+
Which defaults to `~/.config/git-profile/config.json` if `XDG_CONFIG_HOME` is not set.
12+
13+
## Custom config path
14+
15+
Use `--config` to point at a different file:
16+
17+
```bash
18+
git-profile --config ~/dotfiles/git-profile.json list
19+
```
20+
21+
## Config file format
22+
23+
```json
24+
{
25+
"version": 1,
26+
"profiles": {
27+
"work": {
28+
"id": "work",
29+
"git_user": "Jane Dev",
30+
"git_email": "jane@company.com",
31+
"ssh_key_path": "~/.ssh/id_ed25519_work",
32+
"gpg_key_id": "ABC123DEF456",
33+
"sign_commits": true
34+
},
35+
"personal": {
36+
"id": "personal",
37+
"git_user": "Jane Doe",
38+
"git_email": "jane@example.com",
39+
"ssh_key_path": "~/.ssh/id_ed25519_personal"
40+
},
41+
"oss": {
42+
"id": "oss",
43+
"git_user": "Jane Doe",
44+
"git_email": "jane@oss.dev"
45+
}
46+
}
47+
}
48+
```
49+
50+
## Profile fields
51+
52+
| Field | Type | Description |
53+
| -------------- | ------ | ----------------------------------------- |
54+
| `id` | string | Unique profile identifier |
55+
| `git_user` | string | `user.name` written to git config |
56+
| `git_email` | string | `user.email` written to git config |
57+
| `ssh_key_path` | string | Path to SSH private key (`~/` supported) |
58+
| `gpg_key_id` | string | GPG key ID written to `user.signingkey` |
59+
| `sign_commits` | bool | Sets `commit.gpgsign = true` when applied |
60+
61+
## How git config keys are mapped
62+
63+
When you run `git-profile use <id>`, only fields present in the profile are written:
64+
65+
| Profile field | git config key |
66+
| -------------- | ----------------- |
67+
| `git_user` | `user.name` |
68+
| `git_email` | `user.email` |
69+
| `ssh_key_path` | `core.sshCommand` |
70+
| `gpg_key_id` | `user.signingkey` |
71+
| `sign_commits` | `commit.gpgsign` |
72+
73+
Fields absent from the profile are left unchanged in git config.
74+
75+
## Environment variables
76+
77+
| Variable | Description |
78+
| ----------------- | ----------------------------------------------------- |
79+
| `XDG_CONFIG_HOME` | Base directory for config file (default: `~/.config`) |
80+
81+
## Dotfiles integration
82+
83+
Because the config file is plain JSON, you can symlink or copy it from your dotfiles:
84+
85+
```bash
86+
# symlink from dotfiles
87+
ln -s ~/dotfiles/git-profile.json ~/.config/git-profile/config.json
88+
89+
# or use --config flag in a shell alias
90+
alias gp='git-profile --config ~/dotfiles/git-profile.json'
91+
```

docs/guides/gpg.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# GPG Commit Signing
2+
3+
`git-profile` manages all GPG signing settings — `user.signingkey` and `commit.gpgsign` — so you never have to edit them manually.
4+
5+
## 1. Find your GPG key ID
6+
7+
```bash
8+
gpg --list-secret-keys --keyid-format=long
9+
```
10+
11+
```text
12+
sec ed25519/ABC123DEF456 2024-01-01 [SC]
13+
ABCDEF1234567890ABCDEF1234567890ABC123DE
14+
uid [ultimate] Jane Dev <jane@company.com>
15+
```
16+
17+
The key ID is the part after `/` on the `sec` line — `ABC123DEF456` in this example.
18+
19+
## 2. Create a profile with GPG signing
20+
21+
```bash
22+
git-profile add \
23+
--id work \
24+
--name "Jane Dev" \
25+
--email jane@company.com \
26+
--gpg-key "ABC123DEF456" \
27+
--sign-commits
28+
```
29+
30+
## 3. Apply the profile
31+
32+
```bash
33+
git-profile use work
34+
```
35+
36+
This writes four git config keys at once:
37+
38+
```ini
39+
[user]
40+
name = Jane Dev
41+
email = jane@company.com
42+
signingkey = ABC123DEF456
43+
[commit]
44+
gpgsign = true
45+
```
46+
47+
## 4. Verify signing works
48+
49+
```bash
50+
git commit --allow-empty -m "test gpg signing"
51+
git log --show-signature -1
52+
```
53+
54+
## Using different keys per identity
55+
56+
```bash
57+
git-profile add --id work \
58+
--name "Jane Dev" --email jane@company.com \
59+
--gpg-key "WORK_KEY_ID" --sign-commits
60+
61+
git-profile add --id personal \
62+
--name "Jane Doe" --email jane@example.com \
63+
--gpg-key "PERSONAL_KEY_ID" --sign-commits
64+
65+
git-profile add --id oss \
66+
--name "Jane Doe" --email jane@oss.dev
67+
# no GPG — leave unsigned for OSS contributions
68+
69+
cd ~/work-project && git-profile use work
70+
cd ~/personal-blog && git-profile use personal
71+
cd ~/oss-project && git-profile use oss
72+
```
73+
74+
## Disabling GPG signing for a repo
75+
76+
Applying a profile that has no `gpg_key_id` does **not** unset signing keys — it leaves any existing `user.signingkey` and `commit.gpgsign` values in place. To explicitly disable signing:
77+
78+
```bash
79+
git config --unset user.signingkey
80+
git config --unset commit.gpgsign
81+
```
82+
83+
## Troubleshooting
84+
85+
### `gpg: skipped "KEY_ID": No secret key`
86+
87+
The signing key stored in the profile doesn't match any key in your GPG keyring. Either:
88+
89+
- Import the key: `gpg --import private-key.asc`
90+
- Or update the profile with the correct key ID: `git-profile edit work`
91+
92+
### `error: gpg failed to sign the data`
93+
94+
Try running `gpg --status-fd=2 -bsau KEY_ID </dev/null` to test signing directly. Common causes:
95+
96+
- GPG agent is not running: `gpg-agent --daemon`
97+
- On macOS: ensure `pinentry-mac` is installed: `brew install pinentry-mac`

docs/guides/hooks.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Auto-Apply Hooks
2+
3+
Git hooks let `git-profile` automatically enforce the correct identity before every commit and push — no more accidentally committing with the wrong email.
4+
5+
## Setup
6+
7+
```bash
8+
# Step 1: go into your project
9+
cd my-work-project
10+
11+
# Step 2: install the hooks
12+
git-profile install-hooks
13+
14+
# Step 3: set the default profile for this repo
15+
git-profile set-default work
16+
```
17+
18+
That's it. From now on, `git commit` and `git push` in this repo automatically call `git-profile ensure` before running.
19+
20+
## How it works
21+
22+
`install-hooks` writes two hook scripts into `.git/hooks/`:
23+
24+
- **`prepare-commit-msg`** — runs before the commit editor opens
25+
- **`pre-push`** — runs before a push is sent
26+
27+
Each hook calls `git-profile ensure`, which applies the profile following this resolution order:
28+
29+
| Priority | Source | How to set |
30+
| -------- | ------------------------ | ----------------------------------- |
31+
| 1 | Local `gitprofile.default` | `git-profile set-default <id>` |
32+
| 2 | Global `gitprofile.default` | `git-profile set-default <id> --global` |
33+
| 3 | Interactive picker | Terminal only (not in CI) |
34+
35+
## Global fallback
36+
37+
Set a personal profile as the fallback for repos that don't have a local default:
38+
39+
```bash
40+
git-profile set-default personal --global
41+
```
42+
43+
Now any repo without an explicit default uses `personal`, and repos with `set-default work` override it with `work`.
44+
45+
## Non-interactive environments (CI/CD)
46+
47+
When stdin is not a terminal (e.g., in CI), the interactive picker is skipped and `ensure` exits with an error if no default is configured. This prevents CI pipelines from hanging on interactive prompts.
48+
49+
```bash
50+
# In CI: set the profile explicitly before committing
51+
git-profile use ci-bot
52+
```
53+
54+
## Removing hooks
55+
56+
To remove the installed hooks:
57+
58+
```bash
59+
rm .git/hooks/prepare-commit-msg .git/hooks/pre-push
60+
```
61+
62+
## Example: multi-repo workflow
63+
64+
```bash
65+
# Work projects
66+
for repo in ~/work/*; do
67+
cd "$repo"
68+
git-profile install-hooks
69+
git-profile set-default work
70+
done
71+
72+
# Personal projects
73+
for repo in ~/personal/*; do
74+
cd "$repo"
75+
git-profile install-hooks
76+
git-profile set-default personal
77+
done
78+
79+
# Global fallback
80+
git-profile set-default personal --global
81+
```

docs/index.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# git-profile
2+
3+
![git-profile banner](images/banner.png)
4+
5+
[![CI](https://github.com/hapiio/git-profile/actions/workflows/ci.yml/badge.svg)](https://github.com/hapiio/git-profile/actions/workflows/ci.yml)
6+
[![codecov](https://codecov.io/gh/hapiio/git-profile/graph/badge.svg)](https://codecov.io/gh/hapiio/git-profile)
7+
[![Go Report Card](https://goreportcard.com/badge/github.com/hapiio/git-profile)](https://goreportcard.com/report/github.com/hapiio/git-profile)
8+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/hapiio/git-profile/blob/main/LICENSE)
9+
[![Release](https://img.shields.io/github/v/release/hapiio/git-profile)](https://github.com/hapiio/git-profile/releases/latest)
10+
11+
**Switch between multiple git identities with a single command.**
12+
13+
Do you juggle work, personal, and open-source git accounts? `git-profile` lets you define named identity profiles and apply them per-repo or globally — so you never accidentally push a personal commit with your work email again.
14+
15+
## Features
16+
17+
- **Named profiles** — store `user.name`, `user.email`, SSH key, and GPG signing per identity
18+
- **Per-repo or global** — apply any profile locally or to `~/.gitconfig`
19+
- **Auto-apply via git hooks**`prepare-commit-msg` and `pre-push` hooks enforce the right identity before every commit and push
20+
- **Interactive picker** — numbered menu when you can't remember the ID
21+
- **Import existing identity** — bootstrap a profile from your current git config in one command
22+
- **Edit, rename, remove** — full profile lifecycle management
23+
- **Shell completions** — bash, zsh, and fish
24+
- **Zero runtime dependencies** — single static binary, no runtime required
25+
26+
## Quick example
27+
28+
```bash
29+
# Add your profiles
30+
git-profile add --id work --name "Jane Dev" --email jane@company.com
31+
git-profile add --id personal --name "Jane Doe" --email jane@example.com \
32+
--ssh-key ~/.ssh/id_ed25519_personal
33+
34+
# Apply a profile to the current repo
35+
git-profile use work
36+
37+
# See what's active
38+
git-profile current
39+
```
40+
41+
[Get started :material-arrow-right:](installation.md){ .md-button .md-button--primary }
42+
[View on GitHub :material-github:](https://github.com/hapiio/git-profile){ .md-button }

0 commit comments

Comments
 (0)