← Back to list

The “Pre-Receive Hook Declined” Nightmare: How to Resolve Git Conflicts When Force-Pushing is…

Picture this: It’s late afternoon, your feature branch is complete, and you’re ready to merge your pull request. You open the PR only to…

ramesh516390 · 2026-06-23 15:28 · 0 claps · 3.7 min read
#github #git #merge #merge-conflicts #git-merge-conflict
Open on Medium ↗
Wiki topics: 🔓 · Open Source

The “Pre-Receive Hook Declined” Nightmare: How to Resolve Git Conflicts When Force-Pushing is Disabled

Picture this: It’s late afternoon, your feature branch is complete, and you’re ready to merge your pull request. You open the PR only to see the dreaded red warning: This branch has conflicts that must be resolved.

Instinctively, you pull up your terminal, run git rebase origin/release/v3.4.0, locate the conflicting files, clean up the markers, and get ready to update your remote branch. You confidently type:

git push --force-with-lease

You hit Enter, expecting a clean state and a green merge button. Instead, your terminal screen flashes red with a frustrating block of text:

remote: Force-pushing to this repository has been disabled
! [remote rejected] feature/user-auth -> feature/user-auth (pre-receive hook declined)
error: failed to push some refs to 'ssh://github.com/your-org/your-repo.git'

Game over.

If you work in a modern enterprise environment (using GitHub Enterprise, Bitbucket/Stash, or GitLab), you have likely run face-first into this security wall.

In this article, we’ll unpack exactly why this happens, why your usual “rebase-and-force-push” workflow is blocked, and look at the step-by-step “Golden Path” to resolve your conflicts cleanly — without ever needing a force-push.

Why Enterprise Repos Block Force-Pushing (And Why It’s Actually a Good Thing)

First, let’s clear the air: your DevOps team didn’t set this up just to make your life difficult.

When you rebase a branch, Git takes your commits and “re-plays” them on top of the target branch. This process actually deletes your old commits and replaces them with brand-new ones that have completely different hashes. Because you are rewriting history, Git won’t let you push normally; you have to use a force push (-f or --force-with-lease).

In a collaborative enterprise repo, force-pushing is highly dangerous. If a colleague pulled your branch, made a change, and pushed it while you were rebasing, a force push would permanently wipe out their work.

To prevent this, repository admins enable pre-receive hooks that block force-pushing entirely. Your history must remain strictly additive.

Enter the “Standard Merge”: The Savior of Locked-Down Repos

If we can’t rewrite history (rebase), we must add to it. We do this using a Standard Merge.

Instead of moving your commits to the top of the release branch, a merge pulls the release branch into your feature branch and wraps the integration up in a single, clean Merge Commit. No rewritten history, no force-pushing required.

Here is the step-by-step recipe to rescue your branch.

Step 1: Discard the Stalled Rebase (The Clean Slate)

If your terminal is currently stuck in the middle of a rebase, we need to abort it and reset our local files to match what’s on the remote server.

# Fetch the latest updates from the remote server
git fetch origin
# Force your local branch to match the remote server exactly
git reset --hard origin/feature/user-auth

⚠️ Warning: git reset --hard will discard any uncommitted local changes. Make sure your local workspace is clean before running this!

Step 2: Merge the Target Branch Into Your Branch

Now, we explicitly merge the target branch (the one you are trying to merge into, like a release or main branch) into your current working branch.

git merge origin/release/v3.4.0

Git will attempt to auto-merge what it can, but it will pause on files modified in both branches:

CONFLICT (content): Merge conflict in config/default.json
Automatic merge failed; fix conflicts and then commit the result.

Step 3: Resolve the Conflicts (Mind the HEAD!)

Open the conflicting files in your editor (VS Code, IntelliJ, or your preferred IDE). You will see Git’s conflict markers:

<<<<<<< HEAD
  "TIMEOUT_MS": 5000,      (<- This is YOUR branch's code)
=======
  "TIMEOUT_MS": 10000,     (<- This is the TARGET branch's code)
>>>>>>> origin/release/v3.4.0

💡 Crucial Git Tip: HEAD behaves differently in Merges vs. Rebases!

  • During a Rebase, HEAD refers to the target branch you are rebasing onto.
  • During a Merge, HEAD refers to your active feature branch.

Because we are doing a Merge, the top section (HEAD) contains the code you wrote in your feature branch. The bottom section contains the incoming changes from the target release branch.

To resolve the conflict:

  1. Delete the conflict markers (<<<<<<<, =======, >>>>>>>).
  2. Keep the code you want (usually your feature branch’s code, or a combination of both if required).
  3. Ensure the spacing, syntax, and formatting remain intact.

Your final file should look clean:

"TIMEOUT_MS": 5000,

Step 4: Stage, Commit, and Push Normally

Now that the files are clean, we simply commit the resolution and push it. Because this adds a new commit instead of rewriting the past, a normal git push is all you need.

# 1. Stage the resolved files
git add config/default.json
# 2. Commit the merge resolution
git commit -m "Merge branch 'release/v3.4.0' into feature/user-auth and resolve conflicts"
# 3. Push normally! (No force flags!)
git push

Your terminal will show a beautiful success message:

To ssh://github.com/your-org/your-repo.git
   c0f243c..294c6eb  feature/user-auth -> feature/user-auth

The Verdict: Rebase vs. Merge in the Real World

While “clean git history” advocates love rebasing because it keeps commit graphs perfectly linear, the reality of working in a secure enterprise ecosystem requires adaptability.

Using git merge to pull target branches into your feature branch:

  • Keeps your work safe from being overwritten.
  • Respects enterprise pre-receive security hooks.
  • Keeps a clear, auditable trail of when and how conflicts were resolved.

The next time your terminal shouts at you with a blocked force-push, don’t panic. Abort the rebase, merge the target, resolve the code, and push normally. Your PR (and your DevOps team) will thank you!

Did this save you from a Git headache? Let me know in the comments below, and don’t forget to clap if this helped you out!


메타데이터
post_id
a5ae0696d57d
slug
the-pre-receive-hook-declined-nightmare-how-to-resolve-git-conflicts-when-force-pushing-is-a5ae0696d57d
url
https://medium.com/@ramesh516390/the-pre-receive-hook-declined-nightmare-how-to-resolve-git-conflicts-when-force-pushing-is-a5ae0696d57d
canonical_url
https://medium.com/@ramesh516390/the-pre-receive-hook-declined-nightmare-how-to-resolve-git-conflicts-when-force-pushing-is-a5ae0696d57d
author_url
https://medium.com/@ramesh516390
status
ok
fetched_at
2026-06-26 03:39:16