Skip to content

Commit e247859

Browse files
quickfix: Add a command to quickly fixup commits
This is a somewhat faster alternative to using rebase that doesn't need to touch the working tree, but only works when no conflicts arise from the fixup.
1 parent d7d54f2 commit e247859

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed

git-quickfix

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/bin/bash
2+
3+
set -Eeuo pipefail
4+
5+
if [ $# -lt 1 ]; then
6+
cat <<-EOT
7+
Usage: git quickfix <commit>
8+
9+
This command tries to do a quick commit fixup, for which you would usually
10+
use an interactive rebase with fixup commits. This command tries to do the
11+
same, adding the currently staged changes to the given commit, but without
12+
touching your working tree, thus possibly being a lot faster.
13+
14+
The drawback is, that this tool cannot handle any conflicts and will simply
15+
fail if any are encountered.
16+
17+
Make sure that there are no merge commits in the range <commit>..HEAD, it
18+
they would probably get messed up badly.
19+
20+
Good luck!
21+
EOT
22+
exit 1
23+
fi
24+
25+
COMMIT=$(git rev-parse "$1")
26+
shift
27+
28+
redo_commit () {
29+
COMMIT=$1
30+
PREV=$2
31+
32+
TREE=$(git write-tree)
33+
34+
echo $(git show -s --format='%B' $COMMIT | env \
35+
GIT_AUTHOR_NAME="$(git show -s --format='%an' $COMMIT)" \
36+
GIT_AUTHOR_EMAIL="$(git show -s --format='%ae' $COMMIT)" \
37+
GIT_AUTHOR_DATE="$(git show -s --format='%ad' $COMMIT)" \
38+
git commit-tree -p $PREV $TREE)
39+
}
40+
41+
# Write a tree with the staged changes before switching the index file...
42+
FIXED_TREE=$(git write-tree)
43+
44+
GIT_INDEX_FILE=$(git rev-parse --git-dir)/quickfix-index
45+
export GIT_INDEX_FILE
46+
trap "rm $GIT_INDEX_FILE" EXIT
47+
48+
PREV=$(git rev-parse $COMMIT^)
49+
git read-tree $COMMIT
50+
51+
# Try to fixup the commit...
52+
git show -s --format='Fixing %t %s' $COMMIT
53+
if ! git diff-tree -p HEAD $FIXED_TREE | git apply --cached; then
54+
echo Could not apply changes....
55+
echo Aborting...
56+
exit 1
57+
fi
58+
PREV="$(redo_commit $COMMIT $PREV)"
59+
60+
# Replay the remaining commits
61+
for COMMIT in $(git rev-list --reverse "$COMMIT.."); do
62+
git show -s --format='Applying %t %s' $COMMIT
63+
if ! git diff-tree -p $COMMIT | git apply --cached; then
64+
echo Could not apply changes....
65+
echo Aborting...
66+
exit 1
67+
fi
68+
69+
PREV="$(redo_commit $COMMIT $PREV)"
70+
done
71+
72+
git update-ref HEAD $PREV
73+
74+
exit 0

0 commit comments

Comments
 (0)