105

I'm using Github Pages to host & serve a static website.

The static website has the typical directory structure for an app:

.
├ source/
├ build/
│ └ index.html
├ .gitignore
├ config.rb
├ Gemfile
┆ ...
└ README.MD

index.html is under build/, so I want to make that the default www path.

So when users hit username.github.io it renders the content within that subdirectory and yet it doesn't show "/build/" on the URL, cause that's set as the root folder.

Notes:

  • I don't have a custom domain nor planning to get one for this purpose. As you can see, I'm trying to leverage the default URL naming convention github provides.
  • Not using Jekyll nor the automatic page generator function.
1

10 Answers 10

87

There is a detailed gist with all the required steps.

The gist is here:
https://gist.github.com/cobyism/4730490


From the gist

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:

#!/bin/sh
if [ -z "$1" ]
then
  echo "Which folder do you want to deploy to GitHub Pages?"
  exit 1
fi
git subtree push --prefix $1 origin gh-pages

Which lets you type commands like:

git gh-deploy path/to/your/site
6
  • And thus using this URL convention instead: username.github.io/projectname. Right? So that would require renaming the repo to "projectname" instead so I can use the Project Pages setup (help.github.com/articles/user-organization-and-project-pages), right?
    – Oriol
    Apr 22, 2016 at 0:39
  • yep. or you can use custom domain instead
    – CodeWizard
    Apr 22, 2016 at 0:40
  • 1
    Alright. I guess this is the only solution. Thanks!
    – Oriol
    Apr 22, 2016 at 0:52
  • 2
    After further research, there's no way to accomplish what I originally asked. You will need to put the contents of the build folder into the root if you want it to appear at username.github.io. Otherwise use the solution above.
    – Oriol
    Apr 22, 2016 at 16:44
  • 1
    gh-deploy is no longer a valid command. My subfolder is the public folder that Firebase asks you to host in by default. Nov 22, 2016 at 15:17
38

Since August 2016 you can use /docs subfolder of the master branch for your sources.

So if you can tell to your site generator to use /docs in place of /build you are done (without subtree).

Note: As pointed out by @thislooksfun in the comment, this is valid only for project pages (like <username>.github.io/<projectname>), but not for user or organization pages (like <name>.github.io).

2
  • 2
    It's worth noting that this only works with non user/org sites. More specifically, "To publish your site's source files from a /docs folder on your master branch, you must have a master branch and your repository must not follow the repository naming scheme <username>.github.io or <orgname>.github.io" (help.github.com/articles/…) Dec 1, 2016 at 6:45
  • Also note that it seems if you already have another repository <username>.github.io under your account, then the /docs won't work. Only looks for index.html directly on master. See top of page here: help.github.com/articles/… May 22, 2017 at 10:34
14

This is a new solution (in beta).

Go to the Github Pages Settings tab and now change the source to "Github Actions"

Go to the Github Pages Settings tab and now change the source to "Github Actions"

Next, it will let you pick and configure which action to use (Jekyll, or Static HTML). I chose static HTML, and here is where you need to make a single but important change.

By default, the path is set to '.' (the current directory). You need to change this to the sub-folder that is relevant for you.

By default, the path is set to '.' (the current directory). You need to change this to the sub-folder that is relevant for you.

In my case, I have a folder called javadocs which has the relevant HTML. Now save the changes and either push a commit to main or run the action manually to see the live page!

1
  • 2
    For me, when I applied this setup, it still generated a site based on the README.md in the main directory, and putting the subdirectory under the root. Modifying source on the actions/jekyll-build-pages@v1 action did however work like you describe. Sep 26, 2023 at 6:25
3

Publishing a dist folder from master branch using worktree feature to gh-pages branch.

Gist from here: https://gist.github.com/ErickPetru/b1b3138ab0fc6c82cd19ea3a1a944ba6

Setup

First of all, you need to have a gh-pages. If you don't have, create:

git branch gh-pages

This makes a branch based on the master HEAD. It would be okay but the files and the git history of master branch are not meaningful on gh-pages branch. Using an --orphan branch, you can initialize gh-pages in a clean way.

git checkout --orphan gh-pages
git reset --hard
git commit --allow-empty -m "Init gh-pages branch"
git checkout master

Then, mount the branch as a subdirectory using git worktree:

git worktree add dist gh-pages

If you didn't ignore the dist folder, ignore it so that you don't add generated files accidentally in your master branch commits.

echo "dist/" >> .gitignore

Deploy

Every time you build the static bundle, generated files are in dist directory. Since dist folder is now gh-pages branch, you can deploy it directly by just creating a commit and pushing it.

cd dist
git add --all
git commit -m "Deploy on gh-pages updated"
git push origin gh-pages

This way nothing was added to the master branch history, keeping it clean.

2

Somehow for me, the accepted answer only runs the first time. Re-doing it throws errors.

I solved it by running the commands below:

git checkout --orphan gh-pages
git --work-tree build add --all
git --work-tree build commit -m 'gh-pages'
git push origin HEAD:gh-pages --force
git checkout -f master
1
  • error: src refspec HEAD does not match any It tell me this Aug 30, 2021 at 9:19
1

To get this to work for gh-pages branch for hugo sites that use a public/ folder, here is what I have working that is super hacky but gets the job done:

Note: hugolanding is the folder root where your config.toml is, this script runs from a scripts folder, you could totally move it elsewhere and change that line.

#!/bin/bash
# move to root
cd ../hugolanding
# generate public content
hugo -D
# prep copy folder
rm -rf /tmp/public && mkdir -p /tmp/public
# copy out of git shit
cp -R public/* /tmp/public
# git yolo everything
git add -A 
git commit -m 'updates to public'
git push --recurse-submodules=on-demand
git checkout gh-pages
cd ..
cp -R /tmp/public/* .
git add -A 
git commit -m 'updated gh-pages'
git push --recurse-submodules=on-demand
echo "done"
git checkout main
1

I think git-worktree, and deployment from a seperate branch, is a cleaner alternative, since I won't have commits in my main branch, intermingled with commits from re-deployment, which I find more succinct, and I won't have to delete the remote branch every time, if I use git subtree, which is unnecessary.

git-worktree mounts your sub-directory, dist, in this example, to a separate branch, gh-pages.

Here's how:

git branch --track gh-pages origin/gh-pages # Create new gh-pages branch; Add tracking    
git checkout --orphan gh-pages              # Initialize gh-pages without main's history
git reset --hard                            # Remove all history
git commit --allow-empty -m "Init"          # First commit without any files
git checkout main                           # Go back to main (or master) branch
git worktree add dist gh-pages              # Mount dist and bind it to the gh-pages branch

dist is an npm build script which looks like:

"scripts": {
  ...
  "dist": "ng build --configuration production && echo 'gitdir: /home/<user>/<repo>/.git/worktrees/dist' > ./dist/.git"
  ...
}

All it does is re-creates the git-worktree reference, because the .git file in dist was removed by ng build by default. This reference is needed by git to link dist to the index.

And the workflow goes something like this:

npm run dist            # Build website with new changes; Removes dist and re-creates it
cd dist                 # Move to gh-pages branch by switching into a directory (cool huh)
git add .               # Add all generated files to staging area
git commit -m "v0.0.3"  # Update the version history of the gh-pages branch
git push                # Push changes to gh-branch

If you run git status it will reply On branch gh-pages.
And git log will show one commit "Init".

But when you cd .. and run git status again, the response will be On branch main.
And git log will show all of your original commits to main.

So what's happened here is quite interesting. The folder dist now has a separate branch, with it's own, unrelated history to main, and all you have to do to switch is cd dist to access that branch (gh-pages).

This is unlike git checkout dist, which would append the dist directory, with the auto generated build files to your working tree, intermingling your main and deployment histories, which is inconvenient.

Here your src files will be untouched, along with their own history in main, or cd .., and only the files needed for deployment, will be on this branch, which is really convenient, because it keeps the src history seperate from the deployment history.

Now you'd deploy not from a folder, but from a branch, which holds the latest compiled version of your site in GitHub pages, and is built from /(root).

index.html is under build/, so I want to make that the default www path.

Here make certain that the repo that you've created is <username>.github.io. I made this same mistake, by having a different repo name, and was frustrated.

So when users hit username.github.io it renders the content within that subdirectory and yet it doesn't show "/build/" on the URL, cause that's set as the root folder.

Of course there's probably an improvement that could be done here as well. For example make npm run dist do all of this, but my personal preference is to do these steps manually.

Read more about this method here.

But I'd agree, that if you're working on a team, it's probably better to use a tool like gh-pages, to enforce standards in your project.

I hope my explanation is somewhat of a contribution as well, and not just a re-statement of the mentioned methods above.

0

If you want to do this because you have a react app or something similar, the steps described in https://github.com/gitname/react-gh-pages, will solve your problems.

0

add homepage in package.json like this

"homepage": "https://gamingumar.com/watcher",
-2

push-dir will do it:

npm install push-direxample
push-dir --dir=build --branch=gh-pages

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.