Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one `git log` tagged commits only?

Tags:

git

I'd like to git log all the tagged commits on the master branch (and none of the untagged commits). Is this possible?

like image 313
davidchambers Avatar asked Feb 05 '14 05:02

davidchambers


People also ask

What flag must be used to display the tag information in the output of git log?

The --decorate flag makes git log display all of the references (e.g., branches, tags, etc) that point to each commit.

Does git tag also commit?

In order to create a Git tag for a specific commit, use the “git tag” command with the tag name and the commit SHA for the tag to be created. If you want to create an annotated tag for a specific commit, you can use the “-a” and “-m” options we described in the previous section.

Can a commit have 2 tags?

We occasionally have two tags on the same commit. When we use git describe for that commit, git describe always returns the first tag. My reading of the git-describe man page seems to indicate that the second tag should be returned (which makes more sense).

How can I see commits from one branch?

Git rev-list will list commits in one branch that are not in another branch. It is a great tool when you're trying to figure out if code has been merged into a branch or not. Using the --oneline option will display the title of each commit. The ^ operator excludes commits in the specified branch from the list.


1 Answers

The secret trick to this is to realize that git log uses the same rules as git rev-list. The latter command has a --tags flag to look at tags. So, as with the other answers so far, if you're willing to look at all tagged commits, this single command will do it:

git log --no-walk --tags

(The --no-walk prevents this from starting with tags and finding all their parent commits, and the parents' parents, and so on.)

But you asked for "tagged commits on the master branch", which I assume means (in technical terms) "commits that are both pointed to by tags and reachable via the master branch". This is substantially harder (git rev-list can do set union via --stdin --no-walk, but seems to have no way to do set intersection). Here are several methods of finding the right commit-IDs, with various drawbacks:

  1. First make two file lists: "all tagged commits" and "all commits reachable from master":

    git rev-list --tags --no-walk > /tmp/all-tags
    git rev-list master > /tmp/all-master
    

    Now just print lines that appear only in both files. The comm utility can do this. It's documented to expect the files to be sorted, but in all implementations I have seen, the files merely need to be in the same order, as it were, so this works without pre-sorting:

    comm -12 /tmp/all-tags /tmp/all-master
    

    Drawbacks: needs two temporary files (unless you use the special bash syntax that uses /dev/fd); might not work without sorting; requires comm.

  2. Same idea as before, but use uniq -d to produce the list. This really does require sorting, but you can eliminate the temporary files using a pipe:

    (git rev-list --tags --no-walk; git rev-list master) | sort | uniq -d
    

    Drawback: requires sorting. The commits come out in some strange order, not the order you would normally see with git log.

  3. Write your own utility that basically does what the comm method would do, but invokes git rev-list itself (perhaps a script that creates temp files using mktemp to make unique names).

    Drawback: requires a lot more work. :-)

In all cases, once you have the list of commit-IDs, you just need to pass them to git log --no-walk, e.g.:

git log --no-walk $(comm -12 /tmp/all-tags /tmp/all-master)
like image 178
torek Avatar answered Nov 15 '22 22:11

torek