#!/bin/sh # # Tool to rebase a branch with cleaned commits # # Required: # - some tool for the cleanup # - base commit from which on the current branch shall be cleaned # Do config stuff sh "${0%/*}/cleanupToolConfig.sh" if [ "$?" != "0" ] then echo "You need to edit the configuration file before you can use this tool!" echo "Configuration file: ${0%/*}/cleanupTools.config" exit 0 fi # And use config settings . "${0%/*}/cleanupTools.config" if [ "$BASE_COMMIT" = "" ] then echo "You did not specify a base-commit onto which to rebuild history" echo "or another unexpected error happened.." exit 1 fi # First: commit all changes onto current branch git commit -a -m"Cleanup History Commit: Pending Changes of WorkDir" # Create list of commits that needs to be processed COMMIT_LIST=`git log --reverse --format=format:"%H" $BASE_COMMIT..HEAD` # prepare history_cleanup branch git checkout -b history_cleanup $BASE_COMMIT # cleanup history echo "Cleanup History Tool: Cleanup initial state before rewriting history(might result in an empty commit)" $CLEANUP_TOOL > /dev/null git commit -a -m"Cleanup History Commit: Cleanup state before starting cleaning history" for commit in $COMMIT_LIST do git checkout -b history_cleanup_tmp $commit [[ $? != 0 ]] && exit 1 echo "Cleanup History Tool: Cleanup after commit $commit)" $CLEANUP_TOOL > /dev/null git commit -a -m"Cleanup History Commit: Temp cleaned" --allow-empty [[ $? != 0 ]] && exit 1 git checkout history_cleanup [[ $? != 0 ]] && exit 1 ## Catch differences git diff --binary history_cleanup..history_cleanup_tmp > history_cleanup_tmp.patch # Get committer information to store it COMMITTER_N=$(git show -s --pretty=format:'%cn' ${commit}) [[ $? != 0 ]] && exit 1 COMMITTER_M=$(git show -s --pretty=format:'%ce' ${commit}) [[ $? != 0 ]] && exit 1 COMMITTER_D=$(git show -s --pretty=format:'%cd' ${commit}) [[ $? != 0 ]] && exit 1 GIT_COMMITTER_NAME=$COMMITTER_N; GIT_COMMITTER_EMAIL=$COMMITTER_M; GIT_COMMITTER_DATE=$COMMITTER_D; export GIT_COMMITTER_NAME; export GIT_COMMITTER_EMAIL; export GIT_COMMITTER_DATE; # Two cases: either diff is identical to original commit, or not git diff --binary $commit^..$commit > history_cleanup_compare.patch DIFF_COUNT=`diff history_cleanup_tmp.patch history_cleanup_compare.patch | grep ">" | grep -v "> index " | wc -l` echo "Current State: Diffcount=$DIFF_COUNT" if [ "$DIFF_COUNT" = " 0" ] then # identical# TODO this is too strict! git cherry-pick $commit else # different, use new commit # commit object hash COMMIT_HASH=$(git show -s --pretty=format:'%h' ${commit}) [[ $? != 0 ]] && exit 1 # subject COMMIT_SUBJECT=$(git show -s --pretty=format:'%s' ${commit}) [[ $? != 0 ]] && exit 1 # body COMMIT_BODY=$(git show -s --pretty=format:'%b' ${commit}) [[ $? != 0 ]] && exit 1 # whole message COMMIT_MESSAGE=$(echo -e "${COMMIT_SUBJECT}\n\n${COMMIT_BODY}\n\n(cleaned version of ${COMMIT_HASH})") [[ $? != 0 ]] && exit 1 # Apply Cleaned changeset git apply history_cleanup_tmp.patch if [ $? != 0 ] then echo "Could not apply patch with git methods, try with patch tool directly? (y/n)" read line if [ "$line" = "y" ] then patch -p1 -d. < history_cleanup_tmp.patch echo "Please check manually if this worked.." echo "Did it work? (y/n)" read line if [ "$line" != "y" ] then exit 1 fi fi fi if [ $? != 0 ] then echo "Could not apply patch, store in history_cleanup_tmp.patch" exit 1 fi # Git add new files NEW_FILES_LIST=`grep -B1 "new file mode" history_cleanup_tmp.patch | grep "diff --git a/" | sed 's!diff --git a/\(.*\) .*!\1!'` for fline in $NEW_FILES_LIST do git add $fline [[ $? != 0 ]] && exit 1 done # Commit just created commit with original information git commit -a --allow-empty -C"$commit" [[ $? != 0 ]] && exit 1 git commit --amend --allow-empty -m"${COMMIT_MESSAGE}" [[ $? != 0 ]] && exit 1 fi git branch -D history_cleanup_tmp [[ $? != 0 ]] && exit 1 done rm history_cleanup_tmp.patch rm history_cleanup_compare.patch GIT_COMMITTER_NAME=""; GIT_COMMITTER_EMAIL=""; GIT_COMMITTER_DATE=""; export GIT_COMMITTER_NAME; export GIT_COMMITTER_EMAIL; export GIT_COMMITTER_DATE;