Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Deploy to `gh-pages` from a `dist` folder on the master branch. Useful for use with [yeoman](

Deploying a subfolder to GitHub Pages

Sometimes you want to have a subdirectory on the master branch be the root directory of a repository’s gh-pages branch. This is useful for things like sites developed with Yeoman, or if you have a Jekyll site contained in the master branch alongside the rest of your code.

For the sake of this example, let’s pretend the subfolder containing your site is named dist.

Step 1

Remove the dist directory from the project’s .gitignore file (it’s ignored by default by Yeoman).

Step 2

Make sure git knows about your subtree (the subfolder with your site).

git add dist && git commit -m "Initial dist subtree commit"

Step 3

Use subtree push to send it to the gh-pages branch on GitHub.

git subtree push --prefix dist origin gh-pages

Boom. If your folder isn’t called dist, then you’ll need to change that in each of the commands above.

If you do this on a regular basis, you could also create a script containing the following somewhere in your path:

if [ -z "$1" ]
  echo "Which folder do you want to deploy to GitHub Pages?"
  exit 1
git subtree push --prefix $1 origin gh-pages

Which lets you type commands like:

git gh-deploy path/to/your/site
Copy link

shilangyu commented Oct 20, 2018

@sukima solution worked for me

Copy link

aaronkorver commented Nov 19, 2018

git worktree add -b gh-pages dist gh-pages
I will append to this Gist (which was super helpful) that depending on how you cloned your main project the worktree might be in a Detached HEAD state. The above snippet will attach it to a branch so you can push back upstream. This took me a bit to wrap my head around, so maybe it will help those poor souls like me who find this Gist.

Copy link

quantuminformation commented Jan 26, 2019

There is a lot of different ways to do this, what is the simplest way to set this up in 2019 using a bash script?

Copy link

inspectordanno commented Mar 23, 2019

@sukima I've been having a lot of trouble with this problem and I wanted to know if you could help. I've been trying your solution, and when I try to push changes to the gh-pages branch, a message is returned that says "Everything is up to date." It pushes to the master branch fine. Any idea what could be happening?

Copy link

vicentedealencar commented Jun 11, 2019

For user and organizational pages (in which the visible branch is master instead of gh-pages), I ran into the same issue as @daniloprates and managed to get around it by...

  1. In the repo's Settings / Branches, making my src branch the Default Branch
  2. With the src branch checked out, deleting the master branch with git push origin :master
  3. Creating a new master branch with git subtree push --prefix dest origin master
  4. Resetting the master branch as the Default Branch in the repo's Settings.

This was really helpful, thx @lukehler! I just changed the step 3 so that dest can be git-ignored and used the package gh-pages instead of subtree
3. gh-pages -d dest -b master

Copy link

quantuminformation commented Jul 19, 2019

what is the best way on windows?

Copy link

Izhaki commented Sep 13, 2019

Another option:

yarn add --dev gh-pages

Then in package.json:

    "release": "yarn export && touch out/.nojekyll && gh-pages -t -d out"

Related scripts:

    "build": "rimraf .next && cross-env NODE_ENV=production next build",
    "export": "yarn run build && next export",

Copy link

yiyubruceliu commented Nov 8, 2019

This helped me out:

  1. git checkout master # you can avoid this line if you are in master...
  2. git subtree split --prefix dist -b gh-pages # create a local gh-pages branch containing the splitted output folder
  3. git push -f origin gh-pages:gh-pages # force the push of the gh-pages branch to the remote gh-pages branch at origin
  4. git branch -D gh-pages # delete the local gh-pages because you will need it: ref


Thank you so much! This works for me

Copy link

AlienKevin commented Mar 22, 2020

Just want to add that you can also publish a nested subfolder like www/dist:
git add www/dist && git commit -m "Initial www/dist subtree commit"
git subtree push --prefix www/dist origin gh-pages

Copy link

mircohaug commented Apr 30, 2020

If you want to deploy to gh-pages with a github action, you can use

Copy link

kylejbrk commented May 3, 2020

Using the worktree method, how do I get this to work when I clone down the repo again? It seems like break the link between the two branches and the sub directory.

Copy link

mircohaug commented May 4, 2020

you don't ever clone/edit the gh-pages branch directly. You just have this one detached commit on the branch and update this detached branch via

git push origin `git subtree split --prefix dist master`:gh-pages --force

Copy link

kylejbrk commented May 4, 2020

@microhaug im not cloning or editing directly. to give more detail, my master branch generates static html files and puts them in a subdir called public. the public directory is in the .gitignore file in the master. I then have the contents of the public directory set to the gh-pages branch via the worktree.

my issue is when I clone down the whole repo again, the public directory will not exist, and break the relationship between the branches.

Copy link

mircohaug commented May 5, 2020

@kylejbrk this is correct. The downside of this aproach is, that the generated files must be checked in or if you generate them in a CI to be at least not ignored.

Copy link

OdysseasMas commented Jun 9, 2020

I tried to do this on my website but it does not seem to work (or I am not doing smth right). I don't think that that's relevant because the problem was there before but I've hooked the gh page with an AWS 53 DNS but it still needs the /dist at the end to work. I did successfully run git subtree push --prefix dist origin gh-pages but it seems like I'm doing something wrong.

Copy link

ChrisBAshton commented Jul 9, 2020

I used the approach described here:

# just to get us all at the same starting point
git checkout master

# delete your build folder
rm -rf build/

# create a 'build' directory checked out to the gh-pages branch
git worktree add -B gh-pages build origin/gh-pages

# build the project
bundle exec rake build

# cd into 'build' folder, which is now on the gh-pages branch
cd build

# fail if for some reason this isn't the gh-pages branch
current_branch=$(git symbolic-ref --short -q HEAD)
if [ "$current_branch" != "gh-pages" ]; then
  echo "Expected build folder to be on gh-pages branch."
  exit 1

# commit and push to gh-pages
git add . && git commit -m "Update gh-pages"
git push

This is a nice approach because it retains the history of the gh-pages branch. Each build and commit shows only the files that have changed.

Copy link

PhillipUg commented Aug 22, 2020

"deploy-demo": "git push origin :gh-pages && git subtree push --prefix dist origin gh-pages"

worked like a charm 👍. Thanks 😃

Copy link

brugobi commented Nov 10, 2020

I did not understand anything about this tutorial

how can I provide this path/to/your/site if I did not deploy yet (I don't have the pah yet)

Copy link

tyleryoungblood commented Jan 29, 2021

This has been working out for me;

"scripts": {
  "deploy-demo": "git push origin :gh-pages && git subtree push --prefix dist origin gh-pages"

deletes the branch and re-pushes. Avoids all that remote branch being ahead fluff that others are mentioning.

@mikeyhogarth Awesome solution! Thank you! And I'd never seen that method of deleting a branch before.

However, is there a way to delete the remote branch, but only if it already exists? If you run npm run deploy-demo for the first time, it will error out because the gh-pages branch doesn't exist yet. It works perfectly for future deployments, just not the first one.

Copy link

kutsan commented Feb 17, 2021

Using was the way to go for me. Saves tons of headaches especially if you're working with others.

"scripts": {
  "deploy": "gh-pages --dist 'dist' --branch 'release'"

Copy link

alex-drocks commented Oct 16, 2021

Using was the way to go for me. Saves tons of headaches especially if you're working with others.

"scripts": {
  "deploy": "gh-pages --dist 'dist' --branch 'release'"

This cleared my remote project and left only the dist files lol

Copy link

kutsan commented Oct 16, 2021

@alex-drocks This is how it was suppose to do. Some build systems produce file names with hashes in them for caching. In order to prevent duplication, files are on specified branch needs to be deleted before new ones take over.

My suggestion is, use a separate branch for dist files that is generated by your build system and configure GitHub Pages to use root (/) of that branch. Have a good day!

Copy link

TimMTech commented Feb 3, 2022

Hands down one of the worst git deployment step by steps I have ever encountered.

Copy link

cobyism commented Feb 3, 2022

Hands down one of the worst git deployment step by steps I have ever encountered.

@TimMTech Considering this gist of mine is ~8 years old, I’ll be the first admit there are many ways it is far from perfect. For what it’s worth though, you’ll probably get a better response from people when communicating online if you can provide constructive suggestions for improvement alongside any criticism/feedback you decide to share. 💟

Copy link

goelshivam1210 commented Feb 6, 2022

I want to deploy my website using Jekyll-scholar on Github pages. Since Github pages don't deploy it on their own, I will have to use another way of deploying a pre-built website. Can you please suggest some ways how to do that? I used rakefile, and when I force the built _site subdirectory to be the root of the project, it deletes everything, and therefore, nothing can be pushed.
I am using this command git filter-branch --subdirectory-filter _site/ -f"
I am using macOS 11.6 and using Jekyll-scholar. I am extremely new to this, so please pardon my naivety.

Copy link

Azer5C74 commented Apr 3, 2022

Thanks for this helpful contribution, I recently wanted to follow the same steps hoping to deploy a sub folder containing index.tsx file as a main file for a react typescript project, but it didn't work out for me even I succeed to push the subfolder into the remote gh-pages branch.

Copy link

ifaswind commented Apr 7, 2022

Thanks, this solution work well for my subfolder(build/web-mobile).

I did it like:

git subtree push --prefix build/web-mobile github gh-pages

Copy link

przemollo commented Apr 24, 2022

@cobyism Thanks for this thread. At the beggining it didn't help me, but i spend couple of hours thinking and searching what is wrong.

I was getting errors in console (net::ERR_ABORTED 404). Then i realised that I have wrong path in my index.html to .js and .css files. They havn't got "./" at the beggining. I changed this and TA-DAH! It works!
I'm so happy now! Thank You!

Copy link

fabriziomartini commented Jun 16, 2022

"git push origin :gh-pages && git subtree push --prefix dist origin gh-pages" - this command worked perfectly

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