How to fix remote: error: pre-receive hook declined in Git
Fix Git push rejected by "pre-receive hook declined" - protected branch, missing permissions, or commit policy. How to find the rule and push.
Quick fix
Fixes remote: error: pre-receive hook declined
# Example output with context:
remote: error: GH006: Protected branch update failed for refs/heads/main.
remote: error: Required status check "ci/tests" is expected.
remote: error: pre-receive hook declined- Read the full error message carefully
- Check branch protection settings
- Verify your repository permissions
- Fix commit message format issues
# Example output with context:remote: error: GH006: Protected branch update failed for refs/heads/main.remote: error: Required status check "ci/tests" is expected.remote: error: pre-receive hook declinedremote: error: pre-receive hook declined
What this error means
This error indicates that a pre-receive hook on the remote Git server has rejected your push operation. Pre-receive hooks are server-side scripts that run before any refs are updated, allowing administrators to enforce repository policies. When you push commits to a remote repository, the server can execute custom scripts to validate the incoming changes. If the validation fails, the server returns this error and refuses to accept the push. The hook itself does not modify anything on the server - it simply accepts or rejects the push based on predefined rules. Common scenarios where this error appears include: 1. **Protected branch enforcement**: Many Git hosting platforms (GitHub, GitLab, Bitbucket) implement branch protection rules as pre-receive hooks. Attempting to push directly to a protected branch without proper permissions triggers this error. 2. **Push rules validation**: Organizations configure push rules to enforce commit message formats (e.g., requiring JIRA ticket numbers), file size limits, author email verification, or other compliance requirements. 3. **Permission issues**: You may lack the necessary role (e.g., Maintainer vs Developer) to push to certain branches. The error message itself is intentionally generic. The actual reason for rejection is usually provided in lines prefixed with "remote:" that appear before the hook declined message. Always read the full error output carefully to understand the specific violation.
Typical symptoms
- Git push command fails with 'remote: error: pre-receive hook declined' message
- Force push (git push --force) is rejected with this error
- Push to specific branches like main or master fails while other branches work
- CI/CD pipelines fail during the git push step
- Initial push to a new repository is rejected
- Merge commits fail to push after rebasing or amending
- Push works for some team members but not others
Common causes
- Pushing to a protected branch without required permissions (most common)
- Insufficient role assignment (Developer instead of Maintainer on GitLab)
- Commit message does not follow required format (e.g., missing JIRA ticket number)
- File size exceeds repository limit (typically 100MB on GitHub, configurable on GitLab)
- Author email does not match verified emails on the platform
- Attempting force push when force pushes are disabled
- Branch requires pull/merge request workflow instead of direct push
- Non-fast-forward push when history rewriting is blocked
- Custom server hook script validation failure
- Git hosting service experiencing temporary issues
How to fix "remote: error: pre-receive hook declined"
The pre-receive hook error is often accompanied by additional context. Look for lines starting with "remote:" before the hook declined message:
# Example output with context:
remote: error: GH006: Protected branch update failed for refs/heads/main.
remote: error: Required status check "ci/tests" is expected.
remote: error: pre-receive hook declinedThe lines above "pre-receive hook declined" tell you exactly what rule was violated. Common prefixes include:
- GH006: GitHub protected branch violation
- GitLab: Push rules or protected branch issues
- Custom: Organization-specific validation messages
If you're pushing to a protected branch (usually main/master), verify the protection rules:
GitHub:
1. Go to repository Settings > Branches > Branch protection rules
2. Check if the branch matches a protection rule
3. Verify if "Require pull request reviews" is enabled
4. Check if you have bypass permissions
GitLab:
1. Go to Settings > Repository > Protected branches
2. Check "Allowed to push" settings for your branch
3. Verify your role (Maintainer vs Developer)
Bitbucket:
1. Go to Repository settings > Branch permissions
2. Review which users/groups can push directly
If the branch is protected, create a feature branch and open a pull/merge request instead:
# Create a new branch from your current changes
git checkout -b feature/my-changes
# Push the feature branch
git push -u origin feature/my-changes
# Then create a PR/MR through the web interfaceCheck that you have the correct role to push to the target branch:
GitLab roles:
- Guest/Reporter: Cannot push
- Developer: Can push to unprotected branches
- Maintainer/Owner: Can push to protected branches
GitHub roles:
- Read: Cannot push
- Triage/Write: Can push to unprotected branches
- Maintain/Admin: Can push to protected branches or bypass rules
To check your current access:
# Test your SSH connection to verify you're using the right account
ssh -T git@github.com
ssh -T git@gitlab.com
# Check the remote URL
git remote -vIf you need elevated permissions, contact the repository administrator or owner.
If your organization requires specific commit message formats, amend your commits to comply:
# Amend the most recent commit message
git commit --amend -m "JIRA-123: Add new feature"
# Interactive rebase to edit multiple commits
git rebase -i HEAD~3
# In the editor, change 'pick' to 'reword' for commits needing new messages
# Save and follow prompts to enter new messagesCommon commit message requirements:
- JIRA/Ticket numbers: PROJ-123: description
- Conventional commits: feat: add new feature
- Signed-off-by lines: git commit -s
After amending, force push to your branch (if allowed):
git push --force-with-lease origin your-branchNote: Never force push to shared branches without team coordination.
If the error mentions file size limits, remove large files from your commit history:
# Find large files in your repository
git rev-list --objects --all | \
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
awk '/^blob/ {print $3, $4}' | sort -rn | head -20
# Remove a large file from the last commit
git reset --soft HEAD~1
git rm --cached large-file.zip
git commit -m "Your commit message"
# Remove from entire history (use with caution)
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch path/to/large-file.zip" \
--prune-empty --tag-name-filter cat -- --allFor future large files, use Git LFS:
# Install and configure Git LFS
git lfs install
git lfs track "*.zip"
git add .gitattributesIf the error is related to non-fast-forward updates, sync your branch first:
# Fetch latest changes
git fetch origin
# Rebase your changes on top of remote
git pull --rebase origin main
# Or merge if you prefer
git pull origin main
# Then push
git push origin mainIf you have conflicts:
# After resolving conflicts
git add .
git rebase --continue
# Then push
git push origin mainSome platforms require commits to be authored by verified email addresses:
# Check your Git email configuration
git config user.email
# Check the email in your commits
git log --format='%ae' -1
# Update your Git email to match your account
git config --global user.email "your-verified-email@example.com"
# Amend the last commit with correct email
git commit --amend --reset-author --no-edit
# For multiple commits, use interactive rebase
git rebase -i HEAD~5 --exec "git commit --amend --reset-author --no-edit"Verify your email is confirmed on your Git hosting platform (Settings > Emails).
Sometimes the error is caused by temporary server issues:
Check service status:
- GitHub: https://www.githubstatus.com/
- GitLab: https://status.gitlab.com/
- Bitbucket: https://bitbucket.status.atlassian.com/
If the service is experiencing issues, wait and retry later:
# Wait a few minutes, then retry
git push origin mainYou can also check if it's a network issue on your end:
# Test SSH connectivity
ssh -T git@github.com
# Test HTTPS connectivity
curl -I https://github.comAdvanced notes
### Understanding Pre-Receive Hooks
Pre-receive hooks are one of three server-side Git hooks:
1. pre-receive: Runs once before any refs are updated. Can reject the entire push.
2. update: Runs once per branch being updated. Can reject individual branches.
3. post-receive: Runs after all refs are updated. Cannot reject (used for notifications).
The hook receives input via stdin in the format:
<old-sha> <new-sha> <ref-name>If the hook exits with a non-zero status, the push is rejected.
### GitLab Push Rules
GitLab offers built-in push rules (Premium/Ultimate) that act as pre-receive hooks:
# Common push rules that can cause this error:
- Commit message regex (e.g., must contain ticket number)
- Author email regex (must match company domain)
- Branch name regex
- File name blacklist
- Maximum file size
- Prevent secrets (blocks AWS keys, etc.)
- Reject unsigned commitsCheck your project's Settings > Repository > Push Rules.
### GitHub Branch Protection
GitHub's protected branch features that trigger this error:
- Require pull request reviews: Direct pushes blocked
- Require status checks: CI must pass
- Require signed commits: GPG signature required
- Include administrators: Even admins can't bypass
- Restrict pushes: Only specific users/teams can push
### Custom Hook Debugging
If you manage the Git server, debug custom hooks:
# View hook scripts on the server
ls -la /path/to/repo.git/hooks/
# Check hook logs (varies by platform)
# GitLab: /var/log/gitlab/gitaly/current
# GitHub Enterprise: /var/log/github/enterprise/unicorn.log
# Test hook locally (on server)
echo "old-sha new-sha refs/heads/main" | ./hooks/pre-receive### Working Around Protected Branches
If you legitimately need to push to a protected branch:
1. Temporarily disable protection (requires admin access)
2. Add yourself to allowed pushers in branch settings
3. Use the web interface for small changes
4. Request a bypass from repository administrators
### Force Push Considerations
When force pushing is blocked:
# Instead of --force, use --force-with-lease for safer overwrites
git push --force-with-lease origin feature-branch
# This fails if someone else pushed in the meantimeIf force push is completely disabled on the branch, you'll need to:
1. Create a new branch
2. Cherry-pick or merge your changes
3. Open a new PR/MR
### Common Error Patterns
| Error Pattern | Likely Cause |
|---------------|--------------|
| GH006: Protected branch update failed | GitHub branch protection |
| remote: GitLab: You are not allowed | GitLab permission issue |
| remote: Commit message does not follow | Commit message push rule |
| remote: File size exceeds | Large file push rule |
| remote: Signing is required | Missing GPG signature |
Frequently asked questions
- What does "remote: error: pre-receive hook declined" mean?
- This error indicates that a pre-receive hook on the remote Git server has rejected your push operation. Pre-receive hooks are server-side scripts that run before any refs are updated, allowing administrators to enforce repository policies. When you push commits to a remote repository, the server can execute custom scripts to validate the incoming changes.
- How do I fix "remote: error: pre-receive hook declined"?
- Fix Git push rejected by "pre-receive hook declined" - protected branch, missing permissions, or commit policy. How to find the rule and push.
- What causes "remote: error: pre-receive hook declined"?
- Pushing to a protected branch without required permissions (most common) Insufficient role assignment (Developer instead of Maintainer on GitLab) Commit message does not follow required format (e.g., missing JIRA ticket number)
- Is the "remote: error: pre-receive hook declined" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚Git Official Documentation
- 💬Stack Overflow - Git pre-receive hook declined(Stack Overflow)
- 📝
- 📖GitLab - Server hooks documentation(Official Docs)
- 💬Stack Overflow - GitLab pre-receive hook declined(Stack Overflow)
- 📝