{"thread":{"id":"46256","subject":"Getting first tag per branch for a commit","startedAt":"2017-06-25T14:06:51Z","lastAt":"2017-06-26T09:37:22Z","messageCount":4,"participants":["Orgad Shaneh","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"323239","messageId":"CAGHpTBLP9MiYr2ZoUOaGjGMC+aO_EKYO6SwNLfAu6QFSRnPatQ@mail.gmail.com","threadId":"46256","inReplyTo":null,"subject":"Getting first tag per branch for a commit","fromName":"Orgad Shaneh","fromEmail":"orgads@gmail.com","sentAt":"2017-06-25T14:06:41Z","receivedAt":"2017-06-25T14:06:51Z","isPatch":false,"sender":{"key":"orgads@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1246544?v=4"},"body":"Hi,\n\ngit describe --tags <commit> gives me the first tag that includes this commit.\n\ngit tag --contains <commit> shows all the tags that contain the commit.\n\ngit branch -a --contains <commit> shows the branches that include this commit.\n\nWhat I'd like to have is a way to tell the first tag per branch (or\nper merge) that the commit appeared on.\n\nI'll use an example from the Git repository. Let's pick commit\n32b8c581ec which was first introduced in v2.9.3.\n\ngit describe --tags will only show v2.9.3\n\ngit tag --contains shows the following list:\nv2.10.0\nv2.10.0-rc0\nv2.10.0-rc1\nv2.10.0-rc2\nv2.10.1\nv2.10.2\nv2.10.3\nv2.11.0\nv2.11.0-rc0\nv2.11.0-rc1\nv2.11.0-rc2\nv2.11.0-rc3\nv2.11.1\nv2.11.2\nv2.12.0\nv2.12.0-rc0\nv2.12.0-rc1\nv2.12.0-rc2\nv2.12.1\nv2.12.2\nv2.12.3\nv2.13.0\nv2.13.0-rc0\nv2.13.0-rc1\nv2.13.0-rc2\nv2.13.1\nv2.13.2\nv2.9.3\nv2.9.4\n\nWhat really interests me as a user is the \"first in the series\" tag\nfor each version. What I'd expect is:\nv2.10.0-rc0\nv2.9.3\n\nand I can conclude that if it appeared in 2.9.3 then 2.9.4 also has\nit, and if it's in 2.10.0-rc0 then all the following versions (2.10.x\nand up) include it.\n\nI think that this can be done by filtering out tags that are connected\nto already listed tags by first-parent link.\n\nIs there a way to achieve this kind of \"simplified contained in\" list?\n\nRelated: https://bugs.chromium.org/p/gerrit/issues/detail?id=4331\n\n- Orgad\n"},{"id":"323250","messageId":"xmqqy3sf7mxo.fsf@gitster.mtv.corp.google.com","threadId":"46256","inReplyTo":"CAGHpTBLP9MiYr2ZoUOaGjGMC+aO_EKYO6SwNLfAu6QFSRnPatQ@mail.gmail.com","subject":"Re: Getting first tag per branch for a commit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-06-25T21:54:43Z","receivedAt":"2017-06-25T21:54:52Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Orgad Shaneh <orgads@gmail.com> writes:\n\n> What I'd like to have is a way to tell the first tag per branch (or\n> per merge) that the commit appeared on.\n\n> I think that this can be done by filtering out tags that are connected\n> to already listed tags by first-parent link.\n\nYes.  When one tag can be reached by another tag, then the former is\ndefinitely an earlier tag than the latter.\n\nA trivial way to compute it would require O(n^2) invocations of \"git\nmerge-base --is-ancestor\".  Alternatively, I think you can perhaps\nuse \"git merge-base --independent\".\n\nHaving said that, one thing to keep in mind is that a single \"first\ntag\" may not exist at all.\n\nConsider this topology:\n\n          o---X-------.                topic\n         /     \\       \\\n ---o---o---o-------o---N---S---o---   maint\n     \\           \\   \\           \\\n      o---o---o---M---o---o---T---o--- master\n\nwhere a topic branch was forked from the maintenance track, which is\nperiodically merged to the master branch.  That topic branch has the\ncommit of interest, X, which first gets merged to the master branch\nat merge M, which eventually gets tagged as T (i.e. a new feature\nrelease).  But (wall-clock-wise) after merge M is made and the\nchange is tested in the context of the master branch, but before the\nrelease T happens, the topic may be merged down to the maintenance\ntrack at merge N.  Then eventually the tip of the maintenance track\nis tagged as S (i.e. a maintenance release).\n\nTopologically, T and S cannot be compared and they both contain X,\nso the question \"what is the first tag on 'master' that has commit\nX?\" does not have a single unique answer.  Both S and T are eligible.\n\nYou could define various heuristics to tiebreak among these tags.\nYou may be tempted to compare timestamps of S and T.  If they were\nequal, then you might want to compare timestamps of M and N.\n\nBut you'd need to accept that fundamentally there may not be a\nsingle \"first tag\".\n\n\n"},{"id":"323255","messageId":"xmqqd19r7lml.fsf@gitster.mtv.corp.google.com","threadId":"46256","inReplyTo":"xmqqy3sf7mxo.fsf@gitster.mtv.corp.google.com","subject":"Re: Getting first tag per branch for a commit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-06-25T22:22:58Z","receivedAt":"2017-06-25T22:23:04Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Orgad Shaneh <orgads@gmail.com> writes:\n>\n>> What I'd like to have is a way to tell the first tag per branch (or\n>> per merge) that the commit appeared on.\n>\n>> I think that this can be done by filtering out tags that are connected\n>> to already listed tags by first-parent link.\n>\n> Yes.  When one tag can be reached by another tag, then the former is\n> definitely an earlier tag than the latter.\n>\n> A trivial way to compute it would require O(n^2) invocations of \"git\n> merge-base --is-ancestor\".  Alternatively, I think you can perhaps\n> use \"git merge-base --independent\".\n\nAh, forget the latter.  \"independent\" is about solving the opposite\nuse case--it is to cull the ones that can be reached by other tips.\n"},{"id":"323263","messageId":"CAGHpTB+xL1h=1mEssgkTeJbKjQu_iiHrTABWJFgsGfUXitLUnQ@mail.gmail.com","threadId":"46256","inReplyTo":"xmqqy3sf7mxo.fsf@gitster.mtv.corp.google.com","subject":"Re: Getting first tag per branch for a commit","fromName":"Orgad Shaneh","fromEmail":"orgads@gmail.com","sentAt":"2017-06-26T09:37:13Z","receivedAt":"2017-06-26T09:37:22Z","isPatch":false,"sender":{"key":"orgads@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1246544?v=4"},"body":"On Mon, Jun 26, 2017 at 12:54 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Orgad Shaneh <orgads@gmail.com> writes:\n>\n>> What I'd like to have is a way to tell the first tag per branch (or\n>> per merge) that the commit appeared on.\n>\n>> I think that this can be done by filtering out tags that are connected\n>> to already listed tags by first-parent link.\n>\n> Yes.  When one tag can be reached by another tag, then the former is\n> definitely an earlier tag than the latter.\n>\n> A trivial way to compute it would require O(n^2) invocations of \"git\n> merge-base --is-ancestor\".  Alternatively, I think you can perhaps\n> use \"git merge-base --independent\".\n\nI think this feature needs to be implemented in Git (by a flag to git describe).\nO(n^2) is way too much when you have 20,000 tags.\n\nUnfortunately, I don't feel qualified for implementing it myself. Does anyone\nelse volunteer? :)\n\n> Having said that, one thing to keep in mind is that a single \"first\n> tag\" may not exist at all.\n>\n> Consider this topology:\n>\n>           o---X-------.                topic\n>          /     \\       \\\n>  ---o---o---o-------o---N---S---o---   maint\n>      \\           \\   \\           \\\n>       o---o---o---M---o---o---T---o--- master\n>\n> where a topic branch was forked from the maintenance track, which is\n> periodically merged to the master branch.  That topic branch has the\n> commit of interest, X, which first gets merged to the master branch\n> at merge M, which eventually gets tagged as T (i.e. a new feature\n> release).  But (wall-clock-wise) after merge M is made and the\n> change is tested in the context of the master branch, but before the\n> release T happens, the topic may be merged down to the maintenance\n> track at merge N.  Then eventually the tip of the maintenance track\n> is tagged as S (i.e. a maintenance release).\n>\n> Topologically, T and S cannot be compared and they both contain X,\n> so the question \"what is the first tag on 'master' that has commit\n> X?\" does not have a single unique answer.  Both S and T are eligible.\n>\n> You could define various heuristics to tiebreak among these tags.\n> You may be tempted to compare timestamps of S and T.  If they were\n> equal, then you might want to compare timestamps of M and N.\n>\n> But you'd need to accept that fundamentally there may not be a\n> single \"first tag\".\n\nI accept that. Anyway, this looks to me like a corner case, and I don't mind\nhaving several tags from the same branch for this case.\n\n- Orgad\n"}]}