Skip to main content
Updated Feb 23, 2026

Axiom VIII: Version Control is Memory

Axiom VII gave James tests that define what "correct" means. But tests capture what the code should do. They say nothing about what the code used to do, why it changed, or who changed it. A week after the $12,000 discount fix, that gap became painfully clear.

James's team lead called a post-mortem. "Walk us through the original bug," she said. "Show us what the function looked like before the fix." James opened apply_discount() — but only the current version remained. The buggy implementation was gone, overwritten when the AI regenerated. He checked his git history:

commit a1b2c3d
wip

commit b2c3d4e
updates

commit c3d4e5f
fix stuff

Three commits from that week. No messages explaining what changed or why. No record of the original buggy implementation. No trace of which test caught the error. No documentation of the decision to switch from manual review to TDG. James had the right code now, but no memory of how he got there.

"You lost the story," Emma told him after the meeting. She pulled up her own project's history:

commit d4e5f6g
fix(orders): correct discount calculation — multiply by (1 - rate)

apply_discount() was returning price * discount_rate instead of
price * (1 - discount_rate), giving 85% discount instead of 15%.
Caught by TDG test: assert apply_discount(order, 0.15).total == 85.0

Root cause: ambiguous prompt "apply percentage discount" — AI
interpreted as multiply-by-rate. Added 5 specification tests
to prevent recurrence. See test_discount.py.

Impact: $12,000 loss over weekend. Post-mortem: PM-2025-003

Same fix. But Emma's commit was a memory. It recorded not just what changed, but why it changed, what caused the original error, how it was caught, and where to find the broader context. Six months from now, anyone reading that commit would understand the full story without asking a single question.

"Git is not a backup tool," Emma said. "It is the memory of your project. Every commit is a decision you are recording for your future self, your teammates, and your AI. If the memory is wip, you have amnesia."

This is Axiom VIII.


The Problem Without This Axiom

James's post-mortem exposed a pattern that every developer who uses AI will recognize. He had been productive — shipping features, fixing bugs, regenerating implementations through TDG. But his git history was a graveyard of meaningless messages: wip, updates, fix stuff, changes, done. Every commit recorded that something changed. None recorded why.

The consequences compounded:

SituationJames's ExperienceWhat Disciplined Git Provides
"What was the original bug?"File overwritten, no recordgit show HEAD~3:src/discount.py shows the buggy version
"Which test caught the error?""I think it was the boundary test..."Commit message names the specific assertion
"When did shipping get slow?"Manual log searching, guessworkgit bisect finds the exact commit
"Can we undo the ORM change?"Risky manual reversalgit revert abc123 safely creates inverse commit
AI asks "What's the project context?"James explains from scratch every sessionAI reads git log for recent decisions

The cost was invisible day-to-day but catastrophic at the post-mortem. Every undocumented decision became a question nobody could answer. Every unexplained change became a mystery. The team spent three hours reconstructing a story that disciplined commit messages would have told in three minutes.


The Axiom Defined

Axiom VIII: Version Control is Memory. Git provides the persistent memory layer for all work. Every decision, every change, every experiment is recorded. Git is not just version control — it is the system of record for software evolution.

This axiom elevates git from a tool (something you use to save work) to a system (the authoritative record of how and why your software became what it is). James had been using git as a save button — git add . && git commit -m "wip" — the way you might press Ctrl+S in a document editor. Emma taught him to use it as a journal — each entry recording a decision, its rationale, and its context.

The key insight: files give you current state; git gives you all past states and the story between them.

What Git Actually Records

When used with discipline, git captures four dimensions of project memory:

DimensionGit MechanismWhat It Preserves
DecisionsCommit messagesWhy changes were made, what alternatives were rejected
ExperimentsBranchesParallel approaches tried, including failed ones
MilestonesTagsStable points you can always return to
AccountabilityBlame/LogWho made each decision and when

Together, these form the institutional memory that James's post-mortem was missing — a record that survives team changes, context switches, and the passage of time.


From Principle to Axiom

In Chapter 4, you learned Principle 5: Persisting State in Files. That principle established a critical insight: AI systems are stateless between sessions, so all important context must live in files that AI can read.

Axiom VIII builds directly on that foundation:

Principle 5Axiom VIII
Persist state in filesManage that state with history
Files give you current stateGit gives you all past states
CLAUDE.md tells AI what to do nowGit log tells AI what was tried before
Files are the interfaceGit is the memory behind the interface
Solves: "AI forgot my conventions"Solves: "Nobody remembers why"

The relationship is complementary: Principle 5 says where to persist (files). Axiom VIII says how to manage persistence over time (version control). Files without git are snapshots. Files with git are a narrative.

James experienced this progression firsthand:

  • Before Principle 5: His project conventions lived in his head. Every AI session started from zero.
  • After Principle 5: His conventions lived in CLAUDE.md. The AI could read current rules.
  • After Axiom VIII: His conventions lived in versioned CLAUDE.md. The AI could read not just the current rules, but the history of why each rule was added — including the $12,000 discount incident that prompted the TDG requirement.
The Discipline That Preceded Git

The idea that version control could serve as institutional memory has roots older than most developers realize. In April 2005, Linus Torvalds built Git's core in roughly two weeks — not as a side project, but out of necessity. The Linux kernel, the largest collaborative software project in history, had been using a proprietary tool called BitKeeper for version control. When BitKeeper revoked its free license, Torvalds needed a replacement that could handle thousands of distributed developers collaborating without a central server.

The tools that preceded Git — CVS (1990) and Subversion (2000) — required a central server. Every commit went through a single point of failure. If the server was down, nobody could commit. If the server was lost, the history was lost. Torvalds designed Git to be distributed: every developer's copy contains the complete history. There is no single point of failure. The memory lives everywhere.

But Torvalds's deeper insight was about what version control records. CVS tracked file changes. Git tracks snapshots of the entire project state — every commit captures the complete state of every file at that moment. This means you can reconstruct your project at any point in its history, not just individual files. The project's memory is not a collection of diffs. It is a sequence of complete states, each connected to the decision that produced it.

James's wip commits squandered this power. Git was designed to be a complete institutional memory. He had been using it as a save button.


Git as System of Record

Git branching workflow: main branch with a feature/discount branch forking off, commits, and a Pull Request + Review merge back

After the post-mortem, Emma spent an afternoon teaching James how git actually works when used with discipline. "Git gives you four tools," she said. "Commits, branches, tags, and blame. Each one is a different kind of memory."

Commits Are Decisions

Every commit should answer one question: "What decision was made, and why?"

The code diff shows what changed. The commit message explains why it changed. Together, they form a decision record. Emma showed James how to query that record:

# Find all feature decisions this year
git log --oneline --since="2024-01-01" --grep="feat"

# Read the full context of a specific decision
git show abc123

# Find who made a specific decision and when
git blame src/config.py

"Think of each commit as a journal entry," Emma told James. "The diff is what happened. The message is why it matters."

Branches Are Experiments

Branches are not just for "features." They are parallel experiments — hypotheses being tested. When James wanted to try replacing his JSON storage with SQLite (the relational approach from Axiom VI), Emma told him to create a branch:

# Start an experiment
git checkout -b experiment/try-sqlite-storage

# Work on the experiment...
# If it succeeds: merge it
git checkout main && git merge experiment/try-sqlite-storage

# If it fails: keep the record, delete the branch
git checkout main
git branch -d experiment/try-sqlite-storage
# The commits still exist in reflog for 90 days

Even failed experiments have value. The commit history on a deleted branch records what was tried and why it did not work — preventing the team from repeating the same failed approach six months later. "Your team already tried Redis caching last quarter," Emma pointed out. "If they had kept the experiment branch, the new developer would not have spent two weeks rediscovering why it did not work."

Tags Are Milestones

Tags mark stable, known-good states you can always return to. James learned to tag his project before any risky change:

# Mark a release
git tag -a v1.2.0 -m "Feature complete: order management with TDG tests"

# Mark a significant decision point
git tag -a pre-sqlite-migration -m "Last commit before JSON->SQLite migration"

# Return to any milestone instantly
git checkout v1.2.0

If the SQLite migration had failed catastrophically, James could return to pre-sqlite-migration in one command — no manual reversal, no guesswork about what the project looked like before.

Blame Is Context, Not Accusation

Despite its name, git blame is a context tool. It answers: "Who wrote this line, when, and as part of what change?" James used it to understand a mysterious constant in the shipping module:

# Find the context for a confusing line
git blame src/shipping.py -L 42,42

# Result:
# d4e5f6g (Emma 2024-03-15) FREE_SHIPPING_THRESHOLD = 75.0 # PM-2024-019

# Now James knows: Emma set this, on March 15, for product requirement PM-2024-019

Without blame, that 75.0 would be a magic number — nobody would know where it came from or whether it was safe to change. With blame, the full context is one command away.


Commit Discipline

The power of git-as-memory depends entirely on commit quality. James's wip commits were not just lazy — they were destroying information. Every time he bundled three unrelated changes into one commit with no message, he was erasing the decisions that produced those changes. Emma called this "voluntary amnesia."

Atomic Commits: One Logical Change

Each commit should contain exactly one logical change. Emma gave James a simple test: if you have to use "and" to describe it, split it:

# BAD: Multiple unrelated changes in one commit
git add .
git commit -m "fix discount bug and update shipping and add tests"

# GOOD: Three separate atomic commits
git add src/discount.py tests/test_discount.py
git commit -m "fix(orders): correct discount calculation — multiply by (1 - rate)

apply_discount() returned price * rate instead of price * (1 - rate),
giving 85% discount instead of 15%. Caught by TDG specification test:
assert apply_discount(order, 0.15).total == 85.0

Impact: $12,000 loss over weekend. Post-mortem: PM-2025-003"

git add src/shipping.py
git commit -m "feat(shipping): raise free shipping threshold from 50 to 75

Product team decision: $50 threshold was losing margin on small orders.
Analytics showed 68% of orders between $50-$75 added items to qualify.
New threshold reduces free shipping orders by 31%.

Ref: PRODUCT-2025-047"

git add tests/test_shipping.py
git commit -m "test(shipping): add TDG specs for international surcharge

Five specification tests covering domestic, international, free shipping
threshold, and boundary conditions. Written before AI implementation
per TDG workflow (Axiom VII)."

Conventional Commits: Structured Prefixes

After a week of writing atomic commits, James noticed a new problem: his messages were descriptive but unscannable. Reading twenty commit messages to find "the one where I changed the shipping logic" took too long. Emma introduced him to conventional commits — a structured prefix system that makes history scannable at a glance:

PrefixMeaningExample
feat:New featurefeat(shipping): add international surcharge calculation
fix:Bug fixfix(orders): correct discount calculation
docs:Documentationdocs(api): document order endpoints
refactor:Code restructure (no behavior change)refactor(orders): extract discount logic to module
test:Adding/fixing teststest(shipping): add TDG specs for free shipping threshold
chore:Maintenancechore(deps): update fastapi to 0.109.0
perf:Performance improvementperf(shipping): replace O(n^2) rate lookup with dict
ci:CI/CD changesci(github): add Python 3.12 to test matrix

The format: type(scope): description

# James's order management project — scannable history
git log --oneline

# a1b2c3d feat(shipping): add international surcharge calculation
# b2c3d4e fix(orders): correct discount calculation — multiply by (1 - rate)
# c3d4e5f test(orders): add TDG specs for discount edge cases
# d4e5f6g refactor(orders): extract discount logic to module
# e5f6g7h perf(shipping): replace O(n^2) rate lookup with dict
# f6g7h8i docs(orders): document discount business rules

At a glance, James could see: a new shipping feature, the discount bug fix, TDG tests, a refactor, the performance fix for the O(n^2) shipping function from Axiom VII's Green Bar Illusion, and documentation. This is scannable memory — the table of contents for his project's story.

The WHY Rule

The most important discipline — and the one that would have saved James's post-mortem — is this: commit messages explain WHY, not WHAT.

The diff already shows what changed. The message must explain what the diff cannot:

# BAD: Describes WHAT (redundant with the diff)
git commit -m "change FREE_SHIPPING_THRESHOLD from 50 to 75"

# GOOD: Explains WHY (context the diff cannot provide)
git commit -m "feat(shipping): raise free shipping threshold from 50 to 75

Product team decision: $50 threshold was losing margin on small orders.
Analytics showed 68% of orders between $50-$75 added items to qualify.
New threshold reduces free shipping orders by 31%.

Ref: PRODUCT-2025-047"

Six months from now, when someone asks "why is the threshold 75 and not 50?", the commit message answers immediately — it was a product decision backed by analytics, not an arbitrary choice. No Slack archaeology required. This is what James's post-mortem was missing — the why behind every change.


Git and AI: The Collaboration Protocol

When James started using Claude Code for his order management project, he discovered that disciplined git history served a second purpose: it made the AI smarter. The AI could read his commit messages to understand not just the current code, but the decisions that shaped it.

AI Can Read Git History for Context

AI tools can examine your project's history to understand decisions:

# AI reads recent changes to understand current direction
git log --oneline -20

# AI reads the discount module's evolution
git log --follow --oneline src/discount.py

# AI reads the full context of why a change was made
git show abc123

When James's CLAUDE.md said "always use TDG for business logic," the git history explained why — the $12,000 discount disaster. The AI could provide better suggestions because it understood the reasoning behind the rule, not just the rule itself.

AI Commits Should Be Clearly Labeled

When the AI generates code that gets committed, James learned to label it clearly:

# Clear attribution in commit message
git commit -m "feat(orders): implement discount calculation per TDG specs

Passes all 5 specification tests in test_discount.py.
Handles 0%, 15%, and 100% discount edge cases.

Co-Authored-By: Claude <noreply@anthropic.com>"

This matters for three reasons:

  1. Accountability: Code review knows which commits need extra scrutiny
  2. Learning: You can filter git log --author="Claude" to see AI contribution patterns
  3. Audit: In regulated environments, AI-generated code may require additional review

Git Diff as AI Code Review Input

The most natural input for AI code review is a git diff. James started sending diffs to the AI instead of entire files — the diff showed exactly what changed, with no noise:

# Review staged changes before committing
git diff --staged

# Review a feature branch against main
git diff main...feature/order-discounts

# Ask AI to review the diff
git diff main...feature/order-discounts | pbcopy
# Paste into AI: "Review this diff for correctness and edge cases"

Branches for AI Experiments

When James asked the AI to try something experimental — like rewriting his shipping calculator with a different algorithm — Emma insisted he always use a branch:

# Create a safe sandbox for AI experimentation
git checkout -b ai/experiment-new-shipping-algorithm

# AI generates a new shipping calculator...
# You run TDG tests against it...

# If tests pass: merge to main
git checkout main && git merge ai/experiment-new-shipping-algorithm

# If tests fail: discard without risk
git checkout main
git branch -D ai/experiment-new-shipping-algorithm

The branch prefix ai/ makes it immediately clear which branches contain AI-generated experiments. James could let the AI try radical approaches — a completely different discount algorithm, a table-driven shipping calculator — without any risk to the working code on main.

The Agentic Development Workflow

Emma showed James the standard workflow she used for all AI-assisted development on the order management project:

main (stable, protected)

├── feature/order-discounts (human + AI work)
│ ├── commit: test(orders): add TDG specs for discount logic (human)
│ ├── commit: feat(orders): implement discount calculation (AI, reviewed)
│ ├── commit: test(orders): add boundary case for 100% discount (human)
│ └── commit: docs(orders): document discount business rules (AI, reviewed)

└── Pull Request → Human reviews all AI commits → Merge to main

Key rules:

  • main is always stable: Never commit directly to main
  • Feature branches isolate work: Both human and AI changes go here
  • Pull requests require review: Especially for AI-generated code
  • Each commit is atomic: One logical change, clearly attributed

"Notice the pattern," Emma told James. "The human writes the tests — the specification. The AI writes the implementation and documentation. The commit history shows exactly who decided what. This is TDG encoded into your git workflow."


Anti-Patterns: How Git Memory Fails

Open any project that has been running for more than a year and run git log --oneline | head -20. If you see wip, fix, stuff, update, changes — you are looking at a project with amnesia. The commit log reads like a list of words rather than a story. git blame on any line returns a message that tells you nothing.

A developer left six months ago and took the entire architectural context with them, because none of it was written in commits. git bisect is useless because every commit changes forty files for three unrelated reasons. The team lead says "we tried caching last year" but nobody can find the experiment, nobody remembers why it failed, and a new developer spends two weeks rediscovering the same dead end.

This history is not missing information by accident. It is missing information because each developer chose the two-second shortcut of git commit -m "wip", and a thousand two-second shortcuts became a project that cannot explain itself.

These specific patterns destroy git's value as memory. Recognize and avoid them:

Anti-PatternWhy It FailsBetter Approach
Giant commits ("fix everything")Impossible to understand, revert, or bisectOne logical change per commit
Empty messages ("wip", "stuff", "asdf")Zero memory value; future you learns nothingExplain WHY with conventional prefix
Committing secrets/credentialsSecurity breach waiting to happenUse .gitignore and environment variables
Force-pushing shared branchesRewrites other people's historyOnly force-push your own unshared branches
Not using branches for experimentsExperiments pollute main historyBranch first, merge only if successful
Committing generated filesNoise in diffs, merge conflicts.gitignore build outputs, node_modules/, etc.
Squashing all commits on mergeDestroys the detailed decision historyPreserve atomic commits; only squash true "wip"
Never tagging releasesNo stable milestones to reference or rollback toTag every release and significant milestone

The "Giant Commit" Problem in Detail

James's worst commit from before the post-mortem looked like this:

commit x9y8z7
Message: "weekly update"
Files changed: 47
Insertions: 2,391
Deletions: 856

This commit was anti-memory. It recorded that 47 files changed but provided no way to understand why. James could not revert part of it. He could not bisect through it. He could not explain any individual change at the post-mortem.

Emma showed him what the same week's work should have looked like — 12 atomic commits:

feat(auth): add OAuth2 PKCE flow for mobile clients
fix(db): resolve connection leak under high concurrency
refactor(api): extract validation into middleware layer
test(auth): add PKCE challenge verification tests
docs(deploy): update Kubernetes manifest for v2.3
perf(search): add trigram index for fuzzy name matching
...

Each commit is a discrete memory. Each can be individually understood, reverted, or referenced.


Git as Time Machine

Git does not just record history — it lets you travel through it. Two weeks after adopting commit discipline, James experienced its first real payoff: his shipping calculator started returning wrong rates for international orders. Instead of reading through code to find the bug, Emma showed him how to let git find it.

Bisect: Finding When Things Broke

git bisect performs a binary search through history to find the exact commit that introduced a bug:

# Start bisecting
git bisect start

# Mark current state as bad (the bug exists now)
git bisect bad

# Mark a known-good state (the bug did not exist here)
git bisect good v1.2.0

# Git checks out a middle commit. You test it:
python -m pytest tests/test_auth.py
# Tell git the result:
git bisect good # or: git bisect bad

# Repeat until git finds the exact commit:
# "abc123 is the first bad commit"
# feat(auth): add session timeout handling

# Clean up
git bisect reset

With James's new atomic commits, bisect pinpointed the problem in six steps across fifty commits. The culprit was a commit where the AI had regenerated the international surcharge logic and introduced a rounding error. Because the commit was atomic — one logical change — James knew exactly which code to fix. If he had still been making giant "weekly update" commits, bisect would have been useless — finding the bad commit would still leave him sifting through hundreds of unrelated changes.

Revert: Safe Undo

git revert creates a new commit that undoes a previous commit, without rewriting history:

# Safely undo a specific commit
git revert abc123

# Revert creates a NEW commit:
# "Revert 'feat(auth): add session timeout handling'"
# This preserves the full story: we tried it, it broke things, we reverted it.

Unlike git reset, revert is safe for shared branches because it adds to history rather than erasing it. The story is preserved: we tried it, it broke things, we reverted it. Future James — or a new team member — can read the full narrative.

Cherry-Pick: Selective Application

git cherry-pick applies a specific commit from one branch to another. When James found a critical bug fix on his experiment branch that needed to go to main immediately, Emma showed him cherry-pick:

# A critical fix was made on a feature branch
# Apply just that fix to main without merging everything
git checkout main
git cherry-pick def456

# The fix is now on main, with full attribution preserved

Viewing Past States

After learning these commands, James realized he could have answered his team lead's post-mortem question — if his commits had been disciplined. With proper git history, recovering any past version is one command:

# See a file as it was at any point in history
git show v1.0.0:src/discount.py

# Compare the buggy version to the fixed version
git diff abc123 def456 -- src/discount.py

# See all files at a past state (read-only exploration)
git stash # save current work
git checkout v1.0.0
# explore the entire project as it was at the release...
git checkout main
git stash pop # restore current work

If James had made an atomic commit for the original apply_discount() implementation, he could have shown the team lead exactly what the buggy code looked like, when it was introduced, and which TDG test caught the error — all from a single git show command.


Try With AI

Prompt 1: Transform Bad Commits into Good Memory

I have these five commits from an order management project:

1. "updated stuff"
2. "fix"
3. "wip"
4. "changes"
5. "done"

For each one, here is the actual diff summary. Rewrite each commit
message using conventional commit format, explaining the WHY not the WHAT:

1. Changed FREE_SHIPPING_THRESHOLD from 50.0 to 75.0 in shipping.py
2. Added null check before accessing order.customer_id in discount.py
3. Created new file tests/test_discount.py with 5 TDG specification tests
4. Renamed "calculate_total" to "compute_order_total" across 4 files
5. Added .env to .gitignore and removed hardcoded DB connection string

For each rewritten message, explain what future-you would learn from it
that the original message failed to communicate.

What you're learning: The difference between commits as file-saves and commits as decisions. Notice how each rewritten message captures reasoning that would otherwise be lost — the same reasoning James could not reconstruct at his post-mortem. The original messages treat git as a backup tool; the rewrites treat it as institutional memory.

Prompt 2: Design a Branching Strategy for AI Collaboration

I'm working on an order management system with one other developer
and using Claude Code as my AI coding assistant. We deploy weekly.

Design a branching strategy that:
- Keeps main always deployable
- Gives AI a safe space to experiment (like trying a new discount algorithm)
- Makes AI contributions clearly identifiable in history
- Allows easy rollback of AI-generated code specifically
- Supports code review before AI changes reach main

Show me the exact git commands for a typical workflow where AI generates
the implementation for my TDG tests, I review it, and we merge to main.

What you're learning: Git as a collaboration protocol between human and AI. The branching strategy becomes a trust boundary — the AI works freely within branches, but human review gates the path to production. This is the workflow Emma taught James: human writes the specification, AI generates within a branch, tests verify, human merges.

Prompt 3: Investigate a Bug Using Git's Memory

My order management system's shipping calculator started returning
wrong rates for international orders sometime in the last 50 commits.
I know the tagged release v1.2.0 (50 commits ago) worked correctly.

Walk me through EXACTLY how to use git bisect to find the breaking
commit. Show me:
1. The exact commands to start bisecting
2. What I test at each step (I have pytest tests for shipping)
3. How to handle a commit that I can't easily test
4. What to do once I find the bad commit
5. How to safely fix the problem (revert vs fix-forward)

Then explain: why does atomic commit discipline make this process
faster and more effective than if all 50 commits were giant
"weekly update" commits?

What you're learning: Git as an investigative tool, not just a storage tool. Binary search through history only works when commits are atomic — each commit is a single hypothesis to test. This is exactly how James found his international shipping bug: bisect narrowed fifty commits to the one AI-generated change that introduced a rounding error. Giant commits make bisect useless because even finding the bad commit does not tell you which of its two hundred changes caused the problem.


The Permanent Record

A month into his new commit discipline, James made a different kind of mistake. He was setting up the database connection for his order management system and committed the file with the connection string hardcoded: DATABASE_URL=postgresql://admin:s3cretPass@prod-db.company.com/orders. He realized immediately, deleted the line, and committed the fix. Problem solved — or so he thought.

"The password is still in your history," Emma told him. She ran one command:

# This finds secrets in ALL of history, not just current files
git log -p --all -S 'DATABASE_URL'

The original commit appeared — with the full connection string visible. Deleting the file in a later commit does not erase it from history. Git's perfect memory, the same feature that makes it invaluable for recording decisions, makes it dangerous for secrets. Once committed, a credential exists in every clone of the repository, forever.

The Permanent Record is the flip side of Axiom VIII: git remembers everything, including things you wish it would forget. The same mechanism that would have preserved James's buggy apply_discount() for the post-mortem also preserves every accidentally committed password, API key, and credential.

Prevention is the only reliable defense:

# Create .gitignore BEFORE your first commit
echo ".env" >> .gitignore
echo "*.pem" >> .gitignore
echo "credentials.json" >> .gitignore

# Verify nothing sensitive is staged
git diff --staged --name-only
# Check: do any of these files contain secrets?

# Use environment variables instead
export DATABASE_URL="postgresql://user:pass@host/db"
# Reference in code: os.environ["DATABASE_URL"]

If you accidentally commit a secret, as James did:

  1. Rotate the credential immediately — assume it is compromised
  2. Remove from current files and commit the removal
  3. For sensitive repositories, use git filter-branch or BFG Repo-Cleaner to purge from history
  4. Force-push the cleaned history (this is the one valid use of force-push)

James had to rotate the database password that afternoon — an hour of work that a .gitignore file would have prevented entirely. He never committed a credential again.


Key Takeaways

James's post-mortem failed because his git history was a collection of wip messages instead of a record of decisions. Emma's fix was not to write better documentation — it was to write better commits. Linus Torvalds designed Git in 2005 to be a distributed institutional memory. Commit discipline is what makes that memory useful.

  • Git is not a backup tool — it is the memory of your project. James's wip commits destroyed the story of how his code evolved. Emma's disciplined commits preserved every decision, its rationale, and its context. The difference cost James three hours at a post-mortem that should have taken three minutes.
  • Atomic commits enable time travel. When James's shipping calculator broke, git bisect found the exact commit in six steps across fifty commits — because each commit was one logical change. Giant commits make bisect useless.
  • Commit messages explain WHY, not WHAT. The diff already shows what changed. The message records what the diff cannot: the reasoning, the context, the trade-offs. Six months from now, the message is all you have.
  • Git is the collaboration protocol between you and AI. The AI reads your commit history to understand context. You label AI-generated commits for accountability. Branches give the AI a safe space to experiment. Pull requests gate the path to production.
  • The Permanent Record cuts both ways. Git's perfect memory preserves every decision — and every accidentally committed secret. A .gitignore file before your first commit prevents the one mistake that git cannot easily undo.

Looking Ahead

Your shell orchestrates programs. Your knowledge lives in markdown. Your programs have types, tests, and relational data. Your systems are composed from focused units. Your git history records every decision. But how do you know that all of these pieces actually work together? James had tests for individual functions, but nothing that verified the full pipeline: data enters the system, flows through discount calculation, passes through shipping, produces an invoice, and sends a confirmation. Each piece worked in isolation. The pipeline had never been tested end-to-end.

In Axiom IX, you will discover that verification is not a single step — it is a pipeline, and every stage must pass before you trust the whole.