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