You can run rebase with a custom sequence editor. awk
makes it simple enough (depending on your definition of "simple") to detect identical commit messages:
GIT_SEQUENCE_EDITOR='awk "!/^#/{action=\$1;commit=\$2;\$1=\$2=\"\";if(msg==\$0){action=\"fixup\"};print action,commit,\$0;msg=\$0;next}{print}" "$1" > "$1.tmp"; mv "$1.tmp" "$1";:' git rebase -i upstream
The editor command will receive the todo list and can modify it by overwriting the file passed in as $1
.
It's probably best to store this sequencer command in a separate executable script and then simply do GIT_SEQUENCE_EDITOR=path/to/yourscript.sh
or to define a Git alias. This would avoid the escaping madness happening above due to different contexts.
The formatted (and unescaped) awk script with explanations:
!/^#/{ # only process non-comment lines
action=$1; # first field is the action (pick, fixup, etc.)
commit=$2; # second field is the commit id
$1=$2=""; # ignore first two fields when comparing message
if(msg == $0) {
action="fixup" # message was identical to previous line, squash commit
};
print action,commit,$0; # print action, commit id and message (actually, only action + id are required)
msg=$0; # remember current message for next line
next # start processing next line
}
{print} # print comment lines