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

GitVersion ControlBranchGit BranchGit Tag

Git Problem Overview


I am having some difficulty understanding how to use tags versus branches in [tag:Git].

I just moved the current version of our code from [tag:CVS] to [tag:Git], 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?

Git Solutions


Solution 1 - Git

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".

[gitglossary]: https://book.git-scm.com/docs/gitglossary "gitglossary(7) - A GIT Glossary"

Solution 2 - Git

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 3 - Git

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 - Git

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 - Git

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.

Solution 6 - Git

It looks like the best way to explain is that tags act as read only branches. You can use a branch as a tag, but you may inadvertently update it with new commits. Tags are guaranteed to point to the same commit as long as they exist.

Solution 7 - Git

I like to think of branches as where you're going, tags as where you've been.

A tag feels like a bookmark of a particular important point in the past, such as a version release.

Whereas a branch is a particular path the project is going down, and thus the branch marker advances with you. When you're done you merge/delete the branch (i.e. the marker). Of course, at that point you could choose to tag that commit.

Solution 8 - Git

Tags can be either signed or unsigned; branches are never signed.

Signed tags can never move because they are cryptographically bound (with a signature) to a particular commit. Unsigned tags are not bound and it is possible to move them (but moving tags is not a normal use case).

Branches can not only move to a different commit but are expected to do so. You should use a branch for your local development project. It doesn't quite make sense to commit work to a Git repository "on a tag".

Solution 9 - Git

the simple answer is:

> branch: the current branch pointer moves with every commit to the repository

but

> tag: the commit that a tag points doesn't change, in fact the tag is a snapshot of that commit.

Solution 10 - Git

The Git Parable explains how a typical DVCS gets created and why their creators did what they did. Also, you might want to take a look at Git for Computer Scientist; it explains what each type of object in Git does, including branches and tags.

Solution 11 - Git

A tag is used to mark a version, more specifically it references a point in time on a branch. A branch is typically used to add features to a project.

Solution 12 - Git

simple:

> Tags are expected to always point at the same version of a project, while heads are expected to advance as development progresses.

Git User Manual

Solution 13 - Git

We use

  • branches in the dev environment for feature development or bug fix
  • lightweight tags for the test environment on feature branches
  • annotated tags for the release/prd (main branch)

After each annotated tags, all feature branches rebase from the main branch.

As said by others, a branch is a line of development and the head moves forward as newer commits arrive. This is ideal for the feature development.

Lightweight tag is fixed to a specific commit, which makes it ideal to create an internal version and let qa team to test a feature after dev is completed.

Annotated tag is ideal for the release to production, as we can add a formal message and other annotations when merging the tested feature branch to the main branch (stable).

Release Management with Git

Solution 14 - Git

neovim on github:

v0.3 is a branch enter image description here

v0.3.1 ... v0.3.4 ... are tags

enter image description here

nightly and stable are tags, not branches

enter image description here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBialeckiView Question on Stackoverflow
Solution 1 - GitJakub NarębskiView Answer on Stackoverflow
Solution 2 - GittvanfossonView Answer on Stackoverflow
Solution 3 - Gitjub0bsView Answer on Stackoverflow
Solution 4 - GitVonCView Answer on Stackoverflow
Solution 5 - GitJasonView Answer on Stackoverflow
Solution 6 - GitVassili GorshkovView Answer on Stackoverflow
Solution 7 - GitGazzerView Answer on Stackoverflow
Solution 8 - GitGreg HewgillView Answer on Stackoverflow
Solution 9 - GitjsinaView Answer on Stackoverflow
Solution 10 - GitBombeView Answer on Stackoverflow
Solution 11 - GitNumber45View Answer on Stackoverflow
Solution 12 - GitBar Horing AmirView Answer on Stackoverflow
Solution 13 - GitAli KhosroView Answer on Stackoverflow
Solution 14 - GitGood PenView Answer on Stackoverflow