t0ul

Git and GitHub the Safe Way: The One-Page Cheat Sheet

Part of Git and GitHub the Safe Way, a short book on git, GitHub, and the habits that keep a repository from hurting you.

Setup, once per machine (chapter 2)

DoCommand or place
name and emailgit config --global user.name "Ada Gopher", git config --global user.email "ada@example.com"
start on maingit config --global init.defaultBranch main
an editor you can exitgit config --global core.editor "code --wait"
make a keyssh-keygen -t ed25519 -C "ada@example.com"
give GitHub the public keySettings, SSH and GPG keys, New SSH key (once as authentication, once as signing)
test itssh -T git@github.com
sign every commitgit config --global gpg.format ssh, git config --global user.signingkey ~/.ssh/id_ed25519.pub, git config --global commit.gpgsign true
ignore OS and editor junk everywheregit config --global core.excludesFile ~/.gitignore_global

The loop (chapter 3)

DoCommand
what changedgit status --short, git diff
stage part of a filegit add -p file
what the next commit will containgit diff --staged
commitgit commit -m "Do one thing" (add -m "why" for a body)
historygit log --oneline, git log -1 --stat, git log --oneline --graph --all
per-project ignores.gitignore, written before the first git add .

Secrets (chapter 4)

Example keys from a provider’s documentation are deliberately ignored by scanners; test with a randomly generated string.

DoCommand or place
keep the real settings file out.env in .gitignore; commit .env.example instead
scan what is stagedtrufflehog git file://. --since-commit HEAD --fail (exit 183 when something is found)
scan the whole historytrufflehog git file://. (add --results=verified,unknown to see only live or uncheckable credentials)
run the scan on every commit.githooks/pre-commit plus git config core.hooksPath .githooks; git add, then git commit, never -am
one already got inrotate it first; then git filter-repo --invert-paths --path FILE --force; then git push --force-with-lease origin BRANCH for every branch git branch -r lists; collaborators re-clone
let GitHub refuse pushes with secretsSettings, Advanced Security, Secret Protection: Enable, Push protection: Enable

Branches and pull requests (chapter 5)

DoCommand or place
a branch per changegit switch -c fix-the-thing
publish itgit push -u origin fix-the-thing
open the pull requestthe Compare & pull request banner on GitHub
bring main into the branchgit fetch origin, git merge origin/main
a conflictedit between <<<<<<< and >>>>>>>, git add file, git commit; or git merge --abort
after the mergegit switch main, git pull, git branch -d fix-the-thing, git fetch --prune

Protecting main (chapter 6)

DoPlace
the rulesetSettings, Rulesets, New ruleset, New branch ruleset; Enforcement status Active; target the default branch
the rulesRequire a pull request before merging; Block force pushes; Restrict deletions; Require status checks to pass; Require signed commits; Require linear history
a check to require.github/workflows/ci.yml with permissions: contents: read and your test command, on pull_request
owners for the files that matter.github/CODEOWNERS

Reading a pull request (chapter 7)

Shape first (files, lines, commits, description). Then manifests and lockfiles, anything under .github/, config, binaries, weakened tests. Then the stop patterns: key-shaped strings, new hosts, encoded blobs, new reads of env or network, refactors that add behaviour. gh pr checkout N, run it. Review comments that are specific, ask before asserting, and say what you ran.

When it goes wrong (chapter 8)

The mistakeThe rung
bad edit, not stagedgit restore file
staged by accidentgit restore --staged file
last commit wrong, not pushedgit commit --amend
commit wrong, already pushedgit revert <id>
my own branch, go back an hourgit reset --hard <id>; git reflog to find your way back
deleted a branchgit reflog, then git branch name HEAD@{n}
force pushnever to main; only your branch; always --force-with-lease

GitHub hygiene (chapter 9)

DoPlace
second factorSettings, Password and authentication, Enable two-factor authentication; download the recovery codes; add a passkey
a token for a scriptSettings, Developer settings, Personal access tokens, Fine-grained tokens: name, expiry, only select repositories, least permissions
the repository watches itselfSettings, Advanced Security: Dependabot alerts, Secret Protection, Push protection
robots with least privilegeSettings, Actions, General: read-only workflow permissions; require approval for external contributors’ workflows; pin third-party actions to a commit
yearly clean-outApplications, tokens, SSH keys, collaborators, archive finished repositories

← Back to the blog