This post has been translated into Russian.

I have a few little aliases in my .gitconfig that I find useful and that I thought I’d share.

git root: print the absolute path of the repository root directory

# Print absolute path of repo root directory
root = rev-parse --show-toplevel

This is useful in the shell if you end up cded to somewhere deeper in the repository but want to apply a command at the root, eg for a rename:

somewhere/in/repo$ sed -i 's/oldname/newname/g' $(git root)/**

git detach: get to a detached HEAD state on purpose

# Get to a detached HEAD state on purpose! Usage: `git detach [REF]`
detach = !sh -c 'git checkout $(git rev-parse ${1:-HEAD})' --

Usually a detached HEAD state is something you don’t want to be in, but I’ve wanted this in a few instances, so I added it as an alias. Eg, sometimes I want to experiment but not actually create a branch. Running git detach gives me a ‘branch’ I can make changes to, but without needing to name it, and without needing to delete it afterwards. If it turns out I do want to save the work I did, I can always git checkout -b new-branch-name, or git checkout old-branch-name && git merge --ff-only HEAD@{1}.

This alias uses shell expansion by invoking sh -c. The bang runs a shell command, then sh -c runs the rest through sh. The final -- is necessary to send any additional arguments to go to git checkout rather than sh.

git sha1: print short sha1 of a commit

# Print short sha1; usage: `git sha1 [REF]`
sha1 = !sh -c 'git rev-parse --short ${1:-HEAD}' --

Most often used with xsel or pbcopy, as in git sha1 | xsel -i to copy the current commit’s short sha1 to the clipboard.

I use sh -c for shell expansion again, though here it’s just for supplying a default ref.

git gh-url: get the GitHub URL for a repository

# Get the GitHub URL for a GitHub repository. Usage: `git gh-url [REMOTE]`
gh-url = "!f() { \
	if ! remote=${1:-$(git config --get \
		branch.$(git symbolic-ref --short HEAD).remote)}; \
	then \
		echo no remote specified and could not get remote for HEAD; \
		exit; \
	fi; \
	if ! remote_url=$(git config --get remote.$remote.url); \
	then \
		echo "could not get URL for remote \\`$remote\\`"; \
		exit; \
	fi; \
	case $remote_url in \
		git@github.com:*.git) \
			repo=$(echo $remote_url \
				| sed 's/git@github.com:\\(.*\\).git/\\1/');; \
		https://github.com/*) \
			repo=$(echo $remote_url \
				| sed 's+https://github.com/\\(.*\\).git+\\1+');; \
		*) \
			echo "\\`$remote\\` does not appear to have " \
				"a GitHub remote url: $remote_url"; \
			exit 1;; \
	esac; \
	echo https://github.com/$repo; \
}; \
f"

This one is pretty self-explanatory in terms of usage, but it illustrates another pattern of git aliases: defining shell function and immediately calling it. The general pattern is this:

my-alias = "!f() { \
	echo COMMANDS GO HERE, ESCAPING NEWLINES WITH \
		BACKSLASHES, AND TERMINATING WITH SEMICOLONS; \
}; \
f"

Because we’re in a string inside a config file, there’s an annoying amount of escaping necessary, but you get the hang of it fairly quickly.