How to properly force a Git push when dealing with non-fast-forward updates?
I’ve set up a remote non-bare ‘main’ repo and cloned it to my computer. I made some local changes, updated my local repository, and pushed the changes back to the remote repo. Things were working fine initially.
Now, I had to make a change in the remote repo. Then I made another change in my local repo. I realized that the change to the remote repo was unnecessary. When I tried to git push from my local repo to the remote repo, I received this error:
To prevent you from losing history, non-fast-forward updates were
rejected Merge the remote changes before pushing again. See the 'Note
about fast-forwards' section of `git push --help` for details.
I thought that using git push --force would force my local copy to push changes to the remote one and make them identical. While git push --force does force the update, when I go back to the remote repo and make a commit, I notice that the files contain outdated changes (ones that the main remote repo previously had).
As mentioned in the comments to one of the answers:
“I tried forcing, but when going back to master server to save the changes, I get outdated staging. Thus, when I commit the repositories are not the same. And when I try to use git push again, I get the same error.”
How can I fix this issue with Git force push and ensure both repositories stay synchronized?
When dealing with non-fast-forward updates in Git, especially with non-bare repositories, git push --force alone isn’t sufficient because it only updates the branch references but doesn’t synchronize the working directory state. The proper solution involves both force pushing and updating the remote repository’s working directory to ensure complete synchronization.
Contents
- Understanding Non-Fast-Forward Errors
- Why Force Push Alone Fails with Non-Bare Repositories
- Complete Synchronization Workflow
- Step-by-Step Solutions
- Best Practices for Non-Bare Repository Management
- Alternative Approaches
Understanding Non-Fast-Forward Errors
Non-fast-forward errors occur when Git cannot safely merge your local branch history with the remote branch history due to divergent commits. This typically happens when:
- Your local branch is behind the remote branch (commits exist on remote that you don’t have locally)
- You’ve rewritten history locally (rebase, commit amending, etc.)
- Direct commits were made to the remote repository’s working directory
As GeeksforGeeks explains, “Non-fast-forward updates: This happens when the local branch is behind the remote branch, and Git cannot perform a fast-forward merge.”
The error message you received is Git’s safety mechanism preventing you from accidentally overwriting changes made by others or in remote locations.
Why Force Push Alone Fails with Non-Bare Repositories
When you use git push --force, you’re telling Git to overwrite the remote branch reference with your local branch history. However, with non-bare repositories, this creates a problem:
A force push (git push –force) rewrites the remote commit history, creating conflicts with the local branch. source
The issue is that the remote repository’s working directory doesn’t automatically update to reflect the new branch state. This is why when you go back to the remote repository and make a commit, you see outdated changes - the working directory wasn’t synchronized with the force push.
As Automate Library notes, “A git force push is a way to update a remote repository by pushing changes even if they are not fast-forward, potentially overwriting changes on the remote branch.” But this only updates the branch references, not the working directory.
Complete Synchronization Workflow
To properly synchronize a non-bare repository after a force push, you need to:
- Force push your changes to update the branch reference
- Update the remote repository’s working directory to match the new branch state
- Ensure both the branch reference and working directory are in sync
The DataCamp tutorial explains that after rewriting history locally, “a normal push doesn’t update the remote repository, and the sensitive data remains. You get an error message instead.”
Step-by-Step Solutions
Solution 1: Force Push and Manual Update
After force pushing to update the branch reference, you need to manually update the remote repository’s working directory:
# From your local repository
git push --force origin main
# Then go to the remote repository directory and:
git checkout main
git reset --hard HEAD
This hard reset updates the working directory to match the branch state after the force push.
Solution 2: Using git pull --force
If you need to update the remote repository’s working directory after a force push, you can use:
# In the remote repository:
git pull --force origin main
This will force update the working directory to match the remote branch.
Solution 3: Complete Re-synchronization
For a full synchronization between repositories:
# From your local repository:
git fetch --all
git push --force origin main
# In the remote repository:
git fetch --all
git reset --hard origin/main
git clean -fd
The Reddit discussion mentions that “fetch --all and push --force seems to have been the key” for synchronizing multiple repositories.
Solution 4: Preventive Measures
Before making changes in the remote repository:
- Always fetch the latest changes first:
git fetch --all - Use
git pull --rebaseto keep your history linear - Consider using feature branches instead of direct commits to main
Best Practices for Non-Bare Repository Management
Avoid Direct Commits in Remote Repositories
The most reliable approach is to avoid making direct commits in non-bare repositories. Instead:
Use Feature Branches: Develop on separate branches and push those, merging via pull requests rather than pushing directly to main. source
Regular Synchronization
Periodically synchronize your local repository with the remote:
Periodically pull updates from the distant repository in order to synchronize with it. source
Use Protected Branches
Configure branch protection rules to prevent accidental force pushes:
Git has several safety features designed to protect the integrity of a repository. One of the primary features is the use of protected branches, which are configured to reject non-fast-forward pushes. source
Proper Fetch and Prune
Keep your local references up to date:
Regularly Prune Stale References: Make it a habit to use git fetch --prune instead of plain git fetch. It keeps your local repository in sync with the remote by automatically removing outdated references. source
Alternative Approaches
Rebase Instead of Force Push
Instead of force pushing, consider rebasing your local changes:
Git rebasing rewrites your local branch’s history to align with the remote repository, eliminating conflicts and allowing you to push your changes successfully. source
Use git pull --rebase
Before pushing, ensure your local history is up to date:
Pull Before Pushing: Sync local with remote changes first (git pull or git fetch + git merge) to avoid non-fast-forward errors. source
Stash Changes Before Syncing
If you have uncommitted changes that might cause conflicts:
Git stashing saves your local changes temporarily, allowing you to update the local repository without losing your work and resolve the push error. source
Conclusion
To properly handle non-fast-forward updates with non-bare repositories:
- Understand the root cause: Force push only updates branch references, not working directories
- Use complete synchronization: After force pushing, update the remote working directory with
git reset --hard - Prevent issues: Avoid direct commits in non-bare repositories and use proper workflows
- Regular maintenance: Use
git fetch --pruneand keep references updated - Consider alternatives: Rebase instead of force push when possible, and use feature branches
The key insight is that with non-bare repositories, you need to manage both the branch references AND the working directory state to achieve proper synchronization. As CICube warns, “Forcing (git push --force) will overwrite any remote modifications and can destroy workflows for your team” if not done properly.
Sources
- Git Push Force: How it Works and How to Use it Safely | DataCamp
- How to Fix Git Error: ‘failed to push some refs to remote’? - GeeksforGeeks
- A Developer’s Guide to the git push Command with Practical Examples | Udacity
- Git Not Possible to Fast-Forward | CICube
- Git Force Push: When and How to Override Safety Features - Automate Library
- How to Fix: Cannot Lock Ref ‘refs/remotes/origin/
’ During a Git Fetch? | Medium - Git Push Error: Solve ‘Failed to Push Some Refs to’ in 3 Easy Steps - Testkube
- How to Fix the “Cannot Lock Ref” Error in Git - BobCares
- Force sync two remote repos - Reddit r/git
- Pushing, Fetching, and Pulling with Git - circuitlabs.net