Sometimes it’s useful to always prefer the contents of another branch
when merging. Endymion keeps its Python 2 and Python 3 code in
separate branches, and new features are usually implemented in
master
and then merged to the python3
branch. Due to the
changes in the standard library, merging often causes merge
conflicts that I have to solve manually.
On two occasions, the automatic conflict resolution produced
unexpected results: it chose the correct lines, but with the wrong
indentation level (which is bad in Python, where indentation
determines the logical structure of the code). When this happens,
I’ve found it easier to start with the complete Python 2 version of
the code in master
, use 2to3
to convert it, fix the remaining
problems and then commit in the python3
branch. git
offers the
“ours” merge strategy, which will always take the contents of the
current branch over the one from the branch being merged. At least
since git 1.8, there’s no “theirs” merge strategy. Fortunately, it’s
possible to do this ourselves by using git reset
.
First, change to the destination branch and perform a merge whose result we will overwrite later:
git checkout python3
git merge -s ours master
We can now create a temporary branch to point to the merge commit (we could also use the revlog to find the merge commit again, but having a branch pointing to it is much simpler):
git branch temp_branch
A hard reset will set HEAD, the index and the working directory to the
version in master
. We can then set HEAD back to where it should be,
in the python3
branch, thorough a soft reset, which will leave the
index and working tree populated with the files from master
:
git reset --hard master
git reset --soft temp_branch
We can now run 2to3
to convert the code to Python 3 and manually fix
any Python 2 left-overs (mostly interface changes not handled by
2to3
, like urllib2’s get_type
method being replaced by a type
property in urllib.request). When everything is working, overwrite
the original merge commit and delete the temporary branch:
git commit --amend
git branch -D temp_branch
It is actually pretty simple once you understand how git reset
works
(for in-depth explanations, please see
“Git Tools – Reset Demystified” in the Pro Git book).