In most cases, working with the Git version control system is done locally. However, you sometimes need to sync with a remote repository to update your local storage. Git provides two key commands for this: git fetch
and git pull
.
A remote repository is a storage location hosted on the network, usually on platforms like GitHub, GitLab, or Bitbucket. These services allow developers to collaborate on projects, make changes, and synchronize code between local and remote versions.
Both commands are used to download updates from a remote repository, but they work differently. In this guide, we will explore their practical applications and highlight their key differences.
Since this article covers practical usage, you’ll need the following:
Let’s start with what git fetch
does. git fetch
is used to grab the latest data from a remote repository and put it into your local storage without modifying any files in your working directory. Instead, it updates the so-called remote-tracking branches, which reflect the state of the remote repository at the time the command is executed.
This is how git fetch
works:
Basic syntax of git fetch
:
git fetch <remote-repository-url>
Useful options:
git fetch --all
— Downloads updates from all remote repositories linked to the local storage.git fetch --dry-run
— Checks for changes before downloading without making any actual changes.git fetch --force
— Forcefully updates data in the local repository, overwriting any conflicts.git fetch --tags
— Downloads all tags from the remote repository.git fetch --prune
— Removes references to branches that were deleted in the remote repository.Unlike git fetch
, the git pull
command downloads the latest changes from a remote repository and automatically merges them into your current local branch. Essentially, executing git pull
involves two operations:
git fetch
— Downloads new data.git merge
— Merges the downloaded changes with the local branch.This is how git pull
works:
Basic syntax of git pull
:
git pull
Useful options:
git pull [remote-repository] [branch]
— Downloads changes only from the specified repository and branch. For example, git pull origin main
updates the local main branch from the remote repository origin.
git pull --rebase
— Instead of performing a standard merge, this applies the changes on top of the local commits, helping to avoid unnecessary merge commits.
To better understand the differences between these two commands, here's a comparison table:
Criterion |
git fetch |
git pull |
Action |
Only downloads changes |
Downloads and merges changes |
Impact on Local Repository |
Does not modify files or branches |
Modifies the current branch and files |
Safety |
Safe, as it does not cause conflicts |
May cause conflicts during merging |
Previewing Changes |
Allows reviewing and analyzing changes before merging |
Automatically integrates changes without preview |
Flexibility |
Requires manual merging |
Merges automatically |
Before Making Changes to the Source Code: git fetch
allows you to see which commits have been made on the remote branch and evaluate the changes before merging them into your local branch.
When Working in a Team: If multiple developers are working on the project, git fetch
helps you stay up-to-date with their work and minimize potential conflicts before integrating changes.
To Retrieve New Branches and Tags: If a new branch or tag has been added to the remote repository, git fetch
will download them without automatically switching to them.
To Get the Latest Changes: In team projects, members regularly make updates. To bring all the latest changes into your local repository, use git pull
.
For Quick Branch Updates: If you need to quickly update your branch without analyzing the changes beforehand, using git pull
is the easiest approach.
Go to the server where Git is installed. Create a new directory to store your files and navigate to it:
mkdir test-git-fetch-pull && cd test-git-fetch-pull
Initialize a new Git repository:
git init
Create a new file and add a line to it:
echo "Test git fetch and pull commands!" > newfile1.txt
Add the file to the staging area:
git add newfile1.txt
Create an initial commit:
git commit -m "Initial commit"
If you see the message:
Author identity unknown
*** Please tell me who you are
You need to set your name and email using:
git config --global user.email "[email protected]"
git config --global user.name "<name>"
Then, repeat the commit command:
git commit -m "Initial commit"
Add the remote repository. Use the command from the main page of your newly created repository on GitHub. For example:
git remote add origin https://github.com/<github-account>/test-git-fetch-pull.git
Push changes to the remote repository:
git push -u origin main
When prompted for Username for 'https://github.com'
, enter your GitHub username. When prompted for Password for 'https://<username>@github.com'
, enter the previously generated token.
Go back to the GitHub web interface and check that the file is present in the repository.
Now, let’s simulate changes in the remote repository.
git fetch origin
Now, check the file content:
cat newfile1.txt
You'll notice that git fetch
downloaded the changes from the remote repository, but the local branch (main
) and the file remained unchanged.
However, the changes can be seen in the remote branch:
git log origin/main
To see exactly what changes were made in the remote repository after running git fetch
, use:
git diff main origin/main
Now, let's pull the changes into the local branch:
git pull origin main
Display the file content again:
cat newfile1.txt
Now, the changes made in the GitHub interface are applied to the local copy of the repository.
When using git pull
, you may encounter conflicts. In Git terminology, a conflict occurs when the system cannot automatically merge changes from two different sources — the local and remote repositories.
To learn how to resolve conflicts, let's go through a practical example. We'll simulate the following situation:
future-file1.txt
.main
).mkdir git-conflicts && cd git-conflicts
Initialize the Git repository:
git init
Create a new file:
touch future-file1.txt
echo "First message" > future-file1.txt
git add future-file1.txt
git commit -m "Initial commit"
git remote add origin https://github.com/<github-account>/git-conflicts.git
git push -u origin main
You'll be prompted to enter your GitHub username and personal access token.
Now, let's simulate the scenario from the perspective of the second developer (Developer 2). On another machine or in a new directory on the same server, run:
git clone https://github.com/<github-account>/git-conflicts.git
At this point, both developers have an up-to-date copy of the repository.
Switch back to the local repository used by Developer 1:
Add a new line by overwriting the content of future-file1.txt
:
echo "Second message" > future-file1.txt
Stage the changes:
git add future-file1.txt
Commit the changes:
git commit -m "Second commit"
Push changes to the remote repository:
git push origin main
At this point, Developer 1's changes are in the remote repository. However, Developer 2 still has the old version of future-file1.txt
.
echo "Third message" > future-file1.txt
git add future-file1.txt
git commit -m "Third commit"
git pull origin main
As you can see, Git has detected a conflict:
When viewing the file, you will notice a conflict block in the file, marking the conflicting changes.
To resolve the conflict, you need to delete the lines starting with <<<<<<<
and ending with >>>>>>>
. Then, you can decide whether to keep only the local changes or to retain the old ones and add the new ones.
As an example, let's keep the changes from both developers:
After editing the file, stage it again:
git add future-file1.txt
Commit the resolved conflict:
git commit -m "Resolved conflict"
Push the changes to the remote repository:
git push origin main
You will need to enter your username and token to push the changes.
Go to the GitHub interface and verify the result.
The git fetch
and git pull
commands are used to retrieve the latest changes from a remote repository into your local repository, but they do so differently.
git fetch
allows you to safely fetch updates and analyze the changes made by others without affecting your current working copy. This is especially useful for avoiding unexpected conflicts, as no changes are applied automatically.
git pull
fetches the data and immediately merges it into the local repository. This process requires caution. If conflicts occur, you will need to resolve them manually.
The choice between these commands depends on your goals:
git fetch
.git pull
, but be aware of the possible conflicts.