GitPython tags sorted
Asked Answered
F

4

25

I am trying to get the latest tag in the repo using GitPython lib. Usually I was doing it this way:

repo = Repo(project_root)
last_tag = str(repo.tags[-1])

But once version 1.10 was released, I am always getting 1.9 ;( I know it's related to output git tag -l being listing same order. So it will be 1.1, 1.10, 1.2, ..., 1.9

The question is how to get the latest tag using GitPython? (I am aware of git tag -l | sort -V and I know how to solve this not using the repo object. But maybe someone knows what am I missing in getting sorted tags list in this lib)

Custom sorting function is always an option too, but still, I wonder if there a way to do it with GitPython?

Fredel answered 31/7, 2014 at 10:22 Comment(1)
It is working all right for me. python v2.7.6, gitpython v0.1.7. What version are you using?Laxative
C
5

I have just had a look and found the code responsible for the sorting. Therefore I see no other way but to reverse the sorting order yourself, like

reversed(repo.tags)

If preferred, you can also use the underlying git command, and parse the result yourself, such as in this example:

repo.git.tag(l=True) # equals git tag -l

That way, whatever git tag can do, you can do (which could be interesting for listing tags in order of traversal, starting from a given commit).

Ching answered 11/8, 2014 at 20:32 Comment(4)
Link is broken.One
None of this answers the question for me because 1.10 still erroneously shows before 1.2.One
This answer is not really correct - it assumes that the sorting of tags is in an order of creation, which it is not. Its an alphabetic sort. git tag --sort creatordate OTOH will sort by tag creation dateMorpho
@Morpho this is actually exactly the answer. Git flags are passed from Python via kwargs, so repo.git.tag(sort='creatordate').split('\n') (with a formatting alteration) returns a list of tags sorted ascending by created date.Heads
O
32

The IterableList object returned by repo.tags in GitPython extends the list Python class, which means that you can sort it the way you want. To get the latest tag created, you can simply do:

import git
repo = git.Repo('path/to/repo')
tags = sorted(repo.tags, key=lambda t: t.commit.committed_datetime)
latest_tag = tags[-1]
Ortrud answered 14/2, 2017 at 12:17 Comment(0)
S
6

The above will work if there are different commits associated with the tags (which is generally the case). However a more accurate way would be as follows which picks up the tag date:

import git
repo = git.Repo('path/to/repo')
tags = sorted(repo.tags, key=lambda t: t.tag.tagged_date)
latest_tag = tags[-1]
Shuster answered 11/7, 2017 at 10:12 Comment(1)
This worked well, but I had to skip entries for t.tag == None, otherwise blam..Jalopy
C
5

I have just had a look and found the code responsible for the sorting. Therefore I see no other way but to reverse the sorting order yourself, like

reversed(repo.tags)

If preferred, you can also use the underlying git command, and parse the result yourself, such as in this example:

repo.git.tag(l=True) # equals git tag -l

That way, whatever git tag can do, you can do (which could be interesting for listing tags in order of traversal, starting from a given commit).

Ching answered 11/8, 2014 at 20:32 Comment(4)
Link is broken.One
None of this answers the question for me because 1.10 still erroneously shows before 1.2.One
This answer is not really correct - it assumes that the sorting of tags is in an order of creation, which it is not. Its an alphabetic sort. git tag --sort creatordate OTOH will sort by tag creation dateMorpho
@Morpho this is actually exactly the answer. Git flags are passed from Python via kwargs, so repo.git.tag(sort='creatordate').split('\n') (with a formatting alteration) returns a list of tags sorted ascending by created date.Heads
T
2

The sorting is done in alphanumeric order, so "1.9" is ranked higher than "1.10" because it ordering is character wise and "9" > "1".

If you want a more sensible sorting you got two options: zero-pad your version numbers (1.09 instead of 1.9), which would be preferred but it's hard to implement it in hindsight.

The other is sorting the tags in python. There is a library called natsort available that does natural sorts for all kinds of data. But for this simple case you could also use the key argument of the sorting function:

nsort = lambda v:tuple(map(int, v.split('.')))
sorted(repo.tags, key=nsort)
Taxeme answered 8/6, 2018 at 16:0 Comment(1)
A more flexible solution would be to use the LooseVersion class of distutils.version. See this question for more info.Stringency

© 2022 - 2024 — McMap. All rights reserved.