The 'pre-receive hook declined' error occurs when a server-side Git hook rejects your push. This is typically caused by protected branch restrictions, insufficient permissions, commit message format violations, or push rule violations on platforms like GitHub and GitLab.
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.
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 [email protected]
ssh -T [email protected]
# 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 "[email protected]"
# 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 [email protected]
# Test HTTPS connectivity
curl -I https://github.com### 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 |
kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server
fatal: unable to access: Proxy auto-configuration failed
How to fix 'Proxy auto-configuration failed' in Git
fatal: unable to access: Authentication failed (proxy requires basic auth)
How to fix 'Authentication failed (proxy requires basic auth)' in Git
fatal: unable to access: no_proxy configuration not working
How to fix 'no_proxy configuration not working' in Git
fatal: unable to read tree object in treeless clone
How to fix 'unable to read tree object in treeless clone' in Git