Say I'm collaborating with someone via a git repository, and there is a particular file that I never want to accept any external changes to.

Is there any way to set up my local repo to not complain about a conflicted merge every time I git pull? I'd like to always select my local version when merging this file.

  • 29,542
  • 12
  • 100
  • 122
  • 23,742
  • 18
  • 63
  • 67
  • 1
    Just added a simple solution through .gitattributes and a very basic "merge driver" – VonC May 30 '09 at 20:13
  • 14
    TD;LR : `echo 'path/to/file merge=ours' >> .gitattributes && git config --global merge.ours.driver true` – Ciro Santilli OurBigBook.com Apr 28 '14 at 14:51
  • @CiroSantilli: Works like a charm on Linux. This driver is simple enough to be built into Git... – krlmlr Aug 15 '14 at 18:10
  • Do you wish to push your changes to the file? Or is it for example a config file where the default is stored in git. – Ian Ringrose Sep 22 '16 at 11:04
  • @CiroSantilli新疆改造中心六四事件法轮功's comment is correct, but will make this behavior occur for every repo on your system with the `--global` tag. If you only want this behavior for a single repo, leave out the `--global` flag: `echo 'path/to/file merge=ours' >> .gitattributes && git config merge.ours.driver true` – majorobot Feb 25 '19 at 22:09

3 Answers3


On the specific instance of a config file, I would agree with Ron's answer:
the config should be "private" to your workspace (hence "ignored", as in "declared in a .gitignore file").
You may have a config file template with tokenized values in it, and a script transforming that config.template file into a private (and ignored) config file.

However, that specific remark does not answer what is a broader more general question, i.e. your question(!):

How do I tell git to always select my local version for conflicted merges on a specific file ? (for any file or group of files)

This kind of merge is a "copy merge", in which you will always copy 'ours' or 'theirs' version of a file whenever there is a conflict.

(as Brian Vandenberg notes in the comments, 'ours' and 'theirs' are here used for a merge.
They are reversed for a rebase: see "Why is the meaning of “ours” and “theirs” reversed with git-svn", which uses a rebase, "git rebase, keeping track of 'local' and 'remote'")

For "a file" (a file in general, not speaking of a "config" file, since it is a bad example), you would achieve that with a custom script called through merges.
Git will call that script because you will have to define a gitattributes value, which defines a custom merge driver.

The "custom merge driver" is, in this case, a very simple script that basically will keep unchanged the current version, hence allowing you to always select your local version.

IE., As noted by Ciro Santilli:

echo 'path/to/file merge=ours' >> .gitattributes
git config --global merge.ours.driver true

Let's test that in a simple scenario, with a msysgit 1.6.3 on Windows, in a mere DOS session:

cd f:\prog\git\test
mkdir copyMerge\dirWithConflicts
mkdir copyMerge\dirWithCopyMerge
cd copyMerge
git init
Initialized empty Git repository in F:/prog/git/test/copyMerge/.git/

Now, let's make two files, which will both have conflicts, but which will be merged differently.

echo a > dirWithConflicts\a.txt
echo b > dirWithCopyMerge\b.txt
git add -A
git commit -m "first commit with 2 directories and 2 files"
[master (root-commit) 0adaf8e] first commit with 2 directories and 2 files

We will introduce a "conflict" in the content of both those files in two different git branches:

git checkout -b myBranch
Switched to a new branch 'myBranch'
echo myLineForA >> dirWithConflicts\a.txt
echo myLineForB >> dirWithCopyMerge\b.txt
git add -A
git commit -m "add modification in myBranch"
[myBranch 97eac61] add modification in myBranch

git checkout master
Switched to branch 'master'
git checkout -b hisBranch
Switched to a new branch 'hisBranch'
echo hisLineForA >> dirWithConflicts\a.txt
echo hisLineForB >> dirWithCopyMerge\b.txt
git add -A
git commit -m "add modification in hisBranch"
[hisBranch 658c31c] add modification in hisBranch

Now, let's try to merge "hisBranch" upon "myBranch", with:

  • manual resolution for conflicting merges
  • except for dirWithCopyMerge\b.txt where I always want to keep my version of b.txt.

Since the merge occurs in 'MyBranch', we will switch back to it, and add the 'gitattributes' directives which will customize the merge behavior.

git checkout myBranch
Switched to branch 'myBranch'
echo b.txt merge=keepMine > dirWithCopyMerge\.gitattributes
git config merge.keepMine.name "always keep mine during merge"
git config merge.keepMine.driver "keepMine.sh %O %A %B"
git add -A
git commit -m "prepare myBranch with .gitattributes merge strategy"
[myBranch ec202aa] prepare myBranch with .gitattributes merge strategy

We have a .gitattributes file defined in the dirWithCopyMerge directory (defined only in the branch where the merge will occurs: myBranch), and we have a .git\config file which now contains a merge driver.

[merge "keepMine"]
        name = always keep mine during merge
        driver = keepMine.sh %O %A %B

If you do not yet define keepMine.sh, and launch the merge anyway, here is what you get.

git merge hisBranch
sh: keepMine.sh: command not found
fatal: Failed to execute internal merge
git st
# On branch myBranch
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#       modified:   dirWithConflicts/a.txt
no changes added to commit (use "git add" and/or "git commit -a")

type dirWithConflicts\a.txt
<<<<<<< HEAD:dirWithConflicts/a.txt
>>>>>>> hisBranch:dirWithConflicts/a.txt

That is fine:

  • a.txt is ready to be merged and has conflict in it
  • b.txt is still untouched, since the merge driver is supposed to take care of it (due to the directive in the .gitattributes file in its directory).

Define a keepMine.sh anywhere in your %PATH% (or $PATH for our Unix friend. I do both of course: I have an Ubuntu session in a VirtualBox session)

As commented by lrkwz, and described in the "Merge Strategies" section of Customizing Git - Git Attributes, you can replace the shell script with the shell command true.

git config merge.keepMine.driver true

But in the general case, you can define a script file:


# I want to keep MY version when there is a conflict
# Nothing to do: %A (the second parameter) already contains my version
# Just indicate the merge has been successfully "resolved" with the exit status
exit 0

(that was one simple merge driver ;) (Even simpler in that case, use true)
(If you wanted to keep the other version, just add before the exit 0 line:
cp -f $3 $2.
That's it. Your merge driver would always keep the version coming from the other branch, overriding any local change)

Now, let's retry the merge from the beginning:

git reset --hard
HEAD is now at ec202aa prepare myBranch with .gitattributes merge strategy

git merge hisBranch
Auto-merging dirWithConflicts/a.txt
CONFLICT (content): Merge conflict in dirWithConflicts/a.txt
Auto-merging dirWithCopyMerge/b.txt
Automatic merge failed; fix conflicts and then commit the result.

The merge fails... only for a.txt.
Edit a.txt and leave the line from 'hisBranch', then:

git add -A
git commit -m "resolve a.txt by accepting hisBranch version"
[myBranch 77bc81f] resolve a.txt by accepting hisBranch version

Let's check that b.txt has been preserved during this merge

type dirWithCopyMerge\b.txt

The last commit does represent the full merge:

git show -v 77bc81f5e
commit 77bc81f5ed585f90fc1ca5e2e1ddef24a6913a1d
Merge: ec202aa 658c31c
git merge hisBranch
Already up-to-date.

(The line beginning with Merge does prove that)

Consider you can define, combine and/or overwrite merge driver, as Git will:

  • examine <dir>/.gitattributes (which is in the same directory as the path in question): will prevail upon the other .gitattributes in directories
  • Then it examines .gitattributes (which is in the parent directory), and will only set directives if not already set
  • Finally it examines $GIT_DIR/info/attributes. This file is used to override the in-tree settings. It will overwrite <dir>/.gitattributes directives.

By "combining", I mean "aggregate" multiple merge drivers.
Nick Green tries, in the comments, to actually combine merge drivers: see "Merge pom's via python git driver".
However, as mentioned in his other question, it only works in case of conflicts (concurrent modification in both branches).

Mert Ekinci
  • 352
  • 2
  • 13
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 1
    Thank you for the detailed answer! I understand that it makes no sense to version-control config files, but I was after a straightforwards motivating example. Indeed, it's the broader question that interested me. I'd never heard of git merge drivers before, so thank you for enlightening me. – saffsd May 31 '09 at 01:32
  • Example of application of a custom merge driver: http://stackoverflow.com/questions/2250040/using-github-to-host-public-git-repositories-whilst-ensuring-that-sensitive-data – VonC Feb 12 '10 at 07:38
  • This doesn't work for me - I've got .buildpath in my global git ignores, but after putting ".buildpath merge=keepMine" in the .gitattributes, I still get "untracked working tree file '.buildpath' would be overwritten by merge." Obviously it would be best if everyone had added the Eclipse project files to their .gitignores (or Eclipse had kept them out of the project in the first place!) but I'm now stuck with an unmergeable branch. What's my best move from here? – John Y Apr 26 '10 at 12:31
  • @John: an ignored file? But what I describe (with the merge driver) is for *tracked* files (that you don't want to be changed by a merge. – VonC Apr 26 '10 at 12:52
  • @VonC: ah, that explains it - thanks! You'd think a merge would just ignore files that are in .gitignore, of course :) – John Y Apr 27 '10 at 08:06
  • 6
    The `cp -f $3 $2` should probably be quoted, i.e. `cp -f "$3" "$2"`. – Arc Sep 27 '10 at 10:40
  • @VonC: May this work also for an use case like this: http://stackoverflow.com/questions/6588997/git-subtree-merge-strategy-or-subtree-command ? – Fabio Jul 06 '11 at 01:39
  • 1
    @VonC thanks for the detailed answer! The problem I have with it is that it depends on people setting the driver in their .git/config file. I would like to add the driver information to the project itself, so it would be automatic and less setup work to be done. Any pointers? – Juan Delgado Dec 19 '11 at 16:34
  • @Zárate: the driver is declared in a `.gitattributes` file, which is part of the repo. – VonC Dec 19 '11 at 16:42
  • @VonC Thanks for the great answer. To follow up on Zárate's point: is there any way to store the driver script keepMine.sh in the repository as well? Also, what about windows users? Is there an easy way to make this solution more portable? – ulmangt Apr 04 '12 at 14:24
  • I think [this question](http://stackoverflow.com/questions/8839496/add-a-git-merge-driver-to-the-repository) (by your! :)) answers some of my above questions. – ulmangt Apr 04 '12 at 14:29
  • 2
    @ulmangt: you can very much store that script in the git repo as well, ... as long you find a way to add its parent directory to the `PATH` (Unix or Windows `PATH`). Since that script will be interpreted through the Unix bash shell, or through the MingWin bash MsysGit Windows shell, it will be portable. – VonC Apr 04 '12 at 14:32
  • 5
    @VonC Thanks. One more issue. Under certain circumstances (if there haven't been any changes to the local branch being merged into) it appears that the merge driver is never even called, which results in the local files being modified (which are supposed to be using the custom merge driver to prevent them from changing during a merge). Is there any way to **force** git to always use the merge driver? – ulmangt Apr 04 '12 at 15:15
  • @ulmangt not sure right of the top of my mind, I will look into it once I get off the TGV I am in. (research from my phone isn't practical) – VonC Apr 04 '12 at 15:20
  • @ulmangt right, I am out of the TGV by now ;) I have posted a possible answer (that I have tested), but I don't find it perfect. – VonC Apr 08 '12 at 15:05
  • An important caveat should probably be mentioned here. This only works the way you'd expect for a merge. For a rebase (e.g., `git pull --rebase`), the other branch's changes will be treated as local, so your local edits to the file will be automatically rejected. – Brian Vandenberg Jun 20 '14 at 14:29
  • @BrianVandenberg Good point. I have included your caveat in the answer, along with 2 links to other answers of mine, where I discussed that "reversal" during a rebase: [Why is the meaning of “`ours`” and “`theirs`” reversed with `git-svn`](http://stackoverflow.com/a/2960751/6309) and [`git rebase`, keeping track of 'local' and 'remote'](http://stackoverflow.com/a/3052118/6309). – VonC Jun 20 '14 at 14:40
  • @VonC how can you, as you said, "Combine merge drivers". What I'd like is a xml merge driver which resolves some conflicts I expect everytime (Maven versioning things...), after fixings the things I'd expected I'd like to pass the merge state to the 'default' merge driver. We need this, so we can resolve only the things we'd expect (so not simply 'always keep mine file when conflict occurs'..). Any way to do this:)? Any help would be greatly appreciated! – NickGreen Oct 13 '15 at 18:48
  • @NickGreen What I think I meant (6 years ago) by "combine" was more "aggregate": You can define multiple merge manager in multiple files, the aggregation of which defines the list of merge managers that will apply. The combination you mention would be possible if one merge driver would explicitly call another one, which I don't know if it is possible. – VonC Oct 13 '15 at 19:29
  • @VonC FYI I found out how to 'combine' the merge drivers. For others which are interested, see gist: https://gist.github.com/nickgr6/a6837b0c01a4f230bc26 I've got one more challenge to solve, but that's another issue: http://stackoverflow.com/questions/33412003/force-git-custom-merge-driver-for-the-purpose-of-merging-pom-xml-maven-files – NickGreen Nov 16 '15 at 09:40
  • @NickGreen Very interesting. I have included your comment at the end of this answer, for more visibility. – VonC Nov 16 '15 at 09:50
  • You can replace the dummy mergerer `keepMine.sh` with `true`as described in https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes – lrkwz Nov 20 '17 at 09:46
  • @lrkwz Good point. I have included your comment in the answer for more visibility. – VonC Nov 20 '17 at 09:53
  • Wouldn't be the local config more sufficient for specifying the custom merge driver: `git config --local merge.ours.driver true` and not the global settings as shown in the post (cause .gitattributes is also a local file)? – Sebi2020 Dec 18 '21 at 12:10
  • @Sebi2020 "global" here would mean: "apply this to any repository which *also* has a `.gitattributes` with the relevant directive". But yes, you can restrict it to a local configuration too. – VonC Dec 18 '21 at 14:00

As @ciro-santilli has commented, the simple way to do it to use .gitattributes with settings it:

path/to/file merge=ours

and enable this strategy with:

git config --global merge.ours.driver true

(I am adding this as an answer to make it more visible but making it a Community Wiki to not try to get above user's credits for myself. Please upvote his comment under the Q here to give him kudos!)

  • 19,824
  • 17
  • 99
  • 186
Greg Dubicki
  • 5,983
  • 3
  • 55
  • 68
  • 1
    (Aside: if someone gives the answer as a comment and does not add an answer, it is perfectly OK to write a non-CW answer and get the credits. If they are still an active member you can ping them to add an answer if you wish, but they technically already had their chance `:-)`). – halfer Jan 02 '20 at 21:29

We have multiple config files that we never want overwritten. However .gitignore and .gitattributes did not work in our situation. Our solution was to store the config files in a configs branch. Then, allow the files to be changed during the git merge, but immediately following the merge use the "git checkout branch -- ." to copy our config files from the configs branch after every merge. Detailed stackoverflow answer here

  • 1
  • 1
  • 481
  • 1
  • 9
  • 19