Search code examples
gitgitlab

Remove remote git tags older than X months


I am trying to delete git tags that are older than X months

We have release tags that we need to retain, they are all tagged release-* where * = date

I know how to delete a singular tag git push origin :refs/tags/<tagName>

So I extrapolated to get all the remote tags to delete them

git ls-remote --tags origin | xargs git push origin :$1

To skip the release tags I was planning on using egrep -v making the command

git ls-remote --tags origin | egrep -v "(^\*|release*)" | xargs git push origin :$1

But I still haven't figured out how to do it by date.

Locally I can order things by date like so git for-each-ref --sort=taggerdate --format '%(refname)' refs/tags | egrep -v "(^\*|release*)" but that does not help me with remote tags.

If it helps I don't mind deleted or not deleting local tags in order to delete the remote ones.

Finally we use gitlab if it provides a better way of cleanup?

Regardless this needs to be something that can be run like a script through Jenkins to help with our git cleanup needs.

Update

Since we have thousand of git tags I realized that xargs is going to be rather slow.

I believe the way to delete will more likely be something like

git push origin $(< git tag | <sorting_by_date + exclude release> \ | sed -e 's/^/:/' | paste -sd " ")

That way the command will basically be appending :refs/tags/tag1 :refs/tags/tag2 into a single command instead of doing a unique delete for every tag and contacting the remote.


Solution

  • After working on this for the past couple of days I figured out a solution that works quite well.

    First collect all the git tags by chronological order, I excluded release* tags

    git for-each-ref --sort=taggerdate --format '%(refname:short) %(taggerdate:short)' refs/tags | egrep -v "(^\*|release*)"

    This will give the following output

    master_7 2017-12-05
    master_8 2017-12-05
    master_9 2017-12-07
    master_10 2017-12-08
    master_11 2017-12-08
    update_framework_1 2017-12-12
    master_12 2017-12-12
    master_13 2017-12-13
    

    So it's the name of the tag separated by a space and then the date in YYYY-MM-DD format. If you want a full date or something specific update taggerdate:short with something appropriate.

    I then took the output and processed it line by line looking at the date and comparing it with my cut off date.

    This allowed me to generate a list of tags to delete.

    Then I run the deletions by looping through the tag list and performing the following command

    git push origin :refs/tags/<tag1> :refs/tags/<tag2>

    I played it safe and run the command every 50 tags, but git didn't seem to have any problems with this.

    Finally after all the deletions are complete I run git fetch --prune origin +refs/tags/*:refs/tags/* which deletes all local tags that do not exist in the remote.

    And there you have it all tags are cleaned up.