Target Usage: To work with an existing remote repository.
Motivation: You will often need to start with an existing remote repository. You may need to create your own copies and keep them updated when the upstream repository changes.
Lesson plan:
T3L1. Duplicating a Remote Repo on the Cloud covers that part.
T3L2. Creating a Local Copy of a Repo covers that part.
T3L3. Downloading Data Into a Local Repo covers that part.
GitHub allows you to create your own remote copy of another repo through a process called forking.
A fork is a copy of a remote repository created on the same hosting service, such as GitHub, GitLab, or Bitbucket. On GitHub, you can fork a repository owned by another user or organization into your own space, such as your account or an organization where you have the required access. Forking is useful when you want to experiment with a repo but don't have write permissions to the original; it gives you your own remote copy without affecting the original repo.
Preparation Create a GitHub account if you don't have one yet.
1 Go to the GitHub repo you want to fork, e.g., samplerepo-things
2 Click the
button in the top-right corner. On the next screen:
- choose your own account or a GitHub organization where you are an admin.
- uncheck the
[ ] Copy the main branch onlyoption, so that you get copies of other branches (if any) in the repo. You'll learn more about branches in a later lesson.
done!
Forking is not a Git feature, but a feature provided by hosted Git services like GitHub, GitLab, or Bitbucket.
GitHub does not allow you to fork the same repo more than once to the same destination. If you want to re-fork, you need to delete the previous fork.
The next step is to create a local copy of the remote repo by cloning it.
You can clone a repository to create a local copy on your computer. A normal clone downloads the repository history and populates the working directory with the files from the latest commit of the default branch, giving you a local working copy.
Cloning a repo automatically creates a remote named origin, which points to the repo you cloned from.
Conventions:
When configuring remotes for a Git repository, the following naming conventions are commonly used:
origin: The repository that you cloned from is usually given the remote nameorigin. Git sets this remote name automatically when you clone a repository (but you can change it to something else).upstream: In fork-based workflows, the repository you forked from is often added as a second remote namedupstream. This name is not created by Git automatically; it is a convention chosen by developers. Some teams use a more specific name for this, such asteam-repo.
Separately from remote names, the term 'upstream' is also used informally to describe the relationship between an original repository and its duplicates. When one repository is created by duplicating another (for example, by forking or cloning), the original repository is said to be upstream of the duplicate.
Example:
- If you fork R1 to create R2, then R1 is upstream of R2.
- If you then clone R2 to create R3, both R1 and R2 are upstream of R3.

1 Clone the remote repo to your computer. For example, you can clone the samplerepo-things repo, or the fork you created from it in a previous lesson.
Note that the GitHub project page URL is different from the repo URL you need for cloning. For example:
https://github.com/git-mastery/samplerepo-things # GitHub project URL
https://github.com/git-mastery/samplerepo-things.git # the repo URL
You can use the git clone <repository-url> [directory-name] command to clone a repo.
<repository-url>: The URL of the remote repository you want to copy.[directory-name](optional): The name of the folder where you want the repository to be cloned. If you omit this, Git will create a folder with the same name as the repository.
git clone https://github.com/git-mastery/samplerepo-things.git # if using HTTPS
git clone git@github.com:git-mastery/samplerepo-things.git # if using SSH
git clone https://github.com/foo/bar.git my-bar-copy # also specifies a dir to use
For exact steps, see this GitHub document.
File → Clone / New ... and provide the URL of the repo and the destination directory.
File → New ... → Choose as shown below → Provide the URL of the repo and the destination directory in the next dialog.


2 Verify the clone has a remote named origin pointing to the repo you cloned from.
Use the git remote -v command that you learned earlier.
Choose the Repository → Repository Settings menu option.
done!
When there are new commits in the remote repo, you need to pull those commits down to your local repo.
Bringing changes from a remote repository into a local repository involves two steps: 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 Git knows what has changed in the remote repo, but your own local branch remains untouched.
- Merge is the step after fetching that incorporates the fetched changes into your local branch. It combines your local branch with the changes from the corresponding branch in the remote repo.
Scenario You have cloned a remote repo. After you cloned it, two new commits were added to the remote. R and L1 in the diagram below represent this scenario.
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'main'}} }%%
commit id: "add loans.txt"
commit id: "add loan to Ben"
commit id: "add assets.txt"
commit id: "add goals.txt"
commit id: "[HEAD → main] add loan to Chang"
origin]
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'main'}} }%%
commit id: "add loans.txt"
commit id: "add loan to Ben"
commit id: "[HEAD → main][origin/main] add assets.txt"
2 commits behind the remote]
→
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'main'}} }%%
commit id: "add loans.txt"
commit id: "add loan to Ben"
commit id: "add assets.txt"
commit id: "add goals.txt"
commit id: "[HEAD → main][origin/main] add loan to Chang"
the missing commits]
Target Now, you want to bring those missing commits into your clone, taking it from state L1 to state L2 (as shown in the diagram above).
Preparation
Option 1: Create a fresh sandbox using the Git-Mastery app
- i.Navigate inside the
gitmastery-exercisesfolder. - ii.Run the
gitmastery download hp-fetch-mergecommand.
The sandbox will be set up inside the gitmastery-exercises/hp-fetch-merge folder.
Option 2: Manually set up a sandbox
To create the initial remote and local states (R and L1 above), use these steps.
- Clone the repo git-mastery/samplerepo-finances. It has 3 commits. Your clone now has a remote
originpointing to the remote repo you cloned from. - Change the remote
originto point to samplerepo-finances-2. This remote repo is a copy of the one you cloned, but it has two extra commits.
git remote set-url origin https://github.com/git-mastery/samplerepo-finances-2.git
Go to Repository → Repository settings ... to update remotes.
1 Verify Git has not yet learned about the extra commits in the remote.
git status
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
The revision graph should look like this:
If it looks like the image below, Sourcetree may be auto-fetching data from the repo periodically.

2 Fetch from the new remote.
Use the git fetch <remote> command to fetch changes from a remote. If you do not specify <remote>, Git uses the default remote origin.
git fetch origin
remote: Enumerating objects: 8, done.
... # more output ...
afbe966..b201f03 main -> origin/main
Click on the Fetch button on the top menu:

3 Verify the fetch worked: the local repo is now aware of the two missing commits. Also observe that the local main branch ref, the staging area, and the working directory remain unchanged after the fetch.
Use the git status command to confirm the local repo now knows it is behind the remote repo.
git status
On branch main
Your branch is behind 'origin/main' by 2 commits, and can be fast-forwarded.
(use "git pull" to update your local branch)
nothing to commit, working tree clean
Now, the revision graph should look something like this. Note how the origin/main ref is now two commits ahead of the main ref.

4 Merge the fetched changes.
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/main
Updating afbe966..b201f03
Fast-forward
goals.txt | 1 +
loans.txt | 1 +
2 files changed, 2 insertions(+)
create mode 100644 goals.txt
Verify the status of the repo is as expected:
git status
On branch main
Your branch is up to date with 'origin/main'.
git log --oneline --decorate
b201f03 (HEAD -> main, origin/main, origin/HEAD) Add loan to Chang
1b923a4 Add goals.txt
afbe966 Add assets.txt
0434002 Add loan to Ben
fd96227 Add loans.txt
To merge the fetched changes, right-click on the latest commit on the origin/main branch and choose Merge.
In the next dialog, choose as follows:

The final result should look something like this, matching state L2 in the diagram above:

Note that merging fetched changes can get complicated when the repo has multiple branches, or when local commits conflict with remote commits. We will address such situations in a later lesson when we learn more about Git branches.
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 usually pull instead of fetching and merging separately.
pull = fetch + merge
Scenario Use the same scenario as the previous hands-on practical.
Target Use the same target as in the previous hands-on practical, but fetch and merge in one step.
Preparation
Option 1: Create a fresh sandbox using the Git-Mastery app
- i.Navigate inside the
gitmastery-exercisesfolder. - ii.Run the
gitmastery download hp-pull-remotecommand.
The sandbox will be set up inside the gitmastery-exercises/hp-pull-remote folder.
Option 2: Manually set up a sandbox
Set up the same scenario as in the previous hands-on practical, but use a different local folder.
1 Pull the newer commits from the remote instead of fetching and merging separately.
Use the git pull <remote> <branch> command to pull changes.
git pull origin main
remote: Enumerating objects: 8, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 6 (delta 1), reused 6 (delta 1), pack-reused 0 (from 0)
Unpacking objects: 100% (6/6), 557 bytes | 69.00 KiB/s, done.
From https://github.com/git-mastery/samplerepo-finances-2
* branch main -> FETCH_HEAD
afbe966..b201f03 main -> origin/main
Updating afbe966..b201f03
Fast-forward
goals.txt | 1 +
loans.txt | 1 +
2 files changed, 2 insertions(+)
create mode 100644 goals.txt
The following command also works. If you do not specify <remote> and <branch>, Git will pull into the current branch from the remote branch it tracks.
git pull
Click on the Pull button on the top menu:


2 Verify that the outcome matches the fetch + merge steps you did in the previous hands-on practical.
done!
You can pull from multiple remote repos, as long as the repos have a shared history. This is useful when the upstream repo you forked from has new commits that you want to bring into your fork and local repo.
Scenario You have forked and cloned a remote repo. Since then, new commits have been added to the original remote repo that you forked from.
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'main'}} }%%
commit id: "add loans.txt"
commit id: "add loan to Ben"
commit id: "add assets.txt"
commit id: "add goals.txt"
commit id: "[HEAD → main] add loan to Chang"
upstream: the original remote repo
that you forked]
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'main'}} }%%
commit id: "add loans.txt"
commit id: "add loan to Ben"
commit id: "[HEAD → main] add assets.txt"
origin: your fork (remote),
2 commits behind upstream]
gitGraph BT:
%%{init: { 'theme': 'default', 'gitGraph': {'mainBranchName': 'main'}} }%%
commit id: "add loans.txt"
commit id: "add loan to Ben"
commit id: "[HEAD → main][origin/main] add assets.txt"
2 commits behind]
Target Now, you want to bring the new commits into your clone and then update your fork with them.
Preparation
Create a fresh sandbox using the Git-Mastery app
- i.Navigate inside the
gitmastery-exercisesfolder. - ii.Run the
gitmastery download hp-sync-upstreamcommand.
The sandbox will be set up inside the gitmastery-exercises/hp-sync-upstream folder.
1 Confirm your local repo is behind upstream by two commits. Here are two ways to do that:
a) Go to the upstream repo at https://github.com/git-mastery/samplerepo-finances-2, and navigate to the repo's commit list. Compare that list with the commits in your local copy.
OR
b) Do a fetch and examine the revision graph locally, as shown below.
git fetch upstream
git log --oneline --decorate --graph --all
* b201f03 (upstream/main, upstream/HEAD) Add loan to Chang
* 1b923a4 Add goals.txt
* afbe966 (HEAD -> main, origin/main, origin/HEAD) Add assets.txt
* 0434002 Add loan to Ben
* fd96227 Add loans.txt
2 Pull from the upstream repo. Git will bring any new commits into your local repo. For example:
git pull upstream main
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 main
This method is the standard way to synchronize a fork with the upstream repo. Platforms such as GitHub also provide alternatives, including GitHub's Sync fork feature.
done!
SIDEBAR: Distributed vs Centralized Revision Control
Revision control can follow either a centralized or a distributed model.
Centralized RCS uses a single central (server-hosted) repository that is shared by the team. Developers check out a working copy, make changes locally, and then commit directly to the central repository. Developers do not have their own copy of the entire repository history; they only have a working copy of files. One advantage of this model is having one clear "source of truth." A major disadvantage is that the central server becomes a critical dependency: if it's down, most operations (commits and history queries beyond the local working copy) are blocked. Older RCS tools such as CVS, Subversion, and Perforce follow this model.

The centralized RCS approach
Distributed RCS (also known as decentralized RCS) allows multiple remote and local repositories to work together. Workflows vary by team. For example, each team member can have their own remote repository in addition to a local repository. This architecture enables offline work, fast local operations, and more flexible workflows. It also supports multiple integration points (e.g., forks or alternative remotes) and uses cryptographic checksums to ensure history integrity. The trade-offs include more conceptual complexity (multiple repositories, remotes, and sync patterns) and the need for conventions to establish an authoritative integration flow. Git and Mercurial are prominent RCS tools that support the distributed approach.

The decentralized RCS approach
Because Git uses multiple copies of a repository, Git is considered a distributed revision control system, as opposed to a centralized revision control system that keeps only a single repository.
DETOUR: Pulling from Multiple Remotes
You can pull from any number of remote repos, as long as the repos have a shared history.
- Add the GitHub repo URL as a remote using a suitable name, such as
upstream,central,production, orbackup, if you haven't done so already. - Pull (or fetch) from that remote, remembering to select the correct remote.
For example, git pull backup main
Similar to before, but remember to choose the intended remote to pull from.
At this point: Now you can create your own remote and local copies of any accessible GitHub repo you are allowed to fork or clone, and update your copy when there are new commits in the upstream repo.
What's next: Tour 4: Using the Revision History of a Repo