Everyone that uses auto generated files like the
Gemfile.lock or any files that store code coverage reports (or test results) in XML format inside a Git repository has experienced Git conflicts in these files.
Let's see how to resolve this kind of conflict more smoothly.
I'm sure you know that you can delete the
package-lock.json file and run
npm install again - similarly with Yarn.
rm package-lock.json npm install git add package-lock.json
But Git can resolve this automatically (plus this solution works for other auto generated files and binary files, e.g. images).
You can create a special file called
.gitattributes placed in the root of your Git repository where you can manually configure how Git handles files. Let's see an example:
# Auto detect text files and perform LF normalization * text=auto # JS and TS files must always use LF for tools to work *.js eol=lf *.ts eol=lf # Use UTF-16 instead of UTF-8 for C source files. *.c working-tree-encoding=UTF-16LE-BOM # Mark all JPEG files as binary. *.jpg binary # Handle as a text file but merge as binary. package-lock.json merge=binary
The built-in binary merge driver can't merge binary files, so in case of a conflict Git will leave your
package-lock.json as-is but marked in a conflicted state.
💡 If you want to keep these attributes for youself instead of applying them to every user of a Git repository you can use
.git/info/attributes file with the same structure.
If you need the changes from the upstream branch just checkout the theirs version.
git checkout --theirs package-lock.json
This can also be done with a custom merge driver. 👐
A merge driver tries to resolve Git conflicts and you can create your own. Let's define a driver called
theirs that will use the upstream version (
%B) over our version (
git config --global merge.theirs.name "Keep upstream changes" git config --global merge.theirs.driver "cp -f '%B' '%A'"
--global to make this driver available to all repositories in your machine.
Then, add the following to your
Now, every conflict will be resolved by our driver accepting the upstream version. Remember that you should run
npm install to re-add your changes to the
package-lock.json because this driver is not smart enough, and discards your changes to the lock file. You need to keep the file in sync with your changes to the
The npm team has created npm-merge-driver which makes smarter merges than our previous driver - which does an overwrite 😁, keeping the lock file in sync with our changes in the
package.json. You can just install it globally in your machine without affecting your coworkers because the
~/.config/git/attributes is used for all your cloned repositories.
npx npm-merge-driver install --global
The bad part is that this repo is archived and doesn't receive any updates. 🐛
You can find other merge drivers in the npm registry, even for other types of files like the git-json-merge.
Now we've learned how to handle line endings and fix encodings on Windows using the
We can treat auto generated files as a
binary, or as text but with
merge=binary or using a non built-in driver to merge them automatically.
There are long discussions about handling these large files as binaries. Git compresses all the changes so the size of your repo won't be compromised with a binary
package-lock.json file. It's up to you.
Tell me how you manage this type of Git conflicts in the comments.