Git is a time machine with discipline

Git records snapshots of a project over time. It lets you answer: What changed? Why? Can I return to the known-good version? GitHub is a hosted collaboration and automation service built around Git repositories.

The daily goal is simple: keep each change small, understandable, testable, and recoverable.

The three areas

Working directory → Staging area → Commit history
    edit files          choose files      permanent snapshot
git status              # where am I?
git diff                # what changed but is not staged?
git diff --staged       # what will the next commit contain?
git add path/to/file    # choose exact change
git commit -m "feat: add WAN status card"

Run git status constantly. It is the safest first command in Git.

Start a repository

git init
git branch -M main
git add README.md .gitignore
git commit -m "chore: initialise project"
git remote add origin git@github.com:your-name/project.git
git push -u origin main

Put these in .gitignore early:

.env
.venv/
node_modules/
__pycache__/
*.db
*.sql.gz
dist/
.DS_Store

A .gitignore prevents new untracked files; it does not remove a secret already committed. If a secret enters Git history, revoke/rotate it immediately.

A safe feature workflow

git switch main
git pull --ff-only
git switch -c feat/library-filter
# edit, run tests/build
git status
git diff
git add src/pages/guides/index.astro
git commit -m "feat: filter guides in the browser"
git push -u origin feat/library-filter

A branch isolates one coherent change. Name it after intent: feat/..., fix/..., docs/..., chore/.... Do not put unrelated refactors in the same branch/commit.

Commit messages that help future you

feat: add scheduled AC start control
fix: prevent duplicate WAN outage notifications
docs: add Firefly III backup guide
refactor: extract shared API client
chore: update dependencies

First line: imperative, specific, concise. Describe the outcome—not “changes” or “update files”.

Read a diff before every commit

git diff --check  # whitespace errors
git diff          # unstaged changes
git diff --staged # exact next commit

Ask: does it contain secrets, generated files, unrelated edits, debug logging, or a change I cannot explain? If yes, fix it before committing.

Pull, merge, rebase: the practical version

  • git pull --ff-only: update your branch only if it can move forward cleanly. Safe default for main.
  • Merge: joins two histories with a merge commit; preserves branch shape.
  • Rebase: replays your unpublished commits on a newer base; makes a linear history, but rewrites commit IDs.

For your own local work, rebase can be fine. Never rebase shared/published branches unless everyone involved expects it. When in doubt: merge or ask.

Undo without panic

SituationCommandEffect
Discard unstaged file editsgit restore fileRestores file from last commit
Unstage a filegit restore --staged fileKeeps edits, removes from staging
Amend last local commitgit commit --amendReplaces last commit; avoid after sharing
Make a new undo commitgit revert <commit>Safely reverses a published change
See previous statesgit log --oneline --graph --allHistory overview
Recover a lost referencegit reflogGit’s local activity log

Prefer git revert for a change already pushed to main. It preserves a clear audit trail.

Conflicts: calm, mechanical, solvable

A conflict means Git cannot decide which version of overlapping lines is correct. It is not a catastrophe.

git status
# edit files: choose/create correct combined content
git add resolved-file
git commit            # after a merge
# or: git rebase --continue

Look for markers:

<<<<<<< HEAD
your version
=======
the other version
>>>>>>> branch-name

Keep the correct final behaviour, remove all markers, run tests/build, then continue. To abandon an in-progress merge/rebase: git merge --abort or git rebase --abort.

GitHub pull requests

A pull request (PR) is a reviewable proposal to merge a branch. Even solo, it can be useful for CI, a clean diff, and a pause before production.

Good PR description:

What: Added browser-side category/search filtering.
Why: Static Astro cannot apply query filtering at build time.
How tested: npm run build; checked category, direct URL, keyword intersection.
Risk/rollback: Revert this commit if filters fail.

CI should build/test the branch before merge. Review the changed files, not only the green tick.

Tags and releases

Tag meaningful versions, especially firmware or deployments you may need to reproduce:

git tag -a v1.0.0 -m "First stable coop controller release"
git push origin v1.0.0

A tag identifies a fixed point in source history. Pair it with release notes and any compiled firmware artifact when relevant.

The 90-second pre-push checklist

[ ] git status is understood
[ ] git diff --staged contains only intended changes
[ ] No secrets or large private backups
[ ] Formatter/linter/tests/build pass
[ ] Commit message explains outcome
[ ] Deployment/rollback plan is known for risky changes