Reputation: 48023
Background: I'm on a feature branch which has diverged pretty significantly from master. I believe there are five files which have been modified on this branch. I've discovered that one of them should not have been modified at all, so I want to revert it to the state it had as of the time this branch was branched from master. But I can't just copy the file from master, because the same file has accreted other changes on master.
I believe a good way way to recover the file should be
git show 123abc:file5 > file5
where 123abc
is the commit hash for the spot at which the branch I'm on branched off of master. And that seems to work.
But I'd like to double-check this. So rather than overwriting file5
right away, I instead do
git show 123abc:file5 > file5.old
Now I can do
diff file5.old file5
to confirm that I've got the right, older version of file5
, with the differences I expect between that base version and the about-to-be-discarded branch version.
But to really confirm things, I want to double-check with git diff
. I believe that if I invoke
git diff master...
I should get differences between the spot at which my branch branched off from master, and my branch. And those diffs (at least the ones on file5
) should exactly correspond to the diffs I got when I ran diff file5.old file5
.
But they don't! It's not even close! (And, I lied, because I'm not actually sure which "differences I expect between that base version", because there's some work by others involved, and this is part of why I've decided to exclude this branch's changes to file5
from what I'm getting ready to merge back into master. But the point is that I'm not even sure which of the two diffs is more correct.)
So either
git show 123abc:file5
didn't actually get me the base version I thought it did, orgit diff master...
isn't actually diffing against the base version (the "common ancestor") like I think it does.Where have I gone wrong?
Upvotes: 0
Views: 67
Reputation: 779
git "diff" is about comparing two endpoints, not ranges, and the range notations (.. and ...) do not mean a range as defined in the "SPECIFYING RANGES".
So git diff master... will show you the differences between the tip of master and the tip of your current branch, but it will not include the common ancestor of the two.
Command
git diff 123abc...master
will show you the differences between the commit at which your branch was created (with hash '123abc') and the tip of the master. This will include the changes made to 'file5' on 'master' after the branch point.
You can confirm that correct base version of 'file5' by comparing the output of 'git show 123abc:file5' with the file in the common ancestor commit, which can be found via
git merge-base HEAD master
Using the output hash value you can use git show to see the contents of 'file5'
git show <merge-base-hash>:file5
If the compare matches then you have the correct base version of the file.
Upvotes: 0
Reputation: 48023
As is so often the case (a perfect example of rubber duck debugging), right before posting this question, I figured out the answer. But I figure I'll post the question and its answer anyway, in case it's useful to anyone else.
I knew someone was going to ask me for the output of git merge-base
. So I ran it, and it gave me something other than the 123abc
which I asserted was "the commit hash for the spot at which the branch I'm on branched off of master". So, wait, what's going on with that?
And the answer was, it turned out there had been a couple of merges from master into this feature branch, to keep it up to date. So that's what git merge-base
was finding, and of course what git diff master...
was using.
And it's that other commit (the most recent merge from master) that I logically want to be restoring my file5
from.
Upvotes: 1