Steve Summit
Steve Summit

Reputation: 48023

confused about 'git diff' and 'git show' on branch

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

Where have I gone wrong?

Upvotes: 0

Views: 67

Answers (2)

Ugnes
Ugnes

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

Steve Summit
Steve Summit

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

Related Questions