Reputation: 99970
I am concerned that git checkout other_branch -- file will overwrite the file in my current branch and not do a merge at all.
Say I am on a branch called foo. I want to merge a file in foo called bar.js, with the same filepath on a branch called baz;
so git branch -v
looks like:
* foo adbe2d4 pdev:set
baz ae598f5 [ahead 5] sync-msg
The way I know how to do this is to do:
git checkout baz -- bar.js
what I am confused about, is, doesn't this overwrite the file on my branch with the same name?
How can I merge bar.js from baz instead of checking out the file and overwriting the work on the foo branch? Or am I mistaken and a merge does indeed happen?
Upvotes: 0
Views: 1196
Reputation: 487805
You are correct, this form of checkout:
git checkout <tree-ish> -- <path> [ <path> ... ]
simply overwrites the work-tree (and index!) version of each path.
Normally you don't want to merge just one file, but rather some other branch's tip commit with your current commit (resulting in a new merge commit, if successful).
To do a full three-way merge of just one file you must choose a merge base between your current commit and the commit from which you want to merge the one file. This is a bit tricky, and usually unnecessary anyway (see the simpler checkout -p
method below).
If you want to do it, though, you can automate it through git diff --full-index
, piped to git apply -3
. The merge base is your choice: you may want the merge base of your current branch and the tip of the other branch, or you may simply want the parent of the commit you are, in effect, then cherry-picking. Depending on the change you are obtaining, these may end up choosing the same merge-base file anyway:
git diff --full-index ...other -- path/to/file
(note the three dots here! this has the same meaning as HEAD...other
and has special meaning to git diff
) or:
git diff --full-index other~1 other -- path/to/file
These will both produce a diff of the one specified file. The index
line in the diff will provide the merge base, so now you can add the git apply -3
step:
git diff --full-index ...other -- path/to/file | git apply -3
Your file is now three-way-merged if possible, or left with conflict markers if not (in which case, resolve as usual).
If you don't need a full three-way merge, git checkout -p other -- path/to/file
is simpler. This effectively diffs your current version of path/to/file
with the one from other
, then lets you apply each of those changes one "patch" at a time, a la git add -p
. Note that this is substantively different from merging. If you take all of these changes, it's just git diff other HEAD -- path/to/file | git apply
, which winds up doing the same thing as git checkout other -- path/to/file
, which is what you said you don't want, so you must carefully exclude those changes that you don't want.
Upvotes: 1