Skip to content

Instantly share code, notes, and snippets.

@yknx4
Created October 28, 2016 22:03
Show Gist options
  • Save yknx4/470ec4e1378a48382fdbaf6b5896f1d0 to your computer and use it in GitHub Desktop.
Save yknx4/470ec4e1378a48382fdbaf6b5896f1d0 to your computer and use it in GitHub Desktop.
Automatic database backup on branch creation with Post Checkout Git Hook
#!/bin/sh
# --- Command line
PREVIOUS_HEAD="$1"
NEW_HEAD="$2"
IS_BRANCH_CHECKOUT="$3"
# --- Constants
SEPARATOR="/"
MAIN_BACKUP="_backup"
MAIN_DATABASE="awesome_project_db"
DB_USER="postgres"
# --- Functions
database_exists () {
name=${1:0:63}
return `psql -U $DB_USER -lqtA | cut -d\| -f1 | grep -qFx "$name"`
}
kill_connections() {
psql -U $DB_USER -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '$MAIN_DATABASE' AND pid <> pg_backend_pid();" > /dev/null
}
duplicate_database_to() {
name=${1:0:63}
echo "Creating $name from $MAIN_DATABASE"
createdb -U $DB_USER -T $MAIN_DATABASE $name
}
drop_database() {
name=${1:0:63}
echo "Deleting existing $name"
dropdb -U $DB_USER "$name"
}
rename_database() {
old_name=${1:0:63}
new_name=${2:0:63}
psql -U $DB_USER -c "SET standard_conforming_strings=on;" -q -b
psql -U $DB_USER -c "ALTER DATABASE \"$old_name\" RENAME TO \"$new_name\";" -q -e
psql -U $DB_USER -c "SET standard_conforming_strings=off;" -q -b
}
alias branch_name='git name-rev --name-only'
# --- Variables
PREVIOUS_BRANCH=`branch_name $PREVIOUS_HEAD`
NEW_BRANCH=`git branch | grep -e "^*" | cut -d' ' -f 2`
OLD_DATABASE=$MAIN_DATABASE$SEPARATOR$PREVIOUS_BRANCH
NEW_DATABASE=$MAIN_DATABASE$SEPARATOR$NEW_BRANCH
MAIN_BACKUP=$MAIN_DATABASE$MAIN_BACKUP
# --- Script
if [ $IS_BRANCH_CHECKOUT -eq 0 ]; then
exit 0 # Exit script if it is not a branch change
fi
echo "Switching from $PREVIOUS_BRANCH to $NEW_BRANCH"
echo "Killing existing connections to $MAIN_DATABASE"
kill_connections # We need to kill all the connections or the commands here will fail
if ! database_exists $MAIN_BACKUP; then
echo "Creating a main backup, if something goes wrong you can manually restore from this backup."
duplicate_database_to $MAIN_BACKUP # We should always have a master backup
fi
if [ "$PREVIOUS_BRANCH" == "$NEW_BRANCH" ]; then
exit 0 # We didn't change branch, so lets just exit
fi
if database_exists $OLD_DATABASE; then
# We need to remove old backups if they exists (they shouldn't most of the times) but
# sometime when we didn't had changes in the branch when we created another one, so a
# backup for the parent branch is created instead of one for the new branch, this is
# to delete that wrong backup.
drop_database $OLD_DATABASE
fi
if database_exists $NEW_DATABASE; then
# When a backup for the new branch already exists
# If there is already a backup for the branch we are checking to, lets just rename the active database to create a new backup
rename_database $MAIN_DATABASE $OLD_DATABASE
# and then lets rename the existing backup to the active database name
rename_database $NEW_DATABASE $MAIN_DATABASE
else
# If the branch we are checking to doesn't have a backup let's just copy the db to still have an active database
duplicate_database_to $OLD_DATABASE
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment