Ver, Huh, What Is It Good For?
In contrast to the song partially quoted here, the answer is more likely "everything," or at least "a lot." Understanding and orchestrating the concept of versioning is the key to solving the puzzles of software-engineering in the modern world. More and more development is done following the concepts of SOA, and thus, microservices. Modularization and dependency management have become the key factors between the success and failure of a project.
Whenever a project runs long enough, the simple and linear path of adding functionality or fixing existing bugs for the latest released product, releasing the next increment will be eventually broken by the parallel development of the next big increments or hotfixes.
We distinguish between the versioning of the source code and the product (the built artifacts from the source code), though both of them are linked.
Version Control Systems
With the rise of Git, it became very easy to maintain versioning of the source code over several functionally defined streams (though other version control systems have been there for a substantial amount of time aiming for the same goal), and Git Flow is becoming a very popular branching model (including tooling) for an obvious reason.
Semantic Versioning Scheme
It is certainly a matter of taste, but when it comes to versioning schemes, I (and many others) prefer the semantic versioning scheme (www.semver.org). The versioning scheme defines which part of the version descriptor is to be changed if you change your code, and thus the product.
In the case of semantic versioning, the version scheme is described as follows (taken from www.semver.org): "Given a version number MAJOR.MINOR.PATCH, increment the: 1. MAJOR version when you make incompatible API changes, 2. MINOR version when you add functionality in a backwards-compatible manner, and 3. PATCH version when you make backwards-compatible bug fixes."
With this in mind, referencing a changed version of a component, it is already clear to everyone, if the integration MIGHT be broken, SHOULD be reviewed or WILL most likely work.
Not only will this be helpful in the case of reused components or services, it will also help your test team to determine how detailed their testing should be (side note for managers: saving money in the best case).
Linking the Source Code and Product Version
Now we have a VCS for the source code and a released product version. Everyone who has worked on a software project will probably have come to a point where it becomes interesting what changes in the source code happened between two released versions. There are certain causes for that requirement, like auditing, or a regression bug which was found after a release.
Your version control system uses an identifier for each change. These identifiers are linked to product versions via so called tags. When you are developing on different features and versions in parallel, you have already stumbled upon the concept of branches. These branches keep track of a set of changes for different development streams, separating the source code changes.
Reflecting the Source's Change in the Version
As I have stated, the source code changes should be reflected in the change of the version descriptor. So far, I have seen only a few projects which keep track of the changes in that detail.
There are analysis tools in the wild like CLIRR, which can be used to check the changes of the public API between projects. With these changes in mind, the correct new release version can be provided BEFORE releasing the final product.
In my career, I have seen several different ways of releasing varying from manually exporting JAR files from an eclipse project (oh yes, I bet there are still projects which work that way) to semi-automated releases using the maven-release-plugin. Though the maven-release-plugin was a huge leap in the right direction, I do not fancy it for various reasons.
I have been using gradle for a very long time, and I really love this build tool (yes, I am a real fanboy, though I do not even have a gradle sticker on my Mac). Thus, I introduced this build-tool into many projects and I have written numerous plugins for it, even a release plugin. I felt like writing this release plugin over and over every time I started to work for a new employer (they call it intellectual property), but I never had the time to build it the way I wanted it to work.
Recently, I have had some free time to rewrite the plugin and release logic from scratch. I decided to abstract most of the release logic (which includes API checking and version matching) and modularized it so the release logic can be reused for a maven-plugin (anyone?). The plugin can be found at https://github.com/Tanemahuta/gradle-vgfr-plugin and its documentation is being constantly improved.
I want to encourage anyone who runs into the previously described problems to test it out, file issues, and help to improve this free plugin.