In this claim:
git cherry-pick
seems like the obvious choice to me here, but it does not do exactly what I want. The trouble is that git cherry-pick
brings the 'master' branch up to date with all the changes on 'feature' up to commit '0123456789abcdef'.
you have conflated cherry-pick with merge. If you were to run:
git checkout master
git merge 0123456789abcdef
that would locate the merge base of the current tip commit of master, and commit 0123456789abcdef
, and do what you say. But git cherry-pick 0123456789abcdef
locates instead the parent commit of 0123456789abcdef
, then invokes Git's merge engine on the three commits involved here.
The effect is that git cherry-pick
will find the changes from 0123456789abcdef^
—the parent of 0123456789abcdef
—to 0123456789abcdef
, and apply them to the current or HEAD
commit. This will affect more than one file, if more than one file has any difference from 0123456789abcdef^
to 0123456789abcdef
(use git diff 0123456789abcdef^ 0123456789abcdef
, or more simply, git show 0123456789abcdef
, to see; note that 0123456789abcdef
must not be a merge commit).
If you only want the 0123456789abcdef^
-to-0123456789abcdef
changes for one particular file applied, use git cherry-pick -n
so that git cherry-pick
does the initial part of the work, but then stops before committing the result. This gives you the opportunity to back out changes to other files, using git reset
or git restore
. (If using git reset
, be sure to supply file names; git restore
is new in Git 2.23, and is a more limited but more flexible variant of git reset
in this particular regard.)
Note that git cherry-pick
does not do the equivalent of:
git diff master 0123456789abcdef
That is, it's not looking to make the master
version of any file match the version of any file in 0123456789abcdef
. What Git will end up doing is a three-way merge, combining the diffs produced by:
git diff --find-renames 0123456789abcdef^ HEAD
(i.e., what you changed with respect to the parent of 0123456789abcdef
) with those produced by:
git diff --find-renames 0123456789abcdef^ 0123456789abcdef
(i.e., what they changed with respect to their own parent). The combined changes are then applied to the snapshot from 0123456789abcdef^
: this adds your changes to their parent, plus their changes to their parent. The end result—if there are no conflicts—is that you've added their changes to your current commit, where "their changes" are with respect to their commit's parent's snapshot; but this also accounts for any line motion, or even file-name-changes, between their commit's parent and your commit.
Hence, based on your question, it seems that cherry-pick is the answer. If it's not, you're going to need to provide more information about why that is the case.