wolfv
wolfv

Reputation: 993

divide and conquer to locate a code error

The following method uses divide and conquer to locate an error in a program code (not to be confused with git bisect). I used it once and it was useful. Is there a better way to do this in git? Is dragging master branch all over the place good form?

WHAT DIVIDE AND CONQUER LOOKS LIKE IN GIT

A bug could be in any fraction of the code. A 2-level dichotomatic tree with all it's branches looks like this:

* 452a8ff (4/4) i
| * 32d0498 (3/4) h
|/
* 86de3c2 (2/2) g
| * 3740f7e (2/4) f
| | * 4cf909d (1/4) e
| |/
| * e9dc3a4 (1/2) d
|/
* 832edd8 (1/1) c
* a4ca550 'b'
* eafd06c 'a' 

The fractions are branch names. Branch 1/1 contains the entire code. Branch 1/2 contains the first half, and branch 2/2 contains the second half. Branches 1/4, 2/4, 3/4, and 4/4 contain quarters.

Each divide and conquer cycle has 4 steps:

  1. if needed, move HEAD+master branch to a previous commit
  2. eliminate a fraction of the code, compile, and test
  3. commit, where commit message is "error" or "noError"
  4. create a new branch to the current commit, where the branch name is the faction tested

The method uses git reset. Warning: before each git reset, make sure files are committed with a branch pointing to the commit

EXAMPLE

The following example uses divide and conquer to locate an error in the code.

Commit and create the initial branch:

(already on branch to be debugged, reset not needed)
(edit,compile,test)
$ git commit -am "error: description of error we want to locate the source of"
$ git branch 1/1
$ git log --oneline --decorate --graph --all
* 832edd8 (HEAD, master, 1/1) error: description of error
* a4ca550 'b'
* eafd06c 'a'

Error is in branch 1/1. Test first part of branch 1/1:

(already on branch 1/1, reset not needed)
(edit,compile,test)
$ git commit -am "noError"
$ git branch 1/2
$ git log --oneline --decorate --graph --all
* e9dc3a4 (HEAD, master, 1/2) noError
* 832edd8 (1/1) error: description of error
* a4ca550 'b'
* eafd06c 'a' 

No error in branch 1/2. Test other part of branch 1/1:

$ git reset --hard 1/1
(edit,compile,test)
$ git commit -am "error"
$ git branch 2/2
$ git log --oneline --decorate --graph --all
* 86de3c2 (HEAD, master, 2/2) error
| * e9dc3a4 (1/2) noError
|/
* 832edd8 (1/1) error: description of error
* a4ca550 'b'
* eafd06c 'a'

Error in branch 2/2. Test first part of branch 2/2:

(already on branch 2/2, reset not needed)
(edit,compile,test)
$ git commit -am "noError"
$ git branch 3/4
$ git log --oneline --decorate --graph --all
* 32d0498 (HEAD, master, 3/4) noError
* 86de3c2 (2/2) error
| * e9dc3a4 (1/2) noError
|/
* 832edd8 (1/1) error: description of error
* a4ca550 'b'
* eafd06c 'a' 

No error in branch 3/4. Test other part of branch 2/2:

$ git reset --hard 2/2
(edit,compile,test)
$ git commit -am "errorFound"
$ git branch 4/4
$ git log --oneline --decorate --graph --all
* 452a8ff (HEAD, master, 4/4) errorFound
| * 32d0498 (3/4) noError
|/
* 86de3c2 (2/2) error
| * e9dc3a4 (1/2) noError
|/
* 832edd8 (1/1) error: description of error
* a4ca550 'b'
* eafd06c 'a' 

Error found in branch 4/4.

ABBREVIATED VERSION

4-step divide & conquer cycle:

reset & edit
commit & branch

Example:

1/1 error: description
1/2 noError
2/2 error
3/4 noError
4/4 errorFound

Upvotes: 1

Views: 541

Answers (1)

VonC
VonC

Reputation: 1328522

The fractions are branch names. Branch 1/1 contains the entire code. Branch 1/2 contains the first half, and branch 2/2 contains the second half. Branches 1/4, 2/4, 3/4, and 4/4 contain quarters.

Having half (or quarter of, or ...) your code usually doesn't help pinpointing an error, because that error can depends on the context of the codebase (and not the quantity). Meaning: A commit can introduce changes which functionally depends on other changes from other commits.
Simply removing half the code might compromise those functional dependencies, and the code might not work simply because said dependencies are missing.

A git repo looks for the error commit by commit, not set of files by set of files.
The right tool for a "divide and conquer" approach when using commits is git bisect, as commented above.

Upvotes: 2

Related Questions