{"thread":{"id":"43317","subject":"Re: Missing features in git","startedAt":"2006-11-14T13:49:58Z","lastAt":"2006-11-14T22:13:44Z","messageCount":12,"participants":["Karl Hasselström","linux@horizon.com","Jakub Narebski","Shawn Pearce","Junio C Hamano","Petr Baudis","Linus Torvalds"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"294844","messageId":"20061114134958.5326.qmail@science.horizon.com","threadId":"43317","inReplyTo":null,"subject":"Missing features in git","fromName":"","fromEmail":"linux@horizon.com","sentAt":"2006-11-14T13:49:58Z","receivedAt":"2006-11-14T13:49:58Z","isPatch":false,"sender":{"key":"linux@horizon.com","avatar":null},"body":"I've been writing some more git docs, and I came across a few\nthings git does that I'm not sure are desirable.\n\n\nOne thing I noticed is that with ref logs, you've just re-invented the\nCVS problem of associating history with a name.  If you want to rename\na branch (say, from \"mischacks\" to something suitable for publication),\ndo you rename the log or not?  It's a less virulent form, but it seems\nlike the same disease.\n\nAnother minor quibble: AFAICT, \"git checkout -f -m\" is meaningless (-f\noverrides -m), but doesn't complain.\n\n\nOne feature that I noticed is missing, is that there's no easy way to do a\n\"git reset --hard\" while doing a \"git checkout\" style merge.\n\nAn example of when you'd want to do this is performing a \"git bisect\"\nwith a local \"#define DEBUG 1\" change.  Particularly if you\nhit a non-compiling version and need to back up.\n\n  \nThe only way to do this currently is somethig like:\n        git checkout -b temp HEAD^\n        git branch -f bisect temp\n        git checkout bisect\n        git branch -d temp\n\nor the way git-bisect does it\n  \n        echo \"$rev\" > \"$GIT_DIR/refs/heads/new-bisect\"\n        git checkout new-bisect || exit\n        mv \"$GIT_DIR/refs/heads/new-bisect\" \"$GIT_DIR/refs/heads/bisect\" &&\n        GIT_DIR=\"$GIT_DIR\" git-symbolic-ref HEAD refs/heads/bisect\n  \nEither way, it reserves a second branch name, and seems like a bit of\na hack.  I'm already a bit annoyed that \"bisect\" is reserved but not\nclearly documented as such, and note that the branch name \"new-bisect\",\nwhich we are switched to temporarily, does not match the pattern\n\"refs/heads/bisect*\" that bisect_start checks for.\n\nThe only thing I don't know is if this should be a git-checkout\noption or a git-reset option.  The former shares far more code,\nbut the latter might make more logical sense.\n\n  \nPersonally, I'd prefer if the requirement that HEAD point to\nrefs/heads were enforced when checking in rather than checking out.\n  \nThen you could check out an arbitrary version without any of the annoyance\nabove; I could \"git checkout tags/foo\" or even \"git checkout deadbeef~3\".\nI wouldn't be on a current branch (which would necessitate changing\n\"git branch\" output), so HEAD would simply contain an object ID directly\nrather than being a symlink/symref.\n\nIt's a bit of a PITA auditing the code base to find everywhere affected\nby changing this invariant, but it doesn't conceptually difficult.\nIs there anything fundamental that this would break?\n\n\nThe above would make a \"-b <newbranch>\" option to git-commit more useful,\nbut it's not a half-bad idea as it is.  It's just one extra command\n(git checkout -b newbranch; git commit), but it takes a bit of\nthinking to realize that \"git checkout\", which normally modifies the\nworking directory, won't touch your ready-to-be-committed changes in\n"},{"id":"295204","messageId":"ejcl6l$bo0$1@sea.gmane.org","threadId":"43317","inReplyTo":"20061114134958.5326.qmail@science.horizon.com","subject":"Re: Missing features in git","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-14T14:53:18Z","receivedAt":"2006-11-14T14:53:18Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"linux@horizon.com wrote:\n\n> One thing I noticed is that with ref logs, you've just re-invented the\n> CVS problem of associating history with a name.  If you want to rename\n> a branch (say, from \"mischacks\" to something suitable for publication),\n> do you rename the log or not?  It's a less virulent form, but it seems\n> like the same disease.\n\nWell, it would be nice to have command to rename branches (with its reflog)\nand to rename tags (even in their packed format).\n\n[...] \n> Then you could check out an arbitrary version without any of the annoyance\n> above; I could \"git checkout tags/foo\" or even \"git checkout deadbeef~3\".\n> I wouldn't be on a current branch (which would necessitate changing\n> \"git branch\" output), so HEAD would simply contain an object ID directly\n> rather than being a symlink/symref.\n\nAnd what would happen if you want to checkout other branch? Where the ID\nin the HEAD would go to? HEAD just _has_ to be reference to _branch_.\n \n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n\n"},{"id":"295340","messageId":"20061114153922.GA5453@diana.vm.bytemark.co.uk","threadId":"43317","inReplyTo":"20061114134958.5326.qmail@science.horizon.com","subject":"Re: Missing features in git","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2006-11-14T15:39:22Z","receivedAt":"2006-11-14T15:39:22Z","isPatch":false,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On 2006-11-14 08:49:58 -0500, linux@horizon.com wrote:\n\n> One feature that I noticed is missing, is that there's no easy way\n> to do a \"git reset --hard\" while doing a \"git checkout\" style merge.\n>\n> An example of when you'd want to do this is performing a \"git\n> bisect\" with a local \"#define DEBUG 1\" change. Particularly if you\n> hit a non-compiling version and need to back up.\n\nYes, this feature would be good to have. StGIT makes it a little less\npainful to hack around this limitation, but you still have to remember\npopping your patches before running \"git bisect good|bad\".\n\nThen again, in StGIT's case this could be solved by creating an \"stg\nbisect\" command that takes care of this for you. But I still agree\nwith you that it would be a win if regular git could do as you\ndescribe.\n\n-- \nKarl Hasselström, kha@treskal.com\n"},{"id":"294339","messageId":"20061114154739.GB5453@diana.vm.bytemark.co.uk","threadId":"43317","inReplyTo":"ejcl6l$bo0$1@sea.gmane.org","subject":"Re: Missing features in git","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2006-11-14T15:47:39Z","receivedAt":"2006-11-14T15:47:39Z","isPatch":false,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On 2006-11-14 15:53:18 +0100, Jakub Narebski wrote:\n\n> linux@horizon.com wrote:\n>\n> > Then you could check out an arbitrary version without any of the\n> > annoyance above; I could \"git checkout tags/foo\" or even \"git\n> > checkout deadbeef~3\". I wouldn't be on a current branch (which\n> > would necessitate changing \"git branch\" output), so HEAD would\n> > simply contain an object ID directly rather than being a\n> > symlink/symref.\n>\n> And what would happen if you want to checkout other branch? Where\n> the ID in the HEAD would go to? HEAD just _has_ to be reference to\n> _branch_.\n\nThe id that used to be HEAD would not be saved anywhere. It would\nstill be reachable from your refs, presumably, just like before you\nchecked it out. (It would not be the case that you had made commits on\nan unnamed branch that would now get lost, because the tool would\nrefuse to commit until you had created a name for the branch.)\n\n-- \nKarl Hasselström, kha@treskal.com\n"},{"id":"296692","messageId":"200611141815.24236.jnareb@gmail.com","threadId":"43317","inReplyTo":"20061114154739.GB5453@diana.vm.bytemark.co.uk","subject":"Re: Missing features in git","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-14T17:15:23Z","receivedAt":"2006-11-14T17:15:23Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Karl Hasselström wrote:\n> On 2006-11-14 15:53:18 +0100, Jakub Narebski wrote:\n> \n>> linux@horizon.com wrote:\n>>\n>>> Then you could check out an arbitrary version without any of the\n>>> annoyance above; I could \"git checkout tags/foo\" or even \"git\n>>> checkout deadbeef~3\". I wouldn't be on a current branch (which\n>>> would necessitate changing \"git branch\" output), so HEAD would\n>>> simply contain an object ID directly rather than being a\n>>> symlink/symref.\n>>\n>> And what would happen if you want to checkout other branch? Where\n>> the ID in the HEAD would go to? HEAD just _has_ to be reference to\n>> _branch_.\n> \n> The id that used to be HEAD would not be saved anywhere. It would\n> still be reachable from your refs, presumably, just like before you\n> checked it out. (It would not be the case that you had made commits on\n> an unnamed branch that would now get lost, because the tool would\n> refuse to commit until you had created a name for the branch.)\n\nIf HEAD would contain an commit ID directly, then you shouldn't be able\nto commit at all. Not very useful, it is.\n-- \nJakub Narebski\n"},{"id":"298205","messageId":"20061114173657.GC5453@diana.vm.bytemark.co.uk","threadId":"43317","inReplyTo":"200611141815.24236.jnareb@gmail.com","subject":"Re: Missing features in git","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2006-11-14T17:36:57Z","receivedAt":"2006-11-14T17:36:57Z","isPatch":false,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"On 2006-11-14 18:15:23 +0100, Jakub Narebski wrote:\n\n> Karl Hasselström wrote:\n\n> > On 2006-11-14 15:53:18 +0100, Jakub Narebski wrote:\n>\n> > > And what would happen if you want to checkout other branch?\n> > > Where the ID in the HEAD would go to? HEAD just _has_ to be\n> > > reference to _branch_.\n> >\n> > The id that used to be HEAD would not be saved anywhere. It would\n> > still be reachable from your refs, presumably, just like before\n> > you checked it out. (It would not be the case that you had made\n> > commits on an unnamed branch that would now get lost, because the\n> > tool would refuse to commit until you had created a name for the\n> > branch.)\n>\n> If HEAD would contain an commit ID directly, then you shouldn't be\n> able to commit at all.\n\nI agree. You aren't on a branch, so you can't commit. (Of course,\ncreating a branch for the commit you're on is trivial: \"git checkout\n-b <branchname>\".)\n\n> Not very useful, it is.\n\nWell, as long as you only want to visit the past, not change it, it\ncan be useful. For example, we could skip the \"bisect\" branch, since\nyou aren't supposed to commit to that anyway.\n\n-- \nKarl Hasselström, kha@treskal.com\n"},{"id":"297851","messageId":"200611141845.18930.jnareb@gmail.com","threadId":"43317","inReplyTo":"20061114173657.GC5453@diana.vm.bytemark.co.uk","subject":"Re: Missing features in git","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-11-14T17:45:18Z","receivedAt":"2006-11-14T17:45:18Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Dnia wtorek 14. listopada 2006 18:36, Karl Hasselström napisał:\n>\n> For example, we could skip the \"bisect\" branch, since\n> you aren't supposed to commit to that anyway.\n\nWell, to have \"branch\" to which you could not commit, just put ref\noutside refs/heads. \n\nAnother solution would be to be able to put non-head ref in HEAD,\nbut allow to commit only if the prefix is refs/heads/\n-- \nJakub Narebski\n"},{"id":"296034","messageId":"20061114174939.GB4299@spearce.org","threadId":"43317","inReplyTo":"200611141845.18930.jnareb@gmail.com","subject":"Re: Missing features in git","fromName":"Shawn Pearce","fromEmail":"spearce@spearce.org","sentAt":"2006-11-14T17:49:39Z","receivedAt":"2006-11-14T17:49:39Z","isPatch":false,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> wrote:\n> Dnia wtorek 14. listopada 2006 18:36, Karl Hasselström napisa?:\n> >\n> > For example, we could skip the \"bisect\" branch, since\n> > you aren't supposed to commit to that anyway.\n> \n> Well, to have \"branch\" to which you could not commit, just put ref\n> outside refs/heads. \n> \n> Another solution would be to be able to put non-head ref in HEAD,\n> but allow to commit only if the prefix is refs/heads/\n\nThat's not a bad idea.  Then you can checkout a tag and have\n'ref: refs/tags/v1.11' in HEAD, which means anyone who puts\n$(git-symbolic-ref) calls into their PS1 will see \"refs/tags/v1.11\"\nas their current branch, reminding them they are looking at the past.\n\nDoing bisect branch in refs/bisect rather than refs/heads/bisect\nwould then likewise remind the user that they are bisecting, and\nsince neither matches refs/heads/* you cannot commit.\n\n-- \n"},{"id":"297463","messageId":"Pine.LNX.4.64.0611141037120.3327@woody.osdl.org","threadId":"43317","inReplyTo":"20061114174939.GB4299@spearce.org","subject":"Re: Missing features in git","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-11-14T18:40:30Z","receivedAt":"2006-11-14T18:40:30Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 14 Nov 2006, Shawn Pearce wrote:\n\n> Jakub Narebski <jnareb@gmail.com> wrote:\n> > Dnia wtorek 14. listopada 2006 18:36, Karl Hasselström napisa?:\n> > >\n> > > For example, we could skip the \"bisect\" branch, since\n> > > you aren't supposed to commit to that anyway.\n> > \n> > Well, to have \"branch\" to which you could not commit, just put ref\n> > outside refs/heads. \n> > \n> > Another solution would be to be able to put non-head ref in HEAD,\n> > but allow to commit only if the prefix is refs/heads/\n> \n> That's not a bad idea.  Then you can checkout a tag and have\n> 'ref: refs/tags/v1.11' in HEAD, which means anyone who puts\n> $(git-symbolic-ref) calls into their PS1 will see \"refs/tags/v1.11\"\n> as their current branch, reminding them they are looking at the past.\n\nI agree. This would probably be a good way to do \"read-only branches\".\n\nAllowing people to do a \"git checkout\" on anything committish, but then \nnot allowing them to commit to that, is probably the right thing to do.\n\nTogether with a nice readable error message from \"git commit\" (and merge, \nand pull - although you might well allow \"fetch\" to update the thing that \ncurrent HEAD points to, though), this would be a lot easier to use for \npeople who just follow somebody elses branch.\n\nJunio, what do you think? It wouldn't even be backwards incompatible, \nbecause we're strictly allowing a superset of what we used to..\n\n\t\t\tLinus"},{"id":"296529","messageId":"20061114193726.GG7201@pasky.or.cz","threadId":"43317","inReplyTo":"Pine.LNX.4.64.0611141037120.3327@woody.osdl.org","subject":"Re: Missing features in git","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2006-11-14T19:37:26Z","receivedAt":"2006-11-14T19:37:26Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"On Tue, Nov 14, 2006 at 07:40:30PM CET, Linus Torvalds wrote:\n> On Tue, 14 Nov 2006, Shawn Pearce wrote:\n> \n> > Jakub Narebski <jnareb@gmail.com> wrote:\n> > > Dnia wtorek 14. listopada 2006 18:36, Karl Hasselström napisa?:\n> > > >\n> > > > For example, we could skip the \"bisect\" branch, since\n> > > > you aren't supposed to commit to that anyway.\n> > > \n> > > Well, to have \"branch\" to which you could not commit, just put ref\n> > > outside refs/heads. \n> > > \n> > > Another solution would be to be able to put non-head ref in HEAD,\n> > > but allow to commit only if the prefix is refs/heads/\n> > \n> > That's not a bad idea.  Then you can checkout a tag and have\n> > 'ref: refs/tags/v1.11' in HEAD, which means anyone who puts\n> > $(git-symbolic-ref) calls into their PS1 will see \"refs/tags/v1.11\"\n> > as their current branch, reminding them they are looking at the past.\n\n  There's been a brief discussion on a related topic in\n\n\thttp://news.gmane.org/find-root.php?message_id=%3cPine.LNX.4.58.0507120938240.17536%40g5.osdl.org%3e\n\n(apparently the Linus-has-another-totally-awesome-idea kind (no irony\n(*))).  Before, Cogito did basically what's proposed above to permit\nagain: storing a random sha1 in the HEAD when it is seeked away to some\nhistorical commit. It switched to using a temporary branch for this\npurpose, but I'm not sure about the Linus' reasoning that\n\n\t\"in order for a \"git checkout\" to not get confused and possibly\n\tthrowing a cogito temporary head away ...\"\n\nwhich has been apparently clear to me back then. :-(\n\n> I agree. This would probably be a good way to do \"read-only branches\".\n> \n> Allowing people to do a \"git checkout\" on anything committish, but then \n> not allowing them to commit to that, is probably the right thing to do.\n\n  So, the basic relaxation is that \"again after a year, HEAD does not\nhave to be a ref at all\".\n\n> Together with a nice readable error message from \"git commit\" (and merge, \n> and pull - although you might well allow \"fetch\" to update the thing that \n> current HEAD points to, though), this would be a lot easier to use for \n> people who just follow somebody elses branch.\n\n  Hmm, so that there would be something like refs/tracking/master as an\nalternative to refs/heads/master? I'm not really sure if it is a good\nidea. On one hand, you can relax my favorite fastforward restrictions on\nthose tracking branches, but I think the net worth is negative since you\nwill have to burden new users with yet another concept of \"readonly\nbranches\", tell them things like \"either do git clone --no-tracking or\nthe first time you will want to commit something locally, create a\n'head' using git checkout -b master HEAD\" (you are already on a \"master\"\nbranch but it's a different \"master\", you know?) etc.\n\n\n  (*) You never are ironical about Linus, the Chuck Norris of CS. (And a\nhero, too!)\n\n-- \n\t\t\t\tPetr \"Pasky the Wow Pruit Igoe is\n\t\t\t\t\tAwesome Too!\" Baudis\nStuff: http://pasky.or.cz/\n#!/bin/perl -sp0777i<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<j]dsj\n$/=unpack('H*',$_);$_=`echo 16dio\\U$k\"SK$/SM$n\\EsN0p[lN*1\n"},{"id":"296305","messageId":"7v64dhznmx.fsf@assigned-by-dhcp.cox.net","threadId":"43317","inReplyTo":"Pine.LNX.4.64.0611141037120.3327@woody.osdl.org","subject":"Re: Missing features in git","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-14T22:09:26Z","receivedAt":"2006-11-14T22:09:26Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> On Tue, 14 Nov 2006, Shawn Pearce wrote:\n>> That's not a bad idea.  Then you can checkout a tag and have\n>> 'ref: refs/tags/v1.11' in HEAD, which means anyone who puts\n>> $(git-symbolic-ref) calls into their PS1 will see \"refs/tags/v1.11\"\n>> as their current branch, reminding them they are looking at the past.\n>\n> I agree. This would probably be a good way to do \"read-only branches\".\n> ...\n> Junio, what do you think? It wouldn't even be backwards incompatible, \n> because we're strictly allowing a superset of what we used to..\n\n(late reply -- just came back from a clinic)\n\nI do not see any fundamental reason not to allow HEAD to be a\ncommit that you cannot commit on top of because you are not on\nany branch, and I agree it is the right way to go.\n\nI am not sure how much pain we are talking about yet though.\n"},{"id":"298554","messageId":"7vy7qdy8vb.fsf@assigned-by-dhcp.cox.net","threadId":"43317","inReplyTo":"20061114134958.5326.qmail@science.horizon.com","subject":"Re: Missing features in git","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-14T22:13:44Z","receivedAt":"2006-11-14T22:13:44Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"linux@horizon.com writes:\n\n> One thing I noticed is that with ref logs, you've just re-invented the\n> CVS problem of associating history with a name.  If you want to rename\n> a branch (say, from \"mischacks\" to something suitable for publication),\n> do you rename the log or not?  It's a less virulent form, but it seems\n> like the same disease.\n\nI do not think we currently rename the log but it is probably a\nbug.  Renaming tag should also be made easier.\n\n> Another minor quibble: AFAICT, \"git checkout -f -m\" is meaningless (-f\n> overrides -m), but doesn't complain.\n\nIt should be made to complain.\n\n> An example of when you'd want to do this is performing a \"git bisect\"\n> with a local \"#define DEBUG 1\" change.  Particularly if you\n> hit a non-compiling version and need to back up.\n> or the way git-bisect does it\n>   \n>         echo \"$rev\" > \"$GIT_DIR/refs/heads/new-bisect\"\n>         git checkout new-bisect || exit\n>         mv \"$GIT_DIR/refs/heads/new-bisect\" \"$GIT_DIR/refs/heads/bisect\" &&\n>         GIT_DIR=\"$GIT_DIR\" git-symbolic-ref HEAD refs/heads/bisect\n\nThe name new-bisect is really temporary the code just shows it\npunts on a situation it does not expect (it essentially expects\na clean tree and working with a local change is by accident) and\nbeing ony half helpful to the user while recovering from that\nunexpected situation.  In other words, that's a room for\nimprovement.  We should be rewrite the above with something like\nwhat we have in the else clause in git-checkout around line 150.\nIt might make sense to make it a shell function and sharable\nbetween checkout and bisect (perhaps there are other uses).\nThen we do not need the temporary branch.\n\n> Either way, it reserves a second branch name, and seems like a bit of\n> a hack.\n\nYou are correct to call it a hack.  git-bisect started as a\ntechnology demonstration of the underlying rev-list --bisect\nfeature.  The thing is that the technology was so nice and\nuseful that we started using it before cleaning up these\nimplementation details.  I think instead of documenting the duct\ntape that holds git-bisect together (\"rev-list --bisect\" is\ngreat, and what \"git-bisect\" does is basically great but with\nminor glitches like you noticed and with hacky implementation\ndetails; I am calling the latter \"duct tape\"), we should redo\nthe hackish part.\n\nEnough with bisect.  And jumping the head while forward/back\nporting the local change would also involve the same kind of\nchange, so \"git reset --merge-local-change\" might be a good\naddition, but I am not sure about the details yet.\n"}]}