7

We have a branch called upgrade that was branched off master 6 months ago. In the upgrade branch we restructured all projects to maven (master is ant projects), so the structure of a project x in the two branches is totally different.

To restructure the projects to maven we used git mv so we have the history preserved. Next we did some code changes on the files on upgrade as the upgrade process required those changes.

Now I want to merge master into upgrade while preserving all structure as it exists in upgrade. How do I do this?

I tried using git merge master while being on the upgrade branch.

But this is not giving me any conflicts on the code changes we made on upgrade; instead it gave me conflicts in property files. (I'm definitely sure of code changes on upgrade that conflict with master) -- what could be wrong?

Jeromy Irvine
  • 11,614
  • 3
  • 39
  • 52
Rose
  • 2,792
  • 4
  • 28
  • 42
  • Note that `git mv` is just a shortcut for rename, `git rm` and `git add`. See also [this question](http://stackoverflow.com/questions/1094269/whats-the-purpose-of-git-mv). – poke Dec 26 '12 at 22:23
  • @poke what has `git mv` to do with this question? – Nevik Rehnel Dec 26 '12 at 22:26
  • @NevikRehnel From the question: *“[…] we used git mv so we have the history preserved.”* – poke Dec 26 '12 at 22:26
  • @poke: oh woops, that totally went under there; sorry for calling you out :) – Nevik Rehnel Dec 26 '12 at 22:27
  • @NevikRehnel No worries ;) – poke Dec 26 '12 at 22:28
  • @poke - Ohhh, I read the link u sent. Does it mean that the files in "upgrade" are considered different than the ones in "master"? If so that's real bad! :( – Rose Dec 26 '12 at 22:31
  • It just means that using `git mv` does not give you further protection. Git is able to detect “moves” by inspecting content changes, so it is possible that you can resolve this with only minor conflicts. – poke Dec 26 '12 at 22:35
  • Thanks @poke - one last question tho': if git can detect "moves" by some inspection, why didn't it try to compare the files and tell me the conflicts? what did i miss in the merge command? – Rose Dec 26 '12 at 22:53
  • The results from those renaming checks are not stored anywhere, so whenever you want to resolve such things, Git needs to inspect everything again from scratch. As such, it usually won’t do all the checks for performance reasons (for normal cases, you won’t *need* it to analyze that much). But by using the different merge strategies, you can tell Git to do a bit more than usual and very often end up with good results. – poke Dec 26 '12 at 23:00
  • possible duplicate of [git merge -s ours, what about "their"](http://stackoverflow.com/questions/173919/git-merge-s-ours-what-about-their) – competent_tech Dec 27 '12 at 01:14
  • @competent: I don't think so. I think the OP here has changes in both branches as compared with the branch point. – me_and Dec 27 '12 at 08:55

1 Answers1

3

What you want is to use the ours strategy (not the strategy option as mentioned in the previous version of this answer); while being on upgrade, use git merge -s ours master. According to the more detailed information in the git merge manpage, this will not try to do an actual merge at all, but simply use the tree from the ours side for the result and discard every other side in the merge.

Using merge with that will keep all history, create a merge commit (showing the convergence of the two branches in history), but use all files from one side of the merge.

Note that the meaning of "ours" and "theirs" is merely depending on which branch you are on when you initiate the merge ("merge upgrade into master" vs. "merge master into upgrade", which both produce the same resulting history). "Ours" is the one branch you're standing on, and "theirs" is/are the branch(es) you specify on the merge command. More about this is explained in the manpage.

EDIT: As a point of explanation: You (most probably) did not get any conflicts on the code changes you made, because master did not diverge sufficiently from the common code base. By default, git merge uses a three-way merge strategy, which takes the latest common ancestor of the two sides you want to merge, and only actually looks at changes relative to that common ancestor. If only one side of the branch progressed, Git will recognize that all changes there supersede the old code (in your case, the code on master), and it will just use the code from upgrade automatically (i.e. it resolved the "conflict" automatically).

A conflict that you must manually resolve will only be brought up when both sides of the merge have changed in comparison to the common ancestor. In that case, Git does not know which side is "better" -- it might even be that the two sides need to be combined for them to work. That's why the user is asked to resolve such conflicts.

Note: Answer was updated because I had previously misinterpreted the -s and -X options.

Nevik Rehnel
  • 49,633
  • 6
  • 60
  • 50
  • Thanks @Navik. Being on "upgrade" branch, I'll try git merge -Xtheirs master. I'll see if it compares the corresponding files. One sec. – Rose Dec 26 '12 at 22:57
  • @Navik: I run that. To see what got changed I did git status. But it looks like it is not comparing the corresponding files in those 2 branches. No conflicts on almost all the *.java files that were moved to the new structure. It gave me a bunch of new classes added (i.e new project added on master after we branched "upgrade"). Also it found some properties file conflict. But no java code conflict :( Does this mean it is not considering the corresponding .java file pairs for comparison? What can I do to tell it to merge path1/X.java in "master" to path2/X.java in "upgrade"? – Rose Dec 26 '12 at 23:56
  • @Rose: I just noticed that I had misinterpreted the options for `merge`, and will update my answer in a minute. – Nevik Rehnel Dec 27 '12 at 11:04
  • 1
    @Navik: Thanks for the follow up first. Hey I'm worried about the statement about the "ours" strategy that says "effectively ignoring all changes from all other branches" from the man page u shared. My point is - if it ignores changes on master that the other team was developing for 6 months how is that a merge, in the first place? (Am I reading u wrong??) Any way I'll play with it since I can revert. – Rose Dec 27 '12 at 18:03
  • @Rose: You should have mentioned that the master branch has gotten considerable development in the meantime. I was of the impression that you had already incorporated all significant changes into your upgrade branch. In that case, this would ignore those, yes. Unfortunately I don't have a detailed answer for you then, sorry :( – Nevik Rehnel Dec 27 '12 at 18:05