There is a git feature that everyone should enable globally:
git config --global rerere.enabled true
What is rerere? It stands for Reuse Recorded Resolution of conflicted merges.
If you have used long-lived branches before, you know the pain when it comes to merging the main branch.
Merge main frequently
A tip for using long-lived branches is to merge from main frequently. The reason is to add those changes, and verify everything is working as early as possible.
git merge master
If you’re lucky, the merge will have no conflicts.
If you’re very unlucky, especially with tools such as Xcode that has horrendous pbxproj file format, then you will need to resolve the merge conflict.
Resolving conflict is a manual process, but for the same conflict, it can be automated.
A long-lived branch will merge from main branch multiple times. The problem is that every time you merge, you will have to resolve many of the same conflicts again.
The reason is because git performs a 3-way merge strategy: yours, theirs and the common ancestor.
The common ancestor will be the commit at the point the long-lived branch forked. That is the problem why each merge will throw the same conflicts over and over again. BTW you can check who is the ancestor/base with
git merge-base longlived master.
This is where rerere comes in handy. Once you have enabled rerere, git will resolve conflicts automatically – using your previous decision. This magic will happen not only for merge, but also rebase, stash apply etc.
How it works?
When you resolve a conflict and commit, a signature of the file will be added to the project directory
.git/rr-cache/. It looks like this after I resolved a conflict:
You don’t have to know the details, but basically git is using this cache/database to know how to resolve a conflict automatically. Each of the “image” are the source file before and after resolving.
This cache is local, so usually 1 person in the team will do the merge. Or they can share this cache.
Not every file can rerere: pbxproj
For example, Xcode pbxproj is an uncontrollable beast. It is 1 file that can be touched by all. This makes conflict resolution difficult, even when you have resolved before.
I wrote about gitattributes for pbxproj before. In the post, my recommendation is to merge pbxproj manually.
But when the number of conflicts are too many, it will be easier and faster to use
merge=union (accept yours + theirs). If you’re using any diff apps (eg. FileMerge), you can also resolve with a union of both. Doing so can introduce build errors, and you will have fix them manually.