I have an interesting approach to organizing work with Helix. Imagine a quite standard situation, when you have an already running solution with a code base outside web folder, into which gulp script deploys into. Actually, default Helix scenario.
So, you've been working on some module, then halfway down you've renamed that module or simply decided to remove it from solution. After changes finishing with renaming /deleting, and following redeploying the solution, you may potentially get an error (or not get it), but in any case, sooner or later you find out that your web folder still has an old module in a previous stage, dll and configs. To fix that, a DLL of that module needs to be deleted from bin folder manually, as well as all the corresponding old config files from App_Config/Include folder. Not a nice approach...
Things get even worse if you continuously repeat that delete/rename exercise with other modules, increasing chances of malfunction or false positive, and the far you go with that - the more complicated is to clean up the ends. Can you imagine how many unwanted trails are left in your web folder?
For sanity purpose, it is the best practice to ensure that your code is deployed into a clean copy of Sitecore at webroot so that you can be sure that it functions as expected (or not). So how would you achieve obtaining an exactly the same clean Sitecore as you have installed initially, and make this procedure super quick and repeatable? In case you are working on Sitecore previous to version 9 and have used SIM tool in order to install your Sitecore instance, then the answer is obvious - just use SIM backup / restore for that Sitecore instance, quick and reliable. But what if not? What if you are using the latest Sitecore 9?
The method I am suggesting may be sort of arguably, however, it does the job perfectly, quickly and keeps things consistent and at the same place. What I do - I create an isolated git branch called SitecoreFiles_CM at the same git repository where the main codebase sits, and commit an initial state of Sitecore to that branch. Saying initial I mean exactly the same files as they were installed, before Sitecore was even ever accessed - a clean installation. Of course, not all the files are pushed to remote: things like configurations with my individual (for my local dev instance) passwords do not need to be shared with other developers as well as Sitecore license file. That's why on top of that branch that is pushed to remote, I create one more local commit having these individual settings/changes that I do not push. When I have a need to restore vanilla Sitecore, I navigate to web folder and restore folder to that commit. The next step is git clean command required to get rid of the rest of unversioned files on top of vanilla Sitecore that were deployed from the codebase. As simple, as functional.
git reset --hard
git clean -fdx
Both codebase and the corresponding vanilla Sitecore are kept together at the same git repo, for consistency.
Additional benefit: with git diff, you may always see the difference between current web folder state and initial clean install. Not to say, that you can restore each individual file from that set!
When doing platform version upgrades, I upgrade my major codebase along with SitecoreFiles_CM branch, so they again remain consistent Looking ahead, no one stops you from having also a SitecoreFiles_CD branch with a CD set of files, however that is outside of current discussion.
Hope this helps!