Let's say I am on a different branch than <local-branch>
, called <different-branch>
.
When I try to pull from a remote branch to a local branch, I do the following:
git pull origin <remote-branch>:<local-branch>
And, from my understanding this should pull into my <local-branch>
, and not pull into <different-branch>
.
But, then when I check git log
while I'm on <different-branch>
, I see that those commits are from <remote-branch>
?
How do I pull from a remote branch, into a local branch, when the local branch is different from the one that I cam currently on? Thank you.
Using
git pull
with a refspec will not affect the merging part of the pull command. As you maybe know,git pull
is essentially just a combination ofgit fetch
andgit merge
; first, it will fetch the newest changes from the remote and update the remote-tracking branch, and then it will merge that remote-tracking branch into the current branch.Now, as I said, the refspec does not affect the merging part, but it only affects the fetching inside
git pull
. Now to understand what this eventually means, you first have to understand what a refspec is.A refspec is basically just a configuration which remote branches map to which remote-tracking branch. The remote branches are here the branches that actually exist on the remote, and the remote-tracking branches are the branches that are created to track the state of the remote branches; for a remote called “origin”, its remote-tracking branches all start with
origin/
.If you don’t specify a refspec explicitely, it is taken from the configuration file. The default form usually looks like this:
This tells Git to fetch the remote branches located at
refs/heads/*
and map them to remote-tracking branches located atrefs/remotes/origin/*
. So for a remote branchmaster
,refs/heads/master
will map torefs/remotes/origin/master
. The leading+
also tells Git to overwrite the remote-tracking branch regardless of whether the changes could be fast-forwarded or not: After all, you usually want your remote-tracking branches to match exactly the state on the remote, so if the history is rewritten there (which should be avoided) or branches are renamed, you would want the remote-tracking branches to still respect that.Now, when you specify the refspec (using
git fetch
orgit pull
), the default mapping is overridden. Instead, your mapping is used. For example, when you usegit fetch origin master:foo
, then a local branchfoo
is fast-forwarded (if possible) to point to the remote branchmaster
. So this is actually a fine way to update a local branch, without having to check it out: If you leave out the leading+
, then updating the local ref (branch) will fail if it’s not a fast-forward merge, so you’re also safe against conflicts.But coming back to
git pull
—what happened when you ran the command? As I said, a pull is just a fetch and a merge, so yourgit pull
command first did this:So the remote branch is fetched from the remote, and the local branch is updated—if it’s a fast-forward merge. This already does exactly what you wanted: Update
<local-branch>
.But then, the merge part of
git pull
happens; and Git usually runsgit merge FETCH_HEAD
for this purpose.FETCH_HEAD
is a reference to the last fetched branches. In this case, it points at<local-branch>
. So after fetching into<local-branch>
, the command that is being executed isgit merge <local-branch>
. And runninggit merge
will merge into the current branch.So when you’re on
<different-branch>
and rungit pull origin <remote-branch>:<local-branch>
then you will correctly update<local-branch>
to match the remote branch, but you will then also merge those changes into the current branch,<different-branch>
. That’s why you see the changes of that branch in the log of the current branch; they were simply merged.If you want to avoid that, as per my explanations above, just use
git fetch
with the refspec. It will already update the local branch correctly (if it can) without affecting the current branch.If you want to track the remote branch as well you can use the following:
git checkout --track -b local-branch origin/remote-branch
You might need to run
git fetch
first if the remote branch was created after you last fetched.You can always go low tech:
or if you practice rebase pulls