Skip to content

Instantly share code, notes, and snippets.

@jayvdb
Last active September 26, 2017 00:35
Show Gist options
  • Save jayvdb/9b41677f00065dbd94cc02446fc5ba34 to your computer and use it in GitHub Desktop.
Save jayvdb/9b41677f00065dbd94cc02446fc5ba34 to your computer and use it in GitHub Desktop.
Generate git-rebase-todo-list to squash similar commits
# Warning: Due to child_hash optimisation this doesnt support merges
# Usable with GIT_EDITOR='touch'
# TODO: Create a better GIT_EDITOR command that
# strips only blank lines in commit body
# TODO: Support merges
# different levels of merging:
author_tag_format="%ae"
same_author_day_tag_format="%ae-%ad"
almost_identical_tag_format="%ae-%ad-%f"
# chosen level
tag_format="$author_tag_format"
consecutive_file_list=/tmp/consecutive_file_list.txt
git rev-list --all --children > /tmp/children_rev_list.txt
git log --pretty=tformat:"%H ${tag_format}" --date=short --reverse | (
prev_hash=""
prev_tag=""
prev_only_adds_files=""
while read line; do
set $line
hash="$1"
tag="$2"
only_adds_files=""
if [ "$tag" = "$prev_tag" ]; then
if git diff-tree --no-commit-id --name-status -r "$hash" | grep -qv '^A' ; then
true
else
only_adds_files="true"
if [ -z "$prev_only_adds_files" ]; then
if git diff-tree --no-commit-id --name-status -r "$prev_hash" | grep -qv '^A' ; then
true
else
git diff-tree --no-commit-id --name-only -r "$prev_hash" > $consecutive_file_list
prev_only_adds_files="true"
fi
fi
if [ "$prev_only_adds_files" = "true" ]; then
git diff-tree --no-commit-id --name-only -r "$hash" >> $consecutive_file_list
fi
fi
fi
if [ -z "$prev_hash" ]; then
echo "# rebasing onto $hash : $tag"
elif [ "$tag" = "$prev_tag" -a -n "$only_adds_files" -a -n "$prev_only_adds_files" ]; then
echo "squash $hash $tag"
# Peek ahead at the child hash; not very efficient here
child_hash=$(grep "^$hash" /tmp/children_rev_list.txt | cut -d ' ' -f 2)
# If child hash wont be another squash, it is time to write a better commit message
if git diff-tree --no-commit-id --name-status -r "$child_hash" | grep -qv '^A' ; then
echo -n "exec git commit --amend -m 'Added consecutive files'"
cat $consecutive_file_list | while read line; do
printf " -m %q" "$line"
done
echo ""
fi
else
echo "pick $hash $tag"
fi
prev_hash="$hash"
prev_tag="$tag"
prev_only_adds_files="$only_adds_files"
done
)
# Use with
# echo 'print if ! $x{$_}++' > /tmp/strip-seen-lines.pl
# GIT_EDITOR='perl -i -n -f /tmp/strip-seen-lines.pl'
# different levels of merging:
author_tag_format="%ae"
almost_identical_tag_format="%ae-%ad-%f"
# chosen level
tag_format="$almost_identical_tag_format"
git log --pretty=tformat:"%H ${tag_format}" --date=short --reverse | (
prev_hash=""
prev_tag=""
while read line; do
set $line
hash=$1
tag=$2
if [ -z "$prev_hash" ]; then
echo "# rebasing onto $hash : $tag"
elif [ "$tag" = "$prev_tag" ]; then
echo "squash $hash $tag"
else
echo "pick $hash $tag"
fi
prev_hash=$hash
prev_tag=$tag
done
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment