My understanding has always been that git pull
is essentially a combination of git fetch
and git merge ...
but I have encountered it a number of times where pulling, then comparing shows changes that aren't mine until I also do a fetch:
(on branch blob):
git pull origin blob
git diff origin/blob <- shows a bunch of changes that aren't from my but were just pulled from others
git fetch
git diff origin/blob <- shows just my changes
Is my understanding of pull incorrect?
The git pull command first runs git fetch which downloads content from the specified remote repository. Then a git merge is executed to merge the remote content refs and heads into a new local merge commit.
Reason: This can be happened due to the limitations that are applied by git configs. As implied by its name Git configs are configuration values on a global or local project level for Git. If we don't use any options, git configs are written into the local level.
Git Fetch is the command that tells the local repository that there are changes available in the remote repository without bringing the changes into the local repository. Git Pull on the other hand brings the copy of the remote directory changes into the local repository.
This is a common source of confusion, so much so that the #git
IRC channel has a canned help text for it, called !pull4
:
We recommend against using 'git fetch/pull <remote> <refspec>' (i.e. with branch argument), because it doesn't update the <remote>/<branch> ref. The easy way to fetch things properly is to get everything: 'git fetch' or 'git pull' are sufficient if you have one remote; otherwise we recommend 'git fetch <remote>' (plus 'git merge <remote>/<branch>' if you wanted to pull/merge).
What's happening here is that git pull
with no arguments does a git fetch
on the "default remote" (typically origin
), then git merge
s the remote branch corresponding to your current local branch. git pull <remote>
does the same thing with an explicitly specified remote. However, the "four-word pull", git pull <remote> <branch>
, fetches that branch into a temporary location, FETCH_HEAD
, without updating your tracking branches, and then merges FETCH_HEAD
into your current branch.
So, by using git pull origin blob
, you are saying "I want to merge the latest version of the blob
branch on the remote origin
into my current branch, without updating any of my tracking branches or fetching any other data".
If your branch merge configurations are correct (and they probably are, since git clone
and git checkout
try to set them up automatically), you can just git pull
or git pull origin
and it'll fetch everything and then merge the branch corresponding to your currently-checked-out branch. If you want more explicit control, use git fetch
and then git merge
. git pull <remote> <branch>
is rarely what you want.
(The reason the git fetch
fixes things in your example is that, after the pull, your local branch has been updated with the latest remote commits, but the tracking branch hasn't been. git fetch
updates the tracking branch with those commits, at which point the diffs start making sense again.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With