10

I have created a Git repo for a JavaScript library. The repo also contains a demo website that uses the bundled library, which is generated in a dist/ folder. I would now like to deploy that website to GitHub Pages.

However, I have the dist/ folder in my .gitignore and would prefer it to remain ignored.

Is there a way to automatically generate the gh-pages branch, which should include dist/, but keep it off the master branch?

Baleb
  • 653
  • 7
  • 16
  • 2
    Hint 1: `.gitignore` in different branches can be different; `.gitignore` in code and doc branches certainly should be different. Hint 2: you can add and commit even ignored files: `git add --force`. – phd Feb 02 '18 at 20:16

4 Answers4

14

Commit this script and call it after having built your dist:

#!/bin/sh

git commit -am "Save uncommited changes (WIP)"
git branch --delete --force gh-pages
git checkout --orphan gh-pages
git add -f dist
git commit -m "Rebuild GitHub pages"
git filter-branch -f --prune-empty --subdirectory-filter dist && git push -f origin gh-pages && git checkout -

I use it for that ;-)

Philippe
  • 28,207
  • 6
  • 54
  • 78
  • Maybe you could add `git reset` after doing `git checkout --orphan gh-pages` ? otherwise all the tracked files on master (not only dist) will be committed in branch gh-pages (of course, in the end the `git filter-branch ...` command will purge the content outside of dist folder, but I believe it is more idiomatic to do `git reset` after the orphan checkout) – ErikMD Feb 03 '18 at 09:23
  • BTW a drawback of this solution is that we lose the history of branch gh-pages at each invocation of the script. (If this is an issue for the OP, this drawback doesn't occur with the [bash solution](https://github.com/X1011/git-directory-deploy) I had mentioned in my answer.) – ErikMD Feb 03 '18 at 09:35
  • On second thought it's better not to do `git reset` after `git checkout --orphan gh-pages` in this case, because if there is a file e.g. `README.md` in both `dist` and root folder of the repo, the `git filter-branch ...` command would raise `error: Untracked working tree file 'README.md' would be overwritten by merge.` – ErikMD Feb 03 '18 at 09:47
  • 1
    @ErikMD Indeed, the gh-page history is lost but it's not a problem for me (made it on design to not have 2 long history in parallel when looking at branch history). But removing `git branch` and `--orphan` should solve that if you want to keep the history. – Philippe Feb 03 '18 at 14:32
1

To summarize your context:

  • your current branch is master
  • you have a dist/ folder that is ignored and untracked
  • it contains the sources of a website that can be statically served
  • you'd like to publish this dist/ folder on GitHub Pages using a gh-pages branch.

The simplest way to do this seems to follow the workflow suggested in this gist as well as in the documentation of Yeoman.

But note that this relies on the advanced command git subtree and requires that the dist/ folder is not ignored and tracked on master as well.

You could then follow the doc regarding the configuration of GH Pages' publishing source.

Does this address your question or do you really want to have the two branches separated and no dist/* file in the master branch?

In the latter case, the problem is more complicated (because of the untracked or ignored files in the work tree that can hinder the process...) but you may want to have a look at this project, which is an alternative to the git subtree-based solution, and is based on a Bash script.

(Note: I have not tested this "git-directory-deploy" solution; it was suggested in the gist I mentioned above.)

ErikMD
  • 13,377
  • 3
  • 35
  • 71
1

Thanks to this blog post, I finally found a convenient way to forge a commit from a gitignored subfolder on top of another branch. I personally use it to release a built npm package in a release dedicated branch.

Using such a solution is very flexible, keeps history (no need to force push), but involves more git internals:

#!/usr/bin/env bash

# Environment
BUILD_DIR="dist"
RELEASE_BRANCH="gh-pages"
VERSION="$(jq -r ".version" package.json)"

# Script
git fetch origin $RELEASE_BRANCH
git add -f $BUILD_DIR
tree=$(git write-tree --prefix=$BUILD_DIR)
git reset -- $BUILD_DIR
identifier=$(git describe --dirty --always)
commit=$(git commit-tree -p refs/remotes/origin/$RELEASE_BRANCH -m "Deploy $identifier as v$VERSION" $tree)
git update-ref refs/heads/$RELEASE_BRANCH $commit
git tag -a "v$VERSION" -m "Release tag for $VERSION" $commit
git push --follow-tags origin refs/heads/$RELEASE_BRANCH
hlobit
  • 166
  • 6
0

Alternatively, Travis CI or another continuous integration tool could be used to automatically create the build and deploy the generated files on the gh-pages branch: GitHub Pages Deployment

Baleb
  • 653
  • 7
  • 16