Git Merge Disaster with the 'Ours' Strategy
Some time ago, I experienced a disaster when trying to update the feature branch I was working on based on the master branch by running git merge master. The story goes that conflicts arose in several binary files I had modified, while almost all other files merged successfully. The branch I was working on had fallen quite far behind the master branch.
Even though the number of conflicting files was still countable on one hand, I felt there should be a faster way to tell Git to take the files from my branch whenever a conflict occurred. After all, I was fully confident that my branch’s versions of the conflicting files were the correct ones. I also vaguely remembered the keyword ours in Git conflict resolution, which I had learned about before.
Without hesitation — and, more foolishly, without reading the documentation — I immediately ran:
git reset --hard HEAD~
git merge master -s ours
As expected, Git was no longer complaining about conflicts. I then proceeded to commit and pushed my commit straight to the GitHub repository. Not long after, when my teammate acting as reviewer was about to look at my code on GitHub, he was startled and turned to me immediately.
“Sal, why does this show 200+ files changed?”
What? I was shocked. The branch should have had fewer than ten modified files. I immediately tried to investigate the log for that branch. As it turned out, my suspicion was right — Git hadn’t just taken the conflicting files from my branch; it had taken all files that differed from the master branch from my branch.
After that disaster, I finally read the git merge documentation more carefully. It turned out that the git merge master -s ours command I had entered is designed to take all files that differ from the branch we’re currently on (ours). To make Git take only the conflicting files from the current branch, the correct command should have been git merge master -s recursive -Xours.
Eventually, with permission from the reviewer — who also served as the lead engineer on my team — I did a hard reset on my branch to undo the problematic merge commit. I then had to run git push --force to the GitHub repository because the rollback I performed altered that branch’s history.
Lessons learned from this incident:
git merge <branch> -s ours // merge and take all changes from our branch
git merge <branch> -s recursive -Xours // merge and take only conflicting files from our branch