Skip to content

Git Workflow ​

The git setup enforces conventional commits, signs every commit, and puts a passphrase guard in front of git push. The config is git/.gitconfig and the hooks are in git/.git-hooks/, both linked by GNU Stow.

Hooks are installed globally through core.hooksPath = ~/.git-hooks, so they run in every repository on the machine, not just this one.

Commit messages ​

The commit-msg hook checks the first line of every commit message against the Conventional Commits format:

text
<type>(<scope>): <subject>

The scope is optional, and the subject must not be empty.

TypeUse it for
featA new feature
fixA bug fix
docsDocumentation changes
styleFormatting, whitespace, missing semicolons
refactorRestructuring without changing behaviour
testAdding or updating tests
choreMaintenance tasks
perfPerformance improvements
ciCI/CD changes
buildBuild system changes
revertReverting a previous commit
text
feat(auth): add login functionality
fix: resolve memory leak in parser
docs(readme): update installation instructions

A message that does not match is rejected with the list above and the commit is aborted. Only the first line is checked; the body can say anything.

What else the hook does:

  • Tidies bullet points — leading spaces before -, * or + at the start of a line are removed, so the log stays aligned.
  • Warns on long headers — over 72 characters prints a warning but does not block the commit.
  • Skips merge and revert commits — messages starting with Merge or Revert are accepted as they are.

This is also what feeds the changelog: releases are generated from these commit types by git-cliff.

Pre-push guard ​

The pre-push hook asks for a passphrase before anything leaves your machine, so an accidental git push cannot go through unnoticed.

text
$ git push
Enter Passphrase:
Verification Successful. Proceeding with push.

It works by reading the expected value from pass git/push_pass and comparing it with what you type (input is hidden). It aborts when:

  • pass is not installed,
  • the git/push_pass entry is missing or empty, or
  • the typed passphrase does not match.

Create the entry once per machine — see Secrets, pass & GPG.

TIP

This is a safety latch against mistakes, not an access control. Skip it for a single push with git push --no-verify.

Identity and signing ​

Commits are GPG-signed by default (commit.gpgsign = true). The shipped config contains the author's name, email and key ID, so on your own machine override them in ~/.gitconfig.local. That file is included at the end of .gitconfig, which makes its values win:

ini
[user]
  name = Your Name
  email = you@example.com
  signingkey = YOUR_KEY_ID

Setting up the key is covered in Secrets, pass & GPG.

Remotes ​

ini
[url "git@github.com:"]
  pushInsteadOf = "https://github.com/"

Clone and fetch over HTTPS, push over SSH. Paste any https://github.com/... URL and pushes still go through your SSH key. The SSH command pins ~/.ssh/id_ed25519 with IdentitiesOnly=yes, so create or copy that key first.

Aliases ​

AliasWhat it does
git lgPretty graph log with hashes, refs, relative dates and authors
git lgaThe same graph across all branches
git todayCommits since midnight, with times
git yesterdayYesterday's commits
git lastmonthCommits from the past month
git monthstatCommit counts per author for the past month
git mineGraph log of your own commits only
git lastFull details of the most recent commit
git undoSoft-reset the last commit, keeping your changes staged
git unstageUnstage everything (git reset HEAD --)
git goneDelete local branches whose remote branch is gone
git elExport the full log to git_history.txt

WARNING

git gone runs git fetch --prune and then git branch -D on every branch marked gone. That is a force delete — unmerged local work on those branches is lost.

The GitHub CLI config adds contribution stats on top of these (gh today, gh streak, ...); see the GitHub CLI section of the README.

Behaviour worth knowing ​

SettingEffect
pull.rebase = truegit pull rebases instead of creating merge commits
rebase.autosquash, rebase.autostashfixup! commits are squashed automatically; dirty trees are stashed around a rebase
rerere.enabledGit remembers how you resolved a conflict and reuses it
fetch.prune, fetch.pruneTagsDeleted remote branches and tags are cleaned up locally
push.autoSetupRemote, push.followTagsFirst push sets the upstream; annotated tags go with it
branch.sort = -committerdategit branch lists the most recently used branch first
init.defaultBranch = mainNew repositories start on main
core.fsmonitor, core.untrackedCacheFaster git status in large repositories
maintenance.autoBackground housekeeping runs automatically

Diffs and paging ​

delta is the pager and the interactive diff filter, with the Dracula feature set: side-by-side view, line numbers, n/N to jump between files, and clickable hyperlinks. The editor is Helix (hx).

Large files ​

Git LFS is wired in through the filter "lfs" section, so git lfs track works once git-lfs is installed (it is in the default package list).

Sending patches by email ​

See Send Email for the Gmail SMTP setup, which reads its password from pass app/gmail-smtp.

Bypassing the hooks ​

HookSkip withPrefer instead
commit-msggit commit --no-verifyFix the message; merges and reverts are exempt
pre-pushgit push --no-verifyEnter the passphrase

Released under the MIT License.