#!/bin/bash # Make a patch for the current branch based on its tracking branch # Process args while getopts "ahd:" opt; do case "$opt" in a) addendum='-addendum' ;; d) patch_dir=$OPTARG ;; *) echo -e "Usage: $0 [-h] [-a] [-d] \n\ Must be run from within the git branch to make the patch against.\n\ -h - display these instructions.\n\ -a - Add an 'addendum' prefix to the patch name.\n\ -d - specify a patch directory (defaults to ~/patches/)" exit 0 ;; esac done # Find what branch we are on branch=$(git branch |grep '*' |awk '{print $2}') if [ ! "$branch" ]; then echo "Can't determine the git branch. Exiting." >&2 exit 1 fi # Exit if git status is dirty git_dirty=$(git diff --shortstat 2> /dev/null | wc -l|awk {'print $1'}) echo "git_dirty is $git_dirty" if [ "$git_dirty" -ne 0 ]; then echo "Git status is dirty. Commit locally first.">&2 exit 1 fi # Determine the tracking branch git log -n 1 origin/$branch > /dev/null 2>&1 status=$? if [ "$status" -eq 128 ]; then # Status 128 means there is no remote branch tracking_branch='origin/master' elif [ "$status" -eq 0 ]; then # Status 0 means there is a remote branch tracking_branch="origin/$branch" else echo "Unknown error: $?" >&2 exit 1 fi # Deal with invalid or missing $patch_dir if [ ! "$patch_dir" ]; then echo -e "Patch directory not specified. Falling back to ~/patches/." patch_dir=~/patches fi if [ ! -d "$patch_dir" ]; then echo "$patch_dir does not exist. Creating it." mkdir $patch_dir fi # Determine what to call the patch # Check to see if any patch exists that includes the branch name status=$(ls $patch_dir/*$branch* 2>/dev/null|grep -v addendum|wc -l|awk {'print $1'}) if [ "$status" -eq 0 ]; then # This is the first patch we are making for this release prefix='' elif [ "$status" -ge 1 ]; then # At least one patch already exists -- add a version prefix for i in {1..99}; do # Check to see the maximum version of patch that exists if [ ! -f "$patch_dir/$branch-v$i.patch" ]; then version=$i if [ -n "$addendum" ]; then # Don't increment the patch # if it is an addendum echo "Creating an addendum" if [ "$version" -eq 1 ]; then # We are creating an addendum to the first version of the patch prefix='' else # We are making an addendum to a different version of the patch let version=$version-1 prefix="-v$version" fi else prefix="-v$version" fi break fi done fi patch_name="$branch$prefix$addendum.patch" # Do we need to make a diff? git diff --quiet $tracking_branch status=$? if [ "$status" -eq 0 ]; then echo "There is no difference between $branch and $tracking_branch." echo "No patch created." exit 0 fi # Check whether we need to squash or not local_commits=$(git log $tracking_branch..$branch|grep 'Author:'|wc -l|awk {'print $1'}) if [ "$local_commits" -gt 1 ]; then read -p "$local_commits commits exist only in your local branch. Interactive rebase?" yn case $yn in [Yy]* ) git rebase -i $tracking_branch ;; [Nn]* ) echo "Creating $patch_dir/$patch_name using git diff." git diff $tracking_branch > $patch_dir/$patch_name exit 0 ;; esac fi echo "Creating patch $patch_dir/$patch_name using git format-patch" git format-patch --stdout $tracking_branch > $patch_dir/$patch_name