Yes, well, maybe I missed one step of #4:
When encountering a bug, go back to that branch, merge master into it to update it with all the new stuff developed until now, then fix the bug and merge the branch back into master.
You might say: But once you merge master into the feature branch, then all the commits are mixed! Yes.. if you type "git log" and no.. if you type other commands (not 100% sure on the command line way) or use GitHub. git remembers which branch the commits were performed on and can list them for you. An example
here where redv has multiple commits, including a merge and conflict fixes, which still shows only his commits.
Whenever you want a new feature, you checkout the most up to date version of master, and build your new feature on whatever is in master (including all the features that have been previously merged into it). Granted, if you use code from previous features, it will not be possible to just take that branch and merge it into some other repo that doesn't have the "basis features", but it will still be
much easier than if you worked directly on your master since the merger can:
1 - Try to merge your branch
2 - Fail because it depends on another feature
3 - list all changes done to a file in which there is a conflict, to see what else was done
4 - figure out which feature is required and try to merge that (and so on until you reach "basic features" that don't depend on anything)
That's a lot of work, but it more manageable than trying to figure out what is happening when every commit is tagged as being done in master since you have extra information: what branch/feature each commit belongs to and you can approach the problem using branches/features instead of individual commits.