What version control system are you using? The popular distributed version control systems such as Git or Mercurial distinguish between committing and pushing, whereas SVN (Subversion) does not.
The important part is what commits end up in the shared repository. Ideally, no commit that breaks compilation should ever be pushed. And the application should also run, otherwise just by pushing you halt other developers. And, ideally, all the test should pass, especially the ones what was there before.
Before pushing, in many DVCS like Git, you can do whatever you want, but I strive for the same as above. But you can commit broken commits, and then modify them later to one or several nice commits. Sometimes I make broken commits and push them to a separate server, if I need to continue working on another computer. Then I modify the code, and when it is done I undo the broken commit, and make one nice commit.
You can also use different branches, like feature branches, so developers can work on different parts of the system, and push without disturbing other developers. Then when the feature is done, everything compiles, all the tests pass, you can merge the commits into a main branch.
But the best solution to having long periods of code not working is to never get into the situation. Get to a situation where everything works. From this working situation, try and divide the work into smaller incremental changes where each change results in ending up in a new situation where everything still works.