My old versioning policy was to assign just a release code and a patchlevel, in the form of RELEASE.PATCHLEVEL. This was enough for my projects, but when I started to write libraries it was very difficult to tell if an increment in the PATCHLEVEL meant just a bugfix or a change deep enough to make impossible to use the new version as a drop in replacement for the old version (e.g. some API change). This would force an increment in the RELEASE number for medium importance changes, and probably will confuse the users.
Right now I have TWO different versioning policies, one for projects that export some kind of API/ABI, like libraries, whose intended audience is developers, and another for general projects like applications, etc. where the intended audience is the end users.
I'll explain the shorter, simpler policy first, the one for projects intended for end users. Before, I used version numbers like RELEASE.PATCHLEVEL, later RELEASE.MINOR.PATCHLEVEL, and both worked quite good for me. The problem behind this kind of version numbers is that they no longer mean anything for end users. They are not standardized, so depending on the particular project, the MINOR may mean "odd number for development branch, even number for stable branch", or something equally arbitrary. In my opinion, end users just look at the version number and if it is higher than the version number they have currently installed, they may upgrade. Or, if installing for the first time, they will choose probably the the version with the highest number.
So I think it's much easier for me to distribute my end user projects using a single number as the version number. The higher the number, the newer the version. Yes, an increase in the version number doesn't indicate if the change is just a bugfix, a minor change or an entire rewrite, but current practice doesn't provide that kind of information most of the time and it's unnecesarily complex.
I'm pretty sure that end users are way too familiar with version numbers following the X.Y or X.Y.Z scheme, but nonetheless I'm going to break with it. From now on, only single numbers. This works for Apple, right?
When the project is a library, or any other kind of software that needs to export a public API or ABI, a different scheme is needed. For a start, the intended audience is other programmers and they will correctly interpret (most of the time...) what the version number means, so it's a very good idea to provide as much information as possible in the version number.
In this case, I chose the schema of using a major release code, a minor release code and a patchlevel, in the form of MAJOR.MINOR.PATCHLEVEL. A change in the version code will show more exactly how deep is the update in the software. Here is a reference about the meaning of a code change (I use the term library to refer to anything with a public API or ABI):
To summarize: a PATCHLEVEL increment just means "don't worry, I just fixed a bug", a MINOR increment means "I'm on my way of redesigning the library, but you can use this version instead of the previous one without problems" and a MAJOR increment means "read the docs, this library is not the one you used to know soooooo well, sorry".