Creating a Private Fork of a GitHub Repository

I have found myself forking repositories quite frequently recently for school projects and research, and most of the time I have wanted to keep them private on GitHub. It is not that straightforward, so once I figured out the right way to accomplish it I started honing this post to remind myself of the right steps. Hopefully it helps any one else trying to accomplish the same thing!

Basic Steps

  1. Create a new private repository on Github

  2. Fork the repo (BASE_REPO) to your new private repo (PRIVATE_REPO) as follows:

    BASE_REPO_URL=<BASE>  # remote URL of repo you are forking
    PRIVATE_REPO_URL=<PRIVATE>  # remote URL of your new private fork repo
    # Create a bare clone of the base repo
    git clone --bare $BASE_REPO_URL
    # Mirror-push your bare clone to your new private repo
    cd ${BASE_REPO_URL##*/}
    git push --mirror $PRIVATE_REPO_URL
    # Remove the temporary local repository you created in step 2
    cd ..
    rm -rf ${BASE_REPO_URL##*/}

cd to your preferred workspace, then clone your private fork

git clone $PRIVATE_REPO_URL  # clone the private fork
cd ${${PRIVATE_REPO_URL##*/}%%.git}  # cd into the cloned directory

# add the original repo as remote to fetch (potential) future changes.
git remote add upstream $BASE_REPO_URL

# disable push on the remote (as you are not allowed to push to it anyway).
git remote set-url --push upstream DISABLE
  • You can list all your remotes with git remote -v. You should see:

    origin	<PRIVATE_REPO_URL> (fetch)
    origin	<PRIVATE_REPO_URL> (push)
    upstream	<BASE_REPO_URL> (fetch)
    upstream	DISABLE (push)
  • When you push, do so on origin with git push origin.

  • When you want to pull changes from upstream you can just fetch the remote and rebase on top of your work.

      git fetch upstream
      git rebase upstream/main
Note: ##*/ and %%.git are some bash variable mangling to extract everything after the last / in the URL and before the .git respectively.

Additional information on creating a private fork by duplicating a repo is documented here.