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).
But what if you really want to merge just one file?
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 3-way merge
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.