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.3
and1.2.3
are 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 -e
it 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