Migrating GitHub Gists to OpenGist with metadata preservation

On migrating GitHub Gists to a self-hosted OpenGist instance, with metadata preservation.

Migrating GitHub Gists to OpenGist with metadata preservation
Photo by Barth Bailey / Unsplash

Like many software engineers, I’ve accumulated a lot of GitHub Gists over the years. They’re handy for sharing code, snippets, configs, and quick notes.

In an attempt to self-host more and more services in order to have more control, I stumbled upon OpenGist: a self-hosted alternative to GitHub Gists that one can run in a private setup.

I found OpenGist to be almost compatible with GitHub Gists, since it is also powered by Git under the hood. So this should make it easy to migrate from one service to the other. More importantly, some of the GitHub gists are "secret", so ideally they should keep the same level of visibility once migrated.

This post walks through migrating all your GitHub Gists to an OpenGist instance while preserving their metadata. Let's get started.

Goals

When migrating, I wanted to:

  • Keep the original visibility (public vs. secret).
  • Preserve the title and description.
  • Migrate the actual Git repositories intact.

Prerequisites

  • An OpenGist instance running with a user configured. See Install OpenGist for more details.
  • The GitHub CLI (a.k.a., gh) installed.
  • Git installed.

Migration Script

Here is the migration script (stored on my OpenGist instance of course):

The approach here is quite straightforward:

  • Use gh api to list all gists along with their metadata
  • Clone each gist locally
  • Inside each gist clone, add the OpenGist instance as a remote (the /init endpoint is a special endpoint that triggers the creation of a new gist)
  • Push with metadata options (git push -o visibility=... -o title=... -o description=...).

Once you export the OPENGIST_USER and OPENGIST_PASSWORD environment variables in your terminal and run the script, you should get all your GitHub gists imported into your OpenGist instance:

OpenGist interprets the push options provided and applies them to each new gist imported.

A few things to note however:

  • Visibility mapping: GitHub has only public and secret gists. OpenGist supports public, unlisted, and private. In the script, I an mapping everything that is not public in GitHub as private in OpenGist. You can change this to unlisted if that’s more appropriate for your use case.
  • Title: GitHub Gists don’t have a dedicated title field. The convention is to use the first filename in the gist, which is what the script extracts.
  • Description: Pulled directly from GitHub’s gist metadata.
  • Branch names: I ran into an error where some gists were using master. The script detects the current branch automatically.
  • Authentication: Make sure both gh and your git client are authenticated with GitHub. The script uses the OpenGist HTTPS URL with both the username and password, but feel free to rely on the SSH URL instead if needed.
  • Non-idempotent: Running the script twice will create new gists in your OpenGist instance. This was fine for my use case of a one-off migration script.

Wrapping Up

With this script, I was able to migrate my entire gist library to my self-hosted OpenGist in one shot, while keeping the important metadata intact. Now I have my code snippets under my own control.

If you’re running OpenGist and have old GitHub Gists lying around, feel free to give this approach a try.

As usual, feel free to share your thoughts in the comments.