Skip to content

Commit d70b4a8

Browse files
Nanako Shiraishispearce
authored andcommitted
Teach rebase -i to honor pre-rebase hook
The original git-rebase honored pre-rebase hook so that public branches can be protected from getting rebased, but rebase --interactive ignored the hook entirely. This fixes it. Signed-off-by: Nanako Shiraishi <[email protected]> Signed-off-by: Shawn O. Pearce <[email protected]>
1 parent 00e5d48 commit d70b4a8

File tree

3 files changed

+148
-7
lines changed

3 files changed

+148
-7
lines changed

git-rebase--interactive.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,16 @@ output () {
6565
esac
6666
}
6767

68+
run_pre_rebase_hook () {
69+
if test -x "$GIT_DIR/hooks/pre-rebase"
70+
then
71+
"$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
72+
echo >&2 "The pre-rebase hook refused to rebase."
73+
exit 1
74+
}
75+
fi
76+
}
77+
6878
require_clean_work_tree () {
6979
# test if working tree is dirty
7080
git rev-parse --verify HEAD > /dev/null &&
@@ -507,6 +517,7 @@ first and then run 'git rebase --continue' again."
507517
;;
508518
--)
509519
shift
520+
run_pre_rebase_hook ${1+"$@"}
510521
test $# -eq 1 -o $# -eq 2 || usage
511522
test -d "$DOTEST" &&
512523
die "Interactive rebase already started"

git-rebase.sh

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,16 @@ is_interactive () {
144144
done && test -n "$1"
145145
}
146146

147+
run_pre_rebase_hook () {
148+
if test -x "$GIT_DIR/hooks/pre-rebase"
149+
then
150+
"$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
151+
echo >&2 "The pre-rebase hook refused to rebase."
152+
exit 1
153+
}
154+
fi
155+
}
156+
147157
test -f "$GIT_DIR"/rebase-apply/applying &&
148158
die 'It looks like git-am is in progress. Cannot rebase.'
149159

@@ -320,13 +330,7 @@ onto_name=${newbase-"$upstream_name"}
320330
onto=$(git rev-parse --verify "${onto_name}^0") || exit
321331

322332
# If a hook exists, give it a chance to interrupt
323-
if test -x "$GIT_DIR/hooks/pre-rebase"
324-
then
325-
"$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
326-
echo >&2 "The pre-rebase hook refused to rebase."
327-
exit 1
328-
}
329-
fi
333+
run_pre_rebase_hook ${1+"$@"}
330334

331335
# If the branch to rebase is given, that is the branch we will rebase
332336
# $branch_name -- branch being rebased, or HEAD (already detached)

t/t3409-rebase-hook.sh

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#!/bin/sh
2+
3+
test_description='git rebase with its hook(s)'
4+
5+
. ./test-lib.sh
6+
7+
test_expect_success setup '
8+
echo hello >file &&
9+
git add file &&
10+
test_tick &&
11+
git commit -m initial &&
12+
echo goodbye >file &&
13+
git add file &&
14+
test_tick &&
15+
git commit -m second &&
16+
git checkout -b side HEAD^ &&
17+
echo world >git &&
18+
git add git &&
19+
test_tick &&
20+
git commit -m side &&
21+
git checkout master &&
22+
git log --pretty=oneline --abbrev-commit --graph --all &&
23+
git branch test side
24+
'
25+
26+
test_expect_success 'rebase' '
27+
git checkout test &&
28+
git reset --hard side &&
29+
git rebase master &&
30+
test "z$(cat git)" = zworld
31+
'
32+
33+
test_expect_success 'rebase -i' '
34+
git checkout test &&
35+
git reset --hard side &&
36+
EDITOR=true git rebase -i master &&
37+
test "z$(cat git)" = zworld
38+
'
39+
40+
test_expect_success 'setup pre-rebase hook' '
41+
mkdir -p .git/hooks &&
42+
cat >.git/hooks/pre-rebase <<EOF &&
43+
#!$SHELL_PATH
44+
echo "\$1,\$2" >.git/PRE-REBASE-INPUT
45+
EOF
46+
chmod +x .git/hooks/pre-rebase
47+
'
48+
49+
test_expect_success 'pre-rebase hook gets correct input (1)' '
50+
git checkout test &&
51+
git reset --hard side &&
52+
git rebase master &&
53+
test "z$(cat git)" = zworld &&
54+
test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,
55+
56+
'
57+
58+
test_expect_success 'pre-rebase hook gets correct input (2)' '
59+
git checkout test &&
60+
git reset --hard side &&
61+
git rebase master test &&
62+
test "z$(cat git)" = zworld &&
63+
test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test
64+
'
65+
66+
test_expect_success 'pre-rebase hook gets correct input (3)' '
67+
git checkout test &&
68+
git reset --hard side &&
69+
git checkout master &&
70+
git rebase master test &&
71+
test "z$(cat git)" = zworld &&
72+
test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test
73+
'
74+
75+
test_expect_success 'pre-rebase hook gets correct input (4)' '
76+
git checkout test &&
77+
git reset --hard side &&
78+
EDITOR=true git rebase -i master &&
79+
test "z$(cat git)" = zworld &&
80+
test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,
81+
82+
'
83+
84+
test_expect_success 'pre-rebase hook gets correct input (5)' '
85+
git checkout test &&
86+
git reset --hard side &&
87+
EDITOR=true git rebase -i master test &&
88+
test "z$(cat git)" = zworld &&
89+
test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test
90+
'
91+
92+
test_expect_success 'pre-rebase hook gets correct input (6)' '
93+
git checkout test &&
94+
git reset --hard side &&
95+
git checkout master &&
96+
EDITOR=true git rebase -i master test &&
97+
test "z$(cat git)" = zworld &&
98+
test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test
99+
'
100+
101+
test_expect_success 'setup pre-rebase hook that fails' '
102+
mkdir -p .git/hooks &&
103+
cat >.git/hooks/pre-rebase <<EOF &&
104+
#!$SHELL_PATH
105+
false
106+
EOF
107+
chmod +x .git/hooks/pre-rebase
108+
'
109+
110+
test_expect_success 'pre-rebase hook stops rebase (1)' '
111+
git checkout test &&
112+
git reset --hard side &&
113+
test_must_fail git rebase master &&
114+
test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
115+
test 0 = $(git rev-list HEAD...side | wc -l)
116+
'
117+
118+
test_expect_success 'pre-rebase hook stops rebase (2)' '
119+
git checkout test &&
120+
git reset --hard side &&
121+
EDITOR=true test_must_fail git rebase -i master &&
122+
test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
123+
test 0 = $(git rev-list HEAD...side | wc -l)
124+
'
125+
126+
test_done

0 commit comments

Comments
 (0)