Do git tags apply to all branches?

10,791

Solution 1

Let's say you are in branch myBranch. And you create a tag called myTag

-----A-----B-----C-----D-----H-------I-----> master
                       \
                        \
                         \---E----F-----G-----> myBranch
                                        |
                                        myTag

The tag will be only on the commit object of the myBranch branch. I've worked with CVS too, and it tags revisions too, not all branches (but in CVS branches are special tags). I don't think.

If you checkout myTag, you will be in the commit G of the example. You can't create tags with the same name on differente branches. If you do it, you will move the tag.

There's no difference for an annotated tag related to this.

Note: when checking out tags, you end up with "detached HEAD" mode. Your changes will be lost unless you create another branch starting from the tag checked out.

Solution 2

Having read the questions and your comments, I think the basic point that is confusing you here is what it means in git (vs other systems) to be "on a branch".

In git, a git checkout operation checks out some particular commit [but see footnote 1]. It also sets the special name HEAD so that it refers to that particular commit. But: there are two different ways that HEAD can specify a particular commit. It can be:

  • by ID (this is the not-usual case), or
  • by indirect reference to a branch name (this is the more-usual case).

If you do git checkout branchname, git sets up the second, usual case. If you then cat .git/refs/HEAD you will find it contains the literal string ref: followed by refs/heads/branchname [2]. That's what it means to be "on the branch": you have checked out the commit that the branch-name refers to, but also, HEAD is a "symbolic ref". If you make new changes and commit them, git will make the new commit, then "peel off" the branch label sticky-note and paste it onto the new commit you just added. That "moves the branch" to the newly added tip, and you're "still on the branch".

On the other hand, if you do git checkout tagname, git sets up the first, unusual case. It does the same if you check out by SHA-1 ID (those ea56709... style strings). In this case, the file for HEAD just has the literal SHA-1 ID in it. In this state, if you make a new commit, it gets added as usual, but there's no sticky-note-changing to move branch labels around. You're not "on a branch"; HEAD is not a "symbolic ref".

As far as the actual tags themselves go, they are merely names for commits. But wait, isn't that what a branch name is? Yes! The difference between a branch name and a tag name is that a branch name is expected to move, and git will move it automatically in that "on a branch" case. A tag name is not "expected to move" [3] and will never move automatically.


Footnotes:

[1] Just to confuse things (or because git's user interface is "evil", as some would put it :-) ) there are cases when git checkout does not alter HEAD, specifically when you ask it to check out particular pathnames.

[2] In very old versions of git, instead of ref: ... git used a symbolic link. The target of the link was the branch ID-file, e.g., refs/heads/master or whatever, so opening and reading the file got the commit ID, and you had to use lstat to detect "on a branch". This does not work on Windows and precluded "packing" refs (.git/packed-refs), hence the change to use ref: instead.

[3] The phrases "is expected" and "is not expected" should prompt you to ask: expected by whom? Git itself is OK with git users moving tags, it's the people using git (and often, scripts they write) that get confused by this. So don't move a tag unless you've first checked with other people sharing the repository.

Solution 3

To make it simple:

If I add a tag to a git repo, is it applied to all branches or only the current one?

In Git, a tag is simply an alias to a commit id. When you add a tag, Git simply maps your tag name (the tag string) to a given commit id. Since the commit id is relevant to a specific branch (or branches when merging) the tag will be relevant only to that branch (and to any it was merged into).

More info can be found here:

http://git-scm.com/book/en/Git-Basics-Tagging#Creating-Tags

Share:
10,791
Dave Lillethun
Author by

Dave Lillethun

Updated on June 03, 2022

Comments

  • Dave Lillethun
    Dave Lillethun almost 2 years

    I'm getting my feet wet with git tagging, but my previous background is in Subversion, where "tags" were really just copies, not "real" tags...

    If I add a tag to a git repo, is it applied to all branches or only the current one?

    For example, if I currently have these branches (git branch -v):

    * master deadbeef My master head comment
      dev    baddfeed My def head comment
    

    And the currently checked out branch is master, as you can see. Now suppose I git tag -a TAGNAME, does TAGNAME apply only to deadbeef (master branch) or to baddfeed (dev branch) as well?

    e.g., Say I subsequently switch to the dev branch (i.e., not the branch the tag was created on) before checking out the tag:

    git checkout dev
    git checkout TAGNAME
    

    Do I then end up with a checkout of baddfeed or will the tag checkout (second line) switch me back to the master branch (where the tag was created) and give me a checkout of deadbeef? (Or third option, is my understanding of creating and restoring tags too flawed or too simplistic for the answer to be as simple as one of those two options?)

    Also, does the answer to my question change any if I use a lightweight tag (git tag TAGNAME) instead of an annotated tag?

  • Dave Lillethun
    Dave Lillethun almost 11 years
    Thank you, that makes it very clear. So just to close the loop, if I gave the sequence of commands in my OQ (i.e., git checkout dev; git checkout TAGNAME) then I would end up back in the master brach, with the deadbeef commit checked out in detached mode (even if that happened to still be head of master, it would be checked out detached); is that correct?
  • torek
    torek almost 11 years
    Techncially, commits added in "detached HEAD" mode are not lost: they just have no convenient name, so you have to use the raw SHA-1 ID. You can paste on a branch name after-the-fact. It's just a pain to do it that way. (Also, after a while—the default is 90 days—they will get garbage-collected if they still have no "nice" name.)
  • Jean Waghetti
    Jean Waghetti almost 11 years
    @DaveLillethun Yes. You'll be in master again. Even if the commit is the HEAD, you'll be in the detached HEAD mode.
  • Jean Waghetti
    Jean Waghetti almost 11 years
    @torek You're right. And I agree with you: "It's just a pain to do it that way.". Just in case someone gets here and is curious about how to get the commit ID for these "lost" commits, use git reflog.
  • Fareed Alnamrouti
    Fareed Alnamrouti about 4 years
    Wow the best explanation for tags I ever saw, thank you matser