Stop Memorizing Git Commands Blindly
Ask a junior developer how Git works, and they will rattle off four commands: git add ., git commit -m "fix", git pull, and git push origin main. The moment a merge conflict appears or someone pushes a broken commit to the remote repository, complete panic sets in. They clone the entire repo into a new folder, copy-paste files manually, and pray nobody notices.
You cannot build a serious engineering career by treating your version control system like a black box.
Git is not a magic file-sync utility. It is a content-addressable database structured as a directed acyclic graph (DAG). Once you understand how commits point to each other in memory, Git stops being scary. You can rewind time, recover deleted code, and keep your production branch history clean.
1. The Mental Model: How Git Stores Data
Inside your project's hidden .git/objects/ directory, Git stores everything using four primitive objects:
- Blob: Raw file data compressed with zlib. Git does not store file diffs; it stores complete snapshots of file contents keyed by their SHA-1 hash.
- Tree: A directory listing. It maps filenames and file permissions to blob hashes or child tree hashes.
- Commit: A 40-character hash containing a pointer to the top-level tree, parent commit hashes, author metadata, timestamp, and commit message.
- Ref: A simple text file holding a commit hash. A branch is literally just a 41-byte text file in
.git/refs/heads/pointing to the tip commit.
When you switch branches with git checkout feature, Git does not download or duplicate files. It simply updates the HEAD pointer to read a different text file.
2. Merging vs Rebasing: Keeping a Linear History
When you work on a feature branch for five days while teammates merge their PRs into main, your local branch falls behind. You have two options to catch up:
The Merge Approach
git checkout feature/auth
git merge main
This creates an artificial merge commit tying the two branches together. Do this ten times across a team of five engineers, and your Git log looks like a tangled train track. Tracking down which commit introduced a bug via git bisect becomes nightmare fuel.
The Rebase Approach
git checkout feature/auth
git rebase main
Rebasing takes your feature branch commits, temporarily sets them aside, advances your branch pointer to the latest commit of main, and then replays your commits one by one on top.
The result is a completely linear history. It looks like you wrote your feature on top of the newest code this morning.
The Golden Rule of Rebasing: Never rebase a public branch that other developers have checked out. Rebase your personal feature branches freely, but leave shared branches like main and staging untouched.
3. Cleaning up Messy Commits with Interactive Rebase
During local development, you write messy commits: "wip", "fixed typo", "tests passing", "actually fixed typo". Do not send that trash to code review. Senior engineers squash those into clean, logical units before opening a Pull Request:
# Interactively rebase the last 4 commits
git rebase -i HEAD~4
Your terminal opens a text editor showing your recent commits:
pick e4a1b02 feat: add razorpay webhook handler
pick 99c3d11 fix typo in webhook secret verification
pick 12b4e5a update tests for signature checks
pick 8a7c299 clean up console logs
Change the commands on the left:
pick e4a1b02 feat: add razorpay webhook handler
fixup 99c3d11 fix typo in webhook secret verification
squash 12b4e5a update tests for signature checks
fixup 8a7c299 clean up console logs
Save and close the file. Git folds the three fixup commits into the parent commit. Your PR now contains a single, professional commit that is easy to review and safe to revert if needed.
4. Recovering "Deleted" Code with git reflog
Accidentally ran git reset --hard HEAD~3 and wiped out your day's work? Deleted a branch before pushing it to GitHub?
Take a breath. Git almost never deletes commits immediately. It records every single movement of the HEAD pointer in a hidden log called the reference log.
# View recent HEAD movements
git reflog
The output shows every commit you touched over the last 30 days:
a1b2c3d HEAD@{0}: reset: moving to HEAD~3
9f8e7d6 HEAD@{1}: commit: feat: integrate order persistence
5c4b3a2 HEAD@{2}: commit: feat: scaffold sqlite schema
Your missing commit is right there at HEAD@{1} (hash 9f8e7d6). Recover it instantly into a new branch:
# Create a recovery branch pointing directly to the lost commit
git checkout -b recovered-work 9f8e7d6
Your lost files are back. Until Git runs its periodic garbage collection (usually after 30 days), unreferenced commits remain safely on disk.
5. Cherry-Picking: Surgical Bug Fixes
Imagine you are working on a massive feature branch with 15 unreleased commits. While testing, you discover and fix a critical authentication vulnerability. Production needs that fix immediately, but your feature branch is not ready to deploy.
Do not copy-paste code. Use git cherry-pick:
# Switch to production hotfix branch
git checkout main
git checkout -b hotfix/auth-leak
# Apply ONLY the security fix commit
git cherry-pick 7d4a19e
# Push and open hotfix PR immediately
git push origin hotfix/auth-leak
Git copies that exact patch and applies it cleanly to your hotfix branch without pulling in any of your unfinished feature code.
6. Production Team Hygiene Checklist
To avoid production outages and team friction, enforce these four standards on your team:
- Adopt Conventional Commits: Prefix commits with standard tags (
feat:,fix:,refactor:,perf:,docs:). It allows automated changelog generation and semantic release tagging. - Protect the Main Branch: Require at least one peer approval and passing CI test suites before any pull request can merge into
main. Ban direct pushes tomainentirely. - Keep Pull Requests Small: PRs with fewer than 300 lines of changes get reviewed thoroughly within two hours. PRs with 1,500 lines sit in review queues for three days and get rubber-stamped with bugs.
- Curate .gitignore Strictly: Never let credentials,
.envfiles, database binaries, or build directories into git tracking. If you accidentally commit a secret, changing the file in a new commit does not erase it from git history; you must invalidate the credential immediately.
Master these fundamentals. When you understand Git's underlying graph structure, you transition from someone who fears code collaboration to an engineer who moves with confidence.
