2

My goal is to use git bisect. I'm being stymied by the fact that, apparently close to the commit that introduced the problem I am trying to correct, I introduced another minor error that renders a number of neighbor commits untestable.

This second error was a trivial mistake. I corrected it several commits later.

What I would like to do is this:

git checkout master
git checkout -b fully-testable-branch
git rebase -i initial-good-bisect-point

and then the remove the commit that introduced the second error from the list of commits. I expect and am prepared to deal with a few conflicts in the area of code and of history.

Then, if all goes well (and it should -- most of the commits in this project are testable) I could bisect again, this time between the tip of the fully-testable-branch and initial-good-bisect-point, find and study the problem commit, checkout master, and go from there.

This would work fine if history were linear. (I've done it before.) What git rebase -i does, however, is linearize non-linear history. This, in turn, creates many conflicts that have already been resolved (often not by me, often by me on other machines, so my rerere cache isn't much help). These conflicts are in parts of my program related to neither the error I'm trying to nail down nor to the minor one I have identified.

I'm not thrilled about having to resolve these conflicts all over again. This work was tedious and error-prone enough the first time!

So, is there a way to make git rebase -i replay history including branches and merges? Is there another command that will? Am I going about this all wrong, and, if so, what should I try instead?

Edit: Per request, here's a simplified version of history.

A-B-C-D-E--F-G-H-I-J-R-S-T
     \              /
      \            /
       α-N-M---P--- 
        \     /
         β   /
          \ /
           γ                      

There were conflicts that were resolved at P, and the minor error was created at D. This history is flattened into:

A-B'-C'-D'-E'-F'-α'-β'-γ'-N'-M'-P'-F'-G'-H'-I'-J'-Z'

When replaying history thus, there are conflicts at N', M', and P'.

Michael Wolf
  • 2,179
  • 2
  • 16
  • 14
  • A lot of text - but I am still not sure I understand your final goal. Maybe you can show some sample commit graphs that illustrate what you you have now and what you want to have at the end, after the bisect. – Daniel Hilgarth Apr 17 '13 at 16:49
  • Can you just use `git bisect skip` to ignore the broken commits while bisecting? – loganfsmyth Apr 17 '13 at 16:52
  • @loganfsmyth You can, but if you do you may end up with an imprecise answer: git bisect finished by telling me that the broken commit was one in a list. – Michael Wolf Apr 17 '13 at 16:54
  • Duplicate of [How to avoid git rebase killing merge commits](http://stackoverflow.com/questions/6221624/how-to-avoid-git-rebase-killing-merge-commits)? Possibly not since this is asking about interactive mode, and (as of Git 1.7.9) it doesn't always play well with `--preserve-merges`, but judging from my man pages I think removing a commit would work. – ughoavgfhw Apr 17 '13 at 17:30

1 Answers1

1

To do what you're asking, I think you need to rebase each branch individually, and then re-do the merges.

In your example (slightly truncated for brevity), you'd end up with something like:

           β'-----
          /       \
         α'-N'-...-P'
        /            \
       E'-F'-... -J'-R'-S'-T' [fully-testable-branch]
     /
A-B-C-D-E--F-G-H-I-J-R-S-T [master]
     \              /
      \            /
       α-N-M---P--- 
        \     /
         β ---

(ie, you can create your branch at J, then rebase E..J onto C, then rebase α..P onto E', then merge P' to your new branch creating R', then rebase S..T onto R' etc. etc.


An easier approach might be just to stash your reversion of D somewhere (either using stash or just saving a patch file), and then just apply it to fix the working copy on every bisection.

Useless
  • 64,155
  • 6
  • 88
  • 132