Example using git bisect to narrow in on a commit
I learned about
git bisect
from this Stack Overflow poll:
What are your favorite git features or tricks?
I thought it was so cool that I wanted to share an example.
After upgrading from Django 1.2.3 to Django 1.3, something broke on the website
I was working on. To figure out what was wrong, I used git bisect
to find the Django revision that introduced the relevant change. I cloned the
Django github repo and
pip install -e'd it into my virtualenv. Then
I used git bisect as follows:
- Start git bisect
$ git bisect start$ git bisect bad 1.3$ git bisect good 1.2.3 Bisecting: a merge base must be tested [618153bd3b047529f6cfb50917c88270f30e8ea8] Fixed #10843: the textile tests now pass against the latest textile library.
Note:
1.3and1.2.3are git tags in the Django git repo. Commit SHA1 hashes can be used instead. - Start the development server in another terminal. Load the webpage in the browser. The page loads without error.
[04/Aug/2011 19:13:20] "GET /my/webpage/ HTTP/1.1" 200 16279
- Mark the revision good
$ git bisect good Bisecting: 774 revisions left to test after this (roughly 10 steps) [39591cddccffdf3b66cfaaa60b95257daa4ef8c5] Fixed #14781 - Setting "CACHE_PREFIX" should be "CACHE_KEY_PREFIX". Thanks to adamv for report and patch.
- Reload the page. This time it throws a 500 error.
[04/Aug/2011 19:13:59] "GET /my/webpage/ HTTP/1.1" 500 118861
- Mark the revision bad
$ git bisect bad Bisecting: 387 revisions left to test after this (roughly 9 steps) [6630bd24f45c7967c49b90adf82c63dd7d93e6f7] Fixed #13863 -- Corrected decimal separator in Swedish format module. Thanks, Ulf Urdén.
- Reload
[04/Aug/2011 19:15:45] "GET /my/webpage/ HTTP/1.1" 500 117536
- Mark the revision bad
$ git bisect bad Bisecting: 193 revisions left to test after this (roughly 8 steps) [4d19282beb19b95e73aec119b40ed40456065a21] Migrated custom_methods doctests. Thanks to Alex Gaynor.
- Etc...
[04/Aug/2011 19:16:17] "GET /my/webpage/ HTTP/1.1" 500 117536
$ git bisect bad Bisecting: 96 revisions left to test after this (roughly 7 steps) [ed63689b9e3be80c3af51bfc5d6805bcedbae9f0] Added file missing from r13590.
[04/Aug/2011 19:16:46] "GET /my/webpage/ HTTP/1.1" 200 16279
$ git bisect good Bisecting: 48 revisions left to test after this (roughly 6 steps) [2eca0cd7f5fe6efd1f177724a948cdde7475f54c] Fixed #13754 - Add a note about a test client session property gotcha
[04/Aug/2011 19:17:12] "GET /my/webpage/ HTTP/1.1" 200 16279
$ git bisect good Bisecting: 24 revisions left to test after this (roughly 5 steps) [d7e3c7bad40e5f66169b8b951d74c87103ece07d] Fixed #13095 -- `formfield_callback` keyword argument is now more sane and works with widgets defined in `ModelForm.Meta.widgets`. Thanks, hvdklauw for bug report, vung for initial patch, and carljm for review.
[04/Aug/2011 19:17:31] "GET /my/webpage/ HTTP/1.1" 200 16279
$ git bisect good [I forgot to copy/paste the console output for this one]
[04/Aug/2011 19:17:54] "GET /my/webpage/ HTTP/1.1" 500 117536
$ git bisect bad Bisecting: 5 revisions left to test after this (roughly 3 steps) [622bf3b2199e5e7015edccb00f1ab694291ca121] Fixed #11905: Raise an error on model form creation if a non-existent field was listed in fields. Thanks ben and copelco.
[04/Aug/2011 19:18:17] "GET /my/webpage/ HTTP/1.1" 500 117536
$ git bisect bad Bisecting: 2 revisions left to test after this (roughly 2 steps) [57427e9d758eb37b43f6b7804b24c6f47c2fa456] Fixed a test so that it actually tests what it's supposed to test.
[04/Aug/2011 19:18:37] "GET /my/webpage/ HTTP/1.1" 200 16279
$ git bisect good Bisecting: 0 revisions left to test after this (roughly 1 step) [dcb12158881cdcc619de0ae6d3f6cf674a0d4abb] Better error message for calling get_next_by_* on unsaved models. Patch from Marc Fargas. Fixed #7435.
[04/Aug/2011 19:19:07] "GET /my/webpage/ HTTP/1.1" 200 16279
- After marking the last commit, git bisect shows the first bad commit as 622bf3b2199e5e7015edccb00f1ab694291ca121
$ git bisect good 622bf3b2199e5e7015edccb00f1ab694291ca121 is the first bad commit commit 622bf3b2199e5e7015edccb00f1ab694291ca121 Author: kmtracey <kmtracey> Date: Sat Sep 11 01:39:16 2010 +0000 Fixed #11905: Raise an error on model form creation if a non-existent field was listed in fields. Thanks ben and copelco. git-svn-id: http://code.djangoproject.com/svn/django/trunk@13739 bcc190cf-cafb-0310-a4f2-bffc1f526a37 :040000 040000 87ec1601b970938b55382a5aa66db74716552c3d 2d418dfe8dd9f67fea408e022aa13838086ce33b M django :040000 040000 054e6f42b3b467e47f295f8fda6cdc8a7f2c054c 52ba5265ba9d6458f23c8cb4a8a9bdcdbfc1f590 M tests</kmtracey>
Note: checking for failed unit tests instead of checking for a 500 error in the browser
is another (probably better) way to test with git bisect.
Note 2: The problem with my code was that I was adding extra fields to a model
formset in the wrong way. I was trying to use add_fields on a base
model formset instead of creating a custom Form with the extra field
and specifying it in the factory. This
Stack Overflow answer
solved the problem for me.
Extra details
Here's how I installed Django from github
- Clone the Django repo and
pip install -eit in my virtualenv$ git clone https://github.com/django/django.git django-github $ cd django-github $ workon myenv $ pip install -e ./
- In another terminal run the Django development server
$ cd /myproject $ workon myenv $ python manage.py runserver
Related posts
- git notes — posted 2011-08-11
- Colorized, interactive "git blame" in Emacs: vc-annotate — posted 2011-05-28
- Versioning /etc with etckeeper and git — posted 2011-04-24
- My software tools list — posted 2007-08-10
1
Comment
—
Comments feed for this post
Post a comment
About
I'm Eliot and this is my notepad for programming topics such as Python, Django, Ubuntu, Emacs, etc... more »
Search Blog
Tags
-
algorithms
(6)
-
aws
(10)
-
blogproject
(20)
-
c_cplusplus
(12)
-
cardstore
(8)
-
colinux
(2)
-
concurrency
(13)
-
conkeror
(2)
-
core
(2)
-
cygwin
(17)
-
datastructures
(14)
-
datetime
(4)
-
decorators
(4)
-
django
(40)
-
emacs
(22)
-
files_directories
(12)
-
git
(5)
-
hardware
(5)
-
install_setup
(8)
-
javascript
(3)
-
keyboard
(9)
-
matplotlib
(6)
-
mercurial
(4)
-
nginx
(2)
-
persistence
(6)
-
preferences
(7)
-
processes
(4)
-
pyqt
(18)
-
python
(145)
-
ratpoison
(3)
-
regexes
(6)
-
rsync
(3)
-
softwaretools
(17)
-
sql
(14)
-
ssh
(10)
-
subversion
(6)
-
twisted
(7)
-
ubuntu
(65)
-
urxvt
(5)
-
vxworks
(25)
-
webdev
(6)
-
wmii
(7)
Blogroll
- Adam Gomaa
- Alex Clemesha
- Amir Salihefendic
- Armin Ronacher
- David Beazley
- David Ziegler
- Duncan McGreggor
- Gareth Rushgrave
- Glyph Lefkowitz
- Guido van Rossum
- Ian Bicking
- Jacob Kaplan-Moss
- James Bennett
- James Tauber
- Jesper Noehr
- Marty Alchin
- Matt Harrison
- Nikolay Kolev
- Parand Darugar
- Peter Baumgartner
- Peter Bengtsson
- Rob Hudson
- Simon Willison
- Will McGugan
#1 Peter Hanley commented on 2011-09-12:
I've been finding digging into the surface of git that I scratched somewhat difficult - but you laid bare a really specific and clear use case that I get immediately.
I think the problem I have is that I've mostly used git to update from a repo where I'm not a committer, so most of the tutorials, and use cases that are published don't really apply.
Thanks for this.