2.2 Bootstrapping

2.2.1 Bootstrapping using a seed

Bootstrap your own configuration by cloning the seed repository from https://github.com/emacscollective/seed.

The first commit assimilates borg itself and adds several necessary files. The next commit adds auto-compile, which I consider essential. The next few commits add epkg and magit, and their dependencies. If you do not want all of these packages, you can reset to an earlier commit. Resetting to the very first commit gives you a nearly minimal configuration,

The history of the seed repository is occasionally rewritten, ensuring that the simple instructions in the previous paragraph always apply. For that reason you should only use it for bootstrapping, and not pull from this repository. You might still want to keep it as a remote, so that you can always easily consult the current canonical configuration.

Clone the seed repository to either ~/.config/emacs, ~/.emacs.d or for testing purposes to any other location. Below we assume you used the former. If you choose another location, you will have to substitute your chosen path for that in the examples below.

This repository contains a Makefile that imports lib/borg/borg.mk, if available. It also defines the target bootstrap-borg, which clones the Borg repository to lib/borg/.

Run make bootstrap-borg to clone the borg repository. That does not completely setup borg, but it makes the latest version of Borg available, including the bootstrap make target, which completes the setup of all assimilated drones, including Borg itself.

Now that these files are available you can run make bootstrap to clone and configure all package submodules, and to build all drones.

git clone --origin seed https://github.com/emacscollective/seed ~/.config/emacs
cd ~/.config/emacs
make bootstrap-borg
make bootstrap | tee bootstrap.log

The last command run by make bootstrap is git submodule status, which prints one line per module. If a line is prefixed with ‘+’, that means that it was not possible to checkout the recorded commit, and - means that the module could not be cloned. Even if some module could not be cloned, that usually does not render a configuration unusable, so just run emacs now, and then investigate any issues from the comfort of Magit.

If you cloned to somewhere other than ~/.config/emacs, then you can use that configuration using emacs --init-directory /path/to/config/.

During package compilation you may notice that some package modules become "dirty", due to compilation outputs not being ignored in those submodules. Instead of bothering their maintainers, by submitting a pull-request for each such package, I recommend ignoring these files globally and be done with it, by adding this to ~/.config/git/ignore:

*.elc
*-autoloads.el
dir

2.2.2 Bootstrapping from scratch

If you don’t want to base your configuration on the provided seed repository described in the previous section, then you have to do a few things manually.

git init ~/.config/emacs
cd ~/.config/emacs

Even when starting from scratch, it might be a good idea to clone the official seed repository, and reset that to the initial commit, so that you have a working minimal configuration at hand, for reference. Also, feel free to make some changes and then amend to that commit, discarding any existing author information. Doing that is less error prone than coping the same text from this section, and leads to about the same result.

By default Borg installs packages inside the lib/ subdirectory, but since you are starting from scratch, you may choose something else by setting the Git variable borg.drones-directory locally for this repository.

Then you should add a Makefile containing:

-include lib/borg/borg.mk

ifndef BORG_DIR

help helpall::
        $(info )
        $(info Bootstrapping)
        $(info -------------)
        $(info make bootstrap-borg  -- Make borg and make targets available)
        @printf "\n"

GITDIR := $(shell realpath --relative-to=. "$$(git rev-parse --git-dir)")
SRCDIR ?= $(shell git config -f .gitmodules submodule.borg.path)
URL    ?= $(shell git config -f .gitmodules submodule.borg.url)

bootstrap-borg:
        mkdir -p "$(GITDIR)/modules"
        git clone $(URL) $(SRCDIR) --separate-git-dir "$(GITDIR)/modules/borg"

endif

When you later clone your configuration on a new machine, you can use this bootstrap-borg make target to initialize the borg submodule, but this super repository doesn’t have any submodules yet, so instead you have do add the first submodule.

git submodule add --name borg https://github.com/emacscollective/borg lib/borg

Next you have to tell Emacs to initialize Borg instead of Package, by adding a simple early-init.el file containing:

;; -*- no-byte-compile: t; lexical-binding: t -*-

(setq load-prefer-newer t)

(add-to-list 'load-path (expand-file-name "lib/borg" user-emacs-directory))
(require 'borg)
(borg-initialize)

(setq package-enable-at-startup nil)

Changing the values of load-prefer-newer and package-enable-at-startup as shown here is optional but strongly recommended. load-prefer-newer should be enabled before loading borg.

You should also add .gitmodules, containing the following. This isn’t strictly necessary, but if you don’t, then you must use .gitmodules whenever this manual says, that you should set some variable in .borgconfig or .gitremotes.

[include]
        path = .gitremotes
        path = .borgconfig

Other files you might want to create at this time include init.el, .dir-locals.el and .gitignore; before creating the initial commit.

git add --all
git commit -m "Assimilate borg"
make build

Now it is time to assimilate epkg and its dependencies. Because epkg hasn’t been assimilated yet, borg-assimilate doesn’t know where these packages are distributed. Instead copy the URLs from this list, when prompted.

PackageURL
compathttps://github.com/emacs-compat/compat
cond-lethttps://github.com/tarsius/cond-let
llamahttps://github.com/tarsius/llama
emacsqlhttps://github.com/magit/emacsql
closqlhttps://github.com/magit/closql
epkghttps://github.com/emacscollective/epkg
auto-compilehttps://github.com/emacscollective/auto-compile

Create a commit, using a message such as "Assimilate epkg and dependencies".

Next you should assimilate auto-compile, add the following lines to early-init.el, and create a commit.

(require 'auto-compile)
(auto-compile-on-load-mode)
(auto-compile-on-save-mode)

Then you should assimilate magit and its dependencies. Finally you should configure Magit to list submodules in status buffers:

(with-eval-after-load 'magit
  (magit-add-section-hook 'magit-status-sections-hook
                          'magit-insert-modules
                          'magit-insert-stashes
                          'append))

2.2.3 Migrating a legacy configuration

If you are currently using Package and want to gently ease into using Borg alongside that, then you can proceed as described in Use as secondary package manager.

If on the other hand you are already using Git modules manually, then you should proceed as described in Bootstrapping from scratch. Obviously "from scratch" is a misnomer in that case, and you should skip steps like git init.

2.2.4 Using your configuration on another machine

Getting started using your existing configuration on another machine works the same way as described in Bootstrapping using a seed. The main difference is that instead of starting by cloning someone else’s repository, you start by cloning your own repository.

2.2.5 Using ssh URLs

The seed repository tracks submodules using the https protocol, but you can change that on the fly using the following global rules.

git config --global url.git@github.com:.insteadOf https://github.com/
git config --global url.git@gitlab.com:.insteadOf https://gitlab.com/

If you don’t want to configure this globally, then you can also configure Borg itself to prefer the ssh URLs.

(setq borg-rewrite-urls-alist
      '(("https://github.com/" . "git@github.com:")
        ("https://gitlab.com/" . "git@gitlab.com:")))

This does not affect packages that have already been assimilated. During bootstrapping you have to change the URLs for packages that are assimilated by default.

cd ~/.config/emacs
sed -i "s|https://github.com/|git@github.com:|g" .gitmodules
sed -i "s|https://gitlab.com/|git@gitlab.com:|g" .gitmodules
git commit -m "Use ssh URLs for Github and Gitlab"

If you have already run make bootstrap, then you also have to edit .git/config.

cd ~/.config/emacs
sed -i "s|https://github.com/|git@github.com:|g" .git/config
sed -i "s|https://gitlab.com/|git@gitlab.com:|g" .git/config