Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I'd like to mention a feature that's been making my life oh so much easier:

  git bisect
If you're ever looking for "the commit that broke feature XYZ", git bisect is your trusty minion.



Git bisect is wonderful. TortoiseHg also has a bisect command in the Workbench. (But command line hg doesn't seem to have it.)

Here's a tip for anyone using bisect with a Rails app (or any system that uses database migrations):

I do a rake db:migrate after a pull to make sure the database schema is up to date. So the first time I used git bisect on a Rails app, I figured I would use db:migrate after each bisect step.

On this project, as in many Rails projects, schema.rb is checked into git along with the migration files.

Somewhat mysteriously, after some of the bisect steps and db:migrate operations I was seeing an uncommitted schema.rb that was different from the one in git. That shouldn't have happened, I thought.

I finally figured out what perhaps should have been obvious: db:migrate was working fine when bisect moved forward in the history, but it was messing up when bisect moved backward across a migration.

Rails experts will know what went wrong here: After bisect moved backward, the db:migrate had no way of knowing which database changes to reverse, because the migrations that were now in the "future" relative to the latest checkout were removed before I ran the migrate.

I fixed it by using db:reset instead of db:migrate, at least after bisect moved backward in time.

Another bisect tip: Sometimes it can be advantageous to run the equivalent of a bisect manually instead of automatically. For example, you may have some pretty good hunches about which commits may or may not be related to the problem. Or you may want to do a db:migrate before moving back in time to avoid the problem I described above, and by doing the checkouts manually you will know which migrations to reverse before doing the checkout.

In my case, I was looking at a somewhat intermittent bug. As I narrowed down the possible bad commits I wanted to keep track of the specific ones I'd looked at, and git bisect doesn't do this for you. So each time I checked out a different commit I created a local branch first on the commit I'd determined to be (likely) good or bad, giving them names like Good1, Good2, Bad1, Bad2, etc.

This way I could just look at the history as I went along and see at a glance which commits I'd investigated so far.

I guess this trick would work with git bisect as well - just create a local branch before each bisect step.

There may be some better way to do this, but it worked pretty well for me.

BTW, I use SmartGit/Hg and really like it. I know everyone likes their command lines, but I greatly prefer a visual way of working with a source code repo.


If you need to more fiddling to get things working in each bisected commit, you can launch the process manually with 'git bisect start', then pass in refs to 'git bisect bad' and 'git bisect good' to indicate a known-bad and a known-good commit.

At that point, git will check out the "middle" revision and you can do whatever's needed to decide if you should mark it as either good or bad with 'git bisect [good|bad]'. This will check out the new "middle" - lather, rinse, repeat until you get down to one commit.

When you're done, 'git bisect reset' will take you back to the present.

While this isn't quite as quick as the automated version, it's a lifesaver when tracking down a regression in a library whose dependencies have changed radically (finding what b0rked your tests between Rails 3.0 and 4.0, for instance).


> TortoiseHg also has a bisect command in the Workbench. (But command line hg doesn't seem to have it.)

It does, since v1.0 (so about 6 years ago): http://www.selenic.com/mercurial/hg.1.html#bisect

As is usually the case, it's not active by default.

> Rails experts will know what went wrong here: After bisect moved backward, the db:migrate had no way of knowing which database changes to reverse, because the migrations that were now in the "future" relative to the latest checkout were removed before I ran the migrate.

And you can't even do that automatically, because git doesn't have a pre-checkout hook (assuming bisect uses checkout internally, which I'm not certain of)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: