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:
git clone <url>
git remote add <upstream-url>
git fetch upstream HEAD
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 :)
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.