问题
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.
回答1:
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 of git fetch
and git 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:
+refs/heads/*:refs/remotes/origin/*
This tells Git to fetch the remote branches located at refs/heads/*
and map them to remote-tracking branches located at refs/remotes/origin/*
. So for a remote branch master
, refs/heads/master
will map to refs/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
or git pull
), the default mapping is overridden. Instead, your mapping is used. For example, when you use git fetch origin master:foo
, then a local branch foo
is fast-forwarded (if possible) to point to the remote branch master
. 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 your git pull
command first did this:
git fetch origin <remote-branch>:<local-branch>
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 runs git 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 is git merge <local-branch>
. And running git merge
will merge into the current branch.
So when you’re on <different-branch>
and run git 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.
回答2:
You can always go low tech:
git fetch origin #fetches all the remote branches
git checkout <local-branch>
git merge origin/<remote-branch>
or if you practice rebase pulls
git rebase -i origin/<remote-branch> <local-branch>
回答3:
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.
来源:https://stackoverflow.com/questions/32147716/using-colon-in-git-pull-origin-remote-branch-local-branch-does-not-pull