Never Leave Commented-Out Code
Stop commenting out old code. Your git history already remembers it, and your AI assistant gets confused by the dead lines. Every block you "keep just in case" is a block that git already keeps — perfectly, forever, with the commit message explaining why it changed. The commented copy adds nothing except noise, doubt, and worse AI suggestions.
Why dead code is worse than no code
- Humans hesitate. Robert C. Martin called this out in Clean Code: others who see that commented-out code won't have the courage to delete it. Nobody knows if it's important, so it survives review after review and quietly rots.
- It lies over time. The live code around it keeps changing; the dead block doesn't. Within weeks it references variables that no longer exist and logic that no longer applies.
- Your AI assistant reads it as context. A coding agent doesn't skip gray text. Commented-out code sits inside the model's context window like any other token, and it can anchor the model on abandoned approaches — old function signatures, dead parameters, the API you migrated away from. You're paying tokens to make suggestions worse.
- Static analyzers flag it. SonarSource ships rule S125 — "Sections of code should not be commented out" — for Java, Python, TypeScript, C++, and more. If linters treat it as a code smell, treat it as one.
The fix: delete, commit, move on
- # def calculate_discount_v1(price, tier):
- # # old logic, keep for reference
- # if tier == "gold":
- # return price * 0.8
- # return price
def calculate_discount(price, tier):
return price * DISCOUNT_BY_TIER.get(tier, 1.0)
Delete the block and write one honest commit message: refactor: replace tiered discount branches with a lookup table. That message is the "keep for reference" — searchable, dated, attributed, and attached to the exact code it describes.
Rules of thumb
| Situation | Do this |
|---|---|
| Old implementation you replaced | Delete it. The commit diff is the archive. |
| "Might need this next sprint" | Delete it; recover with git log -S in seconds if next sprint actually arrives. |
| Debug prints / temporary toggles | Delete before the PR. Reviewers should never see them. |
| Experimental alternative approach | Put it on a branch, not in a comment block. |
| A why explanation ("workaround for API rate limit") | Keep it — that's a real comment, not dead code. |
The dividing line: comments that explain why are documentation; comments that contain what (executable code) are dead weight.
Power user: git as your recycle bin
The fear behind commented-out code is "I'll never find it again." Git's pickaxe kills that fear:
# Find every commit that added or removed a string
git log -S "calculate_discount_v1" --oneline
# Same, but match a regex against changed lines
git log -G "discount.*tier" --oneline
# Trace the full history of a function, even after it was deleted
git log -L :calculate_discount:pricing.py
# Resurrect one file exactly as it was in an old commit
git show a1b2c3d:src/pricing.py > /tmp/old_pricing.py
-S (the "pickaxe") finds commits that changed the number of occurrences of a string — which is exactly what a deletion does. -L traces a line range or function name through history. Deleted code isn't gone; it's indexed.
Bonus for AI workflows: run your agent on a cleaned file and on the same file with the dead blocks left in. The cleaned version gets more focused completions because every token in context is live, current truth.
Resources
- Clean Code Tip #7: Clean Up Old Commented-Out Code — Robert C. Martin (InformIT)
- Code Smell 151: Commented Code — Maximiliano Contieri
- Dead Code — Refactoring.Guru code smells
- git-log documentation —
-S,-G, and-Lhistory search - SonarSource rule S125: Sections of code should not be commented out
Building with AI coding agents? Yeda AI designs, audits, and ships production LLM systems.