Switch theme in an existing Jekyll installation
This is what I did to change the theme of an existing Jekyll installation. Adjust these instructions to suit your needs.
Pull the new theme
We create a new orphan branch newtheme
and ensure it's empty.
git checkout --orphan newtheme
git rm -rf .
git clean -dfx
Then we pull the theme files into it by adding the theme as an upstream remote. In this example I pull John Otander's Pixyll theme's master
branch.
git remote add upstream https://github.com/johnotander/pixyll.git
git fetch upstream
git pull upstream master
Build the theme and test it.
bundler install
jekyll serve
Merge your changes
Now we merge our posts, configuration, etc. You can use Git checkout
to copy a file or folder from your old Jekyll site. Note that this will overwrite the theme's file if it exists.
git checkout master -- _posts
Alternatively, you can copy a file under a new name, for example to merge it manually.
git show master:_config.yml > _config.yml.old
If you accidently overwrote a theme file, you can restore it.
git checkout upstream/master -- about.md
These are the files I had to copy, merge, adjust or remove:
- Markdown files in the root folder.
- Posts in the
_posts
folder. - Drafts in the
_drafts
folder. - The
_config.yml
configuration file. - The
Gemfile
gem file. - The
CNAME
file (for GitHub pages). - The
Rakefile
(if any). - The favicon files (if any).
- Manual theme changes such as Google Analytics, Disqus, SEO fields (if any).
Commit your changes, and don't forget to test the theme again.
Replace the master branch
Finally we replace our existing master
branch with the new newtheme
branch. Assuming we're on the newtheme
branch:
git checkout newtheme
git merge -s ours master
git checkout master
git merge newtheme
Push the changes.
git push
And clean up the local newtheme
branch.
git branch -d newtheme
That's it! You've successfully replaced your theme. If there's anything I missed, or you have anything to add, please leave a comment.
Updating the theme
If at any later point you want to update the theme to include the latest upstream changes, simply:
git pull upstream master
And fix any merge conflicts. Here I assume the upstream
remote is still set to the theme's repository (you can check this with git remote -v
).
While you could migrate to an existing installation by forking a new theme and then manually copy and pasting over resources like CSS, JS, HTML in the _includes
, _layouts
and other files you may need, this probably isn't a great idea as you end up having a mash up of old and new resources, which may not be of the same name, but in the scenario that they are (for example you didn't overwrite an old stylesheet that your post references), it will cause mixed up CSS styles that you'll have to debug and slowly fix.
Since I'm assuming you have a Jekyll install with Git (if you don't you really should), you could create a branch called new-theme
and switch to that branch from the master
as the working branch. (A simpleton way of having something like this is to just copy your entire Jekyll install and paste it elsewhere as old-Jekyll-install
if you don't want to deal with Git branches (but really, you should. Here's a tutorial that helped me learn)
- Pull down the files for the new theme.
- Manually copy over
_posts
and your customized changes. - Port over your
_config.yml
by manually comparing them and moving over what is necessary. - Build the site and see what you're missing, what might be messed up (for example in the past you might have added a few
<br \>
tags for spacing and you don't want that in the new theme). - Merge with
master
(or push it to production)
That being said all this is fairly manual and a pain, but at least you won't have to deal with conflicts in resources. The downside of doing this though is that your repository won't be synced with the theme repo. So you won't get upstream updates. I would still suggest that you fork the theme repo, port over your personal customizations for your Jekyll site, and then rename that repo for production. (this would of course no longer be using the 'existing' Jekyll installation)
Jekyll v3.2 introduced gem-based themes (for future plans see here):
Gem-based themes make it easy for theme developers to make updates available to anyone who has the theme gem. When there’s an update, theme developers push the update to RubyGems
The goal of gem-based themes is to allow you to get all the benefits of a robust, continually updated theme without having all the theme’s files getting in your way and over-complicating what might be your primary focus: creating content.
Installing a gem-based theme is simple:
- Add the theme to your site’s Gemfile:
gem "jekyll-theme-awesome"
- Install the theme:
bundle install
. - Add the following to your site’s
_config.yml
to activate the theme:theme: jekyll-theme-awesome
- Build your site:
bundle exec jekyll serve
To switch themes, I believe something like this should work:
- Change to the new theme in your site’s Gemfile:
gem "jekyll-theme-new"
- Install the theme:
bundle install
- Change you site’s
_config.yml
to reference the new theme:theme: jekyll-theme-new
- Build your site:
bundle exec jekyll serve
- (optional - uninstall the old theme from your machine) Note down the old theme's installation folder (
bundle show jekyll-theme-awesome
) and uninstall it withgem uninstall jekyll-theme-awesome
. To be on the safe side, make sure its folder was indeed deleted.
Updating gem-based themes is easy:
If you have the theme gem, you can (if you desire) run
bundle update
to update all gems in your project. Or you can runbundle update <THEME>
, replacing with the theme name, such asminima
, to just update the theme gem. Any new files or updates the theme developer has made (such as to stylesheets or includes) will be pulled into your project automatically.
Important note: at the time of writing, GitHub pages only supports a specific set of gem-based themes: Architect, Cayman, Dinky, Hacker, Leap day, Merlot, Midnight, Minima, Minimal, Modernist, Slate, Tactile, and Time machine. Of those, it seems only Minima is blog-oriented (e.g. it's the only one with built-in Disqus support). However, you should be able to use any theme if you are willing to run the Jekyll build process yourself.
Another alternative is GitLab pages (tutorial, sample site).
With GH-Pages
I tested this, but I did it with a project where I didn't have anything I wanted to save, and with fairly simple themes, so this might not work so well with the increased complexity.
-
For safety, create a new branch
git checkout -b newtheme
-
And then add the new theme as a remote
git remote add new-theme-upstream https://github.com:drjekyllthemes/jekyll-minimal-theme.git git pull new-theme-upstream HEAD
- The messy part, you're going to have a bunch of merge conflicts. Check which files have merge conflicts with
git status
, hopefully these conflicts should only be in style files that you want to overwrite. If there any files you want to keep you can either edit them with a text editor: git will have labelled the changes in the file -
Push to your origin
git push origin newtheme
- Go to your project's page on github and you'll notice something like this:
- Create a pull-request and merge the new changes in.
- Your project is still going to show as being a fork of the first theme, and you won't be able to create pull-requests for the upstream of the new theme. But you can merge in new updates for your new theme by using
git pull new-theme-upstream
If you are not using gh-pages or if you are building jekyll locally before pushing to github (I think)
You could keep your themes in git submodules, as separate folders and then symlink the key elements for jekyll. This won't work in gh-pages crude example
blog
|
+-- theme_1/
|
+-- theme_2/
| |
| +-- _layouts/
|
+-- _layouts ln - theme_2/_layouts
That way when changing themes the themes don't collide.
The easiest way to switch theme in an existing or new jekyll installation is to use the following plugin: jekyll-remote-theme, which is available since November 2017.
Although it is currently in beta, it works fine and most importantly it is already white-listed on Github Pages, so there is no need to build locally, unless the requested theme includes unsupported Gems.
Therefore, in the case of a simple web site with pages and blog, you can host and edit your content directly on the Github infrastructure and switch your site theme by typing-in the address of the new remote theme. An extra benefit is that you can test your content with several existing themes before committing to one of them.
In addition to easier switching, the jekyll-remote-theme method should automatically bring-in a new version of the remote theme, as soon as you make a change and there is a new version by the maintainer of the theme. If the maintainer of the theme makes a radical change that you don't like then you are always a few keystrokes away from a new theme.
I have several jekyll installations and I am already employing it without intending to switch in the short term, since it is the most elegant and future proof solution, for the time being.
If your existing jekyll installation is pure (i.e., you have edited only pages, posts, configuration) then the switch is seamless. If your existing theme has special layouts (e.g., splash.html and the new one does not have it) then your pages that employ the respective layout become orphans (i.e., basic html with no special formatting). I have switched an existing installation that had been extensively edited, so I got several orphan pages, but I did not get any of the git merge conflicts that are possible with other methods discussed here.