Git-Mastery: Lessons

T3L3. Downloading Data Into a Local Repo


When there are new changes in the remote, you need to pull those changes down to your local repo.

This lesson covers that part.

There are two steps to bringing over changes from a remote repository into a local repository: fetch and merge.

  • Fetch is the act of downloading the latest changes from the remote repository, but without applying them to your current branch yet. It updates metadata in your repo so that it knows what has changed in the remote repo, but your own local branch remains untouched.
  • Merge is what you do after fetching, to actually incorporate the fetched changes into your local branch. It combines your local branch with the changes from the corresponding branch from the remote repo.
HANDS-ON: Fetch and merge from a remote

Scenario You have cloned a remote repo. After you have cloned, two new commits have been added to it. R and L1 in the diagram below represents this scenario.

gitGraph BT:
    %%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
    commit id: "add loans.txt"
    commit id: "add loan to Ben"
    commit id: "add assets.txt"
    commit id: "add goals.txt"
    commit id: "[head → master] add loan to Chang"

[R: Remote repo origin]

gitGraph BT:
    %%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
    commit id: "add loans.txt"
    commit id: "add loan to Ben"
    commit id: "[head → master][origin/master] add assets.txt"

[L1: Local repo -- currently,
2 commits behind the remote]

gitGraph BT:
    %%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
    commit id: "add loans.txt"
    commit id: "add loan to Ben"
    commit id: "add assets.txt"
    commit id: "add goals.txt"
    commit id: "[head → master][origin/master] add loan to Chang"

[L2: Local repo -- after downloading
the missing commits]

Target Now, you wish to bring over those missing commits to your clone, taking it from the state L1 to state L2 (as given in the diagram above).

Preparation To create the initial state of the remote repo and the local repo (i.e., R and L1 given above), you can use the following steps.

  1. Clone the repo git-mastery/samplerepo-finances. It has 3 commits. Your clone now has a remote origin pointing to the remote repo you cloned from.
  2. Change the remote origin to point to samplerepo-finances-2. This remote repo is a copy of the one you cloned, but it has two extra commits.
CLI
git remote set-url origin https://github.com/git-mastery/samplerepo-finances-2.git
Sourcetree

Go to RepositoryRepository settings ... to update remotes.

1 Verify the local repo is unaware of the extra commits in the remote.

CLI
git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean
Sourcetree

The revision graph should look like the below:

If it looks like the below, it is possible that Sourcetree is auto-fetching data from the repo periodically.

2 Fetch from the new remote.

CLI

Use the git fetch <remote> command to fetch changes from a remote. If the <remote> is not specified, the default remote origin will be used.

git fetch origin
remote: Enumerating objects: 8, done.
... # more output ...
   afbe966..cc6a151  master     -> origin/master
 * [new tag]         beta       -> beta
Sourcetree

Click on the Fetch button on the top menu:

Sourcetree top menu

3 Verify the fetch worked i.e., the local repo is now aware of the two missing commits. Also observe how the local branch ref of the master branch, the staging area, and the working directory remain unchanged after the fetch.

CLI

Use the git status command to confirm the repo now knows that it is behind the remote repo.

git status
On branch master
Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)

nothing to commit, working tree clean
Sourcetree

Now, the revision graph should look something like the below. Note how the origin/master ref is now two commits ahead of the master ref.

4 Merge the fetched changes.

CLI

Use the git merge <remote-tracking-branch> command to merge the fetched changes. Check the status and the revision graph to verify that the branch tip has now moved by two more commits.

git merge origin/master

git status
git log --oneline --decorate
Sourcetree

To merge the fetched changes, right-click on the latest commit on origin/remote branch and choose Merge.

In the next dialog, choose as follows:

The final result should be something like the below (same as the repo state before we started this hands-on practical):

Note that merging the fetched changes can get complicated if there are multiple branches or the commits in the local repo conflict with commits in the remote repo. We will address them when we learn more about Git branches, in a later lesson.

done!

Pull is a shortcut that combines fetch and merge — it fetches the latest changes from the remote and immediately merges them into your current branch. In practice, Git users typically use the pull instead of the fetch-then-merge.

pull = fetch + merge

HANDS-ON: Pull from a remote

Scenario Same as previous hands-on practical.

Target Same as the previous, but this time we intend to fetch and merge in one step.

Preparation Same as previous, but use a different folder.

1 Pull the newer commits from the remote, instead of a fetch-then-merge.

CLI

Use the git pull <remote> <branch> command to pull changes.

git pull origin master

The following works too. If the <remote> and <branch> are not specified, Git will pull to the current branch from the remote branch it is tracking.

git pull
Sourcetree

Click on the Pull button on the top menu:

Sourcetree top menu

In the next dialog, choose as follows:

2 Verify the outcome is same as the fetch + merge steps you did in the previous hands-on practical.

done!

You can pull from any number of remote repos, provided the repos involved have a shared history. This can be useful when the upstream repo you forked from has some new commits that you wish to bring over to your copies of the repo (i.e., your fork and your local repo).

HANDS-ON: Sync your repos with the upstream repo

Scenario You have forked and cloned a remote repo. Since then, new commits have been added to the original remote repo.

gitGraph BT:
    %%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
    commit id: "add loans.txt"
    commit id: "add loan to Ben"
    commit id: "add assets.txt"
    commit id: "add goals.txt"
    commit id: "[head → master] add loan to Chang"

[R: the original remote repo]

gitGraph BT:
    %%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
    commit id: "add loans.txt"
    commit id: "add loan to Ben"
    commit id: "[head → master] add assets.txt"

[F: your fork (remote),
2 commits behind the remote]

gitGraph BT:
    %%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'master'}} }%%
    commit id: "add loans.txt"
    commit id: "add loan to Ben"
    commit id: "[head → master][origin/master] add assets.txt"

[C: your clone (local), also
2 commits behind]

Target Now, you wish to bring over new commits to your clone, and also update your fork with those commits.

Preparation You can use the following steps to create the initial state of the three repos mentioned above:

  1. Fork the repo git-mastery/samplerepo-finances to your account.
  2. Clone that fork to your computer.

1 Add the upstream repo git-mastery/samplerepo-finances-2 as remote named upstream in your local repo.

2 Pull from the upstream repo. If there are new commits, those will come over to your local repo. For example:

git pull upstream master

3 Push to your fork. Any new commits you pulled from the upstream repo will now appear in your fork as well. For example:

git push origin master

The method given above is the more 'standard' method of synchronising a fork with the upstream repo. In addition, platforms such as GitHub can provide other ways (example: GitHub's Sync fork feature).

done!

EXERCISE: fetch-and-pull

DETOUR: Pulling from Multiple Remotes

You can pull from any number of repos, provided the repos involved have a shared history.

  1. Add the GitHub repo URL as a remote while giving a suitable name (e.g., upstream, central, production, backup ...), if you haven't done so already.
  2. Pull (or fetch) from the remote repo -- remember to select the correct remote repo when you do.
CLI

e.g., git pull backup master

Sourcetree

Similar to before, but remember to choose the intended remote to pull from.