Troubleshooting Git ‘rejected non-fast-forward’ Push Conflicts on Ubuntu 20.04 LTS
Resolve Git 'rejected non-fast-forward' errors and push conflicts on Ubuntu 20.04 LTS. Learn to fetch, merge, rebase, and force push safely to unblock your Git workflow.
Resolve Git 'rejected non-fast-forward' errors and push conflicts on Ubuntu 20.04 LTS. Learn to fetch, merge, rebase, and force push safely to unblock your Git workflow.
You're trying to push your latest changes to a remote Git repository, but instead of a successful push, you're greeted with a cryptic "rejected non-fast-forward" error. This frustrating message signifies that your local branch history has diverged from the remote's history. Essentially, the remote repository contains commits that your local branch does not have, preventing a simple, linear update.
As experienced SysAdmins and DevOps engineers, we know this common hurdle can disrupt CI/CD pipelines, automated deployments, and team collaboration. This guide will walk you through diagnosing the root causes and resolving this issue on Ubuntu 20.04 LTS, ensuring your Git workflow remains efficient and your codebase consistent.
Symptom & Error Signature
When attempting to push changes to a remote Git repository, typically via git push origin <branch-name>, you will encounter output similar to the following:
$ git push origin main
To https://github.com/your-org/your-repo.git
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'https://github.com/your-org/your-repo.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (for example,
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
In some scenarios, especially with larger repositories or slower network conditions, you might also see an HTTP error preceding or accompanying this rejection:
remote: Enumerating objects: 123, done.
remote: Counting objects: 100% (123/123), done.
remote: Compressing objects: 100% (122/122), done.
remote: Total 123 (delta 78), reused 0 (delta 0), pack-reused 0
error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413
error: 123 bytes of body are expected
fatal: The remote end hung up unexpectedly
While the HTTP 413 error points to payload size limits (which we'll address briefly), the core Git rejection is non-fast-forward. This guide primarily focuses on resolving the history divergence that leads to the non-fast-forward push error.
Root Cause Analysis
The "rejected non-fast-forward" error occurs when Git cannot simply append your local commits to the remote branch's history. This is due to a divergent history, meaning your local branch and the remote branch have distinct commits that are not part of a linear progression from a common ancestor. Git, by default, prevents non-fast-forward pushes to safeguard against accidental overwrites of remote history and potential data loss.
Here are the primary underlying reasons for this divergence:
- Concurrent Pushes by Other Developers: This is the most common cause. Another developer has pushed changes to the same remote branch (e.g.,
mainordevelop) after you last pulled and before you attempted your push. Your local branch is now "behind" the remote, and your commits are based on an older state of the remote branch. - Remote Branch Updates Outside Your Workflow: The remote branch was updated through a merge request, a direct commit on the Git server, a CI/CD pipeline, or an automated process. Your local repository is unaware of these changes.
- Local History Rewriting: You intentionally (or accidentally) modified your local branch's history using commands like
git rebase,git reset --hard,git commit --amend, orgit filter-repo. When you try to push this rewritten history, it conflicts with the existing (unrewritten) history on the remote. - Multiple Local Repositories: You might have cloned the same repository multiple times. If you push from one clone, then try to push from another clone that hasn't been updated with the first push's changes, you'll encounter this error.
- Force Push by Another User: Less common, but if someone else previously performed a
git push --forceorgit push -fto the branch, it could have rewritten the remote history, causing your local branch to diverge unexpectedly.
Step-by-Step Resolution
The resolution involves integrating the remote changes into your local branch before pushing. The best approach depends on your team's workflow and whether you want to preserve a linear history or allow merge commits.
1. Assess the Situation and Fetch Remote Changes
Before attempting any fix, always get a fresh perspective of the remote repository's state and understand the divergence.
# First, ensure your working directory is clean. Commit or stash any pending changes.
git status
# Fetch the latest changes from the remote without merging them into your local branch.
# This updates your remote-tracking branches (e.g., origin/main).
git fetch origin
Now, visualize the commit history to understand the divergence:
# Display a graphical representation of all branches (local and remote-tracking)
git log --oneline --graph --all
# See commits that are on your local branch but not on the remote-tracking branch
git log origin/main..main
# See commits that are on the remote-tracking branch but not on your local branch
git log main..origin/main
This diagnostic step will help you confirm that the remote has new commits you're missing.
2. Option A: Integrate Remote Changes via git pull (Merge)
This is the most straightforward and safest method, suitable for most team environments as it preserves history by creating a merge commit.
Pull and Merge:
# Pull changes from the remote branch. This is equivalent to `git fetch` followed by `git merge`. git pull origin mainIf your local branch is configured to track
origin/main(which is often the default), you can simply use:git pullResolve Conflicts (If Any): Git will attempt to automatically merge the remote changes into your local branch. If changes overlap, Git will pause the merge and prompt you to resolve conflicts.
# Check which files have conflicts git statusYou will see files listed under "Unmerged paths". Open these files in your editor, look for conflict markers (
<<<<<<<,=======,>>>>>>>), and manually resolve the differences.Carefully review and resolve all conflicts. Incorrectly resolved conflicts can introduce bugs into your codebase. Communicate with your team if you're unsure about specific conflict resolutions.
After editing each conflicted file:
# Stage the resolved file git add <conflicted-file-path> # Repeat `git add` for all conflicted files. # Once all conflicts are resolved and staged, commit the merge. git commit -m "Resolved merge conflicts while integrating remote changes"Push Your Changes: Once the merge is complete and committed, you can now push your combined changes to the remote repository.
git push origin main
3. Option B: Integrate Remote Changes via git rebase (Rewriting History)
This method re-applies your local commits on top of the remote's latest commits, resulting in a cleaner, linear history without extra merge commits. It's often preferred for feature branches before merging them into main or develop.
Rebasing Rewrites History! Do not rebase branches that have already been pushed to a shared remote and are being actively used by others. This can lead to significant history discrepancies and headaches for your team as it invalidates their local histories. Use
git rebaseonly for local branches that haven't been pushed or if you are the sole contributor and understand the implications.
Fetch Remote Changes:
git fetch originRebase Your Local Branch:
git rebase origin/mainGit will rewind your local branch, pull in the new
origin/maincommits, and then attempt to re-apply your commits one by one on top of the neworigin/mainhead.Resolve Conflicts (If Any): During a rebase, conflicts are presented commit-by-commit. If a conflict occurs:
# Check status for conflicted files git statusResolve the conflicts in the specified files, then stage them:
# Edit the conflicted file(s) git add <conflicted-file-path> # Continue the rebase process git rebase --continueRepeat this process for each commit that introduces conflicts. If you decide to stop the rebase at any point:
git rebase --abortPush Your Rebased Changes: Once the rebase is complete, your local branch history is now a linear extension of the remote's history. You can now push.
git push origin main
4. Option C: Force Push (Use with Extreme Caution)
Force pushing overwrites the remote history with your local history. This should only be used in very specific scenarios, typically when you are absolutely certain that your local history is the correct one and no one else's work will be negatively impacted, or after careful coordination with your team.
DANGER: Force Pushing Overwrites Remote History! Using
git push --forceorgit push -fwill delete the remote's current history for that branch and replace it entirely with your local branch's history. This can cause data loss and severe issues for other developers if they have based their work on the remote's original history. Only use this if you are absolutely certain of its consequences and have coordinated with your team.
Always prefer
git push --force-with-leaseovergit push --force.force-with-leaseis a safer alternative because it checks that the remote branch hasn't been updated since you last fetched. If the remote branch has been updated,force-with-leasewill fail, preventing you from accidentally overwriting someone else's new work. It acts as a safety net.
- Execute Force Push (Prefer
force-with-lease):# The recommended and safer force push command git push --force-with-lease origin main # The less safe, unconditional force push command (use only if you know what you're doing) # git push -f origin main
5. Address HTTP 413 (Payload Too Large) Issues (If Applicable)
If your error signature included HTTP 413 alongside the non-fast-forward rejection, it indicates that the Git push operation involved a payload (e.g., a large commit or many objects) exceeding a server-side limit. This is often independent of history divergence but can prevent a successful push.
Increase Git HTTP Buffer Size (Client-side): For very large pushes, your Git client might be timing out or encountering issues when sending data. You can increase the HTTP post buffer size locally.
# Set buffer to 500 MB (524288000 bytes). Adjust as needed. git config --global http.postBuffer 524288000This change is global for your user. If you want it for a specific repository, omit
--global.Adjust Server-side Configuration (If You Control the Server): If you operate your own Git server (e.g., Gitea, GitLab, or a custom Git HTTP server) that sits behind a web server like Nginx, you might need to increase the
client_max_body_sizedirective in your Nginx configuration.Locate your Nginx configuration file, typically
/etc/nginx/nginx.confor a site-specific configuration under/etc/nginx/sites-available/.# Example Nginx configuration snippet http { # ... other http settings ... client_max_body_size 500M; # Adjust to a value greater than your largest push } # Or within a server block, if applicable for specific virtual hosts server { # ... other server settings ... client_max_body_size 500M; # Adjust as needed # ... }After modifying Nginx configuration, you must test the configuration and restart the service:
sudo nginx -t sudo systemctl restart nginxFor Apache, look for
LimitRequestBodyin yourhttpd.confor.htaccess. For other Git hosting solutions, consult their specific documentation (e.g., GitLabnginx['client_max_body_size']setting ingitlab.rb).
By carefully following these steps, you can effectively diagnose and resolve "rejected non-fast-forward" push conflicts, ensuring a smooth and consistent Git workflow on your Ubuntu 20.04 LTS systems. Always prioritize communication with your team, especially when dealing with history-modifying operations like rebase or force push.
Our Production Verification Guarantee
Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.