Git Hacks
Diggin’ Dotfiles CollectionPermalink
It’s time to dig the dotfiles, and to dig in to them! This post is a part of a blog post collection called Diggin’ Dotfiles where I unearth some gems from my personal dotfiles repo erikw/dotfiles.
The following articles are a part of this series:
- Manage shell configurations across different systems
- Wrap Dangerous Commands in pre-post ZFS or BRTFS Snapshots
- Finger of god: using sudo with TouchID on macOS
- Generate permutation shell aliases
- Git hacks
Git HacksPermalink
There’s so many small hacks for git that make everyday usage quicker and more pleasing. In this post I share a few of my collected helpers from my .gitconfig.
git rootPermalink
What: you’re deep down in a directory tree of a git repo and you want to go back to the top root folder of the repo.
How: put this git overlay function in your shell’s startup files such as ~/.zshrc or ~/.bashrc:
# Git overlay which adds a command to cd to the root of a git repo.
git() {
# -q: macOS, suppress name prefix. Replaced with cut(1); not available on GNU/Linux it seems.
# -b: macOS, only search binary not manual
local gitbin=$( whereis -b git | cut -d ' ' -f 2)
if [ "$1" = root ]; then
# Try get root from git submodule:
local root="$($gitbin rev-parse --show-superproject-working-tree)"
# Else we're in the main repo already:
# --show-cdup will not take us to the root if we came here from a symlink.
#test -n "$root" || root="$($gitbin rev-parse --show-cdup)"
# Instead get full path with --show-to-level https://stackoverflow.com/q/39746533/265508
test -n "$root" || root="$($gitbin rev-parse --show-toplevel)"
[ -n "$root" ] && cd "$root"
else
$gitbin $@
fi
}
Now it’s as easy as this to change directory to the root of a git repo when you are nested in some subdirectores:
$ git root
[skip Ci] Commit Message PrefixPermalink
What: many git centric build system with automatic builds support some way of telling the build system to skip the build for a specific commit. For example Netlify allows you to prefix the first line of a commit message with [skip ci].
What if you have already written your commit message and just realized after that you want to prepend the [skip ci] directive?
How: Add this alias to your git config file that will prepend the directive to the last commit’s message:
[alias]
skip-ci = !"git reset && COMMIT_MSG=$(git show -s --format=format:%B) && git commit --allow-empty --amend -m \"[skip ci] $COMMIT_MSG\" && git --no-pager show -s --format='format:New commit message subject: %s%n'"
Generate Commit Message from git status
Permalink
What: when you work esp. with other developer you should spend time craft good commit message. However being honest, there are times when we don’t have time for a private git repo and quickly need to “save the state” just….
How: Add the git cis alias to your git config:
[alias]
# commit-status: generate a commit with message from git-status (staged changes).
# Source: https://gist.github.com/erikw/654386d35ecfdb0354cd2b71763f19ae
# Explanation:
# - Get only staged changes
# - Ignore changes in working area (2nd letter, the Y in XY as explained in $(git help status))
# - + split label and file path to separate lines so we can process the labels separately
# - Keep only the first label using awk
# - Add newline before each label section so we later can truncate \n to put everything on one line
# - Make labels human readable e.g. M -> Modified
# - Put everything on one line and trim leading & trailing whitespaces
commit-status = !" \
TMPFILE=$(mktemp /tmp/git-commit-status-message.XXX); \
git status --porcelain \
| grep '^[MARCDT]' \
| sort \
| sed -re 's/^([[:upper:]])[[:upper:]]?[[:space:]]+/\\1:\\n/' \
| awk '!x[$0]++' \
| sed -re 's/^([[:upper:]]:)$/\\n\\1/' \
| sed -re 's/^M:$/Modified: /' \
| sed -re 's/^A:$/Added: /' \
| sed -re 's/^R:$/Renamed: /' \
| sed -re 's/^C:$/Copied: /' \
| sed -re 's/^D:$/Deleted: /' \
| sed -re 's/^T:$/File Type Changed: /' \
| tr '\n' ' ' | xargs \
> $TMPFILE; \
git commit -F $TMPFILE; \
rm -f $TMPFILE \
"
cis = commit-status
Quickly Refer to the Previous BranchPermalink
What: quickly reference the previous branch. In some git subcommand - will refer to the previous branch that was checked out.
How:
$ git checkout - # Switch to the previous branch
$ git switch - # Ditto
$ git rebase - # Rebase current branch on the previous branch
Quickly Copy the Sha1 of the Tip of Current BranchPermalink
What: do you frequently need to copy the git SHA-1 of HEAD e.g. to deploy that commit in a build system?
How: this git alias makes it easier! Put in your git config (if you’re on linux, replace pbcopy with xclip):
[alias]
sha1head = !"git rev-parse HEAD | tee /dev/tty | tr -d '\n' | pbcopy"
and now simply run in your git repo $ git sha1head to get the sha1 to stdout and in your macOS clipboard!
Please make sure that you know what HEAD is, if you’re really at the tip of the branch that you think you are
Automatically Prune Branches on git fetch
Permalink
What: tired of having your old deleted branches showing up when tab-completing switching local git branches, and of having to manually run $ git remote prune origin to delete branch refs that are removed in origin? Then configure git fetch (and git pull) to automatically prune those!
How: run this:
$ git config --global fetch.prune true
Leave a comment
Your email address will not be published. Required fields are marked *