#!/usr/bin/env bash is_git_repo() { git rev-parse --show-toplevel > /dev/null 2>&1 result=$? if test $result != 0; then >&2 echo 'Not a git repo!' exit $result fi } is_git_repo make_editor_choice() { echo "Which editor do you want to use for this repo?\n"; echo "1. VI\n"; echo "2. NANO\n"; echo "3. Your own\n" echo "You Choose: "; read CHOOSE_EDITOR } get_editor_executable() { echo "What is the path to your prefered test editor?\n"; read EDITOR_PATH } is_has_editor() { SETTINGS_FILE="~/.redate-settings"; if [ -f "$SETTINGS_FILE" ] then OUR_EDITOR=$(cat ${SETTINGS_FILE}); elif [ ! -z "$EDITOR" ] then OUR_EDITOR="$EDITOR"; else make_editor_choice; if [ ${CHOOSE_EDITOR} == 3 ] || [ ${CHOOSE_EDITOR} == "3" ]; then get_editor_executable OUR_EDITOR=${EDITOR_PATH} elif [ ${CHOOSE_EDITOR} == 1 ] || [ ${CHOOSE_EDITOR} == "1" ]; then OUR_EDITOR="vi"; else OUR_EDITOR="nano"; fi echo ${OUR_EDITOR} > ${SETTINGS_FILE} fi } is_has_editor ALL=0 DEBUG=0 LIMITCHUNKS=20 while [[ $# -ge 1 ]] do key="$1" case $key in -c| --commits) COMMITS="$2" if [ -z "${COMMITS}" ]; then COMMITS="5"; fi; shift ;; -l| --limit) LIMITCHUNKS="$2" if [ -z "${LIMITCHUNKS}" ]; then LIMITCHUNKS="20"; fi; shift ;; -d| --debug) DEBUG=1 shift ;; -a| --all) ALL=1 shift ;; *) # unknown option ;; esac shift done die () { echo >&2 `basename $0`: $* exit 1 } tmpfile=$(mktemp gitblah-XXXX) [ -f "$tmpfile" ] || die "could not get tmpfile=[$tmpfile]" trap "rm -f $tmpfile" EXIT datefmt=%cI if [ "`git log -n1 --pretty=format:"$datefmt"`" == "$datefmt" ]; then datefmt=%ci fi if [ "${ALL}" -eq 1 ]; then git log --pretty=format:"$datefmt | %H | %s" > $tmpfile; else if [ -n "${COMMITS+set}" ]; then git log -n ${COMMITS} --pretty=format:"$datefmt | %H | %s" > $tmpfile; else git log -n 5 --pretty=format:"$datefmt | %H | %s" > $tmpfile; fi fi ${VISUAL:-${EDITOR:-${OUR_EDITOR}}} $tmpfile ITER=0 COLITER=0 declare -a COLLECTION COUNTCOMMITS=$(awk 'END {print NR}' $tmpfile) while read commit || [ -n "$commit" ]; do IFS="|" read date hash message <<< "$commit" shopt -s nocasematch if [[ "$date" == 'now' ]]; then date=$(date +%Y-%m-%dT%H:%M:%S%z); fi shopt -u nocasematch if [ "$datefmt" == "%cI" ] then DATE_NO_SPACE="$(echo "${date}" | tr -d '[[:space:]]')" else DATE_NO_SPACE="$(echo "${date}")" fi COMMIT_ENV=$(cat <<-END if [ \$GIT_COMMIT = $hash ]; then export GIT_AUTHOR_DATE="$DATE_NO_SPACE" export GIT_COMMITTER_DATE="$DATE_NO_SPACE"; fi; END ) ((ITER++)) if [ "${DEBUG}" -eq 1 ] && [ $((ITER % LIMITCHUNKS)) == $((LIMITCHUNKS - 1)) ]; then echo "Chunk $COLITER Finished" fi if [ $((ITER % LIMITCHUNKS)) == 0 ] then ((COLITER++)) if [ "${DEBUG}" -eq 1 ]; then echo "Chunk $COLITER Started" fi fi COLLECTION[$COLITER]=${COLLECTION[COLITER]}"$COMMIT_ENV" if [ "${DEBUG}" -eq 1 ] then echo "Commit $ITER/$COUNTCOMMITS Collected" fi done < $tmpfile ITERATOR=0 for each in "${COLLECTION[@]}" do ((ITERATOR++)) if [ "${ALL}" -eq 1 ]; then if [ "${DEBUG}" -eq 1 ]; then echo "Chunk $ITERATOR/"${#COLLECTION[@]}" Started" git filter-branch -f --env-filter "$each" -- --all echo "Chunk $ITERATOR/"${#COLLECTION[@]}" Finished" else git filter-branch -f --env-filter "$each" -- --all >/dev/null fi else if [ "${DEBUG}" -eq 1 ]; then echo "Chunk $ITERATOR/"${#COLLECTION[@]}" Started" git filter-branch -f --env-filter "$each" HEAD~${COMMITS}..HEAD echo "Chunk $ITERATOR/"${#COLLECTION[@]}" Finished" else git filter-branch -f --env-filter "$each" HEAD~${COMMITS}..HEAD >/dev/null fi fi done if [ $? = 0 ] ; then echo "Git commit dates updated. Run 'git push -f BRANCH_NAME' to push your changes." else echo "Git redate failed. Please make sure you run this on a clean working directory." fi