DEV Community

Jonas Brømsø
Jonas Brømsø

Posted on

1

GIST: sorting semantic versioned Git tags

Today I was inspecting some Git version tags. The repositories in question are using semantic versioning and they did not come in the order I expected.

This is an example from an open source repository of mine:

╰─ git tag
0.1.0
0.2.0
0.3.0
0.3.1
0.4.0
0.5.0
0.6.0
0.6.1
v0.10.0
v0.11.0
v0.12.0
v0.13.0
v0.13.1
v0.7.0
v0.8.0
v0.9.0
Enter fullscreen mode Exit fullscreen mode

I attempted to pipe it to sort, expecting it to fail.

╰─ git tag | sort
0.1.0
0.2.0
0.3.0
0.3.1
0.4.0
0.5.0
0.6.0
0.6.1
v0.10.0
v0.11.0
v0.12.0
v0.13.0
v0.13.1
v0.7.0
v0.8.0
v0.9.0
Enter fullscreen mode Exit fullscreen mode

So I fired up my editor and wrote a small Perl script, since my experience with sorting in Perl is that it is pretty powerful.

#!perl

use warnings;
use strict;
use Data::Dumper;
use Getopt::Long;

my $reverse;

GetOptions ('reverse'  => \$reverse)   # flag
    or die("Error in command line arguments\n");

# read all from standard input
my @tags = <STDIN>;

# remove newlines
chomp @tags;

my @sorted_tags = sort {
    ($b =~ /v?(\d+)\.\d+\.\d+/)[0] <=> ($a =~ /v?(\d+)\.\d+\.\d+/)[0]
                        ||
    ($b =~ /v?\d+\.(\d+)\.\d+/)[0] <=> ($a =~ /v?\d+\.(\d+)\.\d+/)[0]
                        ||
    ($b =~ /v?\d+\.\d+\.(\d+)/)[0] <=> ($a =~ /v?\d+\.\d+\.(\d+)/)[0]
                        ||
                fc($a)  cmp  fc($b)
} @tags;

# print sorted tags to standard output on separate lines
if ($reverse) {
    print join("\n", reverse @sorted_tags), "\n";
} else {
    print join("\n", @sorted_tags), "\n";
}

exit 0;
Enter fullscreen mode Exit fullscreen mode

So now I can do:

╰─ git tag | sort_semantic_version_numbers.pl
v0.13.1
v0.13.0
v0.12.0
v0.11.0
v0.10.0
v0.9.0
v0.8.0
v0.7.0
0.6.1
0.6.0
0.5.0
0.4.0
0.3.1
0.3.0
0.2.0
0.1.0
Enter fullscreen mode Exit fullscreen mode

And I even through in a --reverse (-r is the shortform):

╰─ git tag | sort_semantic_version_numbers.pl --reverse
0.1.0
0.2.0
0.3.0
0.3.1
0.4.0
0.5.0
0.6.0
0.6.1
v0.7.0
v0.8.0
v0.9.0
v0.10.0
v0.11.0
v0.12.0
v0.13.0
v0.13.1
Enter fullscreen mode Exit fullscreen mode

There might a better approach, but this was done pretty fast. Yes the script possible lacks support for all sorts of tag formats, but it works for semantic version numbers and that works for my use-case.

Script available as a Gist.

Feedback, suggestions etc. most welcome.

Image of AssemblyAI tool

Transforming Interviews into Publishable Stories with AssemblyAI

Insightview is a modern web application that streamlines the interview workflow for journalists. By leveraging AssemblyAI's LeMUR and Universal-2 technology, it transforms raw interview recordings into structured, actionable content, dramatically reducing the time from recording to publication.

Key Features:
🎥 Audio/video file upload with real-time preview
🗣️ Advanced transcription with speaker identification
⭐ Automatic highlight extraction of key moments
✍️ AI-powered article draft generation
📤 Export interview's subtitles in VTT format

Read full post

Top comments (3)

Collapse
 
jonasbn profile image
Jonas Brømsø

It was no surprise to me that somebody would comment on my gist, with a better solution.

Apparently GNU sort can sort version numbers, so you can do:

git tag | sort --version-sort

And

git tag | sort -r --version-sort

If you have GNU sort installed, which is a part of GNU Core Utils, meaning it can be installed on macOS using Homebrew.

brew install coreutils

Since macOS already has a sort, you have to use gsort

git tag | gsort -r --version-sort

All the lessons learned have been collection in a TIL on the topic

Collapse
 
samuelmugongamwa profile image
Samuelmugongamwa

That great would you love share the knowledge

Collapse
 
jonasbn profile image
Jonas Brømsø

I have indicated the MIT license in the inline documentation in Gist, it is not included here for brevity.

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay