Skip to content

Instantly share code, notes, and snippets.

@grobie
Created March 5, 2011 00:15
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save grobie/855956 to your computer and use it in GitHub Desktop.
Save grobie/855956 to your computer and use it in GitHub Desktop.
# git lye
# An attempt to make rebasing easy, by draining unnessarcy commit noise.
# No warranty, use at own risk.
# Author Hannes Tydén <hannes@tyden.name>
# Contributor Tobias Schmidt <ts@soundcloud.com>
# TODO
# - Don't sign off all commits are by current user.
# Name of the source branch containing the changes.
if [ $# -eq 0 ]; then
echo "usage: git lye <source>"
else
SOURCE=$1
# Format of the change commits in the drained commit.
FORMAT="# Commmit %H%n# Author: %aN <%ae>%n# Date: %ai%n* %B"
# Temp files.
GIT_LYE_LOG=/tmp/git-lye-log
GIT_LYE_AUTHORS=/tmp/git-lye-authors
# Number of commits in target branch not included in source.
# Includes merge commits.
COMMITS=$(git rev-list $SOURCE.. | wc -l | sed -e 's/[[:space:]]//g')
R_COMMITS=$(git rev-list ..$SOURCE | wc -l | sed -e 's/[[:space:]]//g')
if [ $COMMITS -eq 0 ]; then
COMMITER=`git config --get user.email`
printf "# Draining $R_COMMITS commits from branch '$SOURCE'\n" >> $GIT_LYE_LOG
# good commit message: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
printf "# Please provide a descriptive commit message:\n" >> $GIT_LYE_LOG
printf "$SOURCE\n\n" >> $GIT_LYE_LOG
# Merge commit messages are usually not interesting.
git log ..$SOURCE --reverse --no-merges -z --format=format:"$FORMAT" >> $GIT_LYE_LOG
# Append
printf "# End of commits.\n" >> $GIT_LYE_LOG
# List of unique authors, last commiter first.
git log ..$SOURCE --no-merges --format='%aN <%ae>' | cat - | awk '{count[$0]++}END{for(j in count) print j,"("count[j]" commits)"}' > $GIT_LYE_AUTHORS
# Last author will be author of drained commit.
GIT_AUTHOR=$(head -n 1 $GIT_LYE_AUTHORS)
# Date will be date of last commit
AUTHOR_DATE=$(git log $SOURCE -n1 --format=format:%ad)
AUTHORS=$(cat $GIT_LYE_AUTHORS | wc -l | sed -e 's/[[:space:]]//g')
# If there are more then 1 author we list them all at the bottom.
if [ $AUTHORS -gt 1 ]; then
# Prepend
printf "\n$AUTHORS authors:\n" | cat - $GIT_LYE_AUTHORS | tee $GIT_LYE_AUTHORS > /dev/null
else
# If the current user is not in the list of commiters he signs this off.
if [ -z "$(grep $COMMITER $GIT_LYE_AUTHORS)" ]; then
SIGNOFF="-s"
fi
# Clear author list
! > $GIT_LYE_AUTHORS
fi
# Create diff and apply
# git diff ..$SOURCE | git apply --whitespace=nowarn
# To support binary changes
git diff ..$SOURCE --full-index --binary | git apply --whitespace=nowarn
# Add files created through the apply
git add .
# Remove files deleted through the apply
DELETED_FILES=$(git ls-files -d)
if [ -n "$DELETED_FILES" ]; then
git rm $DELETED_FILES
fi
# Commit with template message
git commit "--author=$GIT_AUTHOR" "--date=$AUTHOR_DATE" -e $SIGNOFF -m "$(cat $GIT_LYE_LOG $GIT_LYE_AUTHORS)"
if [ $? -eq 0 ]; then
echo "$R_COMMITS commit(s) drained."
else
git reset --hard
echo "Draining aborted."
fi
# Clean up
rm $GIT_LYE_LOG $GIT_LYE_AUTHORS
else
echo "There are $COMMITS commit(s) in the current branch that prevents draining."
echo "Please merge these into $SOURCE and try again."
echo ""
git log $SOURCE.. --format=oneline
fi
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment