Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to list all tags within a certain git branch

Tags:

git

I have a couple of branches in my git repo. I would like to know if there is a command that lists all the tags within a certain branch not all the tags in the whole repo.

I tried git tag --contains. but it didn't work as expected.

Image 1, there's a list of all the tags with their hashes (the marked two tags have the same hash/commit) enter image description here Image 2, as you can see I'm on a branch called "b" enter image description here Image 3, I queried which branch contains the hash of both tags (both have same hash) and it said they are on branch "b" (the one I'm currently on)enter image description here

Image 4, describing the branch tags, It only gave me ONE tagenter image description here

Image 5, also describing the tags of the hash that is supposed to point to the commit that is tagged with both tags, it only shows ONE tag againenter image description here

like image 206
mkmostafa Avatar asked Aug 23 '15 12:08

mkmostafa


People also ask

How will you list your tags in git?

Listing the available tags in Git is straightforward. Just type git tag (with optional -l or --list ). You can also search for tags that match a particular pattern. The command finds the most recent tag that is reachable from a commit.

Which command is used to see all the list of local branches?

To see all local and remote branches, run this command: git branch -a.

Do git tags belong to a branch?

Tags and branch are completely unrelated, since tags refer to a specific commit, and branch is a moving reference to the last commit of a history. Branches go, tags stay. So when you tag a commit, git doesn't care which commit or branch is checked out, if you provide him the SHA1 of what you want to tag.

How do I checkout a particular tag of a branch?

In order to checkout a Git tag, use the “git checkout” command and specify the tagname as well as the branch to be checked out. Note that you will have to make sure that you have the latest tag list from your remote repository.


2 Answers

Use git tag --sort='creatordate' --merged to list all tags accessible/reachable from HEAD and sort them chronologically.

You can specify a ref if you don't want HEAD, like git tag --sort='creatordate' --merged mybranch

like image 151
qwertzguy Avatar answered Oct 28 '22 02:10

qwertzguy


To print all tags, that point to a certain commit, you can do:

git for-each-ref refs/tags | grep HASH

Or if you are on Windows and don't use Cygwin or similar:

git for-each-ref refs/tags | find "HASH"

If you want the tag name only, you can't use Git's --format , because we need it for grep'ing. Thus we need to strip the stuff we aren't interested in away in the final step (Linux/Cygwin):

git for-each-ref refs/tags | grep HASH | sed -r "s/.*refs\/tags\/(.*)/\1/"

Regarding the initial question:

This iterates over all tags in all branches, asks git which branches contain each tag and filters based on the supplied branch name - but be warned, it's super slow:

git for-each-ref refs/tags --format "%(refname)" | while read x
do
    if git branch --contains $x | grep -q "^[ *] master$"
        then echo $x
    fi
done

The following taken from another answer is much faster:

git log --simplify-by-decoration --decorate --pretty=oneline "master" | fgrep 'tag: '

... but if multiple tags point to the same commit, it will produce:

 (HEAD, tag: Test-Tag1, tag: Test-Tag2, Test-Tag3, fork/devel, devel)
 (tag: Another-Tag)
 (tag: And-Another)

(three tags Test-Tag* pointing to the same commit)

I wrote a Python script that outputs tag names only, one per line (tested on Windows only):

import os
from subprocess import call

print("-" * 80)

dirpath = r"D:\Projekte\arangodb" # << Put your repo root path here!

tagdir = os.path.join(dirpath, ".git", "refs", "tags")
commitspath = os.path.join(dirpath, "_commit_list.tmp")

# could probably read from stdin directly somewhow instead of writing to file...
# write commits in local master branch to file
os.chdir(dirpath)
os.system("git rev-list refs/heads/master > " + commitspath)

tags = {}
for tagfile in os.listdir(tagdir):
    with open(os.path.join(tagdir, tagfile), "r") as file:
        tags[file.read().strip()] = tagfile

tags_set = set(tags)

commits = {}
with open(commitspath, "r") as file:
    for line in file:
        commits[line.strip()] = 1
os.remove(commitspath)

commits_set = set(commits)

for commit in sorted(commits_set.intersection(tags_set), key=lambda x: tags[x]):
    print(tags[commit])

Result:

Test-Tag1
Test-Tag2
Test-Tag3
Another-Tag
And-Another

The commit hash could optionally be printed too for every tag, simply modify the last line to print(commit, tags[commit]). The script seems to perform very well by the way!

Ideally, git would support something like the following command to avoid all these workarounds:

git tag --list --branch master
like image 26
CodeManX Avatar answered Oct 28 '22 03:10

CodeManX