Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to have a separate branch for tagged commits only?

Tags:

git

I was tasked to organize the repository in the way that aside other branches there would be a dedicated branch, where we would only store the commits of released version. Below is the simplified scheme of what I would like to achieve:

| trunk    |           | releases |
|----------+-----------+----------|
| commit 1 |           |          |
| commit 2 | v0.1 ---> | tag 1    |
| commit 3 |           |          |
| commit 4 |           |          |
| commit 5 |           |          |
| commit 6 | v0.2 ---> | tag 2    |
| commit 7 |           |          |
| commit 8 |           |          |
| commit 9 |           |          |

This is a little bit too advanced for me now, so I'd appreciate some guidance on how to do that! I'm not really sure on how would I be able to have the second tag in the "releases" branch w/o having to import all the intermediate commits. Is that possible at all?

Also, if you have a better scheme for achieving the same goal (the goal being to have a dedicated branch for releases only), please do not hesitate to advise!


2 Answers

That wouldn't make sense, since the tagged commits represents the state of a branch, composed of the commits and its predecessors.

Isolate just the tagged commits would write a very different history, since those commits would miss their ancestors: it is the sequence of said ancestors plus the tagged commits which leads the code base to a particular state.

The simpler approach is to make sure you tag your release commits in one dedicated branch (master for instance).

Then, a simple git show-ref --tags can list the comimts referenced by those tags.

Or you can create a branch from any of those tags (for bug fixing a release)

git checkout -b newbranch v1.0

And you can deduce the last release tag from any commit (git describe --long).


The OP wvxvw adds in the comments:

but the branch with releases only to store the history of special commits (the tagged ones) made into it, and point to other branches as being sources from where the commits came from

That would be possible by merging the tag commit in a "release branch", with a merge which keeps "theirs" (ie the source of the merge, meaning the source of the tagged commit)

--x--x--x--x--x--x--x
 (v1)     (v2)
   \        \ 
----y--------y--
like image 75
VonC Avatar answered Jan 26 '26 20:01

VonC


This doesn't really make sense. In git, a branch name is simply a label pointing to a specific commit, in which the name "moves forward" automatically when adding a new commit:

C1 -- C2 -- C3         <-- label X
              \
                D1     <-- label Y

If you add a commit "on branch X" (i.e., where label X points), you get this:

C1 -- C2 -- C3 -- C4   <-- label X
              \
                D1     <-- label Y

A git tag is either "lightweight" or "annotated". The difference is that the first one is just a name—just a label, like X and Y here—pointing to a specific commit, while the second is a label pointing to a special kind of object stored in the repo, with the object pointing to the commit (this allows the annotated tag to carry more data than the lightweight tag: that extra data is stored along with the commit-ID to which the tag points). For our purposes here, though, the distinction is not really relevant.

Suppose I tag commits C4 and D1 with tags TC and TD. I get:

C1 -- C2 -- C3 -- C4   <-- branch X, tag TC
              \
                D1     <-- branch Y, TD

If I add more commits to "branch X" or "branch Y", what happens is that the branch label moves, while the tag label stays fixed. For instance, if I add commit C5 (on "branch X"), X will point to C5, but TC will still point to C4. However, if I do this by merging "branch Y" into "branch X"—this will be the new commit C5—I'll get:

                   .------------- tag TC
                   v
C1 -- C2 -- C3 -- C4 -- C5   <-- branch X
               \      /
                  D1         <-- branch Y, tag TD

I can now (without any complaint from git) delete "branch Y" entirely as its commits are "contained in" (which really means, reachable from) branch X and tag TD. If I do that, "tag TD" is not "on branch Y" at all, as branch Y does not exist. Even if I leave branch Y in place, tag TD is still contained in "branch X"! Starting at C5 and going to the second parent gets me D1, which is where TD points.

like image 21
torek Avatar answered Jan 26 '26 19:01

torek



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!