Tracking when changes were made, and why, is the job of your source control system. Describing what the code does, is mostly the job of the code; variable names, function names and an occasional brief comment. Describing the expected inputs and outputs of the code is the job of unit testing. Describing the intent of the code, well that's a bit harder to get the right balance. Of course there's lots of overlap, and some huge grey areas.
When reading someone else's code to track down a bug, or add a new feature. I can understand what the code is doing by reading it or debugging it. I can discover who and when from source control. Perhaps cross referencing to extra information in a bug tracker. The hardest bit is discovering what the true intent of the code is supposed to be. That's where comments are the most useful.