{"thread":{"id":"20851","subject":"tracking branch for a rebase","startedAt":"2009-09-04T13:54:14Z","lastAt":"2009-10-02T14:54:44Z","messageCount":39,"participants":["Pete Wyckoff","Michael J Gruber","Jeff King","Björn Steinbrink","Junio C Hamano","Johannes Schindelin","Julian Phillips","Johan Herland"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"122436","messageId":"20090904135414.GA3728@honk.padd.com","threadId":"20851","inReplyTo":null,"subject":"tracking branch for a rebase","fromName":"Pete Wyckoff","fromEmail":"pw@padd.com","sentAt":"2009-09-04T13:54:14Z","receivedAt":"2009-09-04T13:54:14Z","isPatch":false,"sender":{"key":"pw@padd.com","avatar":null},"body":"I received an interesting question today.\n\nIf \"git pull\" knows what remote tracking brach to pull from,\nwhy doesn't \"git rebase\" automatically know I want to rebase\non top of my remote tracking branch?\n\nHe had done a \"git remote update\", reviewed the changes, and now\nwants to rebase his changes on top of the new upstream.\n\nI told him about git pull --rebase, and branch.name.rebase,\nbut didn't have an easy answer to the \"what is my remote tracking\nbranch\" question in this case.\n\nAll the information is in git config branch.name.{remote,merge},\nbut I can't find anything that just answers that question.  Nor\ndid I have a good answer for why \"git rebase\" doesn't just default\nto rebasing the current branch on top of the tracking branch.\n\nThoughts?\n\n\t\t-- Pete\n"},{"id":"122437","messageId":"4AA124DD.1030208@drmicha.warpmail.net","threadId":"20851","inReplyTo":"20090904135414.GA3728@honk.padd.com","subject":"Re: tracking branch for a rebase","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2009-09-04T14:31:57Z","receivedAt":"2009-09-04T14:31:57Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Pete Wyckoff venit, vidit, dixit 04.09.2009 15:54:\n> I received an interesting question today.\n> \n> If \"git pull\" knows what remote tracking brach to pull from,\n> why doesn't \"git rebase\" automatically know I want to rebase\n> on top of my remote tracking branch?\n> \n> He had done a \"git remote update\", reviewed the changes, and now\n> wants to rebase his changes on top of the new upstream.\n> \n> I told him about git pull --rebase, and branch.name.rebase,\n> but didn't have an easy answer to the \"what is my remote tracking\n> branch\" question in this case.\n\nI guess he knows that branch if he reviewed it... More seriously,\n\ngit for-each-ref --format='%(upstream)' refs/heads/hisbranch\n\nwill return the upstream of hisbranch.\n\n> \n> All the information is in git config branch.name.{remote,merge},\n> but I can't find anything that just answers that question.  Nor\n> did I have a good answer for why \"git rebase\" doesn't just default\n> to rebasing the current branch on top of the tracking branch.\n\nMaybe because nobody has cared. Doing a \"git pull --rebase\" is not\nequivalent (it may fetch more refs), but close enough for many people.\n\nThere was an initiative by Dscho a while ago to introduce a shortcut for\nthe upstream, which was dwarfed by the lack reserved characters for\nrefnames. Maybe 1.7 time frame would be a good time to change this?\n\nMaking this the default for rebase without arguments may meet some\nobjections (oh no, I didn't mean to rebase), but I guess it's worth trying.\n\nMichael\n"},{"id":"122458","messageId":"20090904181846.GC19093@coredump.intra.peff.net","threadId":"20851","inReplyTo":"4AA124DD.1030208@drmicha.warpmail.net","subject":"Re: tracking branch for a rebase","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-09-04T18:18:46Z","receivedAt":"2009-09-04T18:18:46Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Sep 04, 2009 at 04:31:57PM +0200, Michael J Gruber wrote:\n\n> Making [rebase against upstream] the default for rebase without\n> arguments may meet some objections (oh no, I didn't mean to rebase),\n> but I guess it's worth trying.\n\nFWIW, that has been a patch I have been meaning to do for a while. I\ndon't see it as any more error-prone than \"git pull\" without arguments.\nIn either case, you can always recover with a reset from the reflog.\n\nThe biggest question is whether it should respect branch.*.merge, or\njust branch.*.rebase (I never use the latter simply because I never use\n\"git pull\", but I think it is probably reasonable to restrict it to\ncases where you said you are interested in rebasing in general).\n\n-Peff\n"},{"id":"122462","messageId":"20090904185949.GA21583@atjola.homenet","threadId":"20851","inReplyTo":"20090904181846.GC19093@coredump.intra.peff.net","subject":"Re: tracking branch for a rebase","fromName":"Björn Steinbrink","fromEmail":"b.steinbrink@gmx.de","sentAt":"2009-09-04T18:59:49Z","receivedAt":"2009-09-04T18:59:49Z","isPatch":false,"sender":{"key":"b.steinbrink@gmx.de","avatar":"https://avatars.githubusercontent.com/u/230962?v=4"},"body":"On 2009.09.04 14:18:46 -0400, Jeff King wrote:\n> On Fri, Sep 04, 2009 at 04:31:57PM +0200, Michael J Gruber wrote:\n> \n> > Making [rebase against upstream] the default for rebase without\n> > arguments may meet some objections (oh no, I didn't mean to rebase),\n> > but I guess it's worth trying.\n> \n> FWIW, that has been a patch I have been meaning to do for a while. I\n> don't see it as any more error-prone than \"git pull\" without arguments.\n> In either case, you can always recover with a reset from the reflog.\n\nNote that with:\n\tbranch.foo.remote = origin\n\tbranch.foo.merge = refs/heads/foo\n\n\"git pull --rebase\" is not the same as:\n\"git fetch origin && git rebase origin/foo\", but:\n\ngit fetch origin && git rebase --onto origin/foo $reflog_merge_base\n\nWhere $reflog_merge_base is the first merge base is found between the\ncurrent branch head, and the reflog entries for origin/foo.\n\n\nSame deal for \"git pull --rebase origin bla\", which is not:\n\"git fetch origin bla && git rebase FETCH_HEAD\", but:\n\ngit fetch origin && git rebase --onto FETCH_HEAD $reflog_merge_base\n\nWhere again $reflog_merge_base is found by looking at the reflog for\norigin/foo.\n\nIt does that to try to automatically handle cases where upstream has\nbeen rebased. I'm not completely sure whether I like or hate that.\nEspecially the \"git pull --rebase <remote> <refspec>\" case seems very\nweird to me. And if \"rebase\" is to pickup the same default as \"pull\", I\nguess it should also show the same behaviour, but just skips the \"fetch\"\npart?\n\n> The biggest question is whether it should respect branch.*.merge, or\n> just branch.*.rebase (I never use the latter simply because I never use\n> \"git pull\", but I think it is probably reasonable to restrict it to\n> cases where you said you are interested in rebasing in general).\n\nHm, you'll probably want \"git merge\" to pickup the default as well then,\nright? And that should only do so if branch.*.rebase is not set. So\neffectively, you still have to use the right command, but can skip the\nargument. Having to deal a lot with git-svn, I also regulary use its\n\"git svn rebase --local\", which means \"just rebase, don't fetch\".\n\nNow, basically \"git svn rebase\" is pretty much git-svn's \"pull\". Maybe\nits idea could be taken, so we get \"git pull --local\" to just skip the\nfetch part, but keep \"git rebase\" and \"git merge\" 'dumb', requiring\nexplicit arguments.\n\n(In the past, I once argued for deprecating \"pull\", and having\nmerge/rebase doing the fetch as well, with a --local argument that stops\nthem from doing so. That was probably mostly due to the fact that I ran\ninto too many people that simply didn't understood that \"git pull\" is\nnot \"svn up\". I still kind of like the idea, but seeing just how often I\nuse rebase/merge with already fetched stuff, I can see how having to use\na --local flag with them all the time would be quite a PITA, but now,\nhaving the --local flag for \"pull\" seems to make sense to me.)\n\nBjörn\n"},{"id":"122480","messageId":"20090905061250.GA29863@coredump.intra.peff.net","threadId":"20851","inReplyTo":"20090904185949.GA21583@atjola.homenet","subject":"Re: tracking branch for a rebase","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-09-05T06:12:50Z","receivedAt":"2009-09-05T06:12:50Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Sep 04, 2009 at 08:59:49PM +0200, Björn Steinbrink wrote:\n\n> \"git pull --rebase\" is not the same as:\n> \"git fetch origin && git rebase origin/foo\", but:\n> \n> git fetch origin && git rebase --onto origin/foo $reflog_merge_base\n> \n> Where $reflog_merge_base is the first merge base is found between the\n> current branch head, and the reflog entries for origin/foo.\n\nThanks, I didn't know about the trick (not being, as I mentioned, a pull\n--rebase user). I can see arguments for or against a rebase-default\nusing that feature. On one hand, it simplifies the explanation for\npeople going between \"pull --rebase\" and \"fetch && rebase\". And I think\nit should generally Do What You Mean in the case that upstream hasn't\nrebased. Are there cases you know of where it will do the wrong thing?\n\nI don't know if people would be confused that \"git rebase\" does not\nexactly default to \"git rebase $upstream\", which is at least easy to\nexplain.\n\n> > The biggest question is whether it should respect branch.*.merge, or\n> > just branch.*.rebase (I never use the latter simply because I never use\n> > \"git pull\", but I think it is probably reasonable to restrict it to\n> > cases where you said you are interested in rebasing in general).\n> \n> Hm, you'll probably want \"git merge\" to pickup the default as well then,\n> right? And that should only do so if branch.*.rebase is not set. So\n> effectively, you still have to use the right command, but can skip the\n> argument. Having to deal a lot with git-svn, I also regulary use its\n> \"git svn rebase --local\", which means \"just rebase, don't fetch\".\n\nI hadn't considered whether \"git merge\" should get a default. To be\nhonest, my intended use case was not really to replace pull, but as a\nshorthand for running \"git rebase -i\". Upstream has the published\ncommits, so it is a nice shortcut to say \"let me munge all of the\ncommits that I haven't published yet\".\n\nOf course the \"published\" status of those commits is not guaranteed\n(they might have been published in another branch, your\ntracking refs might not be up to date, etc) but I think it's a good rule\nof thumb.\n\nAnd by automating the shorthand we reduce the chance of errors. For\nexample, I usually base my topic branches from origin/master. But the\nother day I happened to be building a new branch, jk/date, off of\nlt/approxidate, salvaged from origin/pu. I did \"git rebase -i\norigin/master\" and accidentally rewrote the early part of\nlt/approxidate.\n\n> Now, basically \"git svn rebase\" is pretty much git-svn's \"pull\". Maybe\n> its idea could be taken, so we get \"git pull --local\" to just skip the\n> fetch part, but keep \"git rebase\" and \"git merge\" 'dumb', requiring\n> explicit arguments.\n\nThat wouldn't help me, because you can't \"pull -i\". :)\n\n-Peff\n"},{"id":"122518","messageId":"20090905140127.GA29037@atjola.homenet","threadId":"20851","inReplyTo":"20090905061250.GA29863@coredump.intra.peff.net","subject":"Re: tracking branch for a rebase","fromName":"Björn Steinbrink","fromEmail":"b.steinbrink@gmx.de","sentAt":"2009-09-05T14:01:27Z","receivedAt":"2009-09-05T14:01:27Z","isPatch":false,"sender":{"key":"b.steinbrink@gmx.de","avatar":"https://avatars.githubusercontent.com/u/230962?v=4"},"body":"On 2009.09.05 02:12:50 -0400, Jeff King wrote:\n> On Fri, Sep 04, 2009 at 08:59:49PM +0200, Björn Steinbrink wrote:\n> \n> > \"git pull --rebase\" is not the same as:\n> > \"git fetch origin && git rebase origin/foo\", but:\n> > \n> > git fetch origin && git rebase --onto origin/foo $reflog_merge_base\n> > \n> > Where $reflog_merge_base is the first merge base is found between the\n> > current branch head, and the reflog entries for origin/foo.\n> \n> Thanks, I didn't know about the trick (not being, as I mentioned, a pull\n> --rebase user). I can see arguments for or against a rebase-default\n> using that feature. On one hand, it simplifies the explanation for\n> people going between \"pull --rebase\" and \"fetch && rebase\". And I think\n> it should generally Do What You Mean in the case that upstream hasn't\n> rebased. Are there cases you know of where it will do the wrong thing?\n> \n> I don't know if people would be confused that \"git rebase\" does not\n> exactly default to \"git rebase $upstream\", which is at least easy to\n> explain.\n\nFor me, the confusion would arise from the fact that \"git rebase\"\n(without args) would seem like a \"pull --rebase\" without the fetch, but\nisn't. And to reducing the difference to just the fetch would require a\nquite change in bahaviour.\n\nCurrently, when branch.<name>.merge is set:\n\"git rebase <upstream>\" ==> Can't really be done with \"pull --rebase\"\n\"git pull --rebase [...]\" ==> Can't be done with \"rebase\" alone.\n\nCurrently, \"pull\" is a convenience thing, and thus may do more magic,\nwhile \"rebase\" is dumb, and needs arguments. Starting to add _different_\nmagic to rebase seems wrong to me.\n\n> And by automating the shorthand we reduce the chance of errors. For\n> example, I usually base my topic branches from origin/master. But the\n> other day I happened to be building a new branch, jk/date, off of\n> lt/approxidate, salvaged from origin/pu. I did \"git rebase -i\n> origin/master\" and accidentally rewrote the early part of\n> lt/approxidate.\n\nHm, I'd prefer a shorthand for \"upstream for this branch\", instead of\nmagic defaults.\n\n> > Now, basically \"git svn rebase\" is pretty much git-svn's \"pull\". Maybe\n> > its idea could be taken, so we get \"git pull --local\" to just skip the\n> > fetch part, but keep \"git rebase\" and \"git merge\" 'dumb', requiring\n> > explicit arguments.\n> \n> That wouldn't help me, because you can't \"pull -i\". :)\n\nI probably shouldn't tell anyone, as it's a crude hack, but \"git pull\n--rebase -s -i\" does the trick... *hides*\n\nBjörn\n"},{"id":"122519","messageId":"20090905142841.GB15631@coredump.intra.peff.net","threadId":"20851","inReplyTo":"20090905140127.GA29037@atjola.homenet","subject":"Re: tracking branch for a rebase","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-09-05T14:28:41Z","receivedAt":"2009-09-05T14:28:41Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Sep 05, 2009 at 04:01:27PM +0200, Björn Steinbrink wrote:\n\n> > And by automating the shorthand we reduce the chance of errors. For\n> > example, I usually base my topic branches from origin/master. But the\n> > other day I happened to be building a new branch, jk/date, off of\n> > lt/approxidate, salvaged from origin/pu. I did \"git rebase -i\n> > origin/master\" and accidentally rewrote the early part of\n> > lt/approxidate.\n> \n> Hm, I'd prefer a shorthand for \"upstream for this branch\", instead of\n> magic defaults.\n\nThe more I think about, the more I think that is the right solution.\nBecause magic defaults for \"rebase -i\" don't help when you want to do\n\"gitk $UPSTREAM..\".\n\nThe previous discussion on the topic seems to be here:\n\n  http://article.gmane.org/gmane.comp.version-control.git/113666\n\nAnd apparently you and I both participated in the discussion, which I\ntotally forgot about.\n\nLooks like the discussion ended with people liking the idea but not\nknowing what the specifier should look like. Maybe tightening the ref\nsyntax a bit to allow more extensible \"special\" refs is a good v1.7.0\ntopic? I dunno.\n\n> > That wouldn't help me, because you can't \"pull -i\". :)\n> \n> I probably shouldn't tell anyone, as it's a crude hack, but \"git pull\n> --rebase -s -i\" does the trick... *hides*\n\nOK, that's just sick. :)\n\n-Peff\n"},{"id":"122527","messageId":"7v4orh1ddt.fsf@alter.siamese.dyndns.org","threadId":"20851","inReplyTo":"20090905140127.GA29037@atjola.homenet","subject":"Re: tracking branch for a rebase","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-05T17:59:26Z","receivedAt":"2009-09-05T17:59:26Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Björn Steinbrink <B.Steinbrink@gmx.de> writes:\n\n> For me, the confusion would arise from the fact that \"git rebase\"\n> (without args) would seem like a \"pull --rebase\" without the fetch, but\n> isn't.\n\nIt is true that one popular way to explain 'git pull' is:\n\n    'git pull' is 'git fetch' followed by 'git merge'.\n\nThese three command names in the sentence merely refer to the concepts of\nwhat they do.\n\nIt is left up to the readers to extend the concepts to concrete command\nline to suit the needs for their situation.  For example you would\nrestate the above general explanation into this form:\n\n       'git pull git.git master' is 'git fetch git.git master' followed by\n       'git merge FETCH_HEAD'\n\nwhen updating your tree with the master branch of upstream git.git\nrepository.\n\nDon't confuse the general concept with concrete syntax.\n\n    'git pull --rebase' is 'git fetch' followed by 'git rebase'\n\nis exactly the same deal.\n"},{"id":"122580","messageId":"7vfxaz9wfi.fsf@alter.siamese.dyndns.org","threadId":"20851","inReplyTo":"20090905142841.GB15631@coredump.intra.peff.net","subject":"Re: tracking branch for a rebase","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-07T05:05:21Z","receivedAt":"2009-09-07T05:05:21Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n>> Hm, I'd prefer a shorthand for \"upstream for this branch\", instead of\n>> magic defaults.\n>\n> The more I think about, the more I think that is the right solution.\n> Because magic defaults for \"rebase -i\" don't help when you want to do\n> \"gitk $UPSTREAM..\".\n>\n> The previous discussion on the topic seems to be here:\n>\n>   http://article.gmane.org/gmane.comp.version-control.git/113666\n>\n> And apparently you and I both participated in the discussion, which I\n> totally forgot about.\n>\n> Looks like the discussion ended with people liking the idea but not\n> knowing what the specifier should look like. Maybe tightening the ref\n> syntax a bit to allow more extensible \"special\" refs is a good v1.7.0\n> topic? I dunno.\n\nAt-mark currently is reserved for anything that uses reflog, but we can\nsay that it is to specify operations on refs (as opposed to caret and\ntilde are to specify operations on object names).\n\nIt specifies what ref to work on with the operand on its left side (and an\nempty string stands for \"HEAD\"), and what operation is done to it by what\nis in {} on the right side of it.  This view is quite consistent with the\nfollowing existing uses of the notation:\n\n\tref@{number}\t-- nth reflog entry\n        ref@{time}\t-- ref back then\n\t@{-number}\t-- nth branch switching\n\nSo perhaps ref@{upstream}, or any string that is not a number and cannot\nbe time, can trigger the magic operation on the ref with ref@{magic}\nsyntax?\n"},{"id":"122594","messageId":"4AA4C0CE.2070300@drmicha.warpmail.net","threadId":"20851","inReplyTo":"7vfxaz9wfi.fsf@alter.siamese.dyndns.org","subject":"Re: tracking branch for a rebase","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2009-09-07T08:14:06Z","receivedAt":"2009-09-07T08:14:06Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Junio C Hamano venit, vidit, dixit 07.09.2009 07:05:\n> Jeff King <peff@peff.net> writes:\n> \n>>> Hm, I'd prefer a shorthand for \"upstream for this branch\", instead of\n>>> magic defaults.\n>>\n>> The more I think about, the more I think that is the right solution.\n>> Because magic defaults for \"rebase -i\" don't help when you want to do\n>> \"gitk $UPSTREAM..\".\n>>\n>> The previous discussion on the topic seems to be here:\n>>\n>>   http://article.gmane.org/gmane.comp.version-control.git/113666\n>>\n>> And apparently you and I both participated in the discussion, which I\n>> totally forgot about.\n>>\n>> Looks like the discussion ended with people liking the idea but not\n>> knowing what the specifier should look like. Maybe tightening the ref\n>> syntax a bit to allow more extensible \"special\" refs is a good v1.7.0\n>> topic? I dunno.\n> \n> At-mark currently is reserved for anything that uses reflog, but we can\n> say that it is to specify operations on refs (as opposed to caret and\n> tilde are to specify operations on object names).\n> \n> It specifies what ref to work on with the operand on its left side (and an\n> empty string stands for \"HEAD\"), and what operation is done to it by what\n> is in {} on the right side of it.  This view is quite consistent with the\n> following existing uses of the notation:\n> \n> \tref@{number}\t-- nth reflog entry\n>         ref@{time}\t-- ref back then\n> \t@{-number}\t-- nth branch switching\n> \n> So perhaps ref@{upstream}, or any string that is not a number and cannot\n> be time, can trigger the magic operation on the ref with ref@{magic}\n> syntax?\n\nEven @{} is not taken so far... Alternatively, most people associate '^'\nwith 'up', just the way we use it for \"upwards parentship\" ref^ (and\nsomewhat the way we use it for upwards/backwards tag reference\nrelationship resolving ref^{type}), so\n@^\nor\n@{^}\nwould be an option. Read \"at upstream\" :)\n\nMichael\n"},{"id":"122599","messageId":"7vzl97xit9.fsf@alter.siamese.dyndns.org","threadId":"20851","inReplyTo":"4AA4C0CE.2070300@drmicha.warpmail.net","subject":"Re: tracking branch for a rebase","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-07T08:25:38Z","receivedAt":"2009-09-07T08:25:38Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael J Gruber <git@drmicha.warpmail.net> writes:\n\n> @^\n\n\"@\" itself is not reserved, even though \"@{\" is, so this is not an\noption.\n\n> @{^}\n\nThis _could_ work, although it is rather cryptic.\n"},{"id":"122601","messageId":"20090907084324.GB17997@coredump.intra.peff.net","threadId":"20851","inReplyTo":"7vfxaz9wfi.fsf@alter.siamese.dyndns.org","subject":"Re: tracking branch for a rebase","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-09-07T08:43:25Z","receivedAt":"2009-09-07T08:43:25Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Sep 06, 2009 at 10:05:21PM -0700, Junio C Hamano wrote:\n\n> At-mark currently is reserved for anything that uses reflog, but we can\n> say that it is to specify operations on refs (as opposed to caret and\n> tilde are to specify operations on object names).\n\nI assume you meant that @{} is reserved; my reading of the previous\ndiscussion was that \"foo@bar\" is still valid.\n\n> It specifies what ref to work on with the operand on its left side (and an\n> empty string stands for \"HEAD\"), and what operation is done to it by what\n> is in {} on the right side of it.  This view is quite consistent with the\n> following existing uses of the notation:\n> \n> \tref@{number}\t-- nth reflog entry\n>         ref@{time}\t-- ref back then\n> \t@{-number}\t-- nth branch switching\n> \n> So perhaps ref@{upstream}, or any string that is not a number and cannot\n> be time, can trigger the magic operation on the ref with ref@{magic}\n> syntax?\n\nI think using @{} is a reasonable extension format. It's easy to read\nand syntactically obvious. We need to watch out for conflicts with\nthings that might be valid times, but that is an easy thing to check\nwhen adding new keywords. The only danger would be some extension\nspecifier that used arbitrary input, but that would probably be prefixed\nwith a keyword (and I can't even think of an example extension that\nwould want arbitrary input).\n\nMy only two complaints with ref@{upstream} are (and I don't think either\nis a show-stopper, but maybe something we can improve on).\n\n  1. It is a nice abstraction, but it doesn't save typing in most cases.\n     \"origin\" is shorter than \"master@{upstream}\". One of the desired\n     features in the last thread was that it be very short (which isn't\n     to say we can't introduce @{upstream} _now_ and add a shorter\n     synonym later on).\n\n  2. I assume @{upstream} will be equivalent to HEAD@{upstream}. What\n     should it do? The most useful thing to me would be to find the\n     upstream for the current branch. But that is actually quite\n     different from how HEAD@{1} works, which looks at the reflog for\n     HEAD and not the branch.\n\n     Maybe this is an inconsistency we can live with. The features are,\n     after all, only syntactically related. I was just hoping to keep\n     things as simple as possible for users to understand (and they\n     often take semantic clues from syntax).\n\nAnd some final thinking out loud in this area (i.e., these ideas are, I\nthink, somewhat half baked):\n\nWe already have some reserved uppercase ref names like HEAD, FETCH_HEAD,\nORIG_HEAD, and MERGE_HEAD.  One option would be to declare all-caps\nnames as reserved and allow UPSTREAM for the feature in question. I can\nthink of two arguments against it:\n\n 1. The obvious one, that somebody somewhere is using all-caps and we\n    are breaking their setup.\n\n 2. It is not syntactically obvious to the user that it is not a real\n    ref, but rather a magic name. Users are accustomed to punctuation\n    introducing magic, so @{upstream} is probably better in that regard.\n\nSo I think that is a bad idea. But what about allowing \"ref aliases\"?\nObviously a static one like \"f\" for \"foo\" is kind of lame. But if you\ncould use the extension syntax, like:\n\n  git config refalias.% '@{upstream}'\n\nthen we can let people set up whatever shorthand they think is sane (and\nwithout worrying about clobbering unlikely-but-allowed setups, since\nthey are in control of their setup).\n\nLike I said, I am not sure that is not half-baked. ;)\n\n-Peff\n"},{"id":"122602","messageId":"20090907084455.GC17997@coredump.intra.peff.net","threadId":"20851","inReplyTo":"7vzl97xit9.fsf@alter.siamese.dyndns.org","subject":"Re: tracking branch for a rebase","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-09-07T08:44:55Z","receivedAt":"2009-09-07T08:44:55Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Sep 07, 2009 at 01:25:38AM -0700, Junio C Hamano wrote:\n\n> > @{^}\n> \n> This _could_ work, although it is rather cryptic.\n\nBut an identifier composed entirely of punctuation? It might help git\ncatch on with perl programmers. ;)\n\n-Peff\n"},{"id":"122608","messageId":"4AA4CD29.4040805@drmicha.warpmail.net","threadId":"20851","inReplyTo":"20090907084455.GC17997@coredump.intra.peff.net","subject":"Re: tracking branch for a rebase","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2009-09-07T09:06:49Z","receivedAt":"2009-09-07T09:06:49Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Jeff King venit, vidit, dixit 07.09.2009 10:44:\n> On Mon, Sep 07, 2009 at 01:25:38AM -0700, Junio C Hamano wrote:\n> \n>>> @{^}\n>> \n>> This _could_ work, although it is rather cryptic.\n> \n> But an identifier composed entirely of punctuation? It might help\n> git catch on with perl programmers. ;)\n\nRight, that was the true agenda hidden only partially behind the plain\nassociation between ^ and up ;)\n\nMichael (having exactly zero perl fu)\n\nP.S.: @ may not be reserved, and neither @^, but 1.7 should allow us to\nreserve some symbols/combinations with a \"low damage probability\".\nPeople may have a@b refnames (git-svn users for sure), but @^?\n"},{"id":"122610","messageId":"alpine.DEB.1.00.0909071126040.8306@pacific.mpi-cbg.de","threadId":"20851","inReplyTo":"20090907084324.GB17997@coredump.intra.peff.net","subject":"Re: tracking branch for a rebase","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-09-07T09:29:50Z","receivedAt":"2009-09-07T09:29:50Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 7 Sep 2009, Jeff King wrote:\n\n> On Sun, Sep 06, 2009 at 10:05:21PM -0700, Junio C Hamano wrote:\n> \n> > \tref@{number}\t-- nth reflog entry\n> >         ref@{time}\t-- ref back then\n> > \t@{-number}\t-- nth branch switching\n> > \n> > So perhaps ref@{upstream}, or any string that is not a number and cannot\n> > be time, can trigger the magic operation on the ref with ref@{magic}\n> > syntax?\n> \n> I think using @{} is a reasonable extension format.\n\nSorry to enter this thread that late, but I did not realize that it \ntouches my %<branch> work.\n\nYour proposal leads to something like \"master@{upstream}@{2.days.ago}\", \nwhich looks ugly.  And it is much more to type.\n\nI still think that it is not too-much asked for to require the \n\"refs/heads/\" prefix if somebody starts her branch names with \"%\".\n\nOr did I miss something (as I do not have time to read long mails these \ndays, I tend to read only the short, to-the-point ones; I allowed myself \nto only skim over the rest of your mail)?\n\nCiao,\nDscho\n"},{"id":"122612","messageId":"4AA4D81A.1030203@drmicha.warpmail.net","threadId":"20851","inReplyTo":"alpine.DEB.1.00.0909071126040.8306@pacific.mpi-cbg.de","subject":"Re: tracking branch for a rebase","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2009-09-07T09:53:30Z","receivedAt":"2009-09-07T09:53:30Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Johannes Schindelin venit, vidit, dixit 07.09.2009 11:29:\n> Hi,\n> \n> On Mon, 7 Sep 2009, Jeff King wrote:\n> \n>> On Sun, Sep 06, 2009 at 10:05:21PM -0700, Junio C Hamano wrote:\n>>\n>>> \tref@{number}\t-- nth reflog entry\n>>>         ref@{time}\t-- ref back then\n>>> \t@{-number}\t-- nth branch switching\n>>>\n>>> So perhaps ref@{upstream}, or any string that is not a number and cannot\n>>> be time, can trigger the magic operation on the ref with ref@{magic}\n>>> syntax?\n>>\n>> I think using @{} is a reasonable extension format.\n> \n> Sorry to enter this thread that late, but I did not realize that it \n> touches my %<branch> work.\n> \n> Your proposal leads to something like \"master@{upstream}@{2.days.ago}\", \n> which looks ugly.  And it is much more to type.\n> \n> I still think that it is not too-much asked for to require the \n> \"refs/heads/\" prefix if somebody starts her branch names with \"%\".\n> \n> Or did I miss something (as I do not have time to read long mails these \n> days, I tend to read only the short, to-the-point ones; I allowed myself \n> to only skim over the rest of your mail)?\n\nSolution needs to be:\n- practical (short, clear)\n- not too brutal (on existing users of legal \"exotic\" refnames)\n- extensible (for later uses)\n\nMichael\n152 chars for Dscho :)\n"},{"id":"122744","messageId":"alpine.LNX.2.00.0909090003330.6055@reaper.quantumfyre.co.uk","threadId":"20851","inReplyTo":"4AA4D81A.1030203@drmicha.warpmail.net","subject":"Re: tracking branch for a rebase","fromName":"Julian Phillips","fromEmail":"julian@quantumfyre.co.uk","sentAt":"2009-09-08T23:17:37Z","receivedAt":"2009-09-08T23:17:37Z","isPatch":false,"sender":{"key":"julian@quantumfyre.co.uk","avatar":"https://avatars.githubusercontent.com/u/948888?v=4"},"body":"On Mon, 7 Sep 2009, Michael J Gruber wrote:\n\n> Solution needs to be:\n> - practical (short, clear)\n> - not too brutal (on existing users of legal \"exotic\" refnames)\n> - extensible (for later uses)\n\nHow about '/^' and 'ref/^'?  Since you can't create a ref ending / ...\n\n-- \nJulian\n\n  ---\nWhen you ask a question, do you truly want to know the answer, or are you\nmerely flaunting your power?\n\n   -- DMITRI HARKONNEN, Notes to My Sons\n"},{"id":"122753","messageId":"20090909104550.GA20108@coredump.intra.peff.net","threadId":"20851","inReplyTo":"alpine.DEB.1.00.0909071126040.8306@pacific.mpi-cbg.de","subject":"Re: tracking branch for a rebase","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-09-09T10:45:50Z","receivedAt":"2009-09-09T10:45:50Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Sep 07, 2009 at 11:29:50AM +0200, Johannes Schindelin wrote:\n\n> > I think using @{} is a reasonable extension format.\n> \n> Sorry to enter this thread that late, but I did not realize that it \n> touches my %<branch> work.\n> \n> Your proposal leads to something like \"master@{upstream}@{2.days.ago}\", \n> which looks ugly.  And it is much more to type.\n> \n> I still think that it is not too-much asked for to require the \n> \"refs/heads/\" prefix if somebody starts her branch names with \"%\".\n\nI don't have a problem with restricting branch names starting with \"%\".\nHowever, I do think \"%..\" is a bit ugly to read. And I am somewhat\nconcerned that we are eating the last reasonable available\nmeta-character for this feature, which will make things even harder next\ntime somebody suggests a clever feature. Which is why the discussion\nturned to a generic extension syntax.\n\nI wonder if it is worth adding @{upstream} now, which is fairly safe,\nletting it cook for a while, and then adding a \"%\" alias later after the\nconcept has proved itself (and people say \"I like this feature, but it\nreally is too much to type\").\n\n-Peff\n"},{"id":"122792","messageId":"7vzl93cncn.fsf@alter.siamese.dyndns.org","threadId":"20851","inReplyTo":"20090909104550.GA20108@coredump.intra.peff.net","subject":"Re: tracking branch for a rebase","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-10T06:42:16Z","receivedAt":"2009-09-10T06:42:16Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> I wonder if it is worth adding @{upstream} now, which is fairly safe,\n> letting it cook for a while, and then adding a \"%\" alias later after the\n> concept has proved itself (and people say \"I like this feature, but it\n> really is too much to type\").\n\nThat's a sane suggestion, I think.  We can always have a descriptive\nlonghand (e.g. \"branch@{upstream}\") and later add a shorthand for often\nused ones (e.g. \"branch^up\", \"branch/.up\" --- the former is possible\nbecause it cannot be upth parent of the commit at the tip of the branch,\nand the latter is possible because component of hierarchical refname\ncannot begin with a dot).\n\nI find a prefix % not descriptive enough (besides being ugly); if it were\n\"^branch\", as some people said, it would probably have matched its meaning\n\"up\", but that notation is already taken for \"uninteresting\".  If we are\ngoing to use funny symbol as a notation to invoke magic, I think it is\neasier for new people if we limit the number of symbols used.  We already\nhave ^n, ^{type} and ~n magic, all of which operate on objects and peel\nthem in three different ways.\n\nThen there currently is only one kind of magic that works on refs and it\nis spelled as ref@{magic}.  Let's try not to introduce more notation\nbefore it is absolutely necessary.\n\nWhen I say there is only one kind of magic notation for refs, I am\nprimarily talking about the end-user perception.  @{time}, @{number} and\n@{-number} all do their magic using the reflog, but that is about _how_\nthey do what they do.  End-user perception begins with _what_ they do, and\nat that level, the magic consistently works on refs and different genie is\nsummoned depending on what is inside {}.\n\nThe @{upstream} thing won't be using reflog to do its job, but that is\nabout _how_ it is implemented, and the end users don't care.\n\nWhat is more important is _what_ it does.  Given a ref, the @{} magic\nnotation finds something that is related to the ref.  @{time} and\n@{number} finds what the ref itself used to point at. @{-number}\n(applicable only to HEAD ref) finds the ref it used to point at.  And\n@{upstream} will find another ref that it merges from (or rebases onto).\n"},{"id":"122794","messageId":"alpine.DEB.1.00.0909100941330.8306@pacific.mpi-cbg.de","threadId":"20851","inReplyTo":"7vzl93cncn.fsf@alter.siamese.dyndns.org","subject":"Re: tracking branch for a rebase","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-09-10T07:47:52Z","receivedAt":"2009-09-10T07:47:52Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 9 Sep 2009, Junio C Hamano wrote:\n\n> I find a prefix % not descriptive enough (besides being ugly); if it were\n> \"^branch\", as some people said, it would probably have matched its meaning\n> \"up\", but that notation is already taken for \"uninteresting\".\n\nHow about ^^branch? *ducks*\n\nSeriously again, I think that ^{tracking} (with shorthand ^t, maybe) is \nnot too shabby an option.  The point is: if we make this unattractive \nenough by requiring a lot of typing, we will never get to the point where \nit is popular enough to make a shorthand: it just will not be used at all.\n\n> When I say there is only one kind of magic notation for refs, I am\n> primarily talking about the end-user perception.  @{time}, @{number} and\n> @{-number} all do their magic using the reflog, but that is about _how_\n> they do what they do.  End-user perception begins with _what_ they do, and\n> at that level, the magic consistently works on refs and different genie is\n> summoned depending on what is inside {}.\n> \n> The @{upstream} thing won't be using reflog to do its job, but that is\n> about _how_ it is implemented, and the end users don't care.\n\nAh, I get what you're saying.  @{2.days.ago} says something about this \nbranch locally, but @{upstream} says something about this branch remotely \n(well, our local cache).  From that view point, it makes sense.\n\nBut my point stands: @{upstream} is too awkward to type.  Let's have _at \nleast_ a shortcut '@{up}'.\n\nCiao,\nDscho\n"},{"id":"122798","messageId":"alpine.DEB.1.00.0909101135590.8306@pacific.mpi-cbg.de","threadId":"20851","inReplyTo":"alpine.DEB.1.00.0909100941330.8306@pacific.mpi-cbg.de","subject":"[PATCH] Introduce <branch>@{tracked} as shortcut to the tracked branch","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-09-10T09:36:42Z","receivedAt":"2009-09-10T09:36:42Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nOften, it is quite interesting to inspect the branch tracked by a given\nbranch.  This patch introduces a nice notation to get at the tracked\nbranch: '<branch>@{tracked}' can be used to access that tracked branch.\n\nA special shortcut '@{tracked}' refers to the branch tracked by the\ncurrent branch.\n\nSuggested by Pasky.\n\nThe syntax was suggested by Junio.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tI decided that I like @{tracked} better than @{upstream} (which\n\treads to me more like the upstream _repository_), but hey, I made\n\tthe code flexible enough to change that at a whim.\n\n Documentation/git-rev-parse.txt |    4 ++\n sha1_name.c                     |   37 ++++++++++++++++++++--\n t/t1506-rev-parse-tracked.sh    |   64 +++++++++++++++++++++++++++++++++++++++\n 3 files changed, 102 insertions(+), 3 deletions(-)\n create mode 100755 t/t1506-rev-parse-tracked.sh\n\ndiff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\nindex 82045a2..09a2145 100644\n--- a/Documentation/git-rev-parse.txt\n+++ b/Documentation/git-rev-parse.txt\n@@ -231,6 +231,10 @@ when you run 'git-merge'.\n * The special construct '@\\{-<n>\\}' means the <n>th branch checked out\n   before the current one.\n \n+* The suffix '@{tracked}' to a ref (short form 'blabla@{t}') refers to\n+  the branch tracked by that ref.  If no ref was specified, it means the\n+  branch tracked by the current branch.\n+\n * A suffix '{caret}' to a revision parameter means the first parent of\n   that commit object.  '{caret}<n>' means the <n>th parent (i.e.\n   'rev{caret}'\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 44bb62d..a886846 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -5,6 +5,7 @@\n #include \"blob.h\"\n #include \"tree-walk.h\"\n #include \"refs.h\"\n+#include \"remote.h\"\n \n static int find_short_object_filename(int len, const char *name, unsigned char *sha1)\n {\n@@ -238,9 +239,24 @@ static int ambiguous_path(const char *path, int len)\n \treturn slash;\n }\n \n+static inline int tracked_suffix(const char *string, int len)\n+{\n+\tconst char *suffix[] = { \"@{tracked}\", \"@{t}\" };\n+\tint i;\n+\n+\tfor (i = 0; i < ARRAY_SIZE(suffix); i++) {\n+\t\tint suffix_len = strlen(suffix[i]);\n+\t\tif (len >= suffix_len && !memcmp(string + len - suffix_len,\n+\t\t\t\t\tsuffix[i], suffix_len))\n+\t\t\treturn suffix_len;\n+\t}\n+\treturn 0;\n+}\n+\n /*\n  * *string and *len will only be substituted, and *string returned (for\n- * later free()ing) if the string passed in is of the form @{-<n>}.\n+ * later free()ing) if the string passed in is of the form @{-<n>} or\n+ * of the form <branch>@{tracked}.\n  */\n static char *substitute_branch_name(const char **string, int *len)\n {\n@@ -254,6 +270,19 @@ static char *substitute_branch_name(const char **string, int *len)\n \t\treturn (char *)*string;\n \t}\n \n+\tret = tracked_suffix(*string, *len);\n+\tif (ret) {\n+\t\tchar *ref = xstrndup(*string, *len - ret);\n+\t\tstruct branch *tracking = branch_get(*ref ? ref : NULL);\n+\n+\t\tfree(ref);\n+\t\tif (tracking->merge && tracking->merge[0]->dst) {\n+\t\t\t*string = xstrdup(tracking->merge[0]->dst);\n+\t\t\t*len = strlen(*string);\n+\t\t\treturn (char *)*string;\n+\t\t}\n+\t}\n+\n \treturn NULL;\n }\n \n@@ -340,8 +369,10 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)\n \tif (len && str[len-1] == '}') {\n \t\tfor (at = len-2; at >= 0; at--) {\n \t\t\tif (str[at] == '@' && str[at+1] == '{') {\n-\t\t\t\treflog_len = (len-1) - (at+2);\n-\t\t\t\tlen = at;\n+\t\t\t\tif (!tracked_suffix(str + at, len - at)) {\n+\t\t\t\t\treflog_len = (len-1) - (at+2);\n+\t\t\t\t\tlen = at;\n+\t\t\t\t}\n \t\t\t\tbreak;\n \t\t\t}\n \t\t}\ndiff --git a/t/t1506-rev-parse-tracked.sh b/t/t1506-rev-parse-tracked.sh\nnew file mode 100755\nindex 0000000..89193e1\n--- /dev/null\n+++ b/t/t1506-rev-parse-tracked.sh\n@@ -0,0 +1,64 @@\n+#!/bin/sh\n+\n+test_description='test <branch>@{tracked} syntax'\n+\n+. ./test-lib.sh\n+\n+\n+test_expect_success 'setup' '\n+\n+\ttest_commit 1 &&\n+\tgit checkout -b side &&\n+\ttest_commit 2 &&\n+\tgit checkout master &&\n+\tgit clone . clone &&\n+\ttest_commit 3 &&\n+\t(cd clone &&\n+\t test_commit 4 &&\n+\t git branch --track my-side origin/side)\n+\n+'\n+\n+full_name () {\n+\t(cd clone &&\n+\t git rev-parse --symbolic-full-name \"$@\")\n+}\n+\n+commit_subject () {\n+\t(cd clone &&\n+\t git show -s --pretty=format:%s \"$@\")\n+}\n+\n+test_expect_success '@{tracked} resolves to correct full name' '\n+\ttest refs/remotes/origin/master = \"$(full_name @{tracked})\"\n+'\n+\n+test_expect_success '@{t} resolves to correct full name' '\n+\ttest refs/remotes/origin/master = \"$(full_name @{t})\"\n+'\n+\n+test_expect_success 'my-side@{tracked} resolves to correct full name' '\n+\ttest refs/remotes/origin/side = \"$(full_name my-side@{t})\"\n+'\n+\n+test_expect_success 'my-side@{t} resolves to correct commit' '\n+\tgit checkout side &&\n+\ttest_commit 5 &&\n+\t(cd clone && git fetch) &&\n+\ttest 2 = \"$(commit_subject my-side)\" &&\n+\ttest 5 = \"$(commit_subject my-side@{t})\"\n+'\n+\n+test_expect_success 'not-tracking@{t} fails' '\n+\ttest_must_fail full_name non-tracking@{t} &&\n+\t(cd clone && git checkout --no-track -b non-tracking) &&\n+\ttest_must_fail full_name non-tracking@{t}\n+'\n+\n+test_expect_success '<branch>@{t}@{1} resolves correctly' '\n+\ttest_commit 6 &&\n+\t(cd clone && git fetch) &&\n+\ttest 5 = $(commit_subject my-side@{t}@{1})\n+'\n+\n+test_done\n-- \n1.6.4.313.g3d9e3\n"},{"id":"122799","messageId":"4AA8CA88.9060802@drmicha.warpmail.net","threadId":"20851","inReplyTo":"alpine.DEB.1.00.0909101135590.8306@pacific.mpi-cbg.de","subject":"Re: [PATCH] Introduce <branch>@{tracked} as shortcut to the tracked branch","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2009-09-10T09:44:40Z","receivedAt":"2009-09-10T09:44:40Z","isPatch":true,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Johannes Schindelin venit, vidit, dixit 10.09.2009 11:36:\n> \n> Often, it is quite interesting to inspect the branch tracked by a given\n> branch.  This patch introduces a nice notation to get at the tracked\n> branch: '<branch>@{tracked}' can be used to access that tracked branch.\n> \n> A special shortcut '@{tracked}' refers to the branch tracked by the\n> current branch.\n\nSorry, I didn't know the name of the long form was up for discussion.\nBut it should certainly coincide with the key which for-each-ref uses,\nshouldn't it? I don't care whether tracked or upstream, but\nfor-each-ref's \"upstream\" has set the precedent.\n\n> \n> Suggested by Pasky.\n> \n> The syntax was suggested by Junio.\n> \n> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n> ---\n> \n> \tI decided that I like @{tracked} better than @{upstream} (which\n> \treads to me more like the upstream _repository_), but hey, I made\n> \tthe code flexible enough to change that at a whim.\n> \n>  Documentation/git-rev-parse.txt |    4 ++\n>  sha1_name.c                     |   37 ++++++++++++++++++++--\n>  t/t1506-rev-parse-tracked.sh    |   64 +++++++++++++++++++++++++++++++++++++++\n>  3 files changed, 102 insertions(+), 3 deletions(-)\n>  create mode 100755 t/t1506-rev-parse-tracked.sh\n> \n> diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\n> index 82045a2..09a2145 100644\n> --- a/Documentation/git-rev-parse.txt\n> +++ b/Documentation/git-rev-parse.txt\n> @@ -231,6 +231,10 @@ when you run 'git-merge'.\n>  * The special construct '@\\{-<n>\\}' means the <n>th branch checked out\n>    before the current one.\n>  \n> +* The suffix '@{tracked}' to a ref (short form 'blabla@{t}') refers to\n> +  the branch tracked by that ref.  If no ref was specified, it means the\n> +  branch tracked by the current branch.\n> +\n>  * A suffix '{caret}' to a revision parameter means the first parent of\n>    that commit object.  '{caret}<n>' means the <n>th parent (i.e.\n>    'rev{caret}'\n> diff --git a/sha1_name.c b/sha1_name.c\n> index 44bb62d..a886846 100644\n> --- a/sha1_name.c\n> +++ b/sha1_name.c\n> @@ -5,6 +5,7 @@\n>  #include \"blob.h\"\n>  #include \"tree-walk.h\"\n>  #include \"refs.h\"\n> +#include \"remote.h\"\n>  \n>  static int find_short_object_filename(int len, const char *name, unsigned char *sha1)\n>  {\n> @@ -238,9 +239,24 @@ static int ambiguous_path(const char *path, int len)\n>  \treturn slash;\n>  }\n>  \n> +static inline int tracked_suffix(const char *string, int len)\n> +{\n> +\tconst char *suffix[] = { \"@{tracked}\", \"@{t}\" };\n> +\tint i;\n> +\n> +\tfor (i = 0; i < ARRAY_SIZE(suffix); i++) {\n> +\t\tint suffix_len = strlen(suffix[i]);\n> +\t\tif (len >= suffix_len && !memcmp(string + len - suffix_len,\n> +\t\t\t\t\tsuffix[i], suffix_len))\n> +\t\t\treturn suffix_len;\n> +\t}\n> +\treturn 0;\n> +}\n> +\n>  /*\n>   * *string and *len will only be substituted, and *string returned (for\n> - * later free()ing) if the string passed in is of the form @{-<n>}.\n> + * later free()ing) if the string passed in is of the form @{-<n>} or\n> + * of the form <branch>@{tracked}.\n>   */\n>  static char *substitute_branch_name(const char **string, int *len)\n>  {\n> @@ -254,6 +270,19 @@ static char *substitute_branch_name(const char **string, int *len)\n>  \t\treturn (char *)*string;\n>  \t}\n>  \n> +\tret = tracked_suffix(*string, *len);\n> +\tif (ret) {\n> +\t\tchar *ref = xstrndup(*string, *len - ret);\n> +\t\tstruct branch *tracking = branch_get(*ref ? ref : NULL);\n> +\n> +\t\tfree(ref);\n> +\t\tif (tracking->merge && tracking->merge[0]->dst) {\n> +\t\t\t*string = xstrdup(tracking->merge[0]->dst);\n> +\t\t\t*len = strlen(*string);\n> +\t\t\treturn (char *)*string;\n> +\t\t}\n> +\t}\n> +\n>  \treturn NULL;\n>  }\n>  \n> @@ -340,8 +369,10 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)\n>  \tif (len && str[len-1] == '}') {\n>  \t\tfor (at = len-2; at >= 0; at--) {\n>  \t\t\tif (str[at] == '@' && str[at+1] == '{') {\n> -\t\t\t\treflog_len = (len-1) - (at+2);\n> -\t\t\t\tlen = at;\n> +\t\t\t\tif (!tracked_suffix(str + at, len - at)) {\n> +\t\t\t\t\treflog_len = (len-1) - (at+2);\n> +\t\t\t\t\tlen = at;\n> +\t\t\t\t}\n>  \t\t\t\tbreak;\n>  \t\t\t}\n>  \t\t}\n> diff --git a/t/t1506-rev-parse-tracked.sh b/t/t1506-rev-parse-tracked.sh\n> new file mode 100755\n> index 0000000..89193e1\n> --- /dev/null\n> +++ b/t/t1506-rev-parse-tracked.sh\n> @@ -0,0 +1,64 @@\n> +#!/bin/sh\n> +\n> +test_description='test <branch>@{tracked} syntax'\n> +\n> +. ./test-lib.sh\n> +\n> +\n> +test_expect_success 'setup' '\n> +\n> +\ttest_commit 1 &&\n> +\tgit checkout -b side &&\n> +\ttest_commit 2 &&\n> +\tgit checkout master &&\n> +\tgit clone . clone &&\n> +\ttest_commit 3 &&\n> +\t(cd clone &&\n> +\t test_commit 4 &&\n> +\t git branch --track my-side origin/side)\n> +\n> +'\n> +\n> +full_name () {\n> +\t(cd clone &&\n> +\t git rev-parse --symbolic-full-name \"$@\")\n> +}\n> +\n> +commit_subject () {\n> +\t(cd clone &&\n> +\t git show -s --pretty=format:%s \"$@\")\n> +}\n> +\n> +test_expect_success '@{tracked} resolves to correct full name' '\n> +\ttest refs/remotes/origin/master = \"$(full_name @{tracked})\"\n> +'\n> +\n> +test_expect_success '@{t} resolves to correct full name' '\n> +\ttest refs/remotes/origin/master = \"$(full_name @{t})\"\n> +'\n> +\n> +test_expect_success 'my-side@{tracked} resolves to correct full name' '\n> +\ttest refs/remotes/origin/side = \"$(full_name my-side@{t})\"\n> +'\n> +\n> +test_expect_success 'my-side@{t} resolves to correct commit' '\n> +\tgit checkout side &&\n> +\ttest_commit 5 &&\n> +\t(cd clone && git fetch) &&\n> +\ttest 2 = \"$(commit_subject my-side)\" &&\n> +\ttest 5 = \"$(commit_subject my-side@{t})\"\n> +'\n> +\n> +test_expect_success 'not-tracking@{t} fails' '\n> +\ttest_must_fail full_name non-tracking@{t} &&\n> +\t(cd clone && git checkout --no-track -b non-tracking) &&\n> +\ttest_must_fail full_name non-tracking@{t}\n> +'\n> +\n> +test_expect_success '<branch>@{t}@{1} resolves correctly' '\n> +\ttest_commit 6 &&\n> +\t(cd clone && git fetch) &&\n> +\ttest 5 = $(commit_subject my-side@{t}@{1})\n> +'\n> +\n> +test_done\n"},{"id":"122800","messageId":"alpine.DEB.1.00.0909101211340.8306@pacific.mpi-cbg.de","threadId":"20851","inReplyTo":"4AA8CA88.9060802@drmicha.warpmail.net","subject":"Re: [PATCH] Introduce <branch>@{tracked} as shortcut to the tracked branch","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-09-10T10:14:22Z","receivedAt":"2009-09-10T10:14:22Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 10 Sep 2009, Michael J Gruber wrote:\n\n> Johannes Schindelin venit, vidit, dixit 10.09.2009 11:36:\n> > \n> > Often, it is quite interesting to inspect the branch tracked by a given\n> > branch.  This patch introduces a nice notation to get at the tracked\n> > branch: '<branch>@{tracked}' can be used to access that tracked branch.\n> > \n> > A special shortcut '@{tracked}' refers to the branch tracked by the\n> > current branch.\n> \n> Sorry, I didn't know the name of the long form was up for discussion.\n> But it should certainly coincide with the key which for-each-ref uses,\n> shouldn't it? I don't care whether tracked or upstream, but\n> for-each-ref's \"upstream\" has set the precedent.\n\nYou're right.\n\nsed -i -e 's/@{tracked}/@{upstream}/g' -e 's/@{t}/@{u}/g' $PATCH\n\nCiao,\nDscho\n"},{"id":"122801","messageId":"200909101218.06789.johan@herland.net","threadId":"20851","inReplyTo":"4AA8CA88.9060802@drmicha.warpmail.net","subject":"Re: [PATCH] Introduce <branch>@{tracked} as shortcut to the tracked branch","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-09-10T10:18:06Z","receivedAt":"2009-09-10T10:18:06Z","isPatch":true,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Thursday 10 September 2009, Michael J Gruber wrote:\n> Johannes Schindelin venit, vidit, dixit 10.09.2009 11:36:\n> > Often, it is quite interesting to inspect the branch tracked by a\n> > given branch.  This patch introduces a nice notation to get at the\n> > tracked branch: '<branch>@{tracked}' can be used to access that\n> > tracked branch.\n> >\n> > A special shortcut '@{tracked}' refers to the branch tracked by the\n> > current branch.\n>\n> Sorry, I didn't know the name of the long form was up for discussion.\n> But it should certainly coincide with the key which for-each-ref\n> uses, shouldn't it? I don't care whether tracked or upstream, but\n> for-each-ref's \"upstream\" has set the precedent.\n\n...and 'git branch --track' set an even earlier precedent...\n\n\n...Johan\n\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"122802","messageId":"4AA8DC23.6050500@drmicha.warpmail.net","threadId":"20851","inReplyTo":"200909101218.06789.johan@herland.net","subject":"Re: [PATCH] Introduce <branch>@{tracked} as shortcut to the tracked branch","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2009-09-10T10:59:47Z","receivedAt":"2009-09-10T10:59:47Z","isPatch":true,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Johan Herland venit, vidit, dixit 10.09.2009 12:18:\n> On Thursday 10 September 2009, Michael J Gruber wrote:\n>> Johannes Schindelin venit, vidit, dixit 10.09.2009 11:36:\n>>> Often, it is quite interesting to inspect the branch tracked by a\n>>> given branch.  This patch introduces a nice notation to get at the\n>>> tracked branch: '<branch>@{tracked}' can be used to access that\n>>> tracked branch.\n>>>\n>>> A special shortcut '@{tracked}' refers to the branch tracked by the\n>>> current branch.\n>>\n>> Sorry, I didn't know the name of the long form was up for discussion.\n>> But it should certainly coincide with the key which for-each-ref\n>> uses, shouldn't it? I don't care whether tracked or upstream, but\n>> for-each-ref's \"upstream\" has set the precedent.\n> \n> ...and 'git branch --track' set an even earlier precedent...\n\nan unfortunate one, yes. It brings us back to an old discussion. The\nconsensus was what's in the glossary:\n\n       tracking branch\n           A regular git branch that is used to follow changes from\nanother repository. A tracking branch should\n           not contain direct modifications or have local commits made\nto it. A tracking branch can usually be\n           identified as the right-hand-side ref in a Pull: refspec.\n\nI.e., a tracking branch is something under refs/remotes/ (usually; I'll\nuse that simplification).\n\nIf I checkout -b myworkonit refs/remotes/origin/theirstuff then\nmyworkonit *does not track* origin/theirstuff according to the glossary\n(but git checkout says so, unfortunately, and the option is named\nlikewise); rather, it has origin/theirstuff as its upstream.\n\nIn fact, refs/remotes/origin/theirstuff tracks whatever the name is on\nthe left hand side of the correspondig fetch refspec.\n\nMaybe this is a good time to either\n\n- change the definition of \"tracking branch\" (to one having an upstream\nwhich is in refs/remotes/; and call \"remote upbranch\" what's in\nrefs/remotes/) or\n- rename the option and output of git checkout -b/git branch --track.\n\nAccordingly, either tracked or something else (such as upstream) would\nbe appropriate for the for-each-ref key and the ref specifier.\n\nCheers,\nMichael\n"},{"id":"122803","messageId":"20090910111156.GA2910@coredump.intra.peff.net","threadId":"20851","inReplyTo":"200909101218.06789.johan@herland.net","subject":"Re: [PATCH] Introduce <branch>@{tracked} as shortcut to the tracked branch","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-09-10T11:11:56Z","receivedAt":"2009-09-10T11:11:56Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Sep 10, 2009 at 12:18:06PM +0200, Johan Herland wrote:\n\n> > > A special shortcut '@{tracked}' refers to the branch tracked by the\n> > > current branch.\n> >\n> > Sorry, I didn't know the name of the long form was up for discussion.\n> > But it should certainly coincide with the key which for-each-ref\n> > uses, shouldn't it? I don't care whether tracked or upstream, but\n> > for-each-ref's \"upstream\" has set the precedent.\n> \n> ...and 'git branch --track' set an even earlier precedent...\n\nFWIW, that came about from this discussion:\n\n  http://article.gmane.org/gmane.comp.version-control.git/115765\n\n-Peff\n"},{"id":"122804","messageId":"200909101429.30190.johan@herland.net","threadId":"20851","inReplyTo":"4AA8DC23.6050500@drmicha.warpmail.net","subject":"Re: [PATCH] Introduce <branch>@{tracked} as shortcut to the tracked branch","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-09-10T12:29:29Z","receivedAt":"2009-09-10T12:29:29Z","isPatch":true,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Thursday 10 September 2009, Michael J Gruber wrote:\n> Johan Herland venit, vidit, dixit 10.09.2009 12:18:\n> > On Thursday 10 September 2009, Michael J Gruber wrote:\n> >> Johannes Schindelin venit, vidit, dixit 10.09.2009 11:36:\n> >>> Often, it is quite interesting to inspect the branch tracked by a\n> >>> given branch.  This patch introduces a nice notation to get at\n> >>> the tracked branch: '<branch>@{tracked}' can be used to access\n> >>> that tracked branch.\n> >>>\n> >>> A special shortcut '@{tracked}' refers to the branch tracked by\n> >>> the current branch.\n> >>\n> >> Sorry, I didn't know the name of the long form was up for\n> >> discussion. But it should certainly coincide with the key which\n> >> for-each-ref uses, shouldn't it? I don't care whether tracked or\n> >> upstream, but for-each-ref's \"upstream\" has set the precedent.\n> >\n> > ...and 'git branch --track' set an even earlier precedent...\n>\n> an unfortunate one, yes. It brings us back to an old discussion. The\n> consensus was what's in the glossary:\n\n[snip]\n\n> Maybe this is a good time to either\n>\n> - change the definition of \"tracking branch\" (to one having an\n> upstream which is in refs/remotes/; and call \"remote upbranch\" what's\n> in refs/remotes/) or\n> - rename the option and output of git checkout -b/git branch --track.\n>\n> Accordingly, either tracked or something else (such as upstream)\n> would be appropriate for the for-each-ref key and the ref specifier.\n\nSure, as someone else already stated, I don't care too much what it's \nnamed, as long as the naming is consistent across all of git. We do \nhave an unforunate name clash between remote-tracking branches (i.e. \nbranches under refs/remotes/) and 'tracking' branches (i.e. 'git \nbranch --track') [1], and I believe 1.7.0 would be a nice opportunity \nto clean this up.\n\nI think I vote for the second option, renaming 'git branch --track' \nto 'git branch --upstream', and s/@{tracked}/@{upstream}/.\n\n\nHave fun! :)\n\n...Johan\n\n[1]: And also tracked and untracked files, although I believe that is \nunambiguous in most cases.\n\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"122805","messageId":"alpine.DEB.1.00.0909101534440.8306@pacific.mpi-cbg.de","threadId":"20851","inReplyTo":"200909101429.30190.johan@herland.net","subject":"Re: [PATCH] Introduce <branch>@{tracked} as shortcut to the tracked branch","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-09-10T13:35:24Z","receivedAt":"2009-09-10T13:35:24Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 10 Sep 2009, Johan Herland wrote:\n\n> I think I vote for the second option, renaming 'git branch --track' \n> to 'git branch --upstream', and s/@{tracked}/@{upstream}/.\n\nThat does not make any sense, as that --track is to be understood as a \nverb.  How do you \"upstream a branch\"?\n\nCiao,\nDscho\n"},{"id":"122810","messageId":"20090910141618.GB4942@coredump.intra.peff.net","threadId":"20851","inReplyTo":"alpine.DEB.1.00.0909101135590.8306@pacific.mpi-cbg.de","subject":"Re: [PATCH] Introduce <branch>@{tracked} as shortcut to the tracked branch","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-09-10T14:16:18Z","receivedAt":"2009-09-10T14:16:18Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Sep 10, 2009 at 11:36:42AM +0200, Johannes Schindelin wrote:\n\n> diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\n> index 82045a2..09a2145 100644\n> --- a/Documentation/git-rev-parse.txt\n> +++ b/Documentation/git-rev-parse.txt\n> @@ -231,6 +231,10 @@ when you run 'git-merge'.\n>  * The special construct '@\\{-<n>\\}' means the <n>th branch checked out\n>    before the current one.\n>  \n> +* The suffix '@{tracked}' to a ref (short form 'blabla@{t}') refers to\n> +  the branch tracked by that ref.  If no ref was specified, it means the\n> +  branch tracked by the current branch.\n> +\n\nIt looks like the code dereferences symbolic refs when doing the lookup\n(so HEAD@{t} will find the upstream of the current branch), which I\nthink is the best thing to do. However, that does make it behave\nslightly differently than HEAD@{2.minutes.ago}, so it may be worth\nadding a sentence to this paragraph like:\n\n  If the ref is a symbolic ref, it is dereferenced before searching\n  for the upstream ref.\n\nAnd we may want to add a test for HEAD, as well.\n\nAlso, I seem to be able to stimulate a segfault on a detached HEAD, but\nI haven't investigated it yet.\n\n-Peff\n"},{"id":"122811","messageId":"4AA90A67.401@drmicha.warpmail.net","threadId":"20851","inReplyTo":"alpine.DEB.1.00.0909101534440.8306@pacific.mpi-cbg.de","subject":"Re: [PATCH] Introduce <branch>@{tracked} as shortcut to the tracked branch","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2009-09-10T14:17:11Z","receivedAt":"2009-09-10T14:17:11Z","isPatch":true,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Johannes Schindelin venit, vidit, dixit 10.09.2009 15:35:\n> Hi,\n> \n> On Thu, 10 Sep 2009, Johan Herland wrote:\n> \n>> I think I vote for the second option, renaming 'git branch --track' \n>> to 'git branch --upstream', and s/@{tracked}/@{upstream}/.\n> \n> That does not make any sense, as that --track is to be understood as a \n> verb.  How do you \"upstream a branch\"?\n\nWell, that brunch also got its granma wrong tho his speeling is right ;)\n\nSeriously: In\n\ngit branch --track branch1 branch2\n\nwho tracks whom if you read \"--track\" as a verb?\nSo, \"--track\" can only be understood as an attribute to the main (first)\nargument, saying it's tracking something. Just as --upstream could be\nread as an attribute meaning \"has an upstream\".\n\n(Note also how different this is from how -b works for checkout, -b\nactually taking an argument: git checkout -b branch1 branch2)\n\nCheers,\nMichael\n"},{"id":"122812","messageId":"20090910142628.GA7275@coredump.intra.peff.net","threadId":"20851","inReplyTo":"20090910141618.GB4942@coredump.intra.peff.net","subject":"Re: [PATCH] Introduce <branch>@{tracked} as shortcut to the tracked branch","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-09-10T14:26:28Z","receivedAt":"2009-09-10T14:26:28Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Sep 10, 2009 at 10:16:18AM -0400, Jeff King wrote:\n\n> And we may want to add a test for HEAD, as well.\n> \n> Also, I seem to be able to stimulate a segfault on a detached HEAD, but\n> I haven't investigated it yet.\n\nFound it. We should probably squash this in:\n\ndiff --git a/sha1_name.c b/sha1_name.c\nindex a886846..ef4ec11 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -276,7 +276,7 @@ static char *substitute_branch_name(const char **string, int *len)\n \t\tstruct branch *tracking = branch_get(*ref ? ref : NULL);\n \n \t\tfree(ref);\n-\t\tif (tracking->merge && tracking->merge[0]->dst) {\n+\t\tif (tracking && tracking->merge && tracking->merge[0]->dst) {\n \t\t\t*string = xstrdup(tracking->merge[0]->dst);\n \t\t\t*len = strlen(*string);\n \t\t\treturn (char *)*string;\ndiff --git a/t/t1506-rev-parse-tracked.sh b/t/t1506-rev-parse-tracked.sh\nindex 89193e1..2be5b75 100755\n--- a/t/t1506-rev-parse-tracked.sh\n+++ b/t/t1506-rev-parse-tracked.sh\n@@ -61,4 +61,15 @@ test_expect_success '<branch>@{t}@{1} resolves correctly' '\n \ttest 5 = $(commit_subject my-side@{t}@{1})\n '\n \n+test_expect_success 'HEAD@{t} dereferences HEAD' '\n+\t(cd clone && git checkout master) &&\n+\ttest refs/remotes/origin/master = \"$(full_name HEAD@{t})\"\n+'\n+\n+test_expect_success 'HEAD@{t} and @{t} on detached HEAD fail' '\n+\t(cd clone && git checkout master^0) &&\n+\ttest_must_fail full_name @{t} &&\n+\ttest_must_fail full_name HEAD@{t}\n+'\n+\n test_done\n"},{"id":"122814","messageId":"alpine.DEB.1.00.0909101718370.8306@pacific.mpi-cbg.de","threadId":"20851","inReplyTo":"20090910141618.GB4942@coredump.intra.peff.net","subject":"Re: [PATCH] Introduce <branch>@{tracked} as shortcut to the tracked branch","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-09-10T15:22:26Z","receivedAt":"2009-09-10T15:22:26Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 10 Sep 2009, Jeff King wrote:\n\n> Also, I seem to be able to stimulate a segfault on a detached HEAD, but \n> I haven't investigated it yet.\n\nAaargh!\n\nMikachu pointed that out recently, provided a test, I fixed it, and in the \nmeantime I managed to forget about it!\n\n/me needs to do less things per day.\n\nCiao,\nDscho\n"},{"id":"122815","messageId":"alpine.DEB.1.00.0909101723260.8306@pacific.mpi-cbg.de","threadId":"20851","inReplyTo":"20090910142628.GA7275@coredump.intra.peff.net","subject":"Re: [PATCH] Introduce <branch>@{tracked} as shortcut to the tracked branch","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-09-10T15:24:00Z","receivedAt":"2009-09-10T15:24:00Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 10 Sep 2009, Jeff King wrote:\n\n> On Thu, Sep 10, 2009 at 10:16:18AM -0400, Jeff King wrote:\n> \n> diff --git a/sha1_name.c b/sha1_name.c\n> index a886846..ef4ec11 100644\n> --- a/sha1_name.c\n> +++ b/sha1_name.c\n> @@ -276,7 +276,7 @@ static char *substitute_branch_name(const char **string, int *len)\n>  \t\tstruct branch *tracking = branch_get(*ref ? ref : NULL);\n>  \n>  \t\tfree(ref);\n> -\t\tif (tracking->merge && tracking->merge[0]->dst) {\n> +\t\tif (tracking && tracking->merge && tracking->merge[0]->dst) {\n\nAlmost.\n\nMy version dies if tracking is NULL.\n\nCiao,\nDscho\n"},{"id":"122816","messageId":"alpine.DEB.1.00.0909101724520.8306@pacific.mpi-cbg.de","threadId":"20851","inReplyTo":"alpine.DEB.1.00.0909101723260.8306@pacific.mpi-cbg.de","subject":"[PATCH v2] Introduce <branch>@{upstream} as shortcut to the tracked branch","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-09-10T15:25:57Z","receivedAt":"2009-09-10T15:25:57Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nOften, it is quite interesting to inspect the branch tracked by a given\nbranch.  This patch introduces a nice notation to get at the tracked\nbranch: '<branch>@{upstream}' can be used to access that tracked branch.\n\nA special shortcut '@{upstream}' refers to the branch tracked by the\ncurrent branch.\n\nSuggested by Pasky.\n\nThe syntax was suggested by Junio.\n\nA test for a now-fixed crash was provided by Mikael Magnusson.\n\nThe crash has been pointed out by Peff again (because this here developer\nmanaged to forget about the fix).\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tChanges since v1:\n\t- changed to @{upstream} (and @{u})\n\t- included the fix I forgot about\n\n Documentation/git-rev-parse.txt |    4 ++\n sha1_name.c                     |   39 ++++++++++++++++++++--\n t/t1506-rev-parse-tracked.sh    |   69 +++++++++++++++++++++++++++++++++++++++\n 3 files changed, 109 insertions(+), 3 deletions(-)\n create mode 100755 t/t1506-rev-parse-tracked.sh\n\ndiff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\nindex 82045a2..09a2145 100644\n--- a/Documentation/git-rev-parse.txt\n+++ b/Documentation/git-rev-parse.txt\n@@ -231,6 +231,10 @@ when you run 'git-merge'.\n * The special construct '@\\{-<n>\\}' means the <n>th branch checked out\n   before the current one.\n \n+* The suffix '@{upstream}' to a ref (short form 'blabla@{u}') refers to\n+  the branch tracked by that ref.  If no ref was specified, it means the\n+  branch tracked by the current branch.\n+\n * A suffix '{caret}' to a revision parameter means the first parent of\n   that commit object.  '{caret}<n>' means the <n>th parent (i.e.\n   'rev{caret}'\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 44bb62d..ae4280e 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -5,6 +5,7 @@\n #include \"blob.h\"\n #include \"tree-walk.h\"\n #include \"refs.h\"\n+#include \"remote.h\"\n \n static int find_short_object_filename(int len, const char *name, unsigned char *sha1)\n {\n@@ -238,9 +239,24 @@ static int ambiguous_path(const char *path, int len)\n \treturn slash;\n }\n \n+static inline int tracked_suffix(const char *string, int len)\n+{\n+\tconst char *suffix[] = { \"@{upstream}\", \"@{u}\" };\n+\tint i;\n+\n+\tfor (i = 0; i < ARRAY_SIZE(suffix); i++) {\n+\t\tint suffix_len = strlen(suffix[i]);\n+\t\tif (len >= suffix_len && !memcmp(string + len - suffix_len,\n+\t\t\t\t\tsuffix[i], suffix_len))\n+\t\t\treturn suffix_len;\n+\t}\n+\treturn 0;\n+}\n+\n /*\n  * *string and *len will only be substituted, and *string returned (for\n- * later free()ing) if the string passed in is of the form @{-<n>}.\n+ * later free()ing) if the string passed in is of the form @{-<n>} or\n+ * of the form <branch>@{upstream}.\n  */\n static char *substitute_branch_name(const char **string, int *len)\n {\n@@ -254,6 +270,21 @@ static char *substitute_branch_name(const char **string, int *len)\n \t\treturn (char *)*string;\n \t}\n \n+\tret = tracked_suffix(*string, *len);\n+\tif (ret) {\n+\t\tchar *ref = xstrndup(*string, *len - ret);\n+\t\tstruct branch *tracking = branch_get(*ref ? ref : NULL);\n+\n+\t\tfree(ref);\n+\t\tif (!tracking)\n+\t\t\tdie (\"No tracking branch found for '%s'\", ref);\n+\t\tif (tracking->merge && tracking->merge[0]->dst) {\n+\t\t\t*string = xstrdup(tracking->merge[0]->dst);\n+\t\t\t*len = strlen(*string);\n+\t\t\treturn (char *)*string;\n+\t\t}\n+\t}\n+\n \treturn NULL;\n }\n \n@@ -340,8 +371,10 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)\n \tif (len && str[len-1] == '}') {\n \t\tfor (at = len-2; at >= 0; at--) {\n \t\t\tif (str[at] == '@' && str[at+1] == '{') {\n-\t\t\t\treflog_len = (len-1) - (at+2);\n-\t\t\t\tlen = at;\n+\t\t\t\tif (!tracked_suffix(str + at, len - at)) {\n+\t\t\t\t\treflog_len = (len-1) - (at+2);\n+\t\t\t\t\tlen = at;\n+\t\t\t\t}\n \t\t\t\tbreak;\n \t\t\t}\n \t\t}\ndiff --git a/t/t1506-rev-parse-tracked.sh b/t/t1506-rev-parse-tracked.sh\nnew file mode 100755\nindex 0000000..72d0579\n--- /dev/null\n+++ b/t/t1506-rev-parse-tracked.sh\n@@ -0,0 +1,69 @@\n+#!/bin/sh\n+\n+test_description='test <branch>@{upstream} syntax'\n+\n+. ./test-lib.sh\n+\n+\n+test_expect_success 'setup' '\n+\n+\ttest_commit 1 &&\n+\tgit checkout -b side &&\n+\ttest_commit 2 &&\n+\tgit checkout master &&\n+\tgit clone . clone &&\n+\ttest_commit 3 &&\n+\t(cd clone &&\n+\t test_commit 4 &&\n+\t git branch --track my-side origin/side)\n+\n+'\n+\n+full_name () {\n+\t(cd clone &&\n+\t git rev-parse --symbolic-full-name \"$@\")\n+}\n+\n+commit_subject () {\n+\t(cd clone &&\n+\t git show -s --pretty=format:%s \"$@\")\n+}\n+\n+test_expect_success '@{upstream} resolves to correct full name' '\n+\ttest refs/remotes/origin/master = \"$(full_name @{upstream})\"\n+'\n+\n+test_expect_success '@{u} resolves to correct full name' '\n+\ttest refs/remotes/origin/master = \"$(full_name @{u})\"\n+'\n+\n+test_expect_success 'my-side@{upstream} resolves to correct full name' '\n+\ttest refs/remotes/origin/side = \"$(full_name my-side@{u})\"\n+'\n+\n+test_expect_success 'my-side@{u} resolves to correct commit' '\n+\tgit checkout side &&\n+\ttest_commit 5 &&\n+\t(cd clone && git fetch) &&\n+\ttest 2 = \"$(commit_subject my-side)\" &&\n+\ttest 5 = \"$(commit_subject my-side@{u})\"\n+'\n+\n+test_expect_success 'not-tracking@{u} fails' '\n+\ttest_must_fail full_name non-tracking@{u} &&\n+\t(cd clone && git checkout --no-track -b non-tracking) &&\n+\ttest_must_fail full_name non-tracking@{u}\n+'\n+\n+test_expect_success '<branch>@{u}@{1} resolves correctly' '\n+\ttest_commit 6 &&\n+\t(cd clone && git fetch) &&\n+\ttest 5 = $(commit_subject my-side@{u}@{1})\n+'\n+\n+test_expect_success '% without specifying branch crashes on a detached HEAD' '\n+\tgit checkout HEAD^0 &&\n+\ttest_must_fail git rev-parse @{u}\n+'\n+\n+test_done\n-- \n1.6.4.313.g3d9e3\n"},{"id":"122818","messageId":"20090910155547.GA12409@coredump.intra.peff.net","threadId":"20851","inReplyTo":"alpine.DEB.1.00.0909101724520.8306@pacific.mpi-cbg.de","subject":"Re: [PATCH v2] Introduce <branch>@{upstream} as shortcut to the tracked branch","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-09-10T15:55:47Z","receivedAt":"2009-09-10T15:55:47Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Sep 10, 2009 at 05:25:57PM +0200, Johannes Schindelin wrote:\n\n> \tChanges since v1:\n> \t- changed to @{upstream} (and @{u})\n\nHmm. After applying v2, I accidentally tried \"git rev-parse @{t}\" and\nwas surprised to find that it worked! The problem, of course, is that we\nsaw that it was not one of our keywords and therefore dumped it into\napproxidate, which happily converted it into the current time, and\nprovided me with HEAD@{now}.\n\nWhich is sad, because it means \"HEAD@{usptream}\" will silently produce\nincorrect results.\n\nI don't see a way around it, though, short of tightening approxidate's\nparsing. Maybe it could keep a flag for \"I noticed _anything_ of value\nin this string\", and we could barf if it isn't set. That would still\nallow arbitrary stuff like:\n\n  the 6th of july\n\nand keep Linus' favorite\n\n  I ate 6 hot dogs in July.\n\nbut disallow the most obviously wrong dates like:\n\n  t\n  usptream\n  total bogosity\n\n> +\tret = tracked_suffix(*string, *len);\n> +\tif (ret) {\n> +\t\tchar *ref = xstrndup(*string, *len - ret);\n> +\t\tstruct branch *tracking = branch_get(*ref ? ref : NULL);\n> +\n> +\t\tfree(ref);\n> +\t\tif (!tracking)\n> +\t\t\tdie (\"No tracking branch found for '%s'\", ref);\n> +\t\tif (tracking->merge && tracking->merge[0]->dst) {\n> +\t\t\t*string = xstrdup(tracking->merge[0]->dst);\n> +\t\t\t*len = strlen(*string);\n> +\t\t\treturn (char *)*string;\n> +\t\t}\n> +\t}\n> +\n\nI don't think it is a good idea to die for !tracking, but not for\n!tracking->merge. That leads to inconsistent user-visible results:\n\n  $ git checkout HEAD^0\n  $ git rev-parse HEAD@{u}\n  fatal: No tracking branch found for 'HEAD'\n  $ git rev-parse bogus@{u}\n  bogus@{u}\n  fatal: ambiguous argument 'bogus@{u}': unknown revision or path not in the working tree.\n  Use '--' to separate paths from revisions\n\nShouldn't both cases say the same thing?\n\nAlso, your die message has two problems:\n\n 1. It looks at ref immediately after it is free'd, spewing junk.\n\n 2. Ref can be the empty string, which gives you the ugly:\n\n       fatal: No tracking branch found for ''\n\n    Should we munge that into HEAD (or \"the current branch\") for the\n    user?\n\n-Peff\n"},{"id":"122819","messageId":"alpine.DEB.1.00.0909101817521.8306@pacific.mpi-cbg.de","threadId":"20851","inReplyTo":"20090910155547.GA12409@coredump.intra.peff.net","subject":"Re: [PATCH v2] Introduce <branch>@{upstream} as shortcut to the tracked branch","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-09-10T16:18:46Z","receivedAt":"2009-09-10T16:18:46Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 10 Sep 2009, Jeff King wrote:\n\n> I wrote:\n> \n> > +\tret = tracked_suffix(*string, *len);\n> > +\tif (ret) {\n> > +\t\tchar *ref = xstrndup(*string, *len - ret);\n> > +\t\tstruct branch *tracking = branch_get(*ref ? ref : NULL);\n> > +\n> > +\t\tfree(ref);\n> > +\t\tif (!tracking)\n> > +\t\t\tdie (\"No tracking branch found for '%s'\", ref);\n> > +\t\tif (tracking->merge && tracking->merge[0]->dst) {\n> > +\t\t\t*string = xstrdup(tracking->merge[0]->dst);\n> > +\t\t\t*len = strlen(*string);\n> > +\t\t\treturn (char *)*string;\n> > +\t\t}\n> > +\t}\n> > +\n> \n> I don't think it is a good idea to die for !tracking, but not for\n> !tracking->merge. That leads to inconsistent user-visible results:\n> \n>   $ git checkout HEAD^0\n>   $ git rev-parse HEAD@{u}\n>   fatal: No tracking branch found for 'HEAD'\n>   $ git rev-parse bogus@{u}\n>   bogus@{u}\n>   fatal: ambiguous argument 'bogus@{u}': unknown revision or path not in the working tree.\n>   Use '--' to separate paths from revisions\n> \n> Shouldn't both cases say the same thing?\n> \n> Also, your die message has two problems:\n> \n>  1. It looks at ref immediately after it is free'd, spewing junk.\n> \n>  2. Ref can be the empty string, which gives you the ugly:\n> \n>        fatal: No tracking branch found for ''\n> \n>     Should we munge that into HEAD (or \"the current branch\") for the\n>     user?\n\nAll true, but I cannot take care of it today.\n\nCiao,\nDscho\n"},{"id":"122826","messageId":"7vzl92bql9.fsf@alter.siamese.dyndns.org","threadId":"20851","inReplyTo":"20090910111156.GA2910@coredump.intra.peff.net","subject":"Re: [PATCH] Introduce <branch>@{tracked} as shortcut to the tracked branch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-10T18:29:54Z","receivedAt":"2009-09-10T18:29:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Thu, Sep 10, 2009 at 12:18:06PM +0200, Johan Herland wrote:\n>\n>> > > A special shortcut '@{tracked}' refers to the branch tracked by the\n>> > > current branch.\n>> >\n>> > Sorry, I didn't know the name of the long form was up for discussion.\n>> > But it should certainly coincide with the key which for-each-ref\n>> > uses, shouldn't it? I don't care whether tracked or upstream, but\n>> > for-each-ref's \"upstream\" has set the precedent.\n>> \n>> ...and 'git branch --track' set an even earlier precedent...\n>\n> FWIW, that came about from this discussion:\n>\n>   http://article.gmane.org/gmane.comp.version-control.git/115765\n\nAfter re-reading the discussion in the thread that contains the quoted\narticle, it sounds like we may want to fix \"branch --track X Y\".  X does\nnot \"track\" Y in the same sense as origin/master \"tracks\" master at\norigin.  Rather, X builds on Y.\n"},{"id":"122863","messageId":"7vy6om2ia2.fsf@alter.siamese.dyndns.org","threadId":"20851","inReplyTo":"alpine.DEB.1.00.0909100941330.8306@pacific.mpi-cbg.de","subject":"Re: tracking branch for a rebase","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-11T04:54:13Z","receivedAt":"2009-09-11T04:54:13Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> How about ^^branch? *ducks*\n\nYou'd better duck.\n\nJust like %branch, it is a selfish and short-sighted \"good enough for this\nparticular case but there is no room for extending it\" hack that I have\nserious problem with.  It closes the door for people who come later, and\nsuch an attitude is okay only if this is _the last great invention_ and\nthere is no more great feature that deserves short-and-sweet notation to\ncome.  It might be the _latest_ great invention, but chances are that it\nwon't be the last.\n\n> Seriously again, I think that ^{tracking} (with shorthand ^t, maybe) is \n> not too shabby an option.  The point is: if we make this unattractive \n> enough by requiring a lot of typing, we will never get to the point where \n> it is popular enough to make a shorthand: it just will not be used at all.\n\nI actually think it is the other way around.\n\nIf it is so useful to be able to specify the ref your branch is based on\nby applying a magic to the name of your branch, the users will use it even\nif it is rather long to type, as long as the feature is easy to discover\nand remember, and then they will demand a short-hand.\n\nIf on the other hand users say \"Hey, I know can say 'git log X@{upstream}'\nbut why bother?  I always build my branch X on top of origin/X anyway, so\nI'd forego that feature and type 'git log origin/X'.  It's not worth my\ntime to type that long magic,\" then the feature is not as useful as you\nhoped.  And there is no point in coming up with a short-hand syntax for\nit.\n\nI personally suspect that users love to use the feature _despite_ the\ninitial lack of short-hand, and we would end up adding some short-hand,\nand that would be a far better proof that the feature itself is useful\nthan \"it is used just %X happens to be shorter than origin/X\".\n\nBut before that happens, I'd rather not waste short-hand notations, such\nas @{t} or @{u}, that will be in short-supply in the longer term.\n"},{"id":"124135","messageId":"20091002145444.GA27904@atjola.homenet","threadId":"20851","inReplyTo":"7vzl92bql9.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] Introduce <branch>@{tracked} as shortcut to the tracked branch","fromName":"Björn Steinbrink","fromEmail":"b.steinbrink@gmx.de","sentAt":"2009-10-02T14:54:44Z","receivedAt":"2009-10-02T14:54:44Z","isPatch":true,"sender":{"key":"b.steinbrink@gmx.de","avatar":"https://avatars.githubusercontent.com/u/230962?v=4"},"body":"On 2009.09.10 11:29:54 -0700, Junio C Hamano wrote:\n> Jeff King <peff@peff.net> writes:\n> \n> > On Thu, Sep 10, 2009 at 12:18:06PM +0200, Johan Herland wrote:\n> >\n> >> > > A special shortcut '@{tracked}' refers to the branch tracked by the\n> >> > > current branch.\n> >> >\n> >> > Sorry, I didn't know the name of the long form was up for discussion.\n> >> > But it should certainly coincide with the key which for-each-ref\n> >> > uses, shouldn't it? I don't care whether tracked or upstream, but\n> >> > for-each-ref's \"upstream\" has set the precedent.\n> >> \n> >> ...and 'git branch --track' set an even earlier precedent...\n> >\n> > FWIW, that came about from this discussion:\n> >\n> >   http://article.gmane.org/gmane.comp.version-control.git/115765\n> \n> After re-reading the discussion in the thread that contains the quoted\n> article, it sounds like we may want to fix \"branch --track X Y\".  X does\n> not \"track\" Y in the same sense as origin/master \"tracks\" master at\n> origin.  Rather, X builds on Y.\n\nFWIW, I just had a discussion on #git with Jim Ramsay (lack) about that.\nWe agreed that \"branch --track\" is unfortunate and causes confusion,\nwhen it comes to the term \"tracking branch\" (which the glossary\nbasically defines to be something in the refs/remotes/ namespace, at\nleast something you never commit to), as people also start to use that\nfor branch heads that have an \"upstream branch\" set in the\nconfiguration.\n\nJim initially preferred the term \"linked\", while I argued for the option\nto be called --upstream (potentially with the possibility to say\n--upstream=rebase or --upstream=merge, the default being \"merge\", unless\nbranch.autosetuprebase is set).\n\nWe could (I think) to some degree agree that \"upstream\" is quite good,\nalthough we couldn't find a short and sweet term to describe the branch\nhead that has a configured upstream branch (some ideas were \"upstreamed\nbranch\", \"uplinked branch\", \"downstream branch\" and some more, which I\nall dislike). After having read the glossary and finding \"upstream\nbranch\" in there, I'm even more in favor of using the \"upstream\" term in\nsome form.\n\nDuring the discussion, there were some requests (again) for a command\nthat allows to change branch.<name>.remote and branch.<name>.merge for\nalready existing branch heads. With that extra input, I'd now favor:\n\ngit branch --set-upstream X Y\n\nbecause that's potentially reusable for the \"change upstream for an\nexisting branch\" case, though I'm totally clueless how to actually do\nthat, given that \"git branch\" uses flags to switch between \"create new\nbranch\" and \"operate on existing branch\". So reusing a flag won't\n(easily) do the trick, at least not without special casing that could be\ndangerous. You could, for example, accidently change the upstream for an\nexisting branch, while you meant to create a new one.\n\nIt's a bit sad that we don't have subcommands for \"git branch\" like we\ndo for \"git remote\", that would make the whole thing a lot easier, but\nit's way too late to change that, I guess. At least having \"git branch\n<name>\" default to be \"git branch add <name>\" would make some branch\nnames \"invalid\" for that shortform. So that looks like a no-go.\n\nBjörn\n"}]}