gitfetchrepositoryheadgit-fetch

Git Log After Git Fetch Upstream


I really wanted to understand how git behaves and what's happening underneath the plans after I run a git fetch upstream HEAD on a clean local repository.

Basically the steps were as follows:

  1. Create a fork in the remote repository (GitHub in this case)
  2. I clone my forked repository locally: git clone <url>
  3. Set the upstream: git remote add <upstream-url>
  4. Fetch upstream data: git fetch upstream HEAD
    • NOTE: I would like to have only the default branch tracked in my local repository using this command instead of simply git fetch upstream

After that I actually see the data messages being fetched, however, in git log --all I don't see upstream/HEAD for example, it's like nothing happened.

Any explanation will be very welcome :)


Solution

  • What is Head - In Git, any branch is merely a pointer to a commit. Head is nothing but a pointer to current checked out branch. So as you hop (with checkout command) from one branch to another your Head pointer changes and starts pointing to the latest commit of the checked out branch, that's it. Here is detailed explanation of how branches works in Git.

    How fetch and pull works - Secondly, $ git fetch fooBranch simply fetches all latest commits pushed by other contributors to fooBranch from remote repository to your local machine. These fetched changes are safely stored somewhere in .git/ directory on your local machine and can be accessed by doing git log upstream/fooBranch or git log upstream/Head. Although at this point these changes won't be visible in your local files/workspace and you may see different output for following commands

    $ git log upstream/fooBranch
    
    VS
    
    $ git log fooBranch
    

    This shows us that Git stores 2 copies of branches i.e. one tracking changes present in remote repository and other is for local repository. When you make commits they are stored as part of your local branch copy and on push will be pushed to remote repository and eventually will be fetched by other contributors and will be synced up with their own remote copy of fooBranch.

    Coming back to where we were, Now to sync fetched changes with local repository/workspace you will have to run $ git merge upstream/fooBranch. Now both local and remote copy of fooBranch will be synced in your local repository and you will see same output for above 2 commands.

    On similar note, $ git pull upstream fooBranch is basically combination of -

    $ git fetch upstream fooBranch + $ git merge upstream/fooBranch
    

    So this is what happens under the hood when you fetch vs pull and when you do $ git log --all you are expected to see your default branch's commit history.

    I hope this explanation aligned with your ask.