Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are git tags merged?

Lets assume we are developing with git and pull requests and we have :

  1. a master branch
  2. a release/1.... branch and for every hotfix or feature there is also a branch which is merged into the starting branch after the pull request is accepted.

So my questions are:

  1. If the release branch contains Tags and if the release branch is merged into the master after the last released version of release/1.x.y, are the tags also merged?

  2. And for long term support my question is:

    Let's assume somebody wants to check out the state of tag 1.1.1 in 10 years. Is it possible to check out this tagged commit if the release branch was deleted but was merged into the master and we have the master ?

Thanks

enter image description here

like image 205
user1911091 Avatar asked Aug 25 '20 08:08

user1911091


People also ask

How do tags work in git?

Tagging is generally used to capture a point in history that is used for a marked version release (i.e. v1. 0.1). A tag is like a branch that doesn't change. Unlike branches, tags, after being created, have no further history of commits.

Are git tags across branches?

Git Tags and Git Branches Don't get confused between tags and branches. While both offer a similar service (pointing to a specific commit), a tag is fixed. A tag will always, therefore, point to the same commit. Branches, however, will move the pointer forward with each additional commit.

What is merged in git?

Merging is Git's way of putting a forked history back together again. The git merge command lets you take the independent lines of development created by git branch and integrate them into a single branch. Note that all of the commands presented below merge into the current branch.

Can you have multiple tags in git?

However, they do not keep history as the git branches do. Git allows the creation of multiple tags on a branch or different branches. There exist two different types of git tags which are lightweight tags and the annotated git tags.


1 Answers

The literal answer to the question in your subject line—Are git tags merged?—is "no", but that's not an interesting answer, because neither are branch names. Merges, in Git, work through commits.

The diagram you posted is not bad, but it has a few things in it that are misleading. Here are some notes about it:

  • The arrows in it point forwards. Git does not work forwards; Git works backwards. Usually this doesn't matter too much, but in terms of finding commits, it's important.

  • The round circles represent commits. This is all fine.

  • Some commits are merge commits and some commits are ordinary commits. In this case, all the purple feature/* commits are ordinary, as is the single bugfix/bug-1 red one. Most of the yellow and green commits are merge commits.

    Since the diagram has the arrows the wrong way around—it has them forwards instead of Git's backwards-ness—you can tell which commits are merge commits because they have more than one arrow coming in to them. Had the arrows been drawn correctly, i.e., backwards, a merge commit would be any commit with two or more arrows coming out of it.

  • Branch names and tag names simply identify one commit. The diagram is highly misleading here because it puts the names master and release/1.0.0 on the left. If these are branch names, they really should be on the right, pointing to the last commit in that branch.

    Git makes use of the arrows coming out of each commit—that is, the arrows that would be coming out of each commit, if the arrows had been drawn correctly—to work backwards. Hence a branch name always identifies the last commit in the branch. That means the name points to the last commit in the chain.

A tag name, like a branch name, simply points directly to one commit. The key differences between tag names and branch names include the fact that a branch name moves over time, so that as you add new commits, the name continues to point to the last commit. So if we have a tiny repository with just three commits in it, and we use uppercase letters (rather than round circles) to stand in for these commits, we can draw them like this:

A <-B <-C   <--master

The name master points to the last commit, C. Commit C itself points to earlier commit B, which points to very-first commit A. (Since A is that very-first commit, it just doesn't point anywhere, which is how Git knows to stop traversing.)

To add a new commit—let's call it D—Git writes out the new commit so that it points back to existing commit C, which used to be the last commit on the branch. Then Git writes D's actual hash ID, whatever that is, into the name master:

A <-B <-C <-D   <--master

If a tag name is made to point to one of these commits, that tag name stays where it is:

A <-B <-C <-D   <--master
            ^
            |
         tag:v11

When we add some new commits we get:

A <-B <-C <-D <-E <-F   <--master
            ^
            |
         tag:v11

The tag name has not moved, and should never move. (You can manually "move" one, by deleting it and creating another one with the same name, or using one of the force options, but in general you should not do this.)

Is it possible to check out this tagged commit if the release branch was deleted ...

Certainly. Branch names, tag names, and other names serve to locate one specific commit. You can go directly to that commit, using that name. The commit itself will be retained in that Git repository as long as the name itself continues to exist.

Having found some commit—usually, by a name—Git can use the internal arrows embedded inside each commit to move backwards through history. This means that if there's a name for commit D, as in the drawing above, Git can use D to find C, which it can use to find B, which it can use to find A. These four commits will therefore remain in this repository, because D is find-able.

Note that the name master locates commit F, which means commit F is retained. Commit F locates commit E, which locates D, and so on; so these commits will also be retained. There are therefore two names that mean that D-and-earlier must be retained. Deleting either of these names reduces the number of D-retaining-names to 1, but D must still be retained. If the name we delete is master, though, commit F is no longer required to be retained. If commit F is thrown out, that means commit E is no longer find-able either, and commit E can be thrown out as well.

If we add another name to find F, it becomes safe, in some sense, to delete the name master. Deleting the name master will, in effect, "forget" that the last commit in master was, at this time, commit F, but commit F will be find-able through some other name and therefore won't be thrown out.

Note that any merge commit has two (or more1) arrows coming out of it. If that merge commit is find-able, the arrows coming from it retain all the earlier commits down each of those paths. So once you have merged some branch-tip commit, as identified by some branch name, into some other branch whose name you intend to keep, it's safe to delete the merged branch's name: you won't be able to find that tip commit directly, but you can find it indirectly by finding the merge commit that has it as one of its extra parent commit hash IDs.


1Git calls this kind of merge, one that has more than two "legs" coming out of it, an octopus merge. This may be why GitHub use octocat as their logo.

like image 59
torek Avatar answered Sep 30 '22 14:09

torek