Handling push conflicts
Causes of Push Conflicts
Push conflicts typically occur during collaborative development when multiple developers modify the same part of a file simultaneously. Git cannot automatically merge these changes and requires manual intervention. Common scenarios include:
- Two developers modifying the same line of code
- One developer deleting a file while another modifies it
- Incompatible changes during branch merging
// Developer A modified utils.js
function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price, 0);
}
// Developer B simultaneously modified the same function
function calculateTotal(products) {
let total = 0;
products.forEach(product => {
total += product.cost;
});
return total;
}
Detecting Push Conflicts
When attempting to push local commits to a remote repository, Git will clearly indicate conflicts:
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'github.com:user/repo.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
At this point, you need to pull the remote changes first. Git will mark the conflicting files:
CONFLICT (content): Merge conflict in src/utils.js
Automatic merge failed; fix conflicts and then commit the result.
Basic Steps to Resolve Push Conflicts
-
Pull the latest remote changes:
git pull origin main
-
Open the conflicting file. Git will display the conflicting content with special markers:
<<<<<<< HEAD function calculateTotal(items) { return items.reduce((sum, item) => sum + item.price, 0); } ======= function calculateTotal(products) { let total = 0; products.forEach(product => { total += product.cost; }); return total; } >>>>>>> abc1234
-
Manually edit the file to resolve the conflict. You can:
- Keep one version
- Merge the changes from both versions
- Completely rewrite that part of the code
-
Add the resolved file and commit:
git add src/utils.js git commit -m "Resolve merge conflict in utils.js"
-
Complete the push:
git push origin main
Advanced Conflict Resolution Strategies
Using Merge Tools
Configure a graphical merge tool for more intuitive conflict resolution:
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd "code --wait $MERGED"
Then run:
git mergetool
Resetting Branches
For complex conflicts, you can reset to the pre-merge state and try again:
git merge --abort
# or
git reset --hard HEAD
Using Rebase Instead of Merge
Rebasing maintains a linear commit history:
git pull --rebase origin main
When encountering conflicts:
- Resolve the conflicts
git add
the conflicting filesgit rebase --continue
Creating Temporary Branches
For complex conflicts, create a temporary branch to test solutions:
git checkout -b temp-conflict-resolution
# After resolving conflicts
git checkout main
git merge temp-conflict-resolution
Best Practices to Prevent Push Conflicts
-
Frequently Pull Changes:
git fetch origin git rebase origin/main
-
Small Commits: Keep each commit focused and small in scope
-
Team Communication: Team members should communicate about files being modified
-
Branch Strategy:
# Create separate branches for new features git checkout -b feature/new-payment
-
Pre-push Scripts: Run tests before pushing
// package.json { "scripts": { "prepush": "npm test && npm run lint" } }
Handling Specific Types of Conflicts
Binary File Conflicts
For binary files like images or PDFs, typically choose which version to keep:
git checkout --ours image.png # Keep local version
git checkout --theirs image.png # Keep remote version
git add image.png
Delete/Modify Conflicts
When one developer deletes a file while another modifies it:
# To keep the modifications
git add deleted-file.js
# To accept the deletion
git rm deleted-file.js
Line Ending Conflicts
Common in cross-platform development:
git config --global core.autocrlf true # Windows
git config --global core.autocrlf input # Linux/Mac
Automated Conflict Resolution
For predictable conflicts, specify merge strategies in .gitattributes:
package-lock.json merge=ours
*.min.js merge=ours
Or create custom merge drivers:
git config --global merge.ours.driver true
Conflict Management in Team Collaboration
-
Code Owners: Use CODEOWNERS to assign responsibility for specific files
src/utils.js @team/core @user1
-
Protected Branches: Configure branch protection rules requiring PR approval before merging
-
Code Reviews: Reduce conflicts through Pull Request workflows
// Example: Add clear comments to reduce understanding conflicts
/**
* Calculate total product price
* @param {Array} items - Product array requiring price property
* @returns {number} Total price
*/
function calculateTotal(items) {
// More concise with reduce
return items.reduce((sum, item) => sum + item.price, 0);
}
Conflict Resolution in Complex Scenarios
Long-Running Branch Conflicts
When feature branches diverge significantly from main:
git checkout feature
git merge main # Regularly merge main branch changes
# After resolving all conflicts
git push origin feature
Conflicts After History Rewriting
After modifying pushed commit history:
git push --force-with-lease origin main
Submodule Conflicts
When submodule references conflict:
git submodule update --init --recursive
cd submodule
git checkout commit-hash
cd ..
git add submodule
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn