Overview
This guide helps you resolve Git’s error: failed to push some refs. It focuses on DevOps workflows and Git remotes, covering the common causes and safe fixes.
Typical root causes:
- Remote has new commits (non-fast-forward).
- No upstream set for the current branch.
- Protected branch or permissions/pre-receive hook rejections.
- Large files or Git LFS not configured.
- Tag updates rejected.
- Shallow or out-of-date clones.
Symptoms
You run git push and see something like:
- error: failed to push some refs to 'origin'
- Updates were rejected because the remote contains work that you do not have locally
- pre-receive hook declined
- non-fast-forward
Quickstart (most common fix)
If the remote has new commits, rebase your work onto the remote and push:
# On your feature branch
git fetch origin
# Rebase onto the tracked upstream (example: origin/main)
git rebase origin/main
# Resolve conflicts if any, then continue the rebase
# Finally push
git push
If you rebased and need to update a shared branch, use a safe force:
git push --force-with-lease
Minimal working example
Scenario: Your branch is behind origin/main and push fails.
# 1) Get latest from remote
git fetch origin
# 2) Move your work on top of origin/main
git rebase origin/main
# 3) If conflicts appear, resolve files, then:
# git add <resolved files>
# git rebase --continue
# 4) Push updated history
git push
Step-by-step diagnosis and fixes
- Confirm your branch and upstream
- Show current branch and tracking:
git status -sb
# or
git rev-parse --abbrev-ref --symbolic-full-name @{u}
- If there’s no upstream, set it:
git push -u origin <your-branch>
- Fetch and inspect divergence
git fetch --prune origin
# Compare local vs remote for current branch
git log --oneline --graph --decorate --boundary HEAD..@{u}
- Resolve non-fast-forward
- Rebase (keeps history linear):
git rebase @{u}
- Or merge (preserves a merge commit):
git merge --no-ff @{u}
- Push after resolving conflicts. If you rewrote history (rebase on a published branch), use:
git push --force-with-lease
- Protected branches and policies
- If pushing to a protected branch (e.g., main), policy may block pushes.
- Create a feature branch and open a pull request.
- If your push is allowed but needs signed commits or CI checks, satisfy the requirement: sign commits, pass checks, then push.
- Pre-receive hook or permission errors
- Read the server’s message; it often explains the rule (e.g., commit-msg rules, file size limits, required reviewers).
- Fix locally (e.g., amend commit messages, follow naming policies) and push again.
- Large files and Git LFS
- If large files are blocked, use Git LFS:
git lfs install
git lfs track "*.bin"
git add .gitattributes
# Move large files under LFS tracking
git add <large-files>
git commit -m "Track large files with LFS"
git push
- If a large file already exists in history, you may need to rewrite history with git filter-repo or git filter-branch, then force-push (coordinate with your team).
- Tags rejected
- Updating an existing remote tag can be blocked. Safe pattern:
# Replace remote tag v1.2.3
git tag -f v1.2.3 <commit>
git push origin :refs/tags/v1.2.3
git push origin v1.2.3
- Shallow clones or missing history
- If you used a shallow clone, fetch more history:
git fetch --unshallow # or: git fetch --depth=1000
- Then rebase/merge and push.
Cause-to-fix quick map
- Remote has new commits → git fetch; git rebase @{u}; git push.
- No upstream set → git push -u origin <branch>.
- Protected branch → push to feature branch; open PR.
- Policy/hook rejects → follow hook message; amend commits; retry.
- Large files rejected → use Git LFS; possibly rewrite history.
- Tag update rejected → delete and re-push tag or force if policy allows.
- Shallow clone issues → fetch full history; rebase; push.
Pitfalls to avoid
- Using git push --force indiscriminately: prefer --force-with-lease to avoid clobbering teammates’ new commits.
- Rebasing shared branches without coordination: agree on workflow before rewriting public history.
- Pulling with merge by default on linear history repos: prefer git pull --rebase to avoid unnecessary merge commits.
- Forgetting to set upstream: always use -u on first push of a new branch.
- Accidentally pushing tags or all branches: push only what you intend (git push origin HEAD).
Performance notes
- Push only your current branch:
git push origin HEAD
- Reduce object transfer by packing locally:
git gc --aggressive --prune=now
- Avoid pushing large binaries; use LFS to offload them.
- For slow networks, partial clone/fetch helps pull performance; pushes still depend on new objects to send. Keeping history clean reduces push size.
- Use shallow clones for CI to speed clones, then unshallow only when you must push with full history.
Tiny FAQ
Q: Why does git push say “non-fast-forward”?
A: The remote has commits you don’t. Fetch, rebase or merge, then push.
Q: When is force-push safe?
A: Only when you must update rewritten history and you know nobody else has built on top. Use --force-with-lease.
Q: I get “pre-receive hook declined.” What now?
A: Read the hook message. Fix the policy issue (format, tests, signatures, file size) and push again.
Q: First push of a new branch fails.
A: Set the upstream with git push -u origin <branch> and retry.
Q: Tag push rejected?
A: Delete the remote tag and push the new one, or get permission to force-update tags.