Skip to content

Instantly share code, notes, and snippets.

@ellisbrown
Forked from 0xjac/private_fork.md
Last active September 22, 2022 02:16
Show Gist options
  • Save ellisbrown/b880f46c25af40be0b0f0bd280ca7155 to your computer and use it in GitHub Desktop.
Save ellisbrown/b880f46c25af40be0b0f0bd280ca7155 to your computer and use it in GitHub Desktop.
Create a private fork of a public repository

Creating a Private Fork of a GitHub Repository

Basic Steps

  1. Create a new private repository on Github

  2. Fork the repo (BASE_REPO_URL) to your new private repo (PRIVATE_REPO_URL) 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##*/}

Recommended Additional Steps

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

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

see also: https://ellisbrown.github.io/programming/git-private-forks/#basic-steps

@ellisbrown
Copy link
Author

Maybe an example would help as well. I'll demonstrate cloning my personal config repo into a tmp private repo from the /tmp/ dir on my computer:

/tmp $ BASE_REPO_URL=https://github.com/ellisbrown/config.git
/tmp $ PRIVATE_REPO_URL=https://github.com/ellisbrown/tmp.git

/tmp $ git clone --bare $BASE_REPO_URL

Cloning into bare repository 'config.git'...
remote: Enumerating objects: 76, done.
remote: Counting objects: 100% (76/76), done.
remote: Compressing objects: 100% (63/63), done.
remote: Total 76 (delta 29), reused 43 (delta 11), pack-reused 0
Receiving objects: 100% (76/76), 38.24 KiB | 1.82 MiB/s, done.
Resolving deltas: 100% (29/29), done.

/tmp $ cd ${BASE_REPO_URL##*/}

fatal: this operation must be run in a work tree

/tmp/config.git > main $ git push --mirror $PRIVATE_REPO_URL

Enumerating objects: 76, done.
Counting objects: 100% (76/76), done.
Delta compression using up to 8 threads
Compressing objects: 100% (45/45), done.
Writing objects: 100% (76/76), 38.24 KiB | 38.24 MiB/s, done.
Total 76 (delta 29), reused 76 (delta 29), pack-reused 0
remote: Resolving deltas: 100% (29/29), done.
To https://github.com/ellisbrown/tmp.git
 * [new branch]      main -> main
fatal: this operation must be run in a work tree

/tmp/config.git > main $ cd ..
/tmp $ rm -rf ${BASE_REPO_URL##*/}

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment