Skip to content

Instantly share code, notes, and snippets.

@ymendel
Created August 24, 2023 17:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ymendel/248c1b3bdaf6160fa2ffac8f0a7cb224 to your computer and use it in GitHub Desktop.
Save ymendel/248c1b3bdaf6160fa2ffac8f0a7cb224 to your computer and use it in GitHub Desktop.
Little toy git-bisect example

What's this?

This is a very contrived way to show off what git-bisect is good for.

How does it work?

This will create a file called test_file and then do a bunch of commits with one "bad" one randomly inserted somewhere in the middle. And the "bad" commit involves a deletion, so you can't find it using a simple git blame on the file.

Example

./generate_commits.rb
git bisect bad
git bisect good $(git log --oneline | grep "starting state" | cut -d ' ' -f 1)
grep teapot test_file
git bisect [good|bad]
grep teapot test_file
git bisect [good|bad]
...

And based on the result of grep teapot test_file, mark the commit as good or bad until you find the right commit.

You can also just do git bisect run grep teapot test_file and it'll go much more quickly and automatically.

Note

This example has been contrived to make it impossible to use git blame instead of needing to bisect, but it still doesn't require a bisect. You can just do git log -p -G teapot instead. I know this. I just made this to show off how bisect works, and didn't put in the extra work to show where you need to bisect.

#!/usr/bin/env ruby
FILENAME = "test_file"
TOTAL_COMMITS = 100
COMMIT_MESSAGE = "totally innocuous commit"
INITIAL_TEXT = <<~EOT
I'm a little teapot
short and stout
here is my handle
here is my spout
EOT
WORD_LIST = %w[when I get all steamed up hear me shout]
def initial_commit
File.open(FILENAME, mode="w") do |f|
f.puts INITIAL_TEXT
end
system("git", "add", "--all")
system("git", "commit", "--all", "-m", "starting state")
end
def blank_commit
system("git", "commit", "--allow-empty", "-m", COMMIT_MESSAGE)
end
def adding_commit
line = WORD_LIST.shuffle.first(5)
File.open(FILENAME, mode="a") do |f|
f.puts line.join(" ")
end
system("git", "commit", "--all", "-m", COMMIT_MESSAGE)
end
def removing_commit
lines = IO.readlines(FILENAME)
File.open(FILENAME, mode="w") do |f|
f.print lines[0..-2].join()
end
system("git", "commit", "--all", "-m", COMMIT_MESSAGE)
end
def bad_commit
lines = IO.readlines(FILENAME)
File.open(FILENAME, mode="w") do |f|
f.print lines[1..-1].join()
end
system("git", "commit", "--all", "-m", COMMIT_MESSAGE)
end
initial_commit
x = rand((TOTAL_COMMITS/10) .. (TOTAL_COMMITS/5))
bad_commit_index = rand(x .. (TOTAL_COMMITS-x))
1.upto(TOTAL_COMMITS) do |i|
if i == bad_commit_index
bad_commit
next
end
if rand(2).even?
adding_commit
elsif rand(2).even?
removing_commit
else
blank_commit
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment