Saturday, March 11
git-do: execute commands in the top level of a git repo
tl;dr: Use git config --global alias.exec '!exec '
. Or for some
reason you could write a script like this one to execute
commands in the root of a git repository.
❃
This blog lives in a git repository with entries broken up by date. So, for example, when editing this entry, I might be in a path like so:
~/p1k3/archives/2017/3/11/
I also have a Makefile
in the top level of the repo, which contains targets
like render
and publish
. Since make
expects to find a Makefile
in the
current working directory, I often found myself in a loop where I edit a blog
entry, change to the top level of a repo, run a make
command, and then need
to change the blog entry again.
This seems silly, and generalizes to a bunch of different repositories.
Stack Overflow says that you can do
git rev-parse --show-toplevel
to get the root directory of the repository,
which led me to something like:
$ git config --global alias.root "rev-parse --show-toplevel"
$ cd `git root` && make render && cd -
That works, but it’s a stupid amount of typing. There are a couple of solutions for this. One, from that SO post, is:
$ git config --global alias.exec '!exec '
$ git exec make render
This works because the leading !
on the command tells git to treat it as a
shell command, and by default git executes aliases to shell commands from the
top-level directory of the repo. This is probably good enough, but I didn’t
notice it at first so I added a git subcommand called git-do
to do pretty
much the same. A very simple version looks like this:
#!/bin/sh
git_root=`git rev-parse --show-toplevel`
cd "$git_root"
$@
A slightly more “sophisticated” one uses git-sh-setup
, which
provides some boilerplate for shell scripts written as git subcommands:
#!/usr/bin/env bash
# Help messages:
USAGE="<command>"
LONG_USAGE="Executes <command> from the root of the repository."
# Tell git-sh-setup we're ok with being in a subdir:
SUBDIRECTORY_OK=1
source "$(git --exec-path)/git-sh-setup"
# Make sure we're in a working tree, jump to top level, do command:
require_work_tree_exists
cd_to_toplevel
$@
In both cases, $@
is a variable containing all of the arguments to the
script, which run as shell commands.