1 April 2013

300 words 2 mins read

Stopping unwanted git commits on a shared repository

I’ve occasionally run into people who modify and commit to a checked out build repoistory instead of making the changes on their workstation and pushing them in. I noticed that Galen Grover had a fairly neat solution to prevent himself committing to master (one I will probably copy for another workflow.)

So I borrowed and extended it.

#!/bin/bash
USER=`whoami`
DATE=`date --iso-8601=minute`
REPONAME=

PREFIX="$REPONAME_files_attempt"
PATCHFILE="${PREFIX}-${DATE}.patch"

REPODIR="/opt/$REPONAME"
MAINREPO="SOURCEGOESHERE"
EMAIL=
BUILDUSER=builder

if [ `whoami` = $BUILDUSER ];
    then
    echo "You should not be attempting to commit as the $BUILDUSER user"
    exit 1
fi

function diff_all {
    git --no-pager diff $REPODIR
    git ls-files --others --exclude-standard |
    while read -r i; do git --no-pager diff -- /dev/null "$i"; done
}

function repo {

    if [ ! -d "$HOME/$REPONAME" ]; then
        git clone -q $MAINREPO $HOME/$REPONAME 2>/dev/null
    elif [ -d "$HOME/$REPONAME/.git" ]; then
        GIT_WORK_TREE="$HOME/$REPONAME" GIT_DIR="$HOME/$REPONAME/.git" git pull -q $MAINREPO 2>/dev/null
    fi
}

function unstage {
    git reset HEAD
}



echo "Do not commit to this repository."
echo ""
echo "This repository has changes deployed automatically."
echo ""
echo "a clone of this repository will be created or updated in your HOME Directory"
repo
echo ""
echo "Your changes will be unstaged"
unstage
echo "and a patch will be created in your home directory"
diff_all > $HOME/$PATCHFILE
echo "you can apply the patchfile with the following command"
git apply ~/$PATCHFILE --directory=$HOME/$REPONAME/
echo "cd ~/$REPONAME && git-apply ~/$PATCHFILE"
echo "but this script has already done that for you"
echo "now simply add them, commit and push to the primary repo"
echo ""
echo "Please clean up after yourself with a git reset to ensure that this repo is consistant"
diff_all |mail -s "$USER just tried to commit" $EMAIL
echo "git reset HEAD --hard #note that this command should be used sparingly as it wipes all changes"

exit 1