Make a private fork of a public git repository

GitHub currently only allows the creation of public forks. However, it is possible to sync code between a public repository and a private mirror.

This post is a modified version of a Stack Overflow answer.


First, let’s define the locations of the public repo, and the corresponding private mirror, which we will create below.

repo_name="basejump"
public_user="steinbaugh"
private_user="mjsteinbaugh"
# Use SSH instead of HTTPS, if possible.
# Alternate: `https://github.com/`.
git_url="git@github.com:"

We recommend creating a branch other than master in the public repo that will be the destination for commit merges from the private repo. In general, develop works well for this purpose.

# Use a branch other than master for commits.
branch="develop"

Now we’re ready to define and clone the repos from GitHub. First, create a corresponding private repo in your user account using the new repo UI. In our example here, the name should be basejump-private.

public_name="$repo_name"
private_name="${public_name}-private"
public_repo="${git_url}${public_user}/${public_name}.git"
private_repo="${git_url}${private_user}/${private_name}.git"

Clone (mirror) the existing public repo into our newly created private repo on GitHub. Note that this won’t affect anything in the existing public one.

git clone --bare "$public_repo"
cd "${public_name}.git"
git push --mirror "$private_repo"
cd ..
# Safe to remove the bare clone.
rm -rf "${public_name}.git"

Clone local copies of both the public and private repos.

git clone "$public_repo"
git clone "$private_repo"

Ensure we switch away from the master branch in our new private repo.

cd "$private_name"
# Switch away from master branch.
git checkout -b "$branch"
git branch --set-upstream-to="origin/${branch}" "$branch"
git remote add "public" "$public_repo"
cd ..

Set up remotes to the private repo in the public repo, so we can push. We’re switching to the corresponding branch (e.g. “develop” here).

cd "$public_name"
git remote -v
git remote add "$private_name" "$private_repo"
git remote -v
cd ..

Here’s how to make a pull request from the private repo back to the public one. Then simply make a pull request from the branch (e.g. develop) back to master.

cd "$public_name"
git pull "$private_name" "$branch"
git push origin "$branch"
cd ..