23

I have the following directory structure:

/.git
/.git/info/attributes
/MyProject
/MyProject/pom.xml
/MyProject/MyCode.java

I have branch master and bugfix. On both branches pom.xml and MyCode.java were modified. i would like to merge changes from bugfix to master only for MyCode.java and keep master version of pom.xml file.

So I added "/.git/info/attributes" because i don't want to commit .gitattributes with the project

$cat .git/info/attributes
pom.xml merge=ours
$git status
# On branch master
nothing to commit (working directory clean)
$git check-attr -a pom.xml
pom.xml: merge: ours

Finally to the problem:

When I do:

$git merge bugfix
Auto-merging MyProject/pom.xml
CONFLICT (content): Merge conflict in MyProject/pom.xml
Automatic merge failed; fix conflicts and then commit the result.

Git is ignoring attributes setting. What am i missing here?

I prefer not to define "keepMine.sh" per this post

this post is what i need, however i prefer not to go file by file if i have a simple pattern

thanks!

Community
  • 1
  • 1
Barak1731475
  • 780
  • 1
  • 9
  • 15
  • possible duplicate of [.gitattributes & individual merge strategy for a file](http://stackoverflow.com/questions/5465122/gitattributes-individual-merge-strategy-for-a-file) – Ciro Santilli OurBigBook.com Apr 28 '14 at 14:40
  • although you are correct and i didn't find the other question when opened this one, answer here is much better, it is short, clear and works, doing better service to the reader.. – Barak1731475 Apr 29 '14 at 07:59
  • 1
    I agree. But it is better if we focus all good answers in a single place. If you feel the other question could have a better answer, an option is to give it a bounty. And even if this is marked as a duplicate, it can still help people. Being marked as a dup does not mean that a question is not useful, I even upvoted you =) – Ciro Santilli OurBigBook.com Apr 29 '14 at 11:24
  • i see this and try but this is not workd for me sooo plzz any help you? marge time both file marge how to solved? – kiran_ray Jan 05 '21 at 06:45

2 Answers2

28

For locally-modified files:

$ git config merge.ours.driver true

or even

$ git config --global merge.ours.driver true

'ours' isn't one of the built-in merge drivers even though it's perfectly clear to you and me what it should do, and it seems git doesn't error out when a custom merge driver is undefined.

(true above is just the unix true command, its success says it made the local version look right, in this case by doing nothing to it.)

If the local version isn't or might not be modified since the base you'll have to script this, for instance, you can have a post-checkout hook construct branch-specific content, basically a quick-n-dirty make, but by far the easiest is to set this up and add the branch name as a comment in each branch whose version you want to stay untouched.

jthill
  • 55,082
  • 5
  • 77
  • 137
  • 3
    so basically, git book attributes example for merge strategies [http://git-scm.com/book/ch7-2.html] is **just** attributes example and won't work without explicitly turning on even prepackaged, but not default merge drivers.. got it, thanks! – Barak1731475 Dec 31 '12 at 19:37
  • @Barak1731475 ours isn't a default conflict driver. It's just being set to the unix command `true` to indicate "keep the existing file". See the documentation on conflict drivers in .gitattributes. – DylanYoung Jul 24 '20 at 18:37
  • i see this and try but this is not workd for me sooo plzz any help you? marge time both file marge how to solved? – kiran_ray Jan 05 '21 at 06:43
  • it doesn't work even with git config --global merge.ours.driver true. Only works If I specify explicitly :git merge -s ours [branchname] – Mariusz Jul 28 '23 at 19:39
  • The local version has to be modified. I see I didn't call that out explicitly, fixing. – jthill Jul 28 '23 at 19:50
  • then it's not the git ours merge strategy. you are using the recursive merge strategy with the ours option to resolve conflicts – Mariusz Jul 28 '23 at 19:54
  • It's getting the result the ours strategy would produce, which is not the result the ours option would produce, and no, it does not use the ours option, so I disagree. You can easily force a locally-modified version by adding or changing a comment or even just changing white space. – jthill Jul 28 '23 at 20:02
17

From my testing with git version 1.7.1 I find that unless there IS a requirement to merge, no merge driver will execute (regardless of what you put in the config, and regardless of any git attributes).

If you branch out from the "master" to your own local branch "bugfix" and then edit a bunch of stuff in your own branch, commit that. Afterwards you checkout the "master" branch again, then do something like:

git merge bugfix

You might expect the "merge=ours" attribute to protect you in this situation. It won't! Branch "bugfix" will stomp over branch "master" if there have been no edits to that particular file within the master branch since the time "bugfix" branched away from master. No edits implies no need to merge which implies don't run a merge driver. This seems such a common problem that git should have a particular attribute pre-defined to give a file absolute local protection from foreign merges, under ALL situations.

FWIW, I've read other people's opinions that config files should be local and private and not checked into git at all. I think that's kind of bollox: of course I do want to track changes in my config file. Of course the idea of a collaborative tool is that I want to be able to compare my config against what other people in my team are running, or compare the development config to the production config. The whole idea of a tool is that it helps you get your work done.

As a kludgy solution, the best I've come up with is a config directory with each config file having a different name (i.e. config/production config/test config/devel_joe config/devel_bill and so on) and all of these go into git. Then at deployment the actual working config file is copied out of that config directory. I think it's an ugly approach because it is a step backwards away from the idea of named branches, but at least it is safe.

Tel
  • 217
  • 2
  • 3
  • *sigh* this is soo frustrating. Why can't .gitattributes support merge strategies rather than just conflict drivers? (maybe because some of git's commands don't allow a strategy to be specified so it would be inconsistent?). In any case, one thing someone with some gumption could do is implement "branch-notes" in a similar way to how "object/commit notes" are implemented and use a post-checkout hook to populate these into files on checkout. It's ugly and unsafe, but that's the best I could come up with without modifying core git :( – DylanYoung Jul 24 '20 at 19:42
  • i see this and try but this is not workd for me sooo plzz any help you? marge time both file marge how to solved? – kiran_ray Jan 05 '21 at 06:43