When Git Pushes Back: How to Resolve Merge Conflicts (Without Losing Your Mind)

When Git refuses your push with that dreaded “fetch first” message, it’s not the end of the world. Learn how to calmly resolve merge conflicts using a simple rebase workflow that keeps your history clean and your sanity intact.

Table of Contents

Conflicts aren’t chaos — just a chance to fetch, rebase, resolve, and push.

It’s 7:15 p.m. You’ve just finished tweaking a deployment script after a long day of staging issues, server restarts, and Slack pings. You run your final test, everything looks perfect, and you confidently type:

…and Git slaps you with a wall of red text:

Your heart sinks. The day was so close to being over. But no — someone else pushed changes to main while you were working. Now your local repo and the remote branch have diverged, and Git refuses to combine them automatically.

Welcome to one of the most common rites of passage in software development: resolving merge conflicts.


Why This Happens

In Git’s world, the remote branch (origin/main) is the “source of truth.”
If another teammate (or an automated deployment bot) pushes commits before you do, your local main becomes out of date.

When you try to push, Git sees that your local history doesn’t include those remote commits — and it refuses the operation to prevent overwriting someone else’s work.


Step 1: Stay Calm and Fetch

Start by syncing your local view of the repo:

This pulls the latest info from GitHub (or wherever your repo lives) without merging anything yet.

You can confirm what you’re missing:

If you see something like:

Then yes — someone beat you to the push.


Step 2: Rebase to Catch Up (The Clean Way)

To neatly stack your local changes on top of what’s already on origin/main, use:

This tells Git:

“Pretend I made my commits after the latest ones from the remote branch.”

If there are no conflicts, Git will quickly replay your commits on top. Done.
But if there are conflicting edits (e.g., you and a teammate both touched the same line), Git pauses the rebase and marks the files with conflict markers like:

At this point:

  • Open the file in your editor.
  • Decide which code should stay (yours, theirs, or a mix).
  • Save and stage the resolved file:

Then continue the rebase:

Repeat until Git finishes replaying your commits.

💡 Tip: If things get messy, you can always reset the rebase safely:


Step 3: Push With Confidence

Once your rebase is complete, your local branch history matches the remote.
Now it’s time to push:

This time, Git smiles and accepts your changes.


What If You Don’t Want to Rebase?

Some teams prefer merge commits to keep a visible record of when branches were combined.
If that’s your team’s policy, you can use:

Then resolve conflicts as usual and commit the merge.

But for most modern workflows — especially on projects where multiple developers push frequently — rebasing keeps history tidy and readable.


Out of Scope (But Good to Know)

There are more complex scenarios, like:

  • Rebasing public branches with shared commits
  • Handling long-running feature branches that span multiple PRs
  • Recovering from a bad rebase or force-push

Those deserve their own deep dive — we’ll save that for another post.


Final Thoughts

Resolving merge conflicts isn’t a failure — it’s a normal part of teamwork. Once you get comfortable with rebasing, conflict resolution, and Git’s guardrails, you’ll start to see the elegance in how it protects your codebase from chaos.

So next time Git makes a fuss,
Don’t let the warning make you blush.
Just fetch, rebase, resolve, and push —
Git’s your friend, not out to crush!

Have a project or a problem?

Talk with a senior engineer for practical recommendations—no obligation.

Leave a comment

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Posts

Categories

Get a free consultation from Reliable Penguin

Submit the form—or for immediate service call 866-649-7984.