40

I have 2 branches in a git repo, lets call them, dev and test. I have changes in a single file, somecode.js. Both branches have changes to somecode.js. The 2 branches have diverged significantly (but manageably) so a straight "merge" is insufficient.

I have tried http://jasonrudolph.com/blog/2009/02/25/git-tip-how-to-merge-specific-files-from-another-branch/ but it doesn't merge the contents of both files. You basically just write over the file instead of actually merging the contents of the file.

I have also tried:

git checkout -b newbranch
git checkout test somecode.js
git commit -m "somecode changes from newbranch"
git checkout dev
git merge newbranch

And

git checkout -m test somecode.js

(I was really hopeful with the -m for merge, but it didn't appear to work for me...)

I thought I was close to what I needed, but then I realized that it just fast-forwarded the commit meaning it didn't merge, it wrote over the original file in test.

So, to reiterate, how can I merge a specific file from one branch into another branch without just writing over the file in the branch I am merging into using git.

jeremy
  • 4,294
  • 3
  • 22
  • 36
  • Possible duplicate: http://stackoverflow.com/questions/449541/how-do-you-merge-selective-files-with-git-merge – rlegendi Dec 04 '12 at 20:57
  • Cherry-pick doesn't solve the problem because that incorporates complete commits. So it will bring over multiple files and I'll have to look through all the commits to see which are relevant – jeremy Dec 04 '12 at 21:03
  • possible duplicate of [How do I merge changes to a single file, rather than merging commits?](http://stackoverflow.com/questions/10784523/how-do-i-merge-changes-to-a-single-file-rather-than-merging-commits) – Ciro Santilli OurBigBook.com Jul 18 '14 at 19:57

3 Answers3

42

I think you like to use

git checkout -p

In your case

git checkout dev
git checkout -p test somecode.js

And you can interactively apply the diffs.

Peter van der Does
  • 14,018
  • 4
  • 38
  • 42
  • 1
    But you don't allow git to do any merge.. you manually do all the work. – the.malkolm Dec 04 '12 at 21:49
  • 1
    @the.malkolm At the first question you reply with `a` and that's it. (a - apply this hunk and all later hunks in the file) – Peter van der Does Dec 04 '12 at 22:56
  • It just means you apply 'theirs' strategy. – the.malkolm Dec 04 '12 at 23:10
  • Hmmm, doesn't seem to work for me. The message after ``git checkout -p [other_branch] [path_to_file][filename]`` was simply "No changes," which summed up the result perfectly. Perhaps I'm trying to drag in a directory/file that doesn't exist in my current branch??? – SMBiggs Feb 29 '16 at 18:05
  • @ScottBiggs - this is probably because `other_branch` was already merged into your current branch. I'm not sure how to work around that yet. – JBCP Mar 01 '16 at 23:28
  • git merge -p does not appear to be a valid git option anymore! can anyone confirm? I am on git version 2.7.4 – Alexander Mills Dec 21 '16 at 03:25
5
git checkout dev
git show test:somecode.js > somecode.js.theirs
git show $(git merge-base dev test):somecode.js > somecode.js.base
git merge-file somecode.js somecode.js.base somecode.js.theirs 

This way you'll manually make a three-way merge from somecode.js on test branch into somecode.js on dev branch.

Or.. You can create a temporary branch with the changes you want and make a squash merge from it. Is it 'git way' enough? :)

git checkout -b test/filtered $(git merge-base dev test)
git diff ..test -- somecode.js | git apply
git add -- somecode.js
git commit -m "Updated somecode.js"
git checkout dev
git merge --squash test/filtered
git branch -D test/filtered
the.malkolm
  • 2,391
  • 16
  • 16
1

I think git merge-file is what you're looking for. From the man page:

git merge-file incorporates all changes that lead from the <base-file> to
<other-file> into <current-file>. The result ordinarily goes into <current-file>.
git merge-file is useful for combining separate changes to an original. Suppose
<base-file> is the original, and both <current-file> and <other-file> are
modifications of <base-file>, then git merge-file combines both changes.
khagler
  • 3,996
  • 29
  • 40
  • I don't see a way to specify the file from the other branch. This looks like it is for internal use perhaps? Can you show usage? – jeremy Dec 04 '12 at 21:06
  • `git merge-file` is just the 3-way merge driver for files. That description is a bit misleading; it doesn't look at all the commits in between, it just does a classic 3-way merge. – Lily Ballard Dec 04 '12 at 21:12