Repository: spack/spack

Issue:
document git commit versions
Adds documentation for git commit support added in #24639 


Discussion:

Resolving patch:
diff --git a/lib/spack/spack/version.py b/lib/spack/spack/version.py
--- a/lib/spack/spack/version.py
+++ b/lib/spack/spack/version.py
@@ -191,7 +191,43 @@ def Version(string):  # capitalized for backwards compatibility
 
 
 class VersionBase(object):
-    """Class to represent versions"""
+    """Class to represent versions
+
+    Versions are compared by converting to a tuple and comparing
+    lexicographically.
+
+    The most common Versions are alpha-numeric, and are parsed from strings
+    such as ``2.3.0`` or ``1.2-5``. These Versions are represented by
+    the tuples ``(2, 3, 0)`` and ``(1, 2, 5)`` respectively.
+
+    Versions are split on ``.``, ``-``, and
+    ``_`` characters, as well as any point at which they switch from
+    numeric to alphabetical or vice-versa. For example, the version
+    ``0.1.3a`` is represented by the tuple ``(0, 1, 3, 'a') and the
+    version ``a-5b`` is represented by the tuple ``('a', 5, 'b')``.
+
+    Spack versions may also be arbitrary non-numeric strings or git
+    commit SHAs. The following are the full rules for comparing
+    versions.
+
+    1. If the version represents a git reference (i.e. commit, tag, branch), see GitVersions.
+
+    2. The version is split into fields based on the delimiters ``.``,
+    ``-``, and ``_``, as well as alphabetic-numeric boundaries.
+
+    3. The following develop-like strings are greater (newer) than all
+    numbers and are ordered as ``develop > main > master > head >
+    trunk``.
+
+    4. All other non-numeric versions are less than numeric versions,
+    and are sorted alphabetically.
+
+    These rules can be summarized as follows:
+
+    ``develop > main > master > head > trunk > 999 > 0 > 'zzz' > 'a' >
+    ''``
+
+    """
 
     __slots__ = [
         "version",
@@ -457,6 +493,45 @@ def intersection(self, other):
 class GitVersion(VersionBase):
     """Class to represent versions interpreted from git refs.
 
+    There are two distinct categories of git versions:
+
+    1) GitVersions instantiated with an associated reference version (e.g. 'git.foo=1.2')
+    2) GitVersions requiring commit lookups
+
+    Git ref versions that are not paried with a known version
+    are handled separately from all other version comparisons.
+    When Spack identifies a git ref version, it associates a
+    ``CommitLookup`` object with the version. This object
+    handles caching of information from the git repo. When executing
+    comparisons with a git ref version, Spack queries the
+    ``CommitLookup`` for the most recent version previous to this
+    git ref, as well as the distance between them expressed as a number
+    of commits. If the previous version is ``X.Y.Z`` and the distance
+    is ``D``, the git commit version is represented by the tuple ``(X,
+    Y, Z, '', D)``. The component ``''`` cannot be parsed as part of
+    any valid version, but is a valid component. This allows a git
+    ref version to be less than (older than) every Version newer
+    than its previous version, but still newer than its previous
+    version.
+
+    To find the previous version from a git ref version, Spack
+    queries the git repo for its tags. Any tag that matches a version
+    known to Spack is associated with that version, as is any tag that
+    is a known version prepended with the character ``v`` (i.e., a tag
+    ``v1.0`` is associated with the known version
+    ``1.0``). Additionally, any tag that represents a semver version
+    (X.Y.Z with X, Y, Z all integers) is associated with the version
+    it represents, even if that version is not known to Spack. Each
+    tag is then queried in git to see whether it is an ancestor of the
+    git ref in question, and if so the distance between the two. The
+    previous version is the version that is an ancestor with the least
+    distance from the git ref in question.
+
+    This procedure can be circumvented if the user supplies a known version
+    to associate with the GitVersion (e.g. ``[hash]=develop``).  If the user
+    prescribes the version then there is no need to do a lookup
+    and the standard version comparison operations are sufficient.
+
     Non-git versions may be coerced to GitVersion for comparison, but no Spec will ever
     have a GitVersion that is not actually referencing a version from git."""
 


Test patch: