Kategorie: Snippets


Git pre-push hook to check for bad log pattern

I've just written a pre-push hook for Git that will check for certain patterns in the log messages that would get pushed.

This is meant to prevent you from accidentally pushing anything that starts with "fixup!" or "stash!" to certain branches (master, etc). These log messages are meant to be used with the autostash feature, which would setup your file for `git rebase --interactive` accordingly.

The code can be found in my dotfiles: ~df/config/git/template/hooks/pre-push.

I am using this through my Git template directory, which gets used with `git init` (and `git init` in an existing repo will also install missing hooks).

Here's the current version:


# Git pre-push hook to check for "fixup!" and "squash!" in commit messages,
# which are not meant to get pushed to public/non-PR branches.
# It will also prevent fast-forward pushes, because git-log fails for them.
# You can use `--no-verify` with git-push to skip this hook.
# Args:
# 1: name of the remote
# 2: location of the remote
# stdin: <local ref> SP <local sha1> SP <remote ref> SP <remote sha1> LF
# Which remote heads/branches to check?
# (a regular expression for "grep -E").
# The log pattern to check.
# (a regular expression for "git grep")
# Uncomment for debugging.
# (the ":" is there so the function can be "empty")
debug() {
  # echo "debug: $@"
debug "$0: $1 $2 ($#)"
# Return status of the script.
while read local_ref local_sha remote_ref remote_sha; do
  debug "Pushing: $local_ref ($local_sha) => $remote_ref ($remote_sha)"
  # Is this a new remote ref?
  if [ "$remote_sha" = "0000000000000000000000000000000000000000" ]; then
  # Skip certain branches, but no other refs (tags).
  if [ "$remote_ref" != "$remote_head" ]; then
    # This is a head/branch (no tag).
    # Allow any non-protected branch.
    if ! echo "$remote_head" | grep -qE "$CHECK_REMOTE_HEADS"; then
      debug "Skipping remote head: $remote_ref ($remote_head)"
  # Check for the bad log pattern.
  log_cmd="git log --grep $BAD_LOG_PATTERN --color=always $log_arg"
  if [ "$log_ret" != 0 ]; then
    echo "ERROR: git-log failed (non-fast-forward / forced push?)"
    echo "  cmd: $log_cmd"
  if [ -n "$log" ]; then
    echo "ERROR (pre-push): there are commits with a bad pattern ($BAD_LOG_PATTERN)!"
    echo "       local_ref: $local_ref => remote_ref: $remote_ref"
    debug "git-log argument: $log_arg"
    echo "$log" | sed 's/^/  /'
debug "ret=$ret"
exit $ret
By Daniel in development, Open Source, Snippets05/18/15 English (US) Email
Tags: ,


Properly disable terminal capabilities for alternate screen in tmux

A lot of places recommend to use the following tmux config to disable the (outer) terminal emulator's alternate screen:

set -g terminal-overrides 'xterm*:smcup@:rmcup@'

But this will override the default value of the `terminal-overrides` setting, and therefore the following should be used instead:

set -ga terminal-overrides ',xterm*:smcup@:rmcup@'

Without using the "append" (-a) option with "set", the defaults would be overwritten, which are currently:

*256col*:colors=256,xterm*:XT:Ms=\E]52;%p1%s;%p2%s\007:Cs=\E]12;%p1%s\007:Cr=\E]112\007:Ss=\E[%p1%d q:Se=\E[2 q,screen*:XT

The tmux FAQ has been updated.

Another method to remove the "smcup" and "rmcup" capabilities globally is the following (via ~/.zshrc, ~/.bashrc etc):


# Remove smcup/rmcup term capabilities globally.
# See also ~/.dotfiles/tmux.common.conf (terminal-overrides).
# Source: https://blogs.oracle.com/samf/entry/smcup_rmcup_hate
# Fixed: remove escaping backslash from sed regexps.
TERMINFO="/tmp/$(id -un)-terminfo-$TERM-$(uname -s)-fixed"
if [[ ! -d $TERMINFO ]]; then
    mkdir -p $TERMINFO
    infocmp | sed -e 's/smcup.*,' -e 's/rmcup.*,' -e '/^[ \t]*$/d' \
      > $TERMINFO/fixed
    sed -e '1d' -e '3,$d' < $TERMINFO/fixed | grep -w $TERM >/dev/null 2>&1
    if [[ $? -ne 0 ]]; then
        mv $TERMINFO/fixed $TERMINFO/broken
        sed -e "2s/^/$TERM|/" < $TERMINFO/broken > $TERMINFO/fixed
    tic $TERMINFO/fixed
By Daniel in computer, Snippets, Planet Ubuntu2014-11-06 English (EU) Email


Deploying a website using Git via SSH remote

Git has a concept of "remotes" (tracked repositories), which allows to have
arbitrary alternate remote locations besides the typical "origin" remote, like "web".

The basic idea is to setup a user on the remote server ($SSH_DEPLOYUSER) which
is allowed to login via SSH (e.g. by adding your public SSH key to the deploy
user's ~/.ssh/authorized_keys file) and will be used to checkout what you want
to deploy.

To accomplish this you have to setup the Git working directory on the server and
add a "post-receive" hook, which will be invoked by Git after you have pushed
to the repository:


$ mkdir /path/to/repo-checkout
$ cd /path/to/repo-checkout
$ git init
# Create the post-receive file/hook (Ctrl-D to end the input to "cat"):
$ cat > .git/hooks/post-receive
export GIT_DIR=$(pwd)
cd ..
git checkout -f
git submodule update --init --recursive
$ chmod +x .git/hooks/post-receive
$ git config --add receive.denyCurrentBranch ignore
$ chown $SSH_DEPLOYUSER -R .

On the local side you have to add a "remote" (named "web" in this case):

The final step is to initially push to it (which requires to specify the "refspec" once - following deployments can be done by just doing a "git push web"):


$ git remote add web ssh://$DEPLOYUSER@host.example.com/path/to/repo-checkout/.git
$ git push web +master:refs/heads/master

These instructions are based on the howto at toroid.org/ams/git-website-howto, but the main difference is that I am not using a "bare" repository here, which would not allow to use Git submodules; submodules require a "full" Git working directory and having a checkout of the repository requires the receive.denyCurrentBranch=ignore setting.


Use hybrid suspend method by default with pm-utils/Linux (suspend to RAM and disk)

There is this nice method of suspending a computer to RAM (which is quick to suspend and resume, but still uses some battery) and after a given amount of time to disk, if it has not been waken up since then (e.g. after 15 minutes).

Ubuntu (and any other distribution using pm-utils) supports this via the pm-utils package and its pm-suspend-hybrid script.

Unfortunately this is not used by default (even hibernation is not available from the menu by default), but only normal suspend.

The following configuration snippet will make pm-utils use the "suspend_hybrid" method instead of "suspend" when being invoked:

You have to create a file like /etc/pm/config.d/00-use-suspend-hybrid and add the following code (e.g. via sudo -e /etc/pm/config.d/00-use-suspend-hybrid):


# Always use suspend_hybrid instead of suspend
if [ "$METHOD" = "suspend" ]; then

I came up with this solution after having asked for a method to do so at Ask Ubuntu.

This way hybrid suspend will be used automatically if you select e.g. "Suspend" from the menu or close your laptop's lid (both actions call pm-suspend which then gets remapped).

You can configure the amount of time before hibernation (Suspend To Disk) is being invoked with the PM_HIBERNATE_DELAY variable (in seconds), which you can just configure in the same file, too:


# Always use suspend_hybrid instead of suspend
if [ "$METHOD" = "suspend" ]; then
PM_HIBERNATE_DELAY=300  # invoke hibernation to disk after 5 minutes (300 seconds)

You might want to make sure that the hybrid method is supported on your system via the following code. If it says "0" it should work:


sudo pm-is-supported --suspend-hybrid && echo $?

Happy suspending.

Update (2013-10-09): I have updated my own answer at AskUbuntu with another (really hybrid, often preferred method), which you can use with Linux 3.6+.


Disable disk cache in Chromium / Google Chrome

There is no user interface in Google's browser Chrome yet to disable the disk cache, or control its size (version 14 appears to have something in the developer tools section).

But it can be done using command line options when starting the browser, and you can configure this globally for Ubuntu.

The following command line flags will use /dev/null ("the sink") as cache dir, and additionally limits it to 1 byte:

--disk-cache-dir=/dev/null --disk-cache-size=1

(I have tried just --disk-cache-size=0 or 1, but it did not appear to work as expected)

On Ubuntu/Debian, you can just add these flags to the CHROMIUM_FLAGS variable in /etc/chromium-browser/default and it will be used every time when starting Chromium.

The motivation to do this comes from me using a local (intercepting) HTTP proxy with its cache on a RAM disk. Therefore I do not want Chromium to store quite the same retrieved files on disk again.
Additionally, this is a SSD, which is not that happy about being written to in general.
Therefore /tmp is a tmpfs mount already, and the same should be the case for temporary browser files.

By Daniel in Ubuntu, Debian, Snippets2011-09-15 English (EU) Email


Get container ID from inside an OpenVZ container

The following snippet will get you the OpenVZ container, when you're in a container. I have added this to my zsh prompt, but this might be useful in other places, too.


# Get OpenVZ container ID (/proc/bc is only on the host):
if [[ -f /proc/user_beancounters && ! -d /proc/bc ]]; then
  CTID=$(sed -n 3p /proc/user_beancounters | cut -f1 -d: | tr -d '[:space:]')
By Daniel in Snippets2010-11-08 English (EU) Email


Reinstall Debian init.d scripts into default runlevels

The following zsh snippet allows you to re-install any missing startup/init.d links.

This can be useful/required when e.g. installing an upstart based distribution (like Ubuntu Lucid) has removed some of those, and you want them back after downgrading to Hardy or switching to Debian testing (like I just did).
(apt-get install --reinstall won't bring back those links; you would have to purge (apt-get purge) and reinstall the package instead, removing any other configuration of the package though)

It basically looks for any init scripts that are not present in /etc/rc?.d/S* and then looks at the packages' postinstallation script for an update-rc.d command.

It will not install anything, but only output them (and allows you to pipe it into "sh" for execution).

Worked fine on my "messed up" system, but has rather odd results on my Maverick desktop.


for i in /etc/init.d/* ; do
    a=( /etc/rc?.d/S*$i:t(N) );
    ((${#a})) && continue;
    package=$(dpkg -S $i 2>/dev/null |cut -d: -f1);
    [[ -z $package ]] && continue;
    echo "# $i: $package";
    grep "update-rc\.d $i:t" /var/lib/dpkg/info/$package.postinst;

(in case you need to extract the init script altogether, the following might help for starters:
dpkg-deb --extract /var/cache/apt/archives/$PACKAGE.deb /tmp/foo.)