How is a tag different from a branch in Git? Which should I use, here?

245,539

Solution 1

A tag represents a version of a particular branch at a moment in time. A branch represents a separate thread of development that may run concurrently with other development efforts on the same code base. Changes to a branch may eventually be merged back into another branch to unify them.

Usually you'll tag a particular version so that you can recreate it, e.g., this is the version we shipped to XYZ Corp. A branch is more of a strategy to provide on-going updates on a particular version of the code while continuing to do development on it. You'll make a branch of the delivered version, continue development on the main line, but make bug fixes to the branch that represents the delivered version. Eventually, you'll merge these bug fixes back into the main line. Often you'll use both branching and tagging together. You'll have various tags that may apply both to the main line and its branches marking particular versions (those delivered to customers, for instance) along each branch that you may want to recreate -- for delivery, bug diagnosis, etc.

It's actually more complicated than this -- or as complicated as you want to make it -- but these examples should give you an idea of the differences.

Solution 2

From the theoretical point of view:

  • tags are symbolic names for a given revision. They always point to the same object (usually: to the same revision); they do not change.
  • branches are symbolic names for line of development. New commits are created on top of branch. The branch pointer naturally advances, pointing to newer and newer commits.

From the technical point of view:

  • tags reside in refs/tags/ namespace, and can point to tag objects (annotated and optionally GPG signed tags) or directly to commit object (less used lightweight tag for local names), or in very rare cases even to tree object or blob object (e.g. GPG signature).
  • branches reside in refs/heads/ namespace, and can point only to commit objects. The HEAD pointer must refer to a branch (symbolic reference) or directly to a commit (detached HEAD or unnamed branch).
  • remote-tracking branches reside in refs/remotes/<remote>/ namespace, and follow ordinary branches in remote repository <remote>.

See also gitglossary manpage:

branch

A "branch" is an active line of development. The most recent commit on a branch is referred to as the tip of that branch. The tip of the branch is referenced by a branch head, which moves forward as additional development is done on the branch. A single git repository can track an arbitrary number of branches, but your working tree is associated with just one of them (the "current" or "checked out" branch), and HEAD points to that branch.

tag

A ref pointing to a tag or commit object. In contrast to a head, a tag is not changed by a commit. Tags (not tag objects) are stored in $GIT_DIR/refs/tags/. [...]. A tag is most typically used to mark a particular point in the commit ancestry chain.

tag object

An object containing a ref pointing to another object, which can contain a message just like a commit object. It can also contain a (PGP) signature, in which case it is called a "signed tag object".

Solution 3

If you think of your repository as a book that chronicles progress on your project...

Branches

You can think of a branch as one of those sticky bookmarks:

enter image description here

A brand new repository has only one of those (called master), which automatically moves to the latest page (think commit) you've written. However, you're free to create and use more bookmarks, in order to mark other points of interest in the book, so you can return to them quickly.

Also, you can always move a particular bookmark to some other page of the book (using git-reset, for instance); points of interest typically vary over time.

Tags

You can think of tags as chapter headings.

bookmarks

It may contain a title (think annotated tags) or not. A tag is similar but different to a branch, in that it marks a point of historical interest in the book. To maintain its historical aspect, once you've shared a tag (i.e. pushed it to a shared remote), you're not supposed to move it to some other place in the book.

Solution 4

What you need to realize, coming from CVS, is that you no longer create directories when setting up a branch.
No more "sticky tag" (which can be applied to just one file), or "branch tag".
Branch and tags are two different objects in Git, and they always apply to the all repo.

You would no longer (with SVN this time) have to explicitly structure your repository with:

branches
   myFirstBranch
     myProject
       mySubDirs
   mySecondBranch
     ...
tags
   myFirstTag
     myProject
       mySubDirs
   mySecondTag
   ...

That structure comes from the fact CVS is a revision system and not a version system (see Source control vs. Revision Control?).
That means branches are emulated through tags for CVS, directory copies for SVN.

Your question makes senses if you are used to checkout a tag, and start working in it.
Which you shouldn't ;)
A tag is supposed to represent an immutable content, used only to access it with the guarantee to get the same content every time.

In Git, the history of revisions is a series of commits, forming a graph.
A branch is one path of that graph

x--x--x--x--x # one branch
    \ 
     --y----y # another branch
       1.1
        ^
        |
        # a tag pointing to a commit
  • If you checkout a tag, you will need to create a branch to start working from it.
  • If you checkout a branch, you will directly see the latest commit it('HEAD') of that branch.

See Jakub Narębski's answer for all the technicalities, but frankly, at this point, you do not need (yet) all the details ;)

The main point is: a tag being a simple pointer to a commit, you will never be able to modify its content. You need a branch.


In your case, each developer working on a specific feature:

  • should create their own branch in their respective repository
  • track branches from their colleague's repositories (the one working on the same feature)
  • pulling/pushing in order to share your work with your peers.

Instead of tracking directly the branches of your colleagues, you could track only the branch of one "official" central repository to which everyone pushes his/her work in order to integrate and share everyone's work for this particular feature.

Solution 5

Branches are made of wood and grow from the trunk of the tree. Tags are made of paper (derivative of wood) and hang like Christmas Ornaments from various places in the tree.

Your project is the tree, and your feature that will be added to the project will grow on a branch. The answer is branch.

Share:
245,539
Bialecki
Author by

Bialecki

Programmer. Runner. Red Sox fan.

Updated on July 25, 2022

Comments

  • Bialecki
    Bialecki almost 2 years

    I am having some difficulty understanding how to use tags versus branches in .

    I just moved the current version of our code from to , and now I'm going to be working on a subset of that code for a particular feature. A few other developers will be working on this as well, but not all developers in our group are going to care about this feature. Should I be creating a branch or a tag? In what situations should I be using one versus the other?

  • knittl
    knittl over 14 years
    in his case he wants to use branches, maybe you should also note this in your answer ;)
  • Steve Bennett
    Steve Bennett about 12 years
    Question: if you treat a branch like a tag (that is, you create it, then never update it), is there any real difference?
  • VonC
    VonC about 12 years
    @SteveBennett absolutely. There contains different informations (you can sign a tag, you can add a description to a branch). You can move a branch (so even if you never update it, you can still rebase it.). You cannot move a tag (it is linked to a specific commit). You can choose to push a branch. Tags aren't pushed by default. You should never use one for the other (unless you are really in an SVN mindset, in which case you need to "un-learn" that fast if you want to go on with git).
  • Anonigan
    Anonigan about 12 years
    @SteveBennett: There is a difference how Git treats branches vs how it treat tags. Besides what VonC said, you cannot advance tag by mistake: "git checkout <tag>" would generate anonymous unnamed branch (so called 'detached HEAD') and select state of tag. Creating a new commit does it on this unnamed branch, and does not change what tag points to.
  • M.Y.
    M.Y. almost 12 years
    AFAIK, tags are not unique per branch. So yo can't give same names for different commits in separate branches.
  • eonil
    eonil almost 12 years
    IMO, branches are separated timelines (parallel world), and tags are specific moments at a timeline.
  • Chris Cleeland
    Chris Cleeland almost 12 years
    @VonC: I think you mean "SVN" in your answer and not "CVS". CVS does not have the directory structure; SVN does. In fact, tagging in git reminds me much more of tagging in RCS/CVS than tagging in SVN (where tag == degenerate branch).
  • VonC
    VonC almost 12 years
    @ChrisCleeland good point. I have tried to separate a bit more CVS and SVN points in the (edited) answer.
  • Admin
    Admin over 11 years
    No one here has mentioned it yet but you can use a tag as the point to start a branch: git checkout -b <branch name> <tag name>
  • Anonigan
    Anonigan over 11 years
    @KenStailey: You can use any commit (any revision) as a starting point for a branch; using tag is just a special case of this situation.
  • Swivel
    Swivel over 10 years
    @M.Y. Certainly not a bad thing, IMHO. Especially in the way described by tvanfosson, having more than one tag with the same name across different branches could become difficult to maintain. Given the example, I would think that if you could have tags with the same name across different branches, it would quickly be established as a bad practice. Good to know that you can't, though. Thanks M.Y.!
  • 131
    131 about 10 years
    @VonC i find your comment more usefull/concise than your first answer, that is, branches are moved when rebased, when tags aren't.
  • Mārtiņš Briedis
    Mārtiņš Briedis over 9 years
    I would image that a branch would be a book, and bookmarks are tags. You can continue writing a book, but you cannot edit it. Tag is just a fixed moment in the book.
  • jub0bs
    jub0bs over 9 years
    @MārtiņšBriedis In my metaphor, the commit DAG is the book. Since a Git branch is nothing more than a "pointer" to a commit, I think the bookmark analogy is appropriate, here.
  • jub0bs
    jub0bs over 9 years
    Tags are guaranteed to point to the same commit as long as they exist. Not completely true. You can actually move a tag with git tag -f.
  • Mārtiņš Briedis
    Mārtiņš Briedis about 9 years
    @Jubobs I liked the branch explanation as a line of development. A book would be a branch. You can start a new book based on the place where left the main branch. You can write them paralel and then try to merge in to a one book/branch.
  • jub0bs
    jub0bs about 9 years
    @MārtiņšBriedis I understand the way you like to think of a branch, but I find that, in Git, that's actually misleading. See stackoverflow.com/questions/25068543/…
  • Gerald
    Gerald almost 9 years
    Is it GPG instead of PGP signature?
  • Ali Foroughi
    Ali Foroughi over 8 years
    this one is really a time saver answer
  • jterm
    jterm about 8 years
    A tag is just an alias for a commit hash. Same as you can checkout a commit with git checkout 88c9f229f you can do something like git checkout your_tag and you will checkout the commit that was aliased by the tag.
  • doz87
    doz87 almost 8 years
    love for the analogy
  • Viktor Molokostov
    Viktor Molokostov over 7 years
    @jterm, aren't branches aliases too? The only difference is that a branch-alias automatically repoints itself to the most recent commit in the chain.
  • barell
    barell about 7 years
    If you start writing a book and you have first 50 pages, you can copy it (create a new branch from it) and continue writing two books simultaneously (or give the book copy to some other writer - developer) and finally you can merge the changes from the other book to your book.
  • Hubert Grzeskowiak
    Hubert Grzeskowiak over 6 years
    This answer is conveying a very wrong idea. Branches are not part of one linear history like a book is. And your bookmarks are more like tags, pointing to specific points in the story.
  • jub0bs
    jub0bs over 6 years
    @HubertGrzeskowiak I concede that the linear aspect of a book makes my analogy somewhat misleading. However, it is useful and I stand by it. Branches can be moved (hence bookmarks) whereas tags can't/shouldn't (hence chapter headings). An idea that I've encountered many times and is misleading is to think of a branch as a line of development or a series of commits.
  • Hubert Grzeskowiak
    Hubert Grzeskowiak over 6 years
    A "line of development" or "series of commits" is exactly what a branch is.
  • jub0bs
    jub0bs over 6 years
    @HubertGrzeskowiak I beg to differ; it's not as simple as that.
  • Hubert Grzeskowiak
    Hubert Grzeskowiak over 6 years
    I like Chris' answer in your linked question: "the commits that are reachable from the commit pointed to by the branch". By following the parent's parent of a branch's HEAD recursively you eventually end up with a series of commits that represent a line of development. My problem with the book analogy is that you can't simply add new text at the end of a chapter or at any bookmarks, and you can't copy a whole chapter in order to try out some different endings. Also all chapters are linear, making a sequence, whereas branches are part of a directed acyclic graph.
  • jub0bs
    jub0bs over 6 years
    @HubertGrzeskowiak I like Chris's answer too, but "the commits that are reachable from the commit pointed to by the branch" form a DAG, not a line, in the general case. Moreover, there is no one-to-one mapping between 1) the commits that are reachable from the commit pointed to by a branch and 2) those branches. A simple example of this is a repo containing a single commit, with two branches—master and develop, say—both pointing at that commit. You can't unambiguously refer, in speech, to that commit as master or develop.
  • jub0bs
    jub0bs over 6 years
    @HubertGrzeskowiak A branch is more than what it can reach; it has a name, a reflog, etc.
  • Anvesh Yalamarthy
    Anvesh Yalamarthy almost 5 years
    Agree with Tag explanation but not with Branch (as its again Tag).. Branch is actually a parallel world/time line which can merge at some point later..
  • jub0bs
    jub0bs almost 5 years
    @AnveshYalamarthy Whatever metaphor works for you, but be aware that thinking of a branch as a line of development or a sequence of commits is misleading. See stackoverflow.com/questions/25068543/…
  • Anvesh Yalamarthy
    Anvesh Yalamarthy almost 5 years
    @jub0bs, agreed, that is my point too.. !! Writing/traversing a book is similar to sequence of commits..
  • iBobb
    iBobb about 2 years
    Considering all the comments, it seems like most use cases for tags are to just tag stuff...mark them for easier recognition (of a specific release version for example). Then, it seems that only lightweight tags are useful, what's a real use case for a heavy annotated tag? The official Git docs actually recommend using the annotated tags in most cases. Is it because they are checksummed?