gittagsbranch

When I checkout a branch in GIT and then tag without explicity specifying the branch name what happens?


A very simple question I hope... but deceptively difficult to get a straight answer from the documentation or playing around on the command line in GIT. Here is the scenario, I have a local repo and am in master. I create a branch called branch1, I checkout branch1. I then make some change, add / commit the changes (staging and commit). At this point I tag branch1 with "git tag 1.0".

My question is - does that tag automatically pick up the fact that I am in branch1 and therefore apply only to branch1. Or do I need to use the command "git tag 1.0 branch1" explicitly naming the branch to which it refers. I tried "git branch --list" etc from both within branch1 working directory and master working directory and they both list the tag in either case. If I rebased branch1 back into master then I would not be surprised by this outcome. But for time being, without merging changes back, how can I ask to see just the tag that refers to a given branch on the command line (if that is the case)?


Solution

  • A commit is a set of changes; so the first commit changes from 'nothing' to something and each commit after the first changes what existed before it. In this way, each commit is dependent on the previous commits, all the way back to the first one. The path back to the beginning includes all parent commits, but since merge commits have two or more parents, it is not always linear.

    In git there are a number of ways to specify which commit you want to refer to; the default is an SHA1 hash -- but there are others:

    When any of the above are used in a git command, they are first translated by that command to the commit they refer to. They are, after all, just labels used to refer to a commit. Each one completely independent of all the others.

    To take up your various, yet related, questions one at a time:

    When I checkout a branch in GIT and then tag without explicitly specifying the branch name what happens?

    Tags do not refer to branches, they are both labels that refer to commits -- complete independent of each other. So your question is a bit 'odd' in terminology; which seems to have come from a book you read.

    The actual relevant syntax from the man-page for git tag ...: git-tag Manual Page

    git tag <tagname> <commit>
    

    The tag is created by specifying a tag name and the commit the tag is to be attached to. That commit can be specified by hash, another tag, a branch, or another other means. This does not create a connection of any sort between the label used to reference the commit and the tag -- it just references a commit.

    So, what is happens when a commit is not specified (by branch or another other means). Well, a commit is always specified -- git allows command arguments to be left off if it can default that value to HEAD. So what happens is the same as if you specify HEAD: git tag HEAD.

    Again, just to be clear, the newly created tag is attached to the commit currently referenced by HEAD and will not move with HEAD when it changes.

    does that tag automatically pick up the fact that I am in branch1 and therefore apply only to branch1?

    No. When a tag is created it is attached to a specific commit -- what branch(es) (if any) that commit also belongs to is irrelevant.

    **Or do I need to use the command "git tag 1.0 branch1" explicitly naming the branch to which it refers?

    Adding the branch name to the git tag ... command simply uses <branch> as a reference to the commit it currently refers to and attaches the tag to that commit. Since the branch is checked out (in your example), HEAD also refers to the same commit -- so the command git tag <tagname>, git tag <tagname> HEAD and git tag <tagname> <branch> all reference the same commit and will produce the same tag.

    how can I ask to see just the tag that refers to a given branch on the command line (if that is the case)?

    Again, tags do not refer to branches, just to commits -- but, with that aside, getting a list of all tags attached to any of the commits of a single branch does not seem to be something there is a single command for. It has been discussed in a couple of questions (at least)

    Also, questions from comments on other answers (ignoring direct repeats):

    So my question regarding your answer is why does GIT even have syntax for "git tag if it makes absolutely no difference?

    It doesn't have such a syntax -- the book has fallen victim of trying to make the subject simpler than it is. See the above section for a reference to the correct git tag <tagname> <commit> syntax.

    Ok, so you say HEAD commit of branch1 (that sounds correct to me) So it only applies to branch1 before rebasing right?

    First, HEAD is not the same as the head commit of a branch. I defined HEAD above as a label that always refers to the commit currently checked out in the working directory. The head of a branch is the most recent commit in that branch -- the commit the branch label is currently attached to.

    Incidentally, tags are not moved by rebasing. Rebasing creates new commits, any tags referencing the old commits will continue to reference them.

    So are you saying for instance, I commit in master, switch to branch1 (without making any commits) and do a "git tag then it will still tag the last commit in master?

    The tag created will be attached to the latest commit in branch1 -- the head of branch1. Since no commits were created since branching from master, the latest commit in master (its head) is the same commit. This is just a different way of addressing the same commit -- nothing more.

    how do I only query to see the branch(es) to which the tag (commit) refers?

    Short answer is to use the git branch --contains <commit> command and use the tag as a reference to the commit, git branch --contains <tagname>.

    This is discussed in greater detail in this question: How to list branches that contain a given commit?

    I think that covers all of your unique questions -- hope it helps.