Karya Semi
HomeBlogSearchTagsCategoriesAboutContact
Karya Semi

Less noise. More notes.

HomeBlogAboutContactPrivacy PolicyDisclaimer

© 2026 Karya Semi. All rights reserved.

XGitHubLinkedIn
  1. Home
  2. /Categories
  3. /Programming

7 Git Mistakes Every Developer Keeps Making

After two years of using Git and watching developers struggle with it, these are the mistakes I see most often and how to avoid them.

Dian Rijal Asyrof/June 28, 2026/4 min read
Illustration for 7 Git Mistakes Every Developer Keeps Making
Advertisement

Every developer has a Git horror story. Mine involves force-pushing to main at 2 AM and losing four hours of work from two teammates. They still bring it up at team dinners.

After two years of using Git and watching dozens of developers struggle with it, I've noticed the same mistakes come up again and again. Not obscure edge cases. Basic, everyday mistakes that cause real problems.

Here are the ones I see most often, and how to avoid them.

Force Pushing Without Understanding It

git push --force is the nuclear option. It overwrites the remote branch with your local version. If someone else pushed commits after your last pull, those commits are gone.

The safer version is git push --force-with-lease. It checks that the remote branch is where you last fetched it. If someone else pushed in the meantime, it refuses. This one flag has saved me from at least three incidents.

But the real fix is understanding why you need force push in the first place. If you're force pushing because you rebased, that's normal. If you're force pushing because you messed up and want to hide it, stop. Make a revert commit instead. It's honest and it preserves history.

Using git add . Without Looking

I see this constantly. Developers stage everything with git add . and then commit. They don't check what's being staged. This is how API keys, debug logs, temporary files, and personal configs end up in commits.

The fix is simple. Use git add -p (patch mode). It shows you each change and asks if you want to stage it. Yes, it takes longer. But it prevents embarrassing mistakes.

A developer I worked with once committed his AWS access key this way. It was in a .env file he forgot to gitignore. The key was active for six hours before anyone noticed. AWS bills were... educational.

Never Cleaning Up Branches

Open any team's Git repository and run git branch -r | wc -l. I bet the number is way higher than it should be.

Feature branches pile up. Nobody deletes them after merging. Six months later you have 150 remote branches and nobody knows which ones are active. Someone accidentally checks out an old branch, makes changes, and creates a confusing merge situation.

After merging a branch, delete it:

git branch -d feature-name
git push origin --delete feature-name

Or set up your Git config to auto-delete remote tracking branches on pull:

git config --global fetch.prune true

This one line prevents branch pollution. Set it and forget it.

Writing Terrible Commit Messages

"fix stuff" is not a commit message. Neither is "WIP", "asdfasdf", or "changes."

A good commit message explains what changed and why. Not how (the diff shows that). Why.

Bad: "Fixed login bug"

Good: "Redirect to dashboard after login instead of showing blank page"

The first one tells me nothing without reading the diff. The second one tells me exactly what changed and what the bug was. Six months from now, when you're debugging a similar issue, the second message actually helps.

A format that works:

Short summary (50 chars or less)

Optional longer explanation if the change is complex.
Wrap at 72 characters. Explain the motivation, not the mechanics.

You don't need to follow Conventional Commits religiously. Just be specific.

Ignoring Merge Conflicts Instead of Understanding Them

When Git says there's a conflict, some developers panic. They close the editor, checkout the other branch, and start over. Or they pick one side of every conflict without reading the other.

Merge conflicts happen when two people change the same lines. Git doesn't know which version is correct. That's your job.

The conflict markers are:

<<<<<<< HEAD
your changes
=======
their changes
>>>>>>> branch-name

Read both versions. Decide what the correct code should be. Sometimes it's your version, sometimes it's theirs, sometimes it's a combination. Remove the markers and keep the right code.

If you're dealing with a big conflict, use a visual merge tool. VS Code has built-in merge conflict highlighting that shows both versions side by side with "Accept Current" and "Accept Incoming" buttons. It's not perfect but it's way better than reading raw markers.

Not Using .gitignore Early Enough

Every project needs a .gitignore file. Create it before your first commit, not after you've already committed node_modules/ and .env.

GitHub has templates for every language and framework. Go to github.com/github/gitignore and grab the one you need. For a Node.js project:

node_modules/
.env
dist/
*.log
.DS_Store

If you've already committed files that should be ignored, adding them to .gitignore won't remove them from the repo. You need to untrack them:

git rm -r --cached node_modules/
git commit -m "Remove node_modules from tracking"

The --cached flag removes them from Git's index without deleting them from disk. This catches people off guard all the time.

Rebasing Public Branches

Rebasing rewrites history. It takes your commits and replays them on top of a different base. The commit hashes change. If you rebase a branch that other people have based work on, you create duplicate commits and confusion.

The rule is simple: never rebase commits that have been pushed and shared with others. Rebase your local feature branch before pushing it. That's fine. Rebasing main or a shared develop branch? Don't.

If you need to incorporate changes from main into your feature branch, merge instead:

git merge main

Yes, it creates a merge commit. That's fine. Merge commits are honest. They show that two lines of work came together at a specific point.

Using Interactive Rebase to Clean History

Before pushing a feature branch, you can clean up your commit history with interactive rebase. This is one of Git's most useful features and one of the least used.

git rebase -i HEAD~5

This opens your last five commits and lets you squash, reorder, edit, or drop them. Made three "fix typo" commits? Squash them into one. Committed something broken in the middle? Reorder so the fix comes first.

The result is a clean, readable history that tells a coherent story. Your teammates will thank you when they're reviewing your PR and don't have to wade through twelve commits that say "wip" and "fix again."

Interactive rebase feels scary the first time. But it's local, so you can't break anything. Make a backup branch if you're nervous: git branch backup-feature. If the rebase goes wrong, git rebase --abort takes you back.

The One Thing That Helps Most

If I had to pick one habit that makes Git easier, it's this: read git status before every commit. It takes two seconds. It shows you what's staged, what's not, and what's untracked.

Those two seconds have caught more mistakes than any other Git habit I have. Unstaged changes I forgot about. Files I didn't mean to modify. Branch names I forgot to switch.

Git is a tool. Like any tool, it works best when you understand what you're doing instead of just hitting buttons and hoping for the best. The mistakes above aren't hard to avoid. They just require paying a little bit of attention.

Advertisement
DR

Dian Rijal Asyrof

Writes about useful AI tools, programming practice, and the craft of building reliable software.

Previous articleThe Definitive Guide to Test-Driven Development for Modern TypeScript ProjectsNext articleAI Coding Tools in 2026: What Actually Changed My Workflow
gitversion-controlbest-practicesdeveloper-tools
Advertisement
Advertisement
On this page↓
  1. Force Pushing Without Understanding It
  2. Using git add . Without Looking
  3. Never Cleaning Up Branches
  4. Writing Terrible Commit Messages
  5. Ignoring Merge Conflicts Instead of Understanding Them
  6. Not Using .gitignore Early Enough
  7. Rebasing Public Branches
  8. Using Interactive Rebase to Clean History
  9. The One Thing That Helps Most

On this page

  1. Force Pushing Without Understanding It
  2. Using git add . Without Looking
  3. Never Cleaning Up Branches
  4. Writing Terrible Commit Messages
  5. Ignoring Merge Conflicts Instead of Understanding Them
  6. Not Using .gitignore Early Enough
  7. Rebasing Public Branches
  8. Using Interactive Rebase to Clean History
  9. The One Thing That Helps Most

See also

Illustration for Mastering Testing in Modern TypeScript: A Comprehensive Guide for Developers
Software Engineering/Jun 20, 2026

Mastering Testing in Modern TypeScript: A Comprehensive Guide for Developers

Learn essential testing strategies, tools, and patterns for TypeScript applications, including unit, integration, and end-to-end testing with practical examples.

5 min read
typescripttesting
Illustration for Cloudflare Temporary Accounts Show the Next Problem for AI Coding Agents
Technology/Jun 28, 2026

Cloudflare Temporary Accounts Show the Next Problem for AI Coding Agents

Cloudflare temporary accounts let agents deploy without a normal signup flow. The bigger story is how developer platforms must adapt to agent-run work.

2 min read
cloudflareai-agents