The variable GIT_SEQUENCE_EDITOR
was initially used to change the editor. It is possible to pass a script to this variable to use git rebase -i
in a non-interactive manner. So it is possible to use:
GIT_SEQUENCE_EDITOR="sed -i -re 's/^pick 134567/e 1234567/'" git rebase -i 1234567^
This command will run sed
on file provided by git rebase -i
. It will change the line pick 134567
into e 1234567
(and so, edit the commit 1234567). You can change e
with r
(rework), f
(fixup), s
(squash) or d
(drop) (the latter is not supported by old versions of git
).
Based on that, I wrote a script that automatizes this task:
#!/bin/bash
ACTION=$1
COMMIT=$(git rev-parse --short $2)
[[ "$COMMIT" ]] || exit 1
CORRECT=
for A in p pick r reword e edit s squash f fixup d drop t split; do
[[ $ACTION == $A ]] && CORRECT=1
done
[[ "$CORRECT" ]] || exit 1
git merge-base --is-ancestor $COMMIT HEAD || exit 1
if [[ $ACTION == "drop" || $ACTION == "d" ]]; then
GIT_SEQUENCE_EDITOR="sed -i -e '/^pick $COMMIT/d'" git rebase -i $COMMIT^^
elif [[ $ACTION == "split" || $ACTION == "t" ]]; then
GIT_SEQUENCE_EDITOR="sed -i -e 's/^pick $COMMIT/edit $COMMIT/'" git rebase -i $COMMIT^^ || exit 1
git reset --soft HEAD^
echo "Hints:"
echo " Select files to be commited using 'git reset', 'git add' or 'git add -p'"
echo " Commit using 'git commit -c $COMMIT'"
echo " Finish with 'git rebase --continue'"
else
GIT_SEQUENCE_EDITOR="sed -i -e 's/^pick $COMMIT/$1 $COMMIT/'" git rebase -i $COMMIT^^
fi
The first argument should be one action. The script uses the same action names than git-rebase. It also add 'split' action (and allow to use drop
with old versions of git).
It also checks that commit you ask for is an ancestor of HEAD. It a common (and really annoying) mistake with rebase -i
.
The second argument is the commit to want to edit/delete/split/reword.
Then you add an alias to your .gitconfig:
[alias]
autorebase = ! path_to_your_script