1
1
#! /bin/sh
2
2
3
3
USAGE=' [start|bad|good|next|reset|visualize|replay|log|run]'
4
- LONG_USAGE=' git bisect start [<pathspec>] reset bisect state and start bisection.
5
- git bisect bad [<rev>] mark <rev> a known-bad revision.
6
- git bisect good [<rev>...] mark <rev>... known-good revisions.
7
- git bisect next find next bisection to test and check it out.
8
- git bisect reset [<branch>] finish bisection search and go back to branch.
9
- git bisect visualize show bisect status in gitk.
10
- git bisect replay <logfile> replay bisection log.
11
- git bisect log show bisect log.
12
- git bisect run <cmd>... use <cmd>... to automatically bisect.'
4
+ LONG_USAGE=' git bisect start [<bad> [<good>...]] [--] [<pathspec>...]
5
+ reset bisect state and start bisection.
6
+ git bisect bad [<rev>]
7
+ mark <rev> a known-bad revision.
8
+ git bisect good [<rev>...]
9
+ mark <rev>... known-good revisions.
10
+ git bisect next
11
+ find next bisection to test and check it out.
12
+ git bisect reset [<branch>]
13
+ finish bisection search and go back to branch.
14
+ git bisect visualize
15
+ show bisect status in gitk.
16
+ git bisect replay <logfile>
17
+ replay bisection log.
18
+ git bisect log
19
+ show bisect log.
20
+ git bisect run <cmd>...
21
+ use <cmd>... to automatically bisect.'
13
22
14
23
. git-sh-setup
15
24
require_work_tree
@@ -70,14 +79,48 @@ bisect_start() {
70
79
#
71
80
# Get rid of any old bisect state
72
81
#
73
- rm -f " $GIT_DIR /refs/heads/bisect"
74
- rm -rf " $GIT_DIR /refs/bisect/"
82
+ bisect_clean_state
75
83
mkdir " $GIT_DIR /refs/bisect"
84
+
85
+ #
86
+ # Check for one bad and then some good revisions.
87
+ #
88
+ has_double_dash=0
89
+ for arg; do
90
+ case " $arg " in --) has_double_dash=1; break ;; esac
91
+ done
92
+ orig_args=$( sq " $@ " )
93
+ bad_seen=0
94
+ while [ $# -gt 0 ]; do
95
+ arg=" $1 "
96
+ case " $arg " in
97
+ --)
98
+ shift
99
+ break
100
+ ;;
101
+ * )
102
+ rev=$( git-rev-parse --verify " $arg ^{commit}" 2> /dev/null) || {
103
+ test $has_double_dash -eq 1 &&
104
+ die " '$arg ' does not appear to be a valid revision"
105
+ break
106
+ }
107
+ if [ $bad_seen -eq 0 ]; then
108
+ bad_seen=1
109
+ bisect_write_bad " $rev "
110
+ else
111
+ bisect_write_good " $rev "
112
+ fi
113
+ shift
114
+ ;;
115
+ esac
116
+ done
117
+
118
+ sq " $@ " > " $GIT_DIR /BISECT_NAMES"
76
119
{
77
120
printf " git-bisect start"
78
- sq " $@ "
79
- } > " $GIT_DIR /BISECT_LOG"
80
- sq " $@ " > " $GIT_DIR /BISECT_NAMES "
121
+ echo " $orig_args "
122
+ } >> " $GIT_DIR /BISECT_LOG"
123
+ bisect_auto_next
81
124
}
82
125
83
126
bisect_bad () {
@@ -90,12 +133,17 @@ bisect_bad() {
90
133
* )
91
134
usage ;;
92
135
esac || exit
93
- echo " $rev " > " $GIT_DIR /refs/bisect/bad"
94
- echo " # bad: " $( git-show-branch $rev ) >> " $GIT_DIR /BISECT_LOG"
136
+ bisect_write_bad " $rev "
95
137
echo " git-bisect bad $rev " >> " $GIT_DIR /BISECT_LOG"
96
138
bisect_auto_next
97
139
}
98
140
141
+ bisect_write_bad () {
142
+ rev=" $1 "
143
+ echo " $rev " > " $GIT_DIR /refs/bisect/bad"
144
+ echo " # bad: " $( git-show-branch $rev ) >> " $GIT_DIR /BISECT_LOG"
145
+ }
146
+
99
147
bisect_good () {
100
148
bisect_autostart
101
149
case " $# " in
@@ -106,35 +154,54 @@ bisect_good() {
106
154
for rev in $revs
107
155
do
108
156
rev=$( git-rev-parse --verify " $rev ^{commit}" ) || exit
109
- echo " $rev " > " $GIT_DIR /refs/bisect/good-$rev "
110
- echo " # good: " $( git-show-branch $rev ) >> " $GIT_DIR /BISECT_LOG"
157
+ bisect_write_good " $rev "
111
158
echo " git-bisect good $rev " >> " $GIT_DIR /BISECT_LOG"
159
+
112
160
done
113
161
bisect_auto_next
114
162
}
115
163
164
+ bisect_write_good () {
165
+ rev=" $1 "
166
+ echo " $rev " > " $GIT_DIR /refs/bisect/good-$rev "
167
+ echo " # good: " $( git-show-branch $rev ) >> " $GIT_DIR /BISECT_LOG"
168
+ }
169
+
116
170
bisect_next_check () {
117
- next_ok=no
118
- test -f " $GIT_DIR /refs/bisect/bad" &&
119
- case " $( cd " $GIT_DIR " && echo refs/bisect/good-* ) " in
120
- refs/bisect/good-\* ) ;;
121
- * ) next_ok=yes ;;
122
- esac
123
- case " $next_ok ,$1 " in
124
- no,) false ;;
125
- no,fail)
126
- THEN=' '
127
- test -d " $GIT_DIR /refs/bisect" || {
128
- echo >&2 ' You need to start by "git bisect start".'
129
- THEN=' then '
130
- }
131
- echo >&2 ' You ' $THEN ' need to give me at least one good' \
132
- ' and one bad revisions.'
133
- echo >&2 ' (You can use "git bisect bad" and' \
134
- ' "git bisect good" for that.)'
135
- exit 1 ;;
171
+ missing_good= missing_bad=
172
+ git show-ref -q --verify refs/bisect/bad || missing_bad=t
173
+ test -n " $( git for-each-ref " refs/bisect/good-*" ) " || missing_good=t
174
+
175
+ case " $missing_good ,$missing_bad ,$1 " in
176
+ ,,* )
177
+ : have both good and bad - ok
178
+ ;;
179
+ * ,)
180
+ # do not have both but not asked to fail - just report.
181
+ false
182
+ ;;
183
+ t,,good)
184
+ # have bad but not good. we could bisect although
185
+ # this is less optimum.
186
+ echo >&2 ' Warning: bisecting only with a bad commit.'
187
+ if test -t 0
188
+ then
189
+ printf >&2 ' Are you sure [Y/n]? '
190
+ case " $( read yesno) " in [Nn]* ) exit 1 ;; esac
191
+ fi
192
+ : bisect without good...
193
+ ;;
136
194
* )
137
- true ;;
195
+ THEN=' '
196
+ test -d " $GIT_DIR /refs/bisect" || {
197
+ echo >&2 ' You need to start by "git bisect start".'
198
+ THEN=' then '
199
+ }
200
+ echo >&2 ' You ' $THEN ' need to give me at least one good' \
201
+ ' and one bad revisions.'
202
+ echo >&2 ' (You can use "git bisect bad" and' \
203
+ ' "git bisect good" for that.)'
204
+ exit 1 ;;
138
205
esac
139
206
}
140
207
@@ -145,27 +212,32 @@ bisect_auto_next() {
145
212
bisect_next () {
146
213
case " $# " in 0) ;; * ) usage ;; esac
147
214
bisect_autostart
148
- bisect_next_check fail
215
+ bisect_next_check good
216
+
149
217
bad=$( git-rev-parse --verify refs/bisect/bad) &&
150
- good=$( git-rev-parse --sq --revs-only --not \
151
- $( cd " $GIT_DIR " && ls refs/bisect/good-* ) ) &&
152
- rev=$( eval " git-rev-list --bisect $good $bad -- $( cat " $GIT_DIR /BISECT_NAMES" ) " ) || exit
153
- if [ -z " $rev " ]; then
154
- echo " $bad was both good and bad"
155
- exit 1
218
+ good=$( git for-each-ref --format=' ^%(objectname)' \
219
+ " refs/bisect/good-*" | tr ' [\012]' ' ' ) &&
220
+ eval=" git-rev-list --bisect-vars $good $bad --" &&
221
+ eval=" $eval $( cat " $GIT_DIR /BISECT_NAMES" ) " &&
222
+ eval=$( eval " $eval " ) &&
223
+ eval " $eval " || exit
224
+
225
+ if [ -z " $bisect_rev " ]; then
226
+ echo " $bad was both good and bad"
227
+ exit 1
156
228
fi
157
- if [ " $rev " = " $bad " ]; then
158
- echo " $rev is first bad commit"
159
- git-diff-tree --pretty $rev
160
- exit 0
229
+ if [ " $bisect_rev " = " $bad " ]; then
230
+ echo " $bisect_rev is first bad commit"
231
+ git-diff-tree --pretty $bisect_rev
232
+ exit 0
161
233
fi
162
- nr= $( eval " git-rev-list $rev $good -- $( cat $GIT_DIR /BISECT_NAMES ) " | wc -l ) || exit
163
- echo " Bisecting: $nr revisions left to test after this"
164
- echo " $rev " > " $GIT_DIR /refs/heads/new-bisect"
234
+
235
+ echo " Bisecting: $bisect_nr revisions left to test after this"
236
+ echo " $bisect_rev " > " $GIT_DIR /refs/heads/new-bisect"
165
237
git checkout -q new-bisect || exit
166
238
mv " $GIT_DIR /refs/heads/new-bisect" " $GIT_DIR /refs/heads/bisect" &&
167
239
GIT_DIR=" $GIT_DIR " git-symbolic-ref HEAD refs/heads/bisect
168
- git-show-branch " $rev "
240
+ git-show-branch " $bisect_rev "
169
241
}
170
242
171
243
bisect_visualize () {
@@ -190,14 +262,19 @@ bisect_reset() {
190
262
usage ;;
191
263
esac
192
264
if git checkout " $branch " ; then
193
- rm -fr " $GIT_DIR /refs/bisect"
194
- rm -f " $GIT_DIR /refs/heads/bisect" " $GIT_DIR /head-name"
195
- rm -f " $GIT_DIR /BISECT_LOG"
196
- rm -f " $GIT_DIR /BISECT_NAMES"
197
- rm -f " $GIT_DIR /BISECT_RUN"
265
+ rm -f " $GIT_DIR /head-name"
266
+ bisect_clean_state
198
267
fi
199
268
}
200
269
270
+ bisect_clean_state () {
271
+ rm -fr " $GIT_DIR /refs/bisect"
272
+ rm -f " $GIT_DIR /refs/heads/bisect"
273
+ rm -f " $GIT_DIR /BISECT_LOG"
274
+ rm -f " $GIT_DIR /BISECT_NAMES"
275
+ rm -f " $GIT_DIR /BISECT_RUN"
276
+ }
277
+
201
278
bisect_replay () {
202
279
test -r " $1 " || {
203
280
echo >&2 " cannot read $1 for replaying"
0 commit comments