Resolve merge conflicts automatically (mergiraf)
When Git merges, it compares lines of text – it has no idea whether it is looking at a Java class, a YAML file or a go.mod. That is why a conflict shows up as soon as two branches add different things in the same place: two new methods at the end of the same class, two new entries in the same list, two new dependencies.
mergiraf is a merge driver that parses the file first and merges on the syntax tree. It resolves conflicts like these on its own. You can enable it for your managed GitLab at server.camp as self-service – it is available on all plans.
In the customer portal, open the configuration of your GitLab subscription and turn on Syntax-aware merging (mergiraf) under Advanced.
With the next deployment mergiraf is built into your GitLab container and registered as a merge driver. Your instance restarts once while that happens.
An enabled driver does not merge anything yetGit only calls a merge driver for the files a repository explicitly points at it. Without step 2 nothing about your projects changes – deliberately so, because you decide where syntax-aware merging applies.
Create a .gitattributes file in the root of the repository (or extend the existing one):
* merge=mergiraf
That applies the driver to every file. For formats mergiraf does not know it falls back to Git’s normal behaviour automatically, so you can safely leave the line as it is.
If you prefer to be explicit, list the file types individually:
*.java merge=mergiraf
*.go merge=mergiraf
go.mod merge=mergiraf
*.yml merge=mergiraf
*.json merge=mergiraf
mergiraf languages --gitattributes and the mergiraf documentation list every supported language and file extension. Commit the .gitattributes and push it – from then on the driver applies in this repository.
GitLab merges merge requests on the server. When Git runs into a conflict there, it now asks mergiraf first – and only what mergiraf cannot resolve either ends up as a real conflict in GitLab.
An example: two branches extend the same class.
// Branch "feature-a" // Branch "feature-b"
class A { class A {
void a() {} void a() {}
void fromA() {} void fromB() {}
} }
Without mergiraf GitLab reports a conflict here, because both occupy the same line. With mergiraf you get the obvious result – both methods survive:
class A {
void a() {}
void fromA() {}
void fromB() {}
}
- The driver only runs on an actual conflict. Merges Git handles cleanly anyway are unaffected.
- It is no substitute for a review: mergiraf decides structurally, not semantically. Two changes can fit together syntactically and still be wrong.
- Whatever mergiraf cannot resolve stays a normal conflict with the usual conflict markers.
On the server mergiraf helps when merge requests are merged. If you want the same automation for your local git merge or git rebase, install mergiraf on your machine too – the .gitattributes from step 2 applies there just the same. The mergiraf documentation covers the setup.
Turn the switch off in the portal: with the next deployment the driver and the binary are gone from your instance. You can leave the .gitattributes in your repositories as it is – Git ignores a reference to a driver it does not know and merges line by line again.