How Do I 'git fetch' and 'git merge' from a Remote Tracking Branch (like 'git pull')
I have set up some remote tracking branches in git, but I never seem to be able to merge them into the local branch once I have updated them with 'git fetch'.
For example, suppose I have remote branch called 'an-other-branch'. I set that up locally as a tracking branch using
git branch --track an-other-branch origin/an-other-branch
So far, so good. But if that branch gets updated (usually by me moving machine and commiting from that machine), and I want to update it on the original machine, I'm running into trouble with fetch/merge:
git fetch origin an-other-branch
git merge origin/an-other-branch
开发者_如何学编程Whenever I do this, I get an 'Already up-to-date' message and nothing merges.
However, a
git pull origin an-other-branch
always updates it like you would expect.
Also, running git diff
git diff origin/an-other-branch
shows that there are differences, so I think I have my syntax wrong.
What am I doing wrong?
EDIT [2010-04-09]: I have checked a couple of times, and I'm definitely not on a different branch. Should my 'git fetch' followed by a 'git merge' (as shown above) do the exact same thing as a git pull? I will get some workflow showing the results of a git status etc.
You don't fetch a branch, you fetch an entire remote:
git fetch origin
git merge origin/an-other-branch
Selecting just one branch: fetch
/merge
vs. pull
People often advise you to separate "fetching" from "merging". They say instead of this:
git pull remoteR branchB
do this:
git fetch remoteR
git merge remoteR branchB
What they don't mention is that such a fetch command will actually fetch all branches from the remote repo, which is not what that pull command does. If you have thousands of branches in the remote repo, but you do not want to see all of them, you can run this obscure command:
git fetch remoteR refs/heads/branchB:refs/remotes/remoteR/branchB
git branch -a # to verify
git branch -t branchB remoteR/branchB
Of course, that's ridiculously hard to remember, so if you really want to avoid fetching all branches, it is better to alter your .git/config
as described in ProGit.
Huh?
The best explanation of all this is in Chapter 9-5 of ProGit, Git Internals - The Refspec (or via github). That is amazingly hard to find via Google.
First, we need to clear up some terminology. For remote-branch-tracking, there are typically 3 different branches to be aware of:
- The branch on the remote repo:
refs/heads/branchB
inside the other repo - Your remote-tracking branch:
refs/remotes/remoteR/branchB
in your repo - Your own branch:
refs/heads/branchB
inside your repo
Remote-tracking branches (in refs/remotes
) are read-only. You do not modify those directly. You modify your own branch, and then you push to the corresponding branch at the remote repo. The result is not reflected in your refs/remotes
until after an appropriate pull or fetch. That distinction was difficult for me to understand from the git man-pages, mainly because the local branch (refs/heads/branchB
) is said to "track" the remote-tracking branch when .git/config
defines branch.branchB.remote = remoteR
.
Think of 'refs' as C++ pointers. Physically, they are files containing SHA-digests, but basically they are just pointers into the commit tree. git fetch
will add many nodes to your commit-tree, but how git decides what pointers to move is a bit complicated.
As mentioned in another answer, neither
git pull remoteR branchB
nor
git fetch remoteR branchB
would move refs/remotes/branches/branchB
, and the latter certainly cannot move refs/heads/branchB
. However, both move FETCH_HEAD
. (You can cat
any of these files inside .git/
to see when they change.) And git merge
will refer to FETCH_HEAD
, while setting MERGE_ORIG
, etc.
Are you sure you are on the local an-other-branch
when you merge?
git fetch origin an-other-branch
git checkout an-other-branch
git merge origin/an-other-branch
The other explanation:
all the changes from the branch you’re trying to merge have already been merged to the branch you’re currently on.
More specifically it means that the branch you’re trying to merge is a parent of your current branchif you're ahead of the remote repo by one commit, it's the remote repo that's out of date, not you.
But in your case, if git pull
works, that just means you are not on the right branch.
Git pull is actually a combo tool: it runs git fetch (getting the changes) and git merge (merging them with your current copy)
Are you sure you are on the correct branch?
these are the commands:
git fetch origin
git merge origin/somebranch somebranch
if you do this on the second line:
git merge origin somebranch
it will try to merge the local master into your current branch.
The question, as I've understood it, was you fetched already locally and want to now merge your branch to the latest of the same branch.
精彩评论