Reputation: 993
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?
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:
The method uses git reset. Warning: before each git reset, make sure files are committed with a branch pointing to the commit
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.
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
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