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?
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 nameHEAD
so that it refers to that particular commit. But: there are two different ways thatHEAD
can specify a particular commit. It can be:If you do
git checkout branchname
, git sets up the second, usual case. If you thencat .git/refs/HEAD
you will find it contains the literal stringref:
followed byrefs/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 (thoseea56709...
style strings). In this case, the file forHEAD
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 alterHEAD
, 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 uselstat
to detect "on a branch". This does not work on Windows and precluded "packing" refs (.git/packed-refs
), hence the change to useref:
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.
Let's say you are in branch
myBranch
. And you create a tag calledmyTag
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 commitG
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.
To make it simple:
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