git – rebase and push script

18 Jul 2011

For development projects, I use the standard git workflow ie master is my main branch, and I do development in branches (read more about this recommended workflow at A successful Git branching model**).

(** this site also suggests always using –no-ff with merge – a practice I now follow – it certainly makes reading history easier)

nvie.com - A successful Git branching model

nvie.com - A successful Git branching model

When I’m happy with my work in a dev branch I cherry-pick or merge into master. I’ll then want to rebase my other dev branches against master, and push all branches to a “backup” server (ie a bare git repository). On my dev branches I’m frequently rewriting history with git reset, git commit –amend, and git rebase -i, but on my master branch I never rewrite history (ie only ever use git revert). So when I push dev branches I’m going to need to do a git push -f, whereas on the master a git push will suffice.

I’m doing this regularly, and it’s boring and error prone. So I’ve written a script to automate the whole process ie rebase each dev branch against master, and push all local branches somewhere else. If you have branches off (non-master) branches, this script won’t work. But I’ve found in my day-to-day development as a sysadmin (devop?) my branching isn’t that complicated, so this script is adequate.

If you branch off (non-master) branches, don't use this script! (image: Jon Loelger, "Version Control with Git")

If you branch off (non-master) branches, don't use this script! (image: Jon Loelger, "Version Control with Git")

% cat rebase.and.push
#!/bin/bash

# vim: ai ts=4 sts=4 et sw=4 ft=sh

# rebase all local branches against master, then force push
# them to supplied remote. Also push master

original_branch=$(git symbolic-ref -q HEAD)
original_branch=${original_branch##refs/heads/}
original_branch=${original_branch:-HEAD}

if [ $original_branch = 'HEAD' ] ; then
    echo
    echo "On a detached head. Exiting..."
    exit 1
fi

remote=${1:-origin}

# find all local branches
locals=`git br | sed 's/^  |* //' | grep -v master`

# rebase against master
for branch in $locals ; do
    echo
    echo "rebasing against master - $branch ..."
    git co $branch
    if ! [ $? -eq 0 ] ; then
        echo "Unable to checkout $branch. Exiting..."
        exit 1
    fi
    git rebase master
    if ! [ $? -eq 0 ] ; then
        echo "Exiting. Rebase failed..."
        exit 1
    fi
    git push -f $remote $branch
done

echo
echo "push master..."
git co master
if ! [ $? -eq 0 ] ; then
    echo "Unable to checkout master. Exiting..."
    exit 1
fi
git push $remote master

echo
echo "Returning to original branch..."
git co $original_branch
comments powered by Disqus

  « Previous: Next: »