To better understand how git fetch
works let us discuss how Git organizes and stores commits. Behind the scenes, in the repository's ./.git/objects
directory, Git stores all commits, local and remote. Git keeps remote and local branch commits distinctly separate through the use of branch refs. The refs for local branches are stored in the ./.git/refs/heads/
. Executing the git branchcommand will output a list of the local branch refs. The following is an example of git branch
output with some demo branch names.
gitbranch
main
feature1
debug2
Examining the contents of the /.git/refs/heads/
directory would reveal similar output.
ls./.git/refs/heads/
main
feature1
debug2
Remote branches are just like local branches, except they map to commits from somebody else’s repository. Remote branches are prefixed by the remote they belong to so that you don’t mix them up with local branches. Like local branches, Git also has refs for remote branches. Remote branch refs live in the ./.git/refs/remotes/
directory. The next example code snippet shows the branches you might see after fetching a remote repoconveniently named remote-repo:
gitbranch-r
#origin/main
#origin/feature1
#origin/debug2
#remote-repo/main
#remote-repo/other-feature
This output displays the local branches we had previously examined but now displays them prefixed with origin/
. Additionally, we now see the remote branches prefixed with remote-repo
. You can check out a remote branch just like a local one, but this puts you in a detached HEAD
state (just like checking out an old commit). You can think of them as read-only branches. To view your remote branches, simply pass the -r
flag to the git branch
command.
You can inspect remote branches with the usual git checkout
and git log
commands. If you approve the changes a remote branch contains, you can merge it into a local branch with a normal git merge
. So, unlike SVN, synchronizing your local repository with a remote repository is actually a two-step process: fetch, then merge. The git pull
command is a convenient shortcut for this process.
Git fetch commands and options
gitfetch<remote>
Fetch all of the branches from the repository. This also downloads all of the required commits and files from the other repository.
gitfetch<remote><branch>
Same as the above command, but only fetch the specified branch.
gitfetch--all
A power move which fetches all registered remotes and their branches:
gitfetch--dry-run
The --dry-run
option will perform a demo run of the command. It will output examples of actions it will take during the fetch but not apply them.
Git fetch examples
git fetch a remote branch
The following example will demonstrate how to fetch a remote branch and update your local working state to the remote contents. In this example, let usassume there is a central repo origin from which the local repository has been cloned from using the git clone
command. Let us also assume an additional remote repository named coworkers_repo that contains a feature_branch which we will configure and fetch. With these assumptions set let us continue the example.
Firstly we will need to configure the remote repo using the git remotecommand.
gitremoteaddcoworkers_repogit@bitbucket.org:coworker/coworkers_repo.git
Here we have created a reference to the coworker's repo using the repo URL. We will now pass that remote name to git fetch
to download the contents.
gitfetchcoworkers_repocoworkers/feature_branch
fetchingcoworkers/feature_branch
We now locally have the contents of coworkers/feature_branch we will need the integrate this into our local working copy. We begin this process by using the git checkoutcommand to checkout the newly downloaded remote branch.
gitcheckoutcoworkers/feature_branch
Note:checkingoutcoworkers/feature_branch'.Youarein'detachedHEAD'state.Youcanlookaround,makeexperimental
changesandcommitthem,andyoucandiscardanycommitsyoumakeinthis
statewithoutimpactinganybranchesbyperforminganothercheckout.
Ifyouwanttocreateanewbranchtoretaincommitsyoucreate,youmay
doso(noworlater)byusing-bwiththecheckoutcommandagain.Example:
gitcheckout-b<new-branch-name>
The output from this checkout operation indicates that we are in a detached HEAD
state. This is expected and means that our HEAD
ref is pointing to a ref that is not in sequence with our local history. Being that HEAD
is pointed at the coworkers/feature_branch ref, we can create a new local branch from that ref. The 'detached HEAD
' output shows us how to do this using the git checkout
command:
gitcheckout-blocal_feature_branch
Here we have created a new local branch named local_feature_branch. This puts updates HEAD
to point at the latest remote content and we can continue development on it from this point.
Synchronize origin with git fetch
The following example walks through the typical workflow for synchronizing your local repository with the central repository's mainbranch.
gitfetchorigin
This will display the branches that were downloaded:
a1e8fb5..45e66a4main->origin/main
a1e8fb5..9e8ab1cdevelop->origin/develop
*[newbranch]some-feature->origin/some-feature
The commits from these new remote branches are shown as squares instead of circles in the diagram below. As you can see, git fetch
gives you access to the entire branch structure of another repository.
To see what commits have been added to the upstream main, you can run a git log
using origin/mainas a filter:
gitlog--onelinemain..origin/main
To approve the changes and merge them into your local mainbranch usethe following commands:
gitcheckoutmain
gitlogorigin/main
Then we can use git merge origin/main
:
gitmergeorigin/main
The origin/mainand mainbranches now point to the same commit, and you are synchronized with the upstream developments.
Git fetch summary
In review, git fetch
is a primary command used to download contents from a remote repository. git fetch
is used in conjunction with git remote
, git branch
, git checkout
, and git resetto update a local repository to the state of a remote. The git fetch
command is a critical piece of collaborative git work flows. git fetch
has similar behavior to git pull
, however,git fetch
can be considered a safer, nondestructive version.