1

This might have been asked before but I can not find the answer.

Assume following scenario.

I have a local repository with following local branches.

Scenario 1 

local
    Branch A
    Branch B
    Branch C (not reachable from A or B)

if I am on branch A and do a pull, do I implicitly do a fetch for B and C? Is the fetch done in pull operation different form just doing just doing fetch?

if I do fetch on C do I fetch the HEAD for A and B?

What about scenario two where only Branch A is checked out locally?

Scenario 2

local
    Branch A

Remote
    Branch A
    Branch B
    Branch C (not reachable from A or B)
User123456
  • 671
  • 2
  • 9
  • 19
  • See http://stackoverflow.com/questions/292357/whats-the-difference-between-git-pull-and-git-fetch – Joe Apr 27 '13 at 17:44

1 Answers1

1
  • Your description of (and the difference between) the two scenarios is not quite clear , since if the remote has some branches names A, B, and C, it will always exist in your local repo as well as origin/A, origin/B and origin/C, (after you've updated the remote using git fetch or a git pull), irrespective of whether you've checked out the branch locally or not.

  • fetch is used to fetch the updated list of commits from a remote. fetch is done as the first command of a pull operation.

    The commonly syntax is git fetch <REMOTE> <REFSPEC>

    The refspec argument is optional. If you fail to specify one, git is going to pull all the refs from the remote. By refs, it includes all reachable heads and tags in the refspec.

  • The git pull <REMOTE> command without any refspecs is going to bring in all the refs from the remote, and NOT just the commits corresponding to your current local branch you're merging into.

  • In Scenario 1, if you run a git pull origin when you've currently checked out branch A, yes git is going to update origin/A, origin/B, and origin/C in your local repo. In addition, it will merge origin/A into A.

  • In Scenario 1, if you run a git fetch origin C, only origin/C in your local repo is going to get updated. There will be no merges either whatsoever because of this fetch.

  • Scenario 2 is going to yield the same results as Scenario 1. All the refs from the remote will be updated into your local repo's <REMOTE_NAME>/BLAH branches. In fact Scenario 2 is no different than Scenario 1, just that you have fewer local branches checked out which should not matter in any way for the fetch operation.

BTW to answer your question in the comment on what git pull origin <BRANCHNAME> and git fetch origin <BRANCHNAME> do:

  • git pull origin <BRANCHNAME> does something different than what you might expect it to do.

    • git brings in the commits for <BRANCHNAME> from the remote into FETCH_HEAD instead of origin/<BRANCHNAME>.
    • It does not update origin/<BRANCHNAME>
    • It merges FETCH_HEAD into your currently checked out branch, and hence achieves the similar end result as far as the local branch state is concerned.
  • git fetch origin <BRANCHNAME> behaves very similar to git pull origin <BRANCHNAME> described above, except it stops with just bringing in the commits for <BRANCHNAME> from the remote into FETCH_HEAD.

  • If you really want to fetch only the commits corresponding to a particular branch, you need to use the right refspec argument. Read more on it here. To fetch only the commits from the remote origin and branch master, the correct command would be:

     git pull origin refs/heads/master:refs/remotes/origin/master
    
  • You could also use refspecs with fetch to only fetch the commits into origin/master without any merges into your local branches:

     git fetch origin refs/heads/master:refs/remotes/origin/master
    
  • If you do not want to type the long refspecs for a git pull, and do not mind having the info about all refs from the remote, and you do not have a remote tracking branch set, then you could just do this:

    git fetch origin
    git checkout <BRANCH-THAT-NEEDS-TO-BE-MERGED-INTO>
    git merge origin/<BRANCH-TO-BE-MERGED-FROM>
    

BONUS - What does the GIT_FETCH_HEAD do ?

It is a short-lived ref used by git to keep track of any fetches from the remote repositories. You could see the current value of FETCH_HEAD by looking into the file .git/FETCH_HEAD. For example:

72a90cf95456b14630ddff427c3df1b00be24670                branch 'master' of git://github.com/foo/bar.git
Tuxdude
  • 47,485
  • 15
  • 109
  • 110
  • Regarding Scenario two I think you understood me anyway. :), Usually when you branch off you tent to not track the remote branch. Simply one omits the -u. Therefore you need to do "git pull origin ", does this also mean you will do git fetch origin , and hence only update origin/? – User123456 Apr 27 '13 at 18:48
  • @user1043825 - Updated the answer in detail to explain what `git pull origin ` and `git fetch origin ` do and why the commands do not really do what you expect them to ;) – Tuxdude Apr 27 '13 at 19:34
  • Thanks for the in deepth answer first of all. If I understand you correctly, assume scenario 1, if I do "git pull origin A", I will only update GIT_FETCH_HEAD with the implicit fetch in the pull command and not even origin/a, or origin/b or origin/c, and Merge Fetch_Head to A. This also means that after a git pull origin A, A and origin/A will not be in synch, correct? – User123456 Apr 27 '13 at 20:02
  • @user1043825 - Yep that is correct. Did you try the commands with your repo ? – Tuxdude Apr 27 '13 at 20:27
  • I did try the commands on my repo, the funny thing is that it did update my origin/A. even when I did git pull origin A. I made sure that the git pull origin was not tracking remote in the config for the repository. When I type git pull origin, it says you did not specify branch and so on but just above that I can see that it has updated my origin/A branch and origin/b and so on. – User123456 Apr 28 '13 at 11:13
  • do you have reference for the GIT_FETCH_HEAD part and how git pull origin branch bypasses origin/branchname.. I'm probably doing something wrong but I can not reproduce this behavior on my repo. Thanks – User123456 Apr 28 '13 at 20:48
  • @user1043825 - Are you sure you've new commits from the remote that you're pulling and that needs to be merged ? Could you post the exact command output you see as well ? You should see mention of FETCH_HEAD and the list of commits which got fetched and which got merged into where as well. – Tuxdude Apr 29 '13 at 01:44
  • I figured out what I was doing wrong, it was kind of stupied, you see to test that remote tracking is disabled I verified config and then straight after ran "git pull origin". Now this gave the error I expected to see, it fetched as it should but it failed the merge. At this point I did the git pull origin branchname. Now had I done git pull origin branchname only and not tested the way I did everythings should have worked as expected. I did the test again correctly and it worked. – User123456 Apr 29 '13 at 18:27