Let's say I want to locate the first (oldest) Git revision which adds the line delta
to text file file
.
But I want to use git bisect
for this rather than searching the output of git log -p
because of performance reasons (huge repository).
First create a repository testrepo
as a test case for demonstrating the search:
r=testrepo
git init $r && cd $r
dt='2022-12-07 11:30:00 +0100'
an='Guenther Brunthaler' ae='some_username@somewhere.example'
for add in alpha beta gamma delta epsilon zeta eta
do
echo $add >> file
git add file
GIT_AUTHOR_NAME="$an" GIT_COMMITTER_NAME="$an" \
GIT_AUTHOR_EMAIL="$ae" GIT_COMMITTER_EMAIL="$ae" \
GIT_AUTHOR_DATE="$dt" GIT_COMMITTER_DATE="$dt" \
git commit -m "Adding $add"
done
unset r dt am ae
This repository contains a file file
to which the next Greek letter name has been appended in every revision.
Now we want to locate the commit which added the line delta
.
This should be commit a2444b7
, because:
$ git log --oneline | grep delta | tail -n 1
a2444b7 Adding delta
Use the "git bisect" command like this:
relfile=file added=delta
initial=`git log --graph --pretty=%h | cut -d ' ' -f 2 | tail -n 1`
git bisect reset # optional: abort an already running bisect
git bisect start
git bisect bad HEAD
git bisect good $initial
git bisect run sh -c "test ! -e '${relfile?:}' || grep -qv '${added?:}' '${relfile?:}'"
where $initial
is the commit ID of the initial commit, $added
is the RegEx for locating the new feature within file $relfile
.
The above command should display the ID of the commit introducing the feature:
b0ece99babe9ffb16b7792d4e810cb3cc9571385 is the first bad commit
But obviously, this is the wrong commit!
What can I do in order to make git bisect run
report revision a2444b7
as the first bad commit
?
The success exit status of grep
tells that any lines would be printed printed. Usually, this coincides with whether a line that matches the pattern was found. But when you pass -v
, successful exit happens when at least one non-matching line was found. That is not what you want.
Use ! grep
without -v
to stop at the correct commit:
git bisect run sh -c "test ! -e '${relfile?:}' || ! grep -q '${added?:}' '${relfile?:}'"