This is mostly of the nature of a curiosity as I'm trying to get familiar with Git. I have looked at the documentation for 'git fetch' but I don't see an obvious explanation for the below. Thanks in advance, and apologies if this is howlingly obvious.
1) From a central repository, say GitHub, I clone a repository named website
on each of two machines, HostA
and HostB
.
2) on HostA
, I make a change to a file, say README.txt
, and commit it.
At this point on HostA
, the commits for branches master
and
origin/master
are, as expected different since I haven't pushed yet
git show master
git show origin/master
report different hashes (since master
has the change and origin/master
does not)
3) Once I push, they are after that the same.
4) Now, over on HostB
, if I do the following:
git fetch
git merge FETCH_HEAD
afterwards, on HostB master
and origin/master
report the same hash when queried with git show
BUT
if instead I had done, on HostB
:
git fetch origin master
git merge FETCH_HEAD
at that point the hashes still differ.
git show origin
git show origin/master
report different hashes
The tracking branch origin/master
isn't updated until I do a plain git fetch
Why is this?
If your branch has an associated remote tracking branch that means its configuration is like:
git config branch.[branch-name].remote [remote-name]
git config branch.[branch-name].merge [remote-master]
The key part of git fetch
which explain the difference between the two commands is:
<refspec>
The format of a
<refspec>
parameter is an optional plus+
, followed by the source ref<src>
, followed by a colon:
, followed by the destination ref<dst>
.
The remote ref that matches<src>
is fetched, and if<dst>
is not empty string, the local ref that matches it is fast-forwarded using<src>
.
Let me repeat it:
if <dst>
is not empty string, the local ref that matches it is fast-forwarded using <src>
.
Knowing that:
git fetch
is equivalent to git fetch origin master:master
(from the default value of your branch config), so it will update the remote tracking branch: the destination of the refspec is specified for you.
git fetch origin master
is equivalent to "git fetch origin master:
", not to "git fetch origin master:master
"; it stores fetched value of 'master
' branch (of remote 'origin
') in FETCH_HEAD
, and not in 'master
' branch or remote-tracking 'remotes/origin/master
' branch (from Jakub Narębski's answer)
In other words, you didn't specify the destination of your refspec