Git Philosophy: History as Storytelling¶
The main Git history is the single source of truth - it should be clean, effective, and read like a well-crafted storybook full of interesting snapshots of development logic. Each commit should tell a meaningful part of the story, making it easy for anyone (including future me) to understand the evolution of the codebase.
The Storybook Approach¶
Each commit represents a logical, complete thought or feature increment
Commit messages should explain the “why” behind changes, not just the “what”
The history should flow naturally from one logical step to the next
Reading the git log should reveal the development reasoning and decision-making process
Commits capture meaningful moments in development
Each commit should be atomic and focused on a single concern
Changes should be grouped logically, not chronologically
The story should be engaging and informative for reviewers and maintainers
Public vs Private Development¶
Clean Public Commits:¶
Published history is immutable and clean
Every commit in main/published branches passes tests
Commit messages follow consistent conventions
No “fix typo”, “oops”, or “WIP” commits in public history
Each commit stands alone as a meaningful contribution
Messy Private Iterations:¶
Private development can be messy and experimental
Save work frequently with descriptive but informal commit messages
Don’t worry about perfect commits during active development
Use branches liberally for experimentation
Focus on progress over perfection in private branches
Interactive Rebase Strategy¶
Interactive rebase is the bridge between messy development and clean history:
# Before publishing, clean up the history
git rebase -i HEAD~n # where n is number of commits to review
# Common rebase operations:
# - squash: Combine multiple commits into one
# - fixup: Merge commit into previous one without editing message
# - reword: Change commit message
# - edit: Modify commit content
# - drop: Remove commit entirely
Squashing Strategy:¶
Squash related fixes together: Combine bug fixes with the commits they fix
Group feature work: Multiple commits working on the same feature → single logical commit
Remove debugging commits: Squash away temporary logging, console.log, debug prints
Combine refactoring: Group refactoring commits that work toward the same goal
Best Practices¶
Commit Message Format:
type(scope): Brief description of the change
Longer explanation of what and why, not how.
Reference any issues, requirements, or context.
- List specific changes if helpful
- Explain any breaking changes
- Reference related commits or issues
Fixes #123
Resolves SCRUM-456
Branch Strategy¶
main # Clean, release-ready history
├── Feature/user-authentication # New feature development
├── Feature/payment-integration # Another feature in progress
├── BugFix/login-validation-error # Bug fix branch
├── BugFix/memory-leak-fix # Critical bug fix
├── Hotfix/security-patch # Emergency production fix
└── WIP/auth-experiment # Messy experimental branch
Branch Naming Convention¶
Use categorized prefixes to make branch purposes immediately clear:
Feature/ - New Functionality¶
Feature/user-dashboard
Feature/api-rate-limiting
Feature/dark-mode-toggle
Feature/export-functionality
BugFix/ - Issue Resolution¶
BugFix/login-redirect-loop
BugFix/memory-leak-in-parser
BugFix/timezone-calculation-error
BugFix/css-layout-mobile-fix
Other Common Prefixes¶
Hotfix/ # Critical production fixes
Refactor/ # Code improvement without feature changes
Docs/ # Documentation updates
Test/ # Test improvements or additions
WIP/ # Work-in-progress/experimental branches
Chore/ # Maintenance tasks (dependency updates, etc.)
Traceability Benefits¶
This naming convention provides instant context:
Easy filtering:
git branch | grep Feature/shows all features in progressClear purpose: Anyone can understand branch intent at a glance
Better organization: IDEs and Git tools can group branches by category
Release planning: Quickly identify what features/fixes are ready
Code review context: Reviewers know what type of change to expect
Development Workflow¶
Start from clean main: Always branch from latest main
Create categorized branch: Use appropriate prefix (Feature/, BugFix/, etc.)
Develop messily: Make frequent commits during development
Review privately: Use
git log --onelineto review your storyClean with rebase: Interactive rebase to create logical commits
Final review: Ensure each commit is meaningful and complete
Publish/merge: Clean history ready for public consumption
Workflow Examples¶
# Starting a new feature
git checkout main
git pull origin main
git checkout -b Feature/user-profile-settings
# Working on a bug fix
git checkout main
git pull origin main
git checkout -b BugFix/payment-form-validation
# Emergency production fix
git checkout main
git checkout -b Hotfix/security-vulnerability-patch
Tools and Commands¶
# Review your story before cleaning
git log --oneline --graph HEAD~10..HEAD
# Interactive rebase for cleanup
git rebase -i HEAD~5
# Amend last commit (for small fixes)
git commit --amend
# Split a commit that's too large
git rebase -i HEAD~1 # mark as 'edit'
git reset HEAD~1
git add -p # stage parts
git commit # repeat as needed
git rebase --continue
# Preview what rebase will do
git rebase -i --dry-run HEAD~5
Branch Management Commands¶
# List branches by category
git branch | grep Feature/ # All feature branches
git branch | grep BugFix/ # All bug fix branches
git branch | grep Hotfix/ # All hotfix branches
# Delete completed feature branches
git branch -d Feature/completed-feature
git push origin --delete Feature/completed-feature
# Find branches by pattern
git branch --list "Feature/*" # List all feature branches
git branch --list "BugFix/*" # List all bug fix branches
# See branch creation dates (helpful for cleanup)
git for-each-ref --format='%(refname:short) %(committerdate)' refs/heads/ | sort -k2
# Clean up merged branches (be careful!)
git branch --merged main | grep -E "(Feature/|BugFix/)" | xargs -n 1 git branch -d
Why This Matters¶
For Current Development:¶
Clearer debugging: Easy to identify when issues were introduced
Better code reviews: Logical commits make reviews more effective
Faster onboarding: New team members can understand code evolution
Confident refactoring: Clean history makes it safe to change code
For Future Maintenance:¶
Archaeological debugging: Use
git blameandgit logto understand decisionsSelective rollbacks: Clean commits allow precise rollbacks
Feature archaeology: Understand how features were built and why
Documentation: Git history becomes living documentation
For Collaboration:¶
Respectful history: Clean commits respect other developers’ time
Merge confidence: Clean feature branches merge without conflicts
Release notes: Clean commits make release notes generation easy
Bisecting: Clean history makes
git bisectactually useful
Examples¶
Before Cleanup (Messy Development):¶
feat: add user login form
WIP: trying different validation
fix typo in validation
oops forgot to save file
more validation work
fix linting errors
almost working now
WORKING! user login complete
After Rebase (Clean Story):¶
feat(auth): Add user login form with validation
Implement user authentication form with:
- Email/password input fields
- Client-side validation with error messages
- Form submission handling
- Integration with auth service API
The form validates email format and password strength
before submission and provides clear error feedback.
Resolves USER-123
Conclusion¶
Clean Git history is an investment in your future self and your team. It transforms your repository from a messy collection of changes into a readable narrative that tells the story of your code’s evolution. Take the time to craft your commits thoughtfully - your future debugging sessions will thank you.