Deploying a static site to GitHub Pages from any branch, not just main or gh-pages, is surprisingly straightforward once you understand how GitHub Actions can be leveraged to bypass the default branch restrictions.

Let’s see this in action. Imagine you have a project with your static site’s source code in a develop branch, and you want to deploy it to GitHub Pages automatically whenever you push changes to develop.

Here’s a sample main.workflow file (or .github/workflows/deploy.yml in newer versions) that accomplishes this:

name: Deploy to GitHub Pages

on:
  push:
    branches:
      - develop # Or any other branch you want to deploy from

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
        with:
          ref: develop # Explicitly checkout the develop branch

      - name: Setup Node.js
        uses: actions/setup-node@v2
        with:
          node-version: '16.x'

      - name: Install dependencies
        run: npm install # Or yarn install, depending on your package manager

      - name: Build static site
        run: npm run build # Or your build command, e.g., hugo, jekyll build

      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:

          github_token: ${{ secrets.GITHUB_TOKEN }}

          publish_dir: ./dist # The directory where your build output is located
          publish_branch: main # The branch GitHub Pages serves from

This workflow defines a single job, build-and-deploy, that runs on the latest Ubuntu runner.

The first step, Checkout code, is crucial. By default, actions/checkout checks out the branch that triggered the workflow. However, we explicitly tell it to check out the develop branch using with: ref: develop. This ensures that subsequent steps operate on the correct source code.

Next, we set up Node.js, install dependencies, and build the static site. The Build static site step assumes you have a script in your package.json (e.g., "build": "your-build-command") that generates your site’s output, typically into a directory like dist, build, or public.

The final step, Deploy to GitHub Pages, uses the popular peaceiris/actions-gh-pages action. This action handles the heavy lifting of pushing your built site to a specified branch. The github_token is automatically provided by GitHub Actions. The publish_dir points to the output directory of your build, and publish_branch specifies which branch GitHub Pages should serve from. This is typically gh-pages or main (if you’ve configured GitHub Pages to serve from main’s root).

The on: push: branches: - develop configuration tells GitHub Actions to trigger this workflow only when changes are pushed to the develop branch. This is how we deviate from the default behavior of deploying from main.

The mental model here is that GitHub Pages itself still serves from a designated branch (often main or gh-pages). What we’re doing is using GitHub Actions as an automated deployment pipeline. This pipeline checks out the code from your chosen source branch (develop in this case), builds the static site, and then pushes the built output to the branch that GitHub Pages is configured to serve from. The source code for your site lives on develop, but the actual files served by GitHub Pages reside on main (or gh-pages).

When you push code to develop, the Action runs. It builds your site. Then, it takes the output of that build (e.g., dist/index.html, dist/styles.css) and commits it to the main branch. GitHub Pages, watching the main branch, then serves these newly updated files. Your develop branch remains the source of truth for your development, while main becomes the deployment artifact repository.

The peaceiris/actions-gh-pages action, under the hood, often performs a shallow clone of the publish_branch, commits the new files, and then forces a push. This is why it’s important to ensure that your publish_branch is exclusively used for deployed artifacts and not for direct development, to avoid merge conflicts or overwriting your work.

The next concept you’ll likely encounter is managing environment-specific configurations, such as API keys or different backend URLs, for your static site deployments.

Want structured learning?

Take the full Github course →