When to fork a Git repo and how to keep them in-sync
Our team at finnovate.io works on many different products, some of which are based on other products with a few modifications. For example, when we were tasked to deploy a platform we developed for North America in the Europe, we had to make a number feature adjustments just for Europe while keeping the core platform unchanged.
We found that creating a fork of the original Git repository was the best solution because:
- We needed to apply changes to an existing code base without affecting the original repository
- Two different teams are working on the two product variants
- The two product variants required different continuous integration processes with different build steps and targets
A forked repository worked great, but a couple of challenges were immediately apparent:
- How do we keep the forked repository in-sync with patches that are applied in the original repository?
- How do we commit changes that are mutually beneficial from the forked repository back to the original repository?
Creating a fork
Creating a fork is easy. Whether you are working with GitHub, BitBucket or another Git service provider, it’s the same process. You click on the fork button.
This creates a forked copy of the repository.
Going forward, we will call the original repository that we forked from the “upstream” and we will call the forked copy the “origin”.
Cloning the origin
To start writing code to our “origin”, we first need to clone it onto our local computers:
git clone
cd
As usual, this creates an origin remote by default.
Adding an upstream remote
Now we have to attach the upstream repo as a remote so that we can pull changes from it later on:
git remote add upsteam
To verify we have done this correctly, we can enter:
git remote -v
Pulling changes from upstream
Say some changes have been made upstream, and we want these changes to be merged with the code in origin. We can simply:
git pull upstream master
A git pull is the equivalent of a git fetch and git merge executed in that order. Note that this assume we are working off the master branch in origin. If we are work off a development branch, we should first checkout the development branch:
git checkout development
Then pull the upstream development branch into the origin development branch:
git pull upstream development
Now we can resolve conflicts locally if any at all and push the changes into the origin remote:
git push origin HEAD
Push changes upstream via pull requests
Since we only want certain changes from origin to be propagated upstream, we can do so by issuing pull requests (PRs) of selected changes.
You can create a PR from any feature branch in origin targeting a branch upstream.
Once a PR against the upstream repo has been created, it’s up to the team managing the upstream repo to merge or reject the PR.
Finnovate.io is a technology company focused on helping organizations build unique digital experiences on web, mobile and blockchain. Finnovate.io offers development services, training, consulting, as well as a platform that rapidly turns paper based content into digital interactive experiences.
Ветвление репозитория
Вилка — это новый репозиторий, который использует параметры кода и видимости с исходным репозиторием «вышестоящий».
Platform navigation
Tool navigation
About forks
A fork is a new repository that shares code and visibility settings with the original “upstream” repository. Forks are often used to iterate on ideas or changes before they are proposed back to the upstream repository, such as in open source projects or when a user does not have write access to the upstream repository. For more information, see «Working with forks.»
Propose changes to someone else’s project
For example, you can use forks to propose changes related to fixing a bug. Rather than logging an issue for a bug you have found, you can:
- Fork the repository.
- Make the fix.
- Submit a pull request to the project owner.
Use someone else’s project as a starting point for your own idea.
Open source software is based on the idea that by sharing code, we can make better, more reliable software. For more information, see the «About the Open Source Initiative» on the Open Source Initiative.
For more information about applying open source principles to your organization’s development work on GitHub.com, see GitHub’s white paper «An introduction to innersource.»
When creating your public repository from a fork of someone’s project, make sure to include a license file that determines how you want your project to be shared with others. For more information, see «Choose an open source license» at choosealicense.com.
For more information on open source, specifically how to create and grow an open source project, we’ve created Open Source Guides that will help you foster a healthy open source community by recommending best practices for creating and maintaining repositories for your open source project. You can also take a free GitHub Skills course on maintaining open source communities.
Prerequisites
If you haven’t yet, first set up Git and authentication with GitHub.com from Git. For more information, see «Set up Git.»
Forking a repository
You might fork a project to propose changes to the upstream repository. In this case, it’s good practice to regularly sync your fork with the upstream repository. To do this, you’ll need to use Git on the command line. You can practice setting the upstream repository using the same octocat/Spoon-Knife repository you just forked.

- On GitHub.com, navigate to the octocat/Spoon-Knife repository.
- In the top-right corner of the page, click Fork.
Note: If you want to copy additional branches from the upstream repository, you can do so from the Branches page. For more information, see «Creating and deleting branches within your repository.»
To learn more about GitHub CLI, see «About GitHub CLI.»
To create a fork of a repository, use the gh repo fork subcommand.
gh repo fork REPOSITORY
To create the fork in an organization, use the —org flag.
gh repo fork REPOSITORY --org "octo-org"
You can fork a repository on GitHub.com or in GitHub Desktop. For information about forking on GitHub.com, see the web browser version of this article.
In GitHub Desktop, if you attempt to clone a repository that you don’t have write access to, a fork is automatically created for you.



Click the tab that corresponds to the location of the repository you want to clone. You can also click URL to manually enter the repository location.

From the list of repositories, click the repository you want to clone.

To select the local directory into which you want to clone the repository, next to the «Local Path» field, click Choose. and navigate to the directory.
- If you plan to use this fork for contributing to the original upstream repository, click To contribute to the parent project.
- If you plan to use this fork for a project not connected to the upstream, click For my own purposes.
Cloning your forked repository
Right now, you have a fork of the Spoon-Knife repository, but you do not have the files in that repository locally on your computer.
- On GitHub.com, navigate to your fork of the Spoon-Knife repository.
- Above the list of files, click

Code.
-
To clone the repository using HTTPS, under «HTTPS», click

.
git clone https://github.com/YOUR-USERNAME/Spoon-Knife
$ git clone https://github.com/YOUR-USERNAME/Spoon-Knife > Cloning into `Spoon-Knife`. > remote: Counting objects: 10, done. > remote: Compressing objects: 100% (8/8), done. > remote: Total 10 (delta 1), reused 10 (delta 1) > Unpacking objects: 100% (10/10), done.
To learn more about GitHub CLI, see «About GitHub CLI.»
To create a clone of your fork, use the —clone flag.
gh repo fork REPOSITORY --clone=true



Click the tab that corresponds to the location of the repository you want to clone. You can also click URL to manually enter the repository location.

From the list of repositories, click the repository you want to clone.

To select the local directory into which you want to clone the repository, next to the «Local Path» field, click Choose. and navigate to the directory.
Configuring Git to sync your fork with the upstream repository
When you fork a project in order to propose changes to the upstream repository, you can configure Git to pull changes from the upstream repository into the local clone of your fork.
- On GitHub.com, navigate to the octocat/Spoon-Knife repository.
- Above the list of files, click

Code.
-
To clone the repository using HTTPS, under «HTTPS», click

.
- To go to your home directory, type just cd with no other text.
- To list the files and folders in your current directory, type ls .
- To go into one of your listed directories, type cd your_listed_directory .
- To go up one directory, type cd .. .
$ git remote -v > origin https://github.com/YOUR_USERNAME/YOUR_FORK.git (fetch) > origin https://github.com/YOUR_USERNAME/YOUR_FORK.git (push)
git remote add upstream https://github.com/ORIGINAL_OWNER/Spoon-Knife.git
$ git remote -v > origin https://github.com/YOUR_USERNAME/YOUR_FORK.git (fetch) > origin https://github.com/YOUR_USERNAME/YOUR_FORK.git (push) > upstream https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git (fetch) > upstream https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git (push)
Now, you can keep your fork synced with the upstream repository with a few Git commands. For more information, see «Syncing a fork.»
To learn more about GitHub CLI, see «About GitHub CLI.»
To configure a remote repository for the forked repository, use the —remote flag.
gh repo fork REPOSITORY --remote=true
To specify the remote repository’s name, use the —remote-name flag.
gh repo fork REPOSITORY --remote-name "main-remote-repo"
Editing a fork
You can make any changes to a fork, including:
- Creating branches:Branches allow you to build new features or test out ideas without putting your main project at risk.
- Opening pull requests: If you want to contribute back to the upstream repository, you can send a request to the original author to pull your fork into their repository by submitting a pull request.
Find another repository to fork
Fork a repository to start contributing to a project. You can fork any public repository to your personal account, or to an organization where you have permission to create repositories. If you have access to a private repository and the owner permits forking, you can fork the repository to your personal account, or to an organization on GitHub Team where you have permission to create repositories. You cannot fork a private repository to an organization using GitHub Free. For more information about GitHub Team and GitHub Free, see «GitHub’s plans.» For more information about when you can fork a repository, see «About permissions and visibility of forks.»
You can browse Explore GitHub to find projects and start contributing to open source repositories. For more information, see «Finding ways to contribute to open source on GitHub.»
Next Steps
You have now forked a repository, practiced cloning your fork, and configured an upstream repository.
- For more information about cloning the fork and syncing the changes in a forked repository from your computer, see «Set up Git.»
- You can also create a new repository where you can put all your projects and share the code on GitHub. Creating a repository for your project allows you to store code in GitHub. This provides a backup of your work that you can choose to share with other developers. For more information, see “Create a repository.»»
- Each repository on GitHub is owned by a person or an organization. You can interact with the people, repositories, and organizations by connecting and following them on GitHub. For more information, see «Be social.»
- GitHub has a great support community where you can ask for help and talk to people from around the world. Join the conversation on GitHub Community.
Fork and Clone from GitHub AS
This approach assumes a basic familiarity with git and GitHub. As with most things related to git there are many different ways to satisfy any objective. This documentation describes one method for Windows users. Users not comfortable with command line tools and git should obtain the SDK via Downloading the SDK as a zip archive .
Forks vs. Clones
A Fork on GitHub is a copy of another repository on GitHub from one account to another account. The new forked repository retains a parent-child relationship with the origin repository. Forks are typically used when software will have an independent line of development, such as when FTC teams develop their own team code using the FIRST-Tech-Challenge/FtcRobotController repository as a basis. FTC teams should create a Fork of the FIRST-Tech-Challenge/FtcRobotController repository as a convenient way to manage their software development process. Thanks to the parent-child relationship, when changes are made to the parent repository those changes can be easily tracked and fetched/merged into the forked repository, keeping the forked repository up to date.
Teams should not issue pull requests against the upstream parent, the FIRST-Tech-Challenge/FtcRobotContoller repository. Forks of the FIRST-Tech-Challenge/FtcRobotContoller repo may always fetch changes, but should never attempt to push changes up to the repo.
A Clone is a copy of a repository, typically on a local computer. A team member creates a feature branch of the team’s repository for feature development, and clones the branch to a local computer. Software development and testing then happens completely within their local clone. Once they’re finished, or they’ve reached a checkpoint, the changes within the local clone can then be pushed from their local clone back to the team fork. That feature branch can then be merged into the team’s main repository branch once it has been accepted by the team. Multiple different developers can work seamlessly using this process.

Branch Strategies
A branch is a series of commits that are independent of any other lines of development and is typically used to develop new features for the repository. The default branch for the FtcRobotController repository, and its forks and clones, is master (though for all newer repositories created by GitHub the default branch is called main). Using branches judiciously can help developers collaborate on a common set of software by isolating changes, keeping the default branch clean, and providing space for feature development to iterate independent of software that’s been deemed ‘production ready’.

Each circle represents a commit to a branch. The name of the branch always points to the most recent commit, also known as the HEAD. While there may be many branches there is only one HEAD and it always, unless it is in a detached state, points to the latest commit of the currently checked out branch. All other commits point to their immediate parent.
A commit is a snapshot of the entire workspace at a point in time. Git does not store diffs. If you make a change to a file, and create a new commit with the changed file, it stores the entire changed file in the commit. To avoid unnecessary duplication of files, if your repository consists of three files — one changed and the other two were unchanged — then the snapshot merely points back to the unchanged files rather than containing unchanged data.
Note that each commit has a parent which allows git to determine reachability of commits from different branches. It also allows git to determine the common ancestor commit of any two branches, which is important when merging branches. More on that later.
So what is a branch? A branch is simply a named pointer to a commit. When a branch is created you are just telling git to create a name, and point it at a commit. Being on a branch simply means that when you add a new commit, git moves the branch name to the new commit and the new commit’s parent is the commit that the branch name was pointing to previously. Since this creates a line of development independent of the parent, developers can experiment, make changes, develop new features, all without disrupting the work of other team members. When a developer is satisfied that a branch is stable enough to be shared, the branch can be merged back into the parent.

Immediately after creating a branch the new branch name simply points to the latest commit from the branch that the new branch was created from. Now imagine that we create a new commit on that branch.

Note how the new commit caused the name pointer of the feature branch to move to the new commit, while the name pointer for the master branch remains on the prior commit, but the parent of the new commit is the commit that the name pointer for master points to. If a new commit is added to the master branch then the parent of the new commit is also the commit that master is pointing to thereby creating independent lines of development.

Eventually you typically want to merge that feature branch back into the main line of development represented by the master branch. When you merge one branch into another, git traverses the ancestor commits of the branches to find the common ancestor. It then determines what changed from the common ancestor, to the head of each branch, and applies those changes to a new commit called a merge commit. An artifact of this process is that the merge commit will have two parents.

As shown above, the feature branch still exists. New commits added to the feature branch will diverge again from the master branch. However if development of the feature is finished, the branch can be deleted. Deletion of the branch simply results in the name pointer being deleted. Branch deletion does not result in the deletion of any commits that were made on that branch. As you can see here, the commit that was on the feature branch still exists and is reachable by referencing the correct parent from the merge branch.
It can be useful to ensure that the default branch in team forks and clones matches the default branch for FIRST-Tech-Challenge/FtcRobotController. However a typical development pattern will have team developers committing team software back to the master branch, whether via merges from feature branches, or direct commits to master.
Team commits are represented by blue circles, while commits containing SDK updates are represented by green circles. The purple circle is a merge commit. More on merges later. In this instance team commits are interleaved with SDK updates (1), which produces a situation where the two default branches do not match.
(1) Not really, or maybe depending upon how the commit parentage lays out. This is a vastly simplified view of things, but is sufficient to demonstrate the logical concept and is the view of things you get if you simply execute git log. For an in-depth, approachable, explanation of exactly what is happening with commits as they relate to branches see this tutorial.
While this is a perfectly acceptable, and a very common branch management strategy, certain benefits can be obtained if we isolate the default branch so that it always matches the parent. The following figure demonstrates a clone whose master branch is tracking the master branch from FIRST-Tech-Challenge/FtcRobotController.
The purple commit is a merge of v7.1 into the competition branch. In this diagram, v7.2 and v8.0 remain unmerged and the competition branch will be building against v7.1 of the SDK.
Following this model means that commit history for the master branch for the team’s repository will always match the commit history for the FIRST-Tech-Challenge/FtcRobotController’s master branch. All software that teams intend to compete with is merged into a competition branch. Features, new software, experiments, etc, are worked on in child branches of the competition branch and merge back into the competition branch, not the master branch. SDK updates to a team clone’s master branch should always be conflict free, updates can be done independent of merges into a competition branch, and if something goes sideways when doing a merge of an SDK update into development it can be more straightforward to recover as opposed to backing out of an update straight into master where the branches do not match.
More detailed information on the mechanics of branching can be found here Using Branches
Getting Started (Quick-Start Guide)
The following assumes all operations are done on the master branch of your local repository.
- Obtain and install GitForWindows This software contains a git client along with a bash shell. All of the command line snippets below assume you are using a bash shell and that git is in your path. GitForWindows is the easiest way to provide this for Windows machines. Macs have a built in bash shell called terminal, but git must be installed separately.
- Fork the FIRST-Tech-Challenge/FtcRobotController repository into your account on GitHub.
Tip This step requires you to have a GitHub account, and you need to be logged in to GitHub in order to Fork a repository.

Forking the repository is as easy as clicking the “

Fork” button shown in the image above. This will take you to the “Create a new fork” page, and will auto-fill the “Owner” and “Repository name” fields. Just enter a description (optional), leave the “Copy the master branch only” option checked, and click the green “Create fork” button. Once created, your new fork will be located at github.com//FtcRobotController unless you edited the fork name.
Clone from your fork onto your local computer. Note in the image below the account is FIRST-Tech-Challenge, but after your fork, the account should be your team account. In all other respects the user interface will be identical. To clone your fork of the FtcRobotController, follow these steps:
-
Click the green “
git clone
git checkout -b
Best Practices
- Do not make changes to software in the FtcRobotController directory within the repository. SDK updates will be much easier if you do not change anything within the FtcRobotController directory.
- Limit the use of long-lived branches. Branches should implement a feature. Branches should not track milestones. For example a branch named ‘league-meet-1’ is tracking a milestone. It is much better if your branches track smaller units of development. ‘detect-target’, ‘drive-to-parking’, ‘drop-game-element’. Break your software down into tasks for the robot to do, and use branches to implement those tasks. This will allow for much easier collaborative development, much smaller change sets when merging, and much easier fetches and merges.
- Try to keep your git index clean. This will make fetches and merges easier. git status is your best friend here. Use git status often to see what has changed in your local workspace. Commit often in logical chunks so that it is easy to see the most recent changes.
- Use short, meaningful, commit messages. Do not use slang, offensive, or personal messaging in a commit message. When you push your software to GitHub, those commit messages will be public. If you plan to eventually become a professional software developer, and you retain your existing GitHub account any potential employer will be able to review your commit messages. Tread lightly here.
Updating your Fork and Local Clone.
Updating the SDK involves pulling newly released software into both your local clone’s and your fork. There are two ways to go about this. Either directly fetch and merge software from the parent into your fork on github, then fetch and merge to your local, or fetch from the parent into your local clone, merge locally and then push to your fork.
This author prefers the latter because it gives the developer the opportunity test new software before pushing to the fork. It also allows for merge conflict resolution locally instead of through GitHub’s UI.
Obtaining the Latest Software
When describing how to update a repository many basic tutorials will use the git pull command. The git pull command is actually doing a fetch and merge for the user behind the scenes. This can be fine, but it is useful to understand the concepts of fetching and merging as independent operations. If things go south, and you have a good concept of the underlying mechanics, you are much more likely to be able to fix any subsequent problems.
Remotes
Git is fundamentally built around the idea that there can be many copies of a repository floating about on the internet, or other people’s machines, or corporate file servers, or any number of locations. And that these repositories can linked to each other remotely. A remote repository is simply defined as a version of a repository hosted somewhere else. In the preceding examples, your fork of FtcRobotController is a remote of your local clone.
Remotes may be referenced in git commands and a repository can have any number of remotes. The default name for the remote of a repository that has been cloned is ‘origin’. The conventional name of a remote that tracks the parent of a fork is ‘upstream’.
To see what remote are established for a given repository
$ git remote -v
How to Update Fork Repo From Original Repo
Something we don’t do daily, but it’s handy when we need it
Published in
Level Up Coding
2 min read
Jun 30, 2020
Y ou have forked a repository. After a while, your forked repository is outdated. How do you sync it up?
Update the master branch
1. Clone your fork repository locally
git clone
2. Set the original repo as your upstream repo
git remote add upstream
Note: In case you don’t know what the origin repo is, you can git to the origin repo folder and type git remote -v
3. Update your local Master to be in synch with the original repo
Assuming if your forked repo master was not altered at all, then you can do the below
git pull upstream master
If you have altered it, you then need to rebase it.
git rebase upstream/master
and resolve the conflict if any.
4. Update the forked repo master by pushing the local repo up
If everything is updated accordingly without rebase, you can then push up as below.
git push origin master
If you have rebased it, then you’ll need to force push it
git push -f origin master
Move some branches over
In case you are interested to bring some of the new branch over from the original repo as well. You can do the following (assuming after you have done the above syncing the master branch etc)
1. Fetch from the original repo
git fetch upstream
2. Pull the branch from the original repo
git checkout
3. Push the branch from local to forked repo
git push origin
Repeat steps 2 and 3 above for all the branches of interest.
Hopes this little process helps your fork repo sync work. In case more reference is needed, check out the official fee documentation