GitHub doesn't support private branches in public repositories. You can't even fork a public repository and make it private.

My use case: I create tutorial content and I sometimes complement it with a source code on GitHub. While I'm working on my future content, I want to keep it private until I'm ready to publish it with my article/video...

To overcome this GitHub limitation, my idea is to have 2 repositories:

  • private repository is the source of truth
  • public repository is the mirror of the private repository's main branch

(I know there is a git --mirror, but it won't do what I want, right?)

I have a GitHub action in the private repository that mirrors the main branch:

name: Mirror main to public-repo

on:
  push:
    branches: [ main ]

permissions:
  contents: read

env:
  PAT_TOKEN: ${{ secrets.PAT_TOKEN }}
  PUBLIC_REPO: firebase-expo-demo
  OWNER: ${{ github.repository_owner }}
jobs:
  mirror:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: main
          fetch-depth: 0
          persist-credentials: false
      - name: Push to public-repo
        run: |
          git config user.name  "mirror-bot"
          git config user.email "[email protected]"

          git remote add public-repo https://x-access-token:${{env.PAT_TOKEN}}@github.com/${{env.OWNER}}/${{env.PUBLIC_REPO}}
          git push public-repo main

Whenever I push to main or merge to main from my private repository, this action will be triggered. Force-with-lease is just there if I happen to rebase something and its nicer than just using force.

GH_TOKEN is a fine grained private access token that has Contents Read and Write, and Workflows Read and Write access to the public repository.

One thing I haven't figured out, a clean solution to not send my mirror.yml file to public main. And I have to figure out how to make a nice scheduled github merge to main. When I figure it out, I'll let you know.

If you have a better solution for my problem, please share in the comment section, thanks!