Git95 min total · 17 parts
Git Internals and Workflows: Branching, Merging, and Rebasing
Part 17 of 17 · ~3 min
Common Mistakes Worth Remembering
Every one of these turned up somewhere in the shift-swap story, and most of them inside a single week.
- Rebasing commits someone else had already pulled. You nearly did this on Wednesday, and the only thing that made it safe was telling Theo first. Rewriting shared commits forces a painful reconciliation on everyone downstream, because their repository still has the originals and Git cannot tell the copies are the same work.
- Assuming
HEADmeans "my branch" during a rebase. It does not.HEADis the branch you are rebasing onto, and your commit is the incoming side — the exact inverse of a merge. Resolve a rebase conflict on merge instincts and you will delete the commit you are currently replaying. - Reaching for
git push --forceinstead of--force-with-lease. Plain--forcewould have erased Theo's review commit with no record anywhere. And--force-with-leaseon its own has a real gap: a baregit fetchrefreshes the lease and lets the overwrite through. Pair it with--force-if-includes. - Resetting a branch that is already public.
git reset --hardon a pushedmainundoes nothing for anybody else and sets up a force-push over a shared trunk. If it is public,git revert. - Forgetting
-mwhen reverting a merge commit — and then, two weeks later, forgetting that merging the branch again will reportAlready up to date.and change nothing. Revert the revert. - Confusing
git fetchwithgit pull.fetchdownloads and touches nothing local.pullimmediately merges or rebases into whatever you have checked out. One is a question; the other is a change. - Stashing without
-u. Untracked files stay in the working tree and follow you onto every branch you visit, which produces failures that look supernatural until you notice the stray file. - Committing generated files or secrets because
.gitignorewas written after the first commit. Ignoring only applies to files Git is not already tracking, and deleting a secret in a later commit does not remove it from history — it is still in every clone, and it must be treated as compromised and rotated, not just deleted. - Leaving work in detached HEAD. Git warns you and prints the hash. Read the warning; it is telling you exactly what to do.
- Letting merged branches accumulate. Deleting a merged branch deletes a label and nothing else.
git branch --merged mainlists what is safe to remove. - Treating lost work as gone for good after a
reset --hardgone wrong, or a rebase that took a bad turn.git reflogalmost always still has it — the one real exception is work that was never committed in the first place. - Resolving a conflict by taking one side wholesale without reading the other. Those markers show up precisely because each person had a legitimate reason for making a different change. On Wednesday, keeping either side alone would have shipped a bug: yours drops a timezone correctness fix, Nadia's drops the feature you spent two days on. The resolution usually has to serve both intents, not crown a winner.
That last one is the only entry on this list that Git cannot help you with, and it is the one that matters most. Everything else here is a mechanism you can learn once. Reading a conflict properly is reading code carefully, under mild time pressure, at the exact moment you most want to be finished.
If you want to see a real, if small, history with a lot of this in it, the code behind this site is public at github.com/HMankad8/screening-platform. For the data model all of this version control is ultimately protecting — joins, transactions, and the queries themselves — that is in SQL Fundamentals: Joins, NULL, Aggregate Functions, and Subqueries, and the code lab is right there if you would rather run real code than just read about it.
Continue learning
- Interview & Career PrepThe Non-Technical Half of the Interview: Behavioral Questions, the STAR Method, and What Recruiters Are Actually Scoring
- AI & LLM EngineeringAI & LLM Engineering Fundamentals: Prompting, RAG, Embeddings, and Function Calling
- TypeScriptTypeScript Fundamentals: Types, Interfaces, Generics, and Why It Catches Bugs Before Runtime