I recently released two new versions of liboggz,
liboggz-1.0.2 and
liboggz-1.1.1.
These are unremarkable maintenance releases, fixing some bugs but adding no new functionality.

Last year I released
liboggz-1.1.0,
which introduced a new oggz_packet type.
This changed some of the public API while remaining binary compatible. As this was a
fairly insidious change, I decided to also keep maintaining the previous 1.0.x version
so that any distributions shipping that could easily upgrade without risking breakage.
I do general maintenance work and bugfixes on the 1.0.x version as much as possible, and
then adapt those to 1.1.x. Luckily this is quite straightforward to keep track of in git.

After committing a change to the 1.0-stable branch I merge that into master:

As these were just maintenance releases, the commit graph produced by
git lol is quite well woven:

Lightweight branching makes it easy to keep track of these changes so that simple
maintenance work is isolate from other development. The upshot is that these branches
are ready for release at any time; if a critical fix comes along that requires a new
release, then no backporting or cherry-picking needs to be done to get the code into
shape: there is always a branch in releasable state.

Of course on top of that I also have topic branches for new features under development,
and I periodically merge master into those. When the new features are ready for release
they can simply be merged back into the master branch and shipped, without ever getting
in the way of general maintenance work.