{"thread":{"id":"2698","subject":"keeping remote repo checked out?","startedAt":"2005-11-28T07:13:31Z","lastAt":"2005-12-01T02:43:10Z","messageCount":25,"participants":["James Cloos","Junio C Hamano","Petr Baudis","Linus Torvalds","Daniel Barkalow","Matthias Urlichs"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"12845","messageId":"m3k6et9rdw.fsf@lugabout.cloos.reno.nv.us","threadId":"2698","inReplyTo":null,"subject":"keeping remote repo checked out?","fromName":"James Cloos","fromEmail":"cloos@jhcloos.com","sentAt":"2005-11-28T07:13:31Z","receivedAt":"2005-11-28T07:13:31Z","isPatch":false,"sender":{"key":"cloos@jhcloos.com","avatar":"https://gravatar.com/avatar/ec9a05787d29afe41e243e4b60bd0e2f69d757688e8f0bfe5e78bc185a3e317f?d=mp&s=160"},"body":"I am testing git as a replacement for how I was using bk to manage web\nsites.  As such, I created a new git repo on the server, populated it\nwith the old data (ignoring history; there wasn't much relevant on\nthat site) and cloned that to the laptop.\n\nEditing on the server works well.  I can add, checking and a\nsubsequent pull on the laptop grabs the changes.\n\nBut any edits on the laptop's copy are not checked out when I push\nthem to the server.\n\nIs it possible to arrange that a push does a checkout on the remote\nthe same way a pull does on the local?\n\n-JimC\n-- \nJames H. Cloos, Jr. <cloos@jhcloos.com>\n"},{"id":"12848","messageId":"7vbr051ad1.fsf@assigned-by-dhcp.cox.net","threadId":"2698","inReplyTo":"m3k6et9rdw.fsf@lugabout.cloos.reno.nv.us","subject":"Re: keeping remote repo checked out?","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-11-28T07:48:26Z","receivedAt":"2005-11-28T07:48:26Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"James Cloos <cloos@jhcloos.com> writes:\n\n> Is it possible to arrange that a push does a checkout on the remote\n> the same way a pull does on the local?\n\nCreative use of hooks/post-update would solve that.\n\nHowever, you should be very careful if you sometimes edit on\nserver and sometimes push from other machine to the server on\nthe same branch on the server.\n"},{"id":"12862","messageId":"20051128105736.GO22159@pasky.or.cz","threadId":"2698","inReplyTo":"7vbr051ad1.fsf@assigned-by-dhcp.cox.net","subject":"Re: keeping remote repo checked out?","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2005-11-28T10:57:36Z","receivedAt":"2005-11-28T10:57:36Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Mon, Nov 28, 2005 at 08:48:26AM CET, I got a letter\nwhere Junio C Hamano <junkio@cox.net> said that...\n> James Cloos <cloos@jhcloos.com> writes:\n> \n> > Is it possible to arrange that a push does a checkout on the remote\n> > the same way a pull does on the local?\n> \n> Creative use of hooks/post-update would solve that.\n> \n> However, you should be very careful if you sometimes edit on\n> server and sometimes push from other machine to the server on\n> the same branch on the server.\n\nWhy? At worst you will get files with conflict markers on the server,\nwhich isn't that huge problem and just what you have to expect when you\ndo this kind of thing. I could imagine having an option in the config\nfile describing whether the repository is \"raw\" or has the working copy\nassociated, and in the later case have the updating code in the default\npost-update hook.\n\nPS: If someone is bored, it would be very useful to have a manual page\nfor the git configuration file, containing the list of all options.\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nVI has two modes: the one in which it beeps and the one in which\nit doesn't.\n"},{"id":"12890","messageId":"7vsltgtvk4.fsf@assigned-by-dhcp.cox.net","threadId":"2698","inReplyTo":"20051128105736.GO22159@pasky.or.cz","subject":"Re: keeping remote repo checked out?","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-11-28T19:35:23Z","receivedAt":"2005-11-28T19:35:23Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Petr Baudis <pasky@suse.cz> writes:\n\n> Dear diary, on Mon, Nov 28, 2005 at 08:48:26AM CET, I got a letter\n> where Junio C Hamano <junkio@cox.net> said that...\n>> James Cloos <cloos@jhcloos.com> writes:\n>> \n>> > Is it possible to arrange that a push does a checkout on the remote\n>> > the same way a pull does on the local?\n>> \n>> Creative use of hooks/post-update would solve that.\n>> \n>> However, you should be very careful if you sometimes edit on\n>> server and sometimes push from other machine to the server on\n>> the same branch on the server.\n>\n> Why? At worst you will get files with conflict markers on the server,\n> which isn't that huge problem and just what you have to expect when you\n> do this kind of thing.\n\nBoth of us are right and talking about the same thing.  You are\nright that as long as hooks/post-update is done correctly the\none who works on the server should not have to worry.  I am\nright that the hooks/post-update for that setup needs to be done\nvery carefully ;-).\n\nHere are the things whoever is doing the hooks/post-update for\nthis particular setup needs to think about.\n\n - is it safe to assume that the guy working on the server\n   working tree never switch branches?  otherwise, what to do if\n   the working tree has different branch checked out when push\n   called post-update?\n\n - should it allow forced-push that sets HEAD to non descendant\n   of the current HEAD?  In a shared repository setup,\n   disallowing forced-push is a good discipline.  OTOH, if this\n   is primarily used as an installation mechanism to a remote\n   hosting site, allowing forced-push may be ok.\n\n - should it do 'git-checkout', 'git-reset --hard HEAD', or\n   'git-pull . branch_to_push_into'?  The former two pretty much\n   assumes no development happens on the server repository and\n   git push is used primarily as an installation mechanism.  The\n   latter is to keep a branch, other than \"master\" that is\n   always checked out on the server machine, and have people\n   push into a different branch and merge with it automatically\n   when a push happens.  what would you do when a merge conflict\n   happens?\n\nOn a tangent, the last point brings up an interesting\nshared-repo usage pattern.  When you have a shared central\nrepository like CVS, you could arrange things this way:\n\n * On the shared repository, prepare one branch per developer\n   who is pushing into it, plus \"master\".\n\n * The developer pull from \"master\" and work in her private\n   repository.  The changes are pushed into her own branch on\n   the shared repository machine.\n\n * The the shared repository machine tries to merge \"master\"\n   into developer branches when the developer branch head is\n   updated.  If it does not trivially resolve, the developer\n   branch head is left as the last push by the developer\n   (i.e. not recording the merge).  If it does resolve, it is\n   checked out into playpen area, built and testsuite run, and\n   if all look well, \"master\" is updated with the result of the\n   merge.  A notification is sent to the developer to tell which\n   of the above actions happened.\n\n   This does not have to happen in the update hook and you\n   probably would not want to because it would be a lenthy\n   operation.  The update hook can be used to maintain recent\n   push log for a cron job that runs the \"merge-test-integrate\"\n   procedure to decide which branch is interesting.\n\nI am not sure if people would find this useful, though.\n"},{"id":"12895","messageId":"20051128212804.GV22159@pasky.or.cz","threadId":"2698","inReplyTo":"7vsltgtvk4.fsf@assigned-by-dhcp.cox.net","subject":"Re: keeping remote repo checked out?","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2005-11-28T21:28:04Z","receivedAt":"2005-11-28T21:28:04Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Mon, Nov 28, 2005 at 08:35:23PM CET, I got a letter\nwhere Junio C Hamano <junkio@cox.net> said that...\n> Both of us are right and talking about the same thing.  You are\n> right that as long as hooks/post-update is done correctly the\n> one who works on the server should not have to worry.  I am\n> right that the hooks/post-update for that setup needs to be done\n> very carefully ;-).\n\nAha, then I misunderstood what you wrote before - sorry. Obviously,\nyou are right. ;-)\n\n> Here are the things whoever is doing the hooks/post-update for\n> this particular setup needs to think about.\n> \n>  - is it safe to assume that the guy working on the server\n>    working tree never switch branches?  otherwise, what to do if\n>    the working tree has different branch checked out when push\n>    called post-update?\n\nI wouldn't do anything. Working copy reflects the HEAD; if you don't\nupdate HEAD, you needn't touch the working copy.\n\n>  - should it allow forced-push that sets HEAD to non descendant\n>    of the current HEAD?  In a shared repository setup,\n>    disallowing forced-push is a good discipline.  OTOH, if this\n>    is primarily used as an installation mechanism to a remote\n>    hosting site, allowing forced-push may be ok.\n\nI would just leave this on the particular head policy.\n\n>  - should it do 'git-checkout', 'git-reset --hard HEAD', or\n>    'git-pull . branch_to_push_into'?  The former two pretty much\n>    assumes no development happens on the server repository and\n>    git push is used primarily as an installation mechanism.\n\nFiles should be removed properly, which pretty much excludes the former\ntwo, I think.\n\n>    The latter is to keep a branch, other than \"master\" that is\n>    always checked out on the server machine, and have people\n>    push into a different branch and merge with it automatically\n>    when a push happens.  what would you do when a merge conflict\n>    happens?\n\nThis seems weird and overcomplicated, and it seems to mirror that GIT\ndoes not want to deal with trees containing local modifications - which\nis fine, but I don't think you should go over huge hoops in the workflow\nto adjust to that. Just verify in the pre-update hook that the tree\ncontains no local modifications, and disallow the push otherwise. Cogito\ncan then use own update hooks which will enable it to handle local\nchanges more gracefully (albeit still not ideally).\n\n> On a tangent, the last point brings up an interesting\n> shared-repo usage pattern.  When you have a shared central\n> repository like CVS, you could arrange things this way:\n..snip..\n> I am not sure if people would find this useful, though.\n\nIt is certainly quite interesting idea. I'm not sure how useful in\npractice is it either, though. ;-)\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nVI has two modes: the one in which it beeps and the one in which\nit doesn't.\n"},{"id":"12896","messageId":"7vd5kksaxw.fsf@assigned-by-dhcp.cox.net","threadId":"2698","inReplyTo":"20051128212804.GV22159@pasky.or.cz","subject":"Re: keeping remote repo checked out?","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-11-28T21:46:03Z","receivedAt":"2005-11-28T21:46:03Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Petr Baudis <pasky@suse.cz> writes:\n\n>> Here are the things whoever is doing the hooks/post-update for\n>> this particular setup needs to think about.\n>> \n>>  - is it safe to assume that the guy working on the server\n>>    working tree never switch branches?  otherwise, what to do if\n>>    the working tree has different branch checked out when push\n>>    called post-update?\n>\n> I wouldn't do anything. Working copy reflects the HEAD; if you don't\n> update HEAD, you needn't touch the working copy.\n>\n>>  - should it allow forced-push that sets HEAD to non descendant\n>>    of the current HEAD?  In a shared repository setup,\n>>    disallowing forced-push is a good discipline.  OTOH, if this\n>>    is primarily used as an installation mechanism to a remote\n>>    hosting site, allowing forced-push may be ok.\n>\n> I would just leave this on the particular head policy.\n\nIn case it was not obvious, I was not outlining what I would\nwant as a git-wide policy.  It was meant as an example of things\npeople need to think about, IOW, what their head policy should\nbe, if they want to use git in a workflow that magically checks\nthings out when a push happens.\n\n>>  - should it do 'git-checkout', 'git-reset --hard HEAD', or\n>>    'git-pull . branch_to_push_into'?  The former two pretty much\n>>    assumes no development happens on the server repository and\n>>    git push is used primarily as an installation mechanism.\n>\n> Files should be removed properly, which pretty much excludes the former\n> two, I think.\n\nUnless you screw with the branch head under a checked out tree,\ngit-checkout would remove files properly, and \"git-reset --hard\"\nwould do the right thing even when you update the branch head of\na checked out tree.  The last one is interesting and might be\nuseful.\n"},{"id":"12898","messageId":"Pine.LNX.4.64.0511281420390.3263@g5.osdl.org","threadId":"2698","inReplyTo":"20051128212804.GV22159@pasky.or.cz","subject":"Re: keeping remote repo checked out?","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-11-28T22:26:55Z","receivedAt":"2005-11-28T22:26:55Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 28 Nov 2005, Petr Baudis wrote:\n> \n> >  - should it do 'git-checkout', 'git-reset --hard HEAD', or\n> >    'git-pull . branch_to_push_into'?  The former two pretty much\n> >    assumes no development happens on the server repository and\n> >    git push is used primarily as an installation mechanism.\n> \n> Files should be removed properly, which pretty much excludes the former\n> two, I think.\n\nThere are major locking issues with two people pushing at the same time.\n\nThe git logic does the right thing for a non-checked-out branch, but it \ncan do the right thing exactly _because_ it's not checked out. It can \ncreate all the new objects whether the actual push succeeds or not, and it \ncan do the final switch-over as a single atomic file operation.\n\nThe same is most emphatically _not_ true of \"git checkout\".\n\nIn other words, you need to add your very own locking for the shared \nchecked-out tree, and you need to (_within_ that lock) separately remember \nwhat the _previous_ tree was that was checked out, because you can't just \nrely on the previous head as reported by git, because that will have been \ndone ourside your \"checked out lock\".\n\nAnd locking really isn't trivial. Especially if you _also_ do this with \nmultiple clients touching the same checked-out repo over NFS (which I'd \nseriously suggest you not do).\n\nThere's a really good reason why the git core does _not_ do this. It's \ndamn complicated.\n\n\t\tLinus\n"},{"id":"12901","messageId":"Pine.LNX.4.64.0511281845280.25300@iabervon.org","threadId":"2698","inReplyTo":"Pine.LNX.4.64.0511281420390.3263@g5.osdl.org","subject":"Re: keeping remote repo checked out?","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-11-29T00:19:05Z","receivedAt":"2005-11-29T00:19:05Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Mon, 28 Nov 2005, Linus Torvalds wrote:\n\n> On Mon, 28 Nov 2005, Petr Baudis wrote:\n> > \n> > >  - should it do 'git-checkout', 'git-reset --hard HEAD', or\n> > >    'git-pull . branch_to_push_into'?  The former two pretty much\n> > >    assumes no development happens on the server repository and\n> > >    git push is used primarily as an installation mechanism.\n> > \n> > Files should be removed properly, which pretty much excludes the former\n> > two, I think.\n> \n> There are major locking issues with two people pushing at the same time.\n> \n> The git logic does the right thing for a non-checked-out branch, but it \n> can do the right thing exactly _because_ it's not checked out. It can \n> create all the new objects whether the actual push succeeds or not, and it \n> can do the final switch-over as a single atomic file operation.\n> \n> The same is most emphatically _not_ true of \"git checkout\".\n> \n> In other words, you need to add your very own locking for the shared \n> checked-out tree, and you need to (_within_ that lock) separately remember \n> what the _previous_ tree was that was checked out, because you can't just \n> rely on the previous head as reported by git, because that will have been \n> done ourside your \"checked out lock\".\n\nWe really ought to keep track of what the current checked out tree is, \nindependant of the head that it's supposed to match. Then it would be safe \nto push to a head that's checked out (it wouldn't update it, but the \nsystem would understand what's going on).\n\nThe rest should be easy from there, just by locking on that file, since \nyou probably don't care about the race between checking out the head and \nupdating the head. (You would want to have the case for not getting the \nlock loop until it can get the lock, rather than aborting, however, so \nthat the last version does get checked out even if checkout wins with push \nbut the hook runs before checkout completes.)\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"12902","messageId":"Pine.LNX.4.64.0511281637480.3177@g5.osdl.org","threadId":"2698","inReplyTo":"Pine.LNX.4.64.0511281845280.25300@iabervon.org","subject":"Re: keeping remote repo checked out?","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-11-29T00:43:13Z","receivedAt":"2005-11-29T00:43:13Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 28 Nov 2005, Daniel Barkalow wrote:\n> \n> We really ought to keep track of what the current checked out tree is, \n> independant of the head that it's supposed to match. Then it would be safe \n> to push to a head that's checked out (it wouldn't update it, but the \n> system would understand what's going on).\n\nWell, that's what branches are all about. \n\nYou really have two choices:\n - do it all yourself\n - use git branches\n\nbut if you use a special git branch for the checked-out state, then you \nhave to realize that nobody can push directly to it.\n\nYou'd have a trigger that triggers on a push to _another_ branch, and then \nthe trigger basically does an automatic \"git pull\" from that branch (and \nupdates the checked-out state as part of that).\n\nBut you _still_ need to do the locking. That's very fundamental. There is \nno locking in a \"git push\", exactly because it can push in parallel, by \ndesign. And you _cannot_ check out a tree in parallel, so you have to do \nlocking for that.\n\nThere's no way you can avoid the locking. You can do shortcuts: for \nexample, you could avoid any explicit locking by having the \"checkout\" \njust happen once an hour, with an automatic \"pull\" from the changed \nbranch. Again, that means that the branch that is checked out can NOT be \none of the branches that people push to.\n\n\t\tLinus\n"},{"id":"12904","messageId":"Pine.LNX.4.64.0511282027360.25300@iabervon.org","threadId":"2698","inReplyTo":"Pine.LNX.4.64.0511281637480.3177@g5.osdl.org","subject":"Re: keeping remote repo checked out?","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-11-29T02:35:39Z","receivedAt":"2005-11-29T02:35:39Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Mon, 28 Nov 2005, Linus Torvalds wrote:\n\n> On Mon, 28 Nov 2005, Daniel Barkalow wrote:\n> > \n> > We really ought to keep track of what the current checked out tree is, \n> > independant of the head that it's supposed to match. Then it would be safe \n> > to push to a head that's checked out (it wouldn't update it, but the \n> > system would understand what's going on).\n> \n> Well, that's what branches are all about. \n> \n> You really have two choices:\n>  - do it all yourself\n>  - use git branches\n> \n> but if you use a special git branch for the checked-out state, then you \n> have to realize that nobody can push directly to it.\n\nThe idea is to have something which is private, to match the working tree, \nwhich is obviously private (because it doesn't even exist from the point \nof view of the database). Of course, you don't want most of the branch \nmechanism, with HEAD pointing to a file, because when you commit, you want \nto update something else, and when you check out, you want to check out \nsomething else. You want to use a normal git branch, but still have git \nkeep track of what it thinks should be in your working tree, regardless of \nwhat the branch you're on does, so that checkout doesn't get confused if \nsomebody's pushed to the branch you're on.\n\nThen, if someone pushes to a branch that's checked out, git doesn't lose \ntrack of what it put in the working tree, so it can handle the \"git \ncheckout\" that you do afterwards to update the working tree. Making \neverything work okay if multiple \"git checkout\"s happen at the same time \nis future work, and will definitely involve locking.\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"12905","messageId":"Pine.LNX.4.64.0511281837040.3177@g5.osdl.org","threadId":"2698","inReplyTo":"Pine.LNX.4.64.0511282027360.25300@iabervon.org","subject":"Re: keeping remote repo checked out?","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-11-29T02:39:24Z","receivedAt":"2005-11-29T02:39:24Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 28 Nov 2005, Daniel Barkalow wrote:\n> > \n> > but if you use a special git branch for the checked-out state, then you \n> > have to realize that nobody can push directly to it.\n> \n> The idea is to have something which is private, to match the working tree, \n> which is obviously private (because it doesn't even exist from the point \n> of view of the database).\n\nSure. It's private because it has its own name, and you can make _sure_ \nthat nobody tries to push to it by having a trigger that refuses to update \nthat branch.\n\nNow, if you want to make it also be _invisible_ (so that when others don't \nclone, they don't see what the checked-out state was when they cloned), \nyou'd have to make some new rules to git. We could have rules like \"branch \nnames that start with '.' aren't listed\", which would effectively do \nexactly that..\n\n\t\t\tLinus\n"},{"id":"12906","messageId":"Pine.LNX.4.64.0511282208050.25300@iabervon.org","threadId":"2698","inReplyTo":"Pine.LNX.4.64.0511281837040.3177@g5.osdl.org","subject":"[PATCH] Re: keeping remote repo checked out?","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-11-29T03:40:33Z","receivedAt":"2005-11-29T03:40:33Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Mon, 28 Nov 2005, Linus Torvalds wrote:\n\n> On Mon, 28 Nov 2005, Daniel Barkalow wrote:\n> > > \n> > > but if you use a special git branch for the checked-out state, then you \n> > > have to realize that nobody can push directly to it.\n> > \n> > The idea is to have something which is private, to match the working tree, \n> > which is obviously private (because it doesn't even exist from the point \n> > of view of the database).\n> \n> Sure. It's private because it has its own name, and you can make _sure_ \n> that nobody tries to push to it by having a trigger that refuses to update \n> that branch.\n> \n> Now, if you want to make it also be _invisible_ (so that when others don't \n> clone, they don't see what the checked-out state was when they cloned), \n> you'd have to make some new rules to git. We could have rules like \"branch \n> names that start with '.' aren't listed\", which would effectively do \n> exactly that..\n\nI was planning to keep it in .git (instead of .git/refs/...), because it's \ninformation about the working tree, not properly part of the repository. \nIt's like MERGE_HEAD in being about what the user is in the middle of.\n\nI actually have a bit of a patch now, which only updates checkout and \ncommit (anything that updates HEAD should also update CHECKED_OUT, and \nsome things probably ought to read CHECKED_OUT instead of HEAD), but \nshould serve to give an idea of what I mean. Essentially, if somebody's \nmessed with your HEAD, than \"git checkout\" will update to that, and \"git \ncommit\" will give an error message until you do (I added a check so it \nhappens before you write a message, but the third argument to \n\"git-update-ref HEAD\" would also complain).\n\nObviously, not for application, since it breaks things like \"git resolve\" \nwhich are supposed to change what your working tree contains and aren't \nupdated to make CHECKED_OUT match.\n\n---\n\nKeep a private copy of the commit whose tree corresponds to the\ngit-provided state of the working tree, in case somebody changes the\nbranch we're on behind our backs.\n\nSigned-off-by: Daniel Barkalow <barkalow@iabervon.org>\n\n---\n\n git-checkout.sh |    5 ++++-\n git-commit.sh   |   10 +++++++++-\n 2 files changed, 13 insertions(+), 2 deletions(-)\n\napplies-to: fe523a4df93cce3e5c5b0266b9d3f1cbea009afa\n8831e2595f29c90a259586250d5c6d044e9d7c8c\ndiff --git a/git-checkout.sh b/git-checkout.sh\nindex 4cf30e2..503b34f 100755\n--- a/git-checkout.sh\n+++ b/git-checkout.sh\n@@ -5,7 +5,8 @@ usage () {\n     die \"usage: git checkout [-f] [-b <new_branch>] [<branch>] [<paths>...]\"\n }\n \n-old=$(git-rev-parse HEAD)\n+old=$(git-rev-parse --revs-only CHECKED_OUT)\n+[ -z $old ] && old=$(git-rev-parse HEAD)\n new=\n force=\n branch=\n@@ -117,6 +118,8 @@ else\n     git-read-tree -m -u $old $new\n fi\n \n+git-update-ref CHECKED_OUT $new\n+\n # \n # Switch the HEAD pointer to the new branch if it we\n # checked out a branch head, and remove any potential\ndiff --git a/git-commit.sh b/git-commit.sh\nindex 3d250ec..e73003b 100755\n--- a/git-commit.sh\n+++ b/git-commit.sh\n@@ -108,6 +108,13 @@ t,*)\n esac || exit 1\n git-update-index -q --refresh || exit 1\n \n+current=$(git-rev-parse --revs-only CHECKED_OUT)\n+if test ! -z \"$current\" -a \"$current\" != \"$(git-rev-parse HEAD)\"\n+then\n+\techo \"Changes have been pushed to this branch since you checked it out\"\n+\texit 1\n+fi\n+\n case \"$verify\" in\n t)\n \tif test -x \"$GIT_DIR\"/hooks/pre-commit\n@@ -232,7 +239,8 @@ then\n \ttree=$(git-write-tree) &&\n \tcommit=$(cat \"$GIT_DIR\"/COMMIT_MSG | git-commit-tree $tree $PARENTS) &&\n \tgit-update-ref HEAD $commit $current &&\n-\trm -f -- \"$GIT_DIR/MERGE_HEAD\"\n+\trm -f -- \"$GIT_DIR/MERGE_HEAD\" &&\n+\tgit-update-ref CHECKED_OUT $commit\n else\n \techo >&2 \"* no commit message?  aborting commit.\"\n \tfalse\n---\n0.99.9.GIT\n"},{"id":"12908","messageId":"Pine.LNX.4.64.0511282029290.3177@g5.osdl.org","threadId":"2698","inReplyTo":"Pine.LNX.4.64.0511282208050.25300@iabervon.org","subject":"Re: [PATCH] Re: keeping remote repo checked out?","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-11-29T04:34:11Z","receivedAt":"2005-11-29T04:34:11Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 28 Nov 2005, Daniel Barkalow wrote:\n> \n> I was planning to keep it in .git (instead of .git/refs/...), because it's \n> information about the working tree, not properly part of the repository. \n> It's like MERGE_HEAD in being about what the user is in the middle of.\n\nThat's fine.\n\nHowever, your patch isn't.\n\nYour patch just creates this eternal confusion of \"why is HEAD different \nfrom CHECKED_OUT\". \n\nIt's really easy to do what you want to do _without_ any tool changes:\n\n\tgit-rev-parse HEAD > .git/CHECKED_OUT\n\trm .git/HEAD\n\tln -s refs/heads/../../CHECKED_OUT .git/HEAD\n\nand you're done. No tool changes necessary.\n\nNow \"HEAD\" always points to the checked-out thing, but a \"git clone\" won't \never actually clone your CHECKED_OUT branch.\n\n\t\tLinus\n"},{"id":"12910","messageId":"Pine.LNX.4.64.0511282337170.25300@iabervon.org","threadId":"2698","inReplyTo":"Pine.LNX.4.64.0511282029290.3177@g5.osdl.org","subject":"Re: [PATCH] Re: keeping remote repo checked out?","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-11-29T06:02:07Z","receivedAt":"2005-11-29T06:02:07Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Mon, 28 Nov 2005, Linus Torvalds wrote:\n\n> On Mon, 28 Nov 2005, Daniel Barkalow wrote:\n> > \n> > I was planning to keep it in .git (instead of .git/refs/...), because it's \n> > information about the working tree, not properly part of the repository. \n> > It's like MERGE_HEAD in being about what the user is in the middle of.\n> \n> That's fine.\n> \n> However, your patch isn't.\n> \n> Your patch just creates this eternal confusion of \"why is HEAD different \n> from CHECKED_OUT\". \n> \n> It's really easy to do what you want to do _without_ any tool changes:\n> \n> \tgit-rev-parse HEAD > .git/CHECKED_OUT\n> \trm .git/HEAD\n> \tln -s refs/heads/../../CHECKED_OUT .git/HEAD\n> \n> and you're done. No tool changes necessary.\n> \n> Now \"HEAD\" always points to the checked-out thing, but a \"git clone\" won't \n> ever actually clone your CHECKED_OUT branch.\n\nBut CHECKED_OUT isn't a branch. The whole point of it is that you stay on \nsome real branch, so you can actually use the tools to affect the \nrepository (i.e., the things under refs/). The reason to keep CHECKED_OUT \nis so that you can tell if the branch you're on changes out from under \nyou.\n\nFor example, I want to have a repository where I push into the \n\"production\" branch, and I want to be able to get these changes in the \nworking tree that the repository is in. If I have HEAD point to \nrefs/heads/production, git doesn't know any more what's in the working \ntree, so it can't do the two-way merge. If I have HEAD point to \nCHECKED_OUT, git doesn't know any more what I want to get, so it can't do \nthe two-way merge. That is, what I want to have work is:\n\n  server$ git checkout production\n  work$ git push server:production\n  server$ git checkout\n\nand this should leave the working tree on server with the changes pushed \nfrom work. Currently, I have to make sure server *isn't* tracking the \nbranch I care about when the push happens, so that it doesn't lose track \nof its state, and then switch to the branch to get the changes, and copy \nthe branch to a new branch, and switch to that so the next branch won't \nmess up the state.\n\nHEAD is a symbolic ref to the ref in the repository that is the current \nbranch. CHECKED_OUT is a ref to the hash that's in the working tree. \nUsually they match, because usually nothing is changing current branch \nwithout changing the working tree (or making the current branch match \nchanges in the working tree), but the point of the patch is to respond \nsensibly to cases where this stops being true, because those can actually \nbe part of desirable usage patterns.\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"12914","messageId":"7vmzjom00m.fsf@assigned-by-dhcp.cox.net","threadId":"2698","inReplyTo":"Pine.LNX.4.64.0511282337170.25300@iabervon.org","subject":"Re: [PATCH] Re: keeping remote repo checked out?","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-11-29T06:38:33Z","receivedAt":"2005-11-29T06:38:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Daniel Barkalow <barkalow@iabervon.org> writes:\n\n> the two-way merge. That is, what I want to have work is:\n>\n>   server$ git checkout production\n>   work$ git push server:production\n>   server$ git checkout\n>\n> and this should leave the working tree on server with the changes pushed \n> from work.\n\nI think the approach Linus was suggesting before he suggested\nthe funny refs/heads/../.. symlink idea (honestly, I think he\nwas half joking) is cleaner, easier to understand, easier to\nimplement and generally makes more sense.  Your work cycle would\nbecome like this:\n\n    server$ git checkout production\n    work$ git checkout master\n    work$ git pull server production ;# merge into work's master\n    work$ git push server master:receive_from_work\n    server$ git pull . receive_from_work ;# merge into server's production\n\nand you make sure receive_from_work is not checked out on server\n(or production is never pushed into) and always do fast forward\nand nothing else.\n"},{"id":"12915","messageId":"Pine.LNX.4.64.0511290141220.25300@iabervon.org","threadId":"2698","inReplyTo":"7vmzjom00m.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Re: keeping remote repo checked out?","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-11-29T06:57:09Z","receivedAt":"2005-11-29T06:57:09Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Mon, 28 Nov 2005, Junio C Hamano wrote:\n\n> Daniel Barkalow <barkalow@iabervon.org> writes:\n> \n> > the two-way merge. That is, what I want to have work is:\n> >\n> >   server$ git checkout production\n> >   work$ git push server:production\n> >   server$ git checkout\n> >\n> > and this should leave the working tree on server with the changes pushed \n> > from work.\n> \n> I think the approach Linus was suggesting before he suggested\n> the funny refs/heads/../.. symlink idea (honestly, I think he\n> was half joking) is cleaner, easier to understand, easier to\n> implement and generally makes more sense.  Your work cycle would\n> become like this:\n> \n>     server$ git checkout production\n>     work$ git checkout master\n>     work$ git pull server production ;# merge into work's master\n>     work$ git push server master:receive_from_work\n>     server$ git pull . receive_from_work ;# merge into server's production\n> \n> and you make sure receive_from_work is not checked out on server\n> (or production is never pushed into) and always do fast forward\n> and nothing else.\n\nThat's what I'm doing currently, actually (with work pushing to \n\"production\", but server having checked out \"deploy\"), and I find it \nannoying to have to do the pull each time and have a separate head. It \nalso means that, if the stuff on the server is set up as a hook, it'll \nhave to do the locking against concurrent changes to the working tree in \npull, which is much more complicated than checkout.\n\nIt's also somewhat non-intuitive, and leaves a surprising way for the user \nto confuse the system in a way that it can't detect.\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"12919","messageId":"7v8xv7lwlr.fsf@assigned-by-dhcp.cox.net","threadId":"2698","inReplyTo":"Pine.LNX.4.64.0511290141220.25300@iabervon.org","subject":"Re: [PATCH] Re: keeping remote repo checked out?","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-11-29T07:52:16Z","receivedAt":"2005-11-29T07:52:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Daniel Barkalow <barkalow@iabervon.org> writes:\n\n>>     server$ git checkout production\n>>     work$ git checkout master\n>>     work$ git pull server production ;# merge into work's master\n>>     work$ git push server master:receive_from_work\n>>     server$ git pull . receive_from_work ;# merge into server's production\n>> \n>> and you make sure receive_from_work is not checked out on server\n>> (or production is never pushed into) and always do fast forward\n>> and nothing else.\n>\n> That's what I'm doing currently, actually (with work pushing to \n> \"production\", but server having checked out \"deploy\"), and I find it \n> annoying to have to do the pull each time and have a separate head. It \n> also means that, if the stuff on the server is set up as a hook, it'll \n> have to do the locking against concurrent changes to the working tree in \n> pull, which is much more complicated than checkout.\n\nThis depends on what is on the checked-out working tree and how\nit is used, but one use pattern I was imagining was actually\nmuch more elaborate.  I would set up two non-naked repositories\non the server; let's call them treeR and treeP (reception and\npublish).\n\nEach work machine push into its own reception branch of treeR\nrepository (so you have N reception branches for N workers).  On\nthe server machine, a daemon monitors the reception branch heads\n(inotify or idle poll loop looking at mtime; the details do not\nmatter), and run the git pull into \"master\" of treeR.  My daemon\nmight want to forbid anything but fast forward for this pull, or\nmight allow any clean merge.  It compiles and runs testsuites\nnext.  If anything fails during the above process, the owner of\nthe reception branch is notified about the failure; I might even\nwant to forcibly rewind her reception branch in this case to\n\"master\" when this happens.\n\nWhen everything goes well, the daemon goes to treeP and pulls\nfrom treeR's master into \"deploy\", which is checked out.  This\nprocedure is the only thing that touches treeP, so this pull is\nguaranteed to be a fast forward.\n\nThe serialization happens by having a single such daemon\nrunning; no need to worry about locking anymore.\n"},{"id":"12932","messageId":"pan.2005.11.29.12.14.05.485826@smurf.noris.de","threadId":"2698","inReplyTo":"Pine.LNX.4.64.0511290141220.25300@iabervon.org","subject":"Re: [PATCH] Re: keeping remote repo checked out?","fromName":"Matthias Urlichs","fromEmail":"smurf@smurf.noris.de","sentAt":"2005-11-29T12:14:07Z","receivedAt":"2005-11-29T12:14:07Z","isPatch":true,"sender":{"key":"matthias@urlichs.de","avatar":"https://gravatar.com/avatar/2708905af227313eba6f2b2ae0f7d0259b5ac5d71baef58fe5a13c699ce0bbf0?d=mp&s=160"},"body":"Hi, Daniel Barkalow wrote:\n\n> That's what I'm doing currently, actually (with work pushing to \n> \"production\", but server having checked out \"deploy\"), and I find it \n> annoying to have to do the pull each time and have a separate head.\n\nWhy? I think \"what's currently deployed\" and \"the latest commit on the\nproduction branch\" are two distinct concepts, and should be treated as\nsuch.\n\nThat way, a clean push (update of PRODUCTION, controlled by the update\nhook) and an update of DEPLOY (the fast-forward merge (unless you need\nto roll back something) from your production branch, controlled by the\npost-update hook) are also distinct, can be handled individually.\n\nPersonally I just use \"git-read-tree -m -u deploy master && \\\ncat refs/heads/master > refs/heads/deploy\" in the post-update trigger.\nI don't care about HEAD at all; nobody is supposed to change that\ndirectory manually anyway.\n\n-- \nMatthias Urlichs   |   {M:U} IT Design @ m-u-it.de   |  smurf@smurf.noris.de\nDisclaimer: The quote was selected randomly. Really. | http://smurf.noris.de\n - -\nBringing computers into the home won't change either one, but may\nrevitalize the corner saloon.\n"},{"id":"12935","messageId":"pan.2005.11.29.13.39.01.958465@smurf.noris.de","threadId":"2698","inReplyTo":"7v8xv7lwlr.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Re: keeping remote repo checked out?","fromName":"Matthias Urlichs","fromEmail":"smurf@smurf.noris.de","sentAt":"2005-11-29T13:39:02Z","receivedAt":"2005-11-29T13:39:02Z","isPatch":true,"sender":{"key":"matthias@urlichs.de","avatar":"https://gravatar.com/avatar/2708905af227313eba6f2b2ae0f7d0259b5ac5d71baef58fe5a13c699ce0bbf0?d=mp&s=160"},"body":"Hi, Junio C Hamano wrote:\n\n> When everything goes well, the daemon goes to treeP and pulls\n> from treeR's master into \"deploy\", which is checked out.\n\nWhy do you need a separate tree for that? -EOVERKILL.\nI just use a separate index file for the production tree (and a well-known\nname in refs/heads that's associated with it, for which the commit hook\nblocks updates).\n\n-- \nMatthias Urlichs   |   {M:U} IT Design @ m-u-it.de   |  smurf@smurf.noris.de\nDisclaimer: The quote was selected randomly. Really. | http://smurf.noris.de\n - -\nNothing is so important that nothing else is important.\n"},{"id":"12938","messageId":"Pine.LNX.4.64.0511291157260.25300@iabervon.org","threadId":"2698","inReplyTo":"7v8xv7lwlr.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Re: keeping remote repo checked out?","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-11-29T17:22:21Z","receivedAt":"2005-11-29T17:22:21Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Mon, 28 Nov 2005, Junio C Hamano wrote:\n\n> Daniel Barkalow <barkalow@iabervon.org> writes:\n> \n> >>     server$ git checkout production\n> >>     work$ git checkout master\n> >>     work$ git pull server production ;# merge into work's master\n> >>     work$ git push server master:receive_from_work\n> >>     server$ git pull . receive_from_work ;# merge into server's production\n> >> \n> >> and you make sure receive_from_work is not checked out on server\n> >> (or production is never pushed into) and always do fast forward\n> >> and nothing else.\n> >\n> > That's what I'm doing currently, actually (with work pushing to \n> > \"production\", but server having checked out \"deploy\"), and I find it \n> > annoying to have to do the pull each time and have a separate head. It \n> > also means that, if the stuff on the server is set up as a hook, it'll \n> > have to do the locking against concurrent changes to the working tree in \n> > pull, which is much more complicated than checkout.\n> \n> This depends on what is on the checked-out working tree and how\n> it is used, but one use pattern I was imagining was actually\n> much more elaborate.  I would set up two non-naked repositories\n> on the server; let's call them treeR and treeP (reception and\n> publish).\n\nThis is quite elaborate.\n\n> Each work machine push into its own reception branch of treeR\n> repository (so you have N reception branches for N workers).  On\n> the server machine, a daemon monitors the reception branch heads\n> (inotify or idle poll loop looking at mtime; the details do not\n> matter), and run the git pull into \"master\" of treeR.  My daemon\n> might want to forbid anything but fast forward for this pull, or\n> might allow any clean merge. It compiles and runs testsuites\n> next.  If anything fails during the above process, the owner of\n> the reception branch is notified about the failure; I might even\n> want to forcibly rewind her reception branch in this case to\n> \"master\" when this happens.\n\nThis seems maximally inconvenient. If you lose a race, you only find out \nlater, your reception branch is screwed up, and you have no way of finding \nout in advance that this is going to happen? It's much nicer to have \npeople all push to a single branch, and tell them if they lose (i.e., the \nchange wouldn't be a fast-forward).\n\n> When everything goes well, the daemon goes to treeP and pulls\n> from treeR's master into \"deploy\", which is checked out.  This\n> procedure is the only thing that touches treeP, so this pull is\n> guaranteed to be a fast forward.\n> \n> The serialization happens by having a single such daemon\n> running; no need to worry about locking anymore.\n\nI'm not sure what the big deal about locking is. We do locking for \nupdating everything else; I don't see a problem with having a lock for \nwhen git updates the working tree, so long as it doesn't need to hold some \nother lock as well at the same time (in which case we'd have to think \nabout lock ordering).\n\n(Actually, adding CHECKED_OUT would also allow pulling the current branch \ncleanly without all the special-casing in get-fetch.sh and git-pull.sh; it \nwould have the predictable effect of leaving your working tree not up to \ndate, but the ref it follows up to date, and the usual two-way merge in a \npull would obviously do the right thing. Or you could just fetch, find out \nwhat will change with \"git diff\", and get the changes with \"git \ncheckout\". In general, it would fix aliasing problems between \nrefs/heads/* and HEAD.)\n"},{"id":"12940","messageId":"7v1x0zicn8.fsf@assigned-by-dhcp.cox.net","threadId":"2698","inReplyTo":"pan.2005.11.29.13.39.01.958465@smurf.noris.de","subject":"Re: [PATCH] Re: keeping remote repo checked out?","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-11-29T17:31:39Z","receivedAt":"2005-11-29T17:31:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Matthias Urlichs <smurf@smurf.noris.de> writes:\n\n> Hi, Junio C Hamano wrote:\n>\n>> When everything goes well, the daemon goes to treeP and pulls\n>> from treeR's master into \"deploy\", which is checked out.\n>\n> Why do you need a separate tree for that? -EOVERKILL.\n\nYes that is overkill, but treeR is used for merge and the scheme\nallows that merge to be real merge not just fast forwards ---\nyou need a checked out tree for that.  We can use multiple\nchecked out tree sharing the same .git/ directory with separate\nindex files instead.\n"},{"id":"12942","messageId":"7vk6erfe3o.fsf@assigned-by-dhcp.cox.net","threadId":"2698","inReplyTo":"Pine.LNX.4.64.0511291157260.25300@iabervon.org","subject":"Re: [PATCH] Re: keeping remote repo checked out?","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-11-29T19:28:27Z","receivedAt":"2005-11-29T19:28:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Daniel Barkalow <barkalow@iabervon.org> writes:\n\n> This seems maximally inconvenient. If you lose a race, you only find out \n> later, your reception branch is screwed up, and you have no way of finding \n> out in advance that this is going to happen?\n\nI am not sure what you mean by \"your reception branch is screwed\nup\".  We _could_ rewind that reception branch after acceptance\ntest fails but I did not mention that because I haven't thought\nit through.\n\nThis was actually designed to reduce the chance of getting a\nrace in the first place, so I am not sure if it makes things\ninconvenient.\n\nAlice and Bob starts out from the central repository commit O\n(for origin), and make progress independently.  They have one\ncommit on top of O each, A and B where A~1 === O and B~1 === O.\n\nAlice pushes first, the central repository has O and accepts\nbecause updating from O to A is a fast forward.  Bob tries to\npush, and in the classic CVS-style shared repository setup in\nthe tutorial, this is prevented because this is not a fast\nforward.  Bob needs to first pull and merge A and B to create C\n(C^1 === B, C^2 === A) and push that.  This succeeds.\n\nInstead, the approach allows you to choose to do the merge on\nthe server side unattended, as part of the acceptance check.\n\nAlice pushes, and both her reception branch and the reception\nrepository master becomes A (fast forward).  When Bob pushes B\nto his reception branch, we attempt to pull it into reception\nrepository master --- we do not have to fail this pull even if\nit is not a fast forward (we could choose to fail it). reception\nrepository master becomes C which is a merge between A and B.\nThe result of this automerge needs to be checked for sanity, so\nbefore this C (new reception repository master) is pulled into\nthe deployment repository, there is a validation step (this step\ncan do things other than validation; e.g. making tarballs for\ndistribution, automatic tagging).  While all that is happening,\nother people can be pushing into their own reception branches,\nwaiting for their turn.  And we guarantee that what is moved to\nthe deployment repository has been tested \"clean\" (depending on\nthe quality of test, that is).\n\nIf the central repository acceptance policy is simple enough,\nnamely, if it takes whatever an individiual developer with push\naccess says is good at the face value, then we do not need any\nof the above, and a simple \"fast forward only\" is good enough,\nfar simpler to explain and understand.\n\nOn the other hand, at places where management already has rules\nthat require any update to the central repository to first pass\na test suite, the acceptance test can take time to complete ---\nwhich enlarges the race window --- and more importantly when a\npush that passed a simple \"fast forward only\" rule fails, we\nsomehow need to prevent that failed head from leaking out to the\npublic.  That is cumbersome to arrange if we only use a single\nreception branch.\n\nIn case it was not obvious, the reception repository is meant to\nbe push-only, and all the fetching for public consumption are\nmeant to happen from the deployed repository \"master\".  Most\nimportantly, reception branches in reception repository are not\nto be pulled by individual developers.\n"},{"id":"12947","messageId":"Pine.LNX.4.64.0511291525360.25300@iabervon.org","threadId":"2698","inReplyTo":"7vk6erfe3o.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Re: keeping remote repo checked out?","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-11-29T21:44:56Z","receivedAt":"2005-11-29T21:44:56Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Tue, 29 Nov 2005, Junio C Hamano wrote:\n\n> Daniel Barkalow <barkalow@iabervon.org> writes:\n> \n> > This seems maximally inconvenient. If you lose a race, you only find out \n> > later, your reception branch is screwed up, and you have no way of finding \n> > out in advance that this is going to happen?\n> \n> I am not sure what you mean by \"your reception branch is screwed\n> up\".  We _could_ rewind that reception branch after acceptance\n> test fails but I did not mention that because I haven't thought\n> it through.\n> \n> This was actually designed to reduce the chance of getting a\n> race in the first place, so I am not sure if it makes things\n> inconvenient.\n> \n> Alice and Bob starts out from the central repository commit O\n> (for origin), and make progress independently.  They have one\n> commit on top of O each, A and B where A~1 === O and B~1 === O.\n> \n> Alice pushes first, the central repository has O and accepts\n> because updating from O to A is a fast forward.  Bob tries to\n> push, and in the classic CVS-style shared repository setup in\n> the tutorial, this is prevented because this is not a fast\n> forward.  Bob needs to first pull and merge A and B to create C\n> (C^1 === B, C^2 === A) and push that.  This succeeds.\n> \n> Instead, the approach allows you to choose to do the merge on\n> the server side unattended, as part of the acceptance check.\n> \n> Alice pushes, and both her reception branch and the reception\n> repository master becomes A (fast forward).  When Bob pushes B\n> to his reception branch, we attempt to pull it into reception\n> repository master --- we do not have to fail this pull even if\n> it is not a fast forward (we could choose to fail it). reception\n> repository master becomes C which is a merge between A and B.\n\nIf the merge works automatically, then Bob can do it without any trouble. \nIf it doesn't work automatically, then Bob has to do it. But if Bob might \nhave to do a merge, he can't leave for the day until his commit has gone \nall the way through, in which case he might as well do any merges while he \nwaits. In my mind, the critical issue for developers is time to success or \nfailure, and that's longer in your scheme. Perhaps a better idea is to \nhave a script on Bob's end react to failure of the push (due to not being \na fast-forward) by automatically pulling the thing that it's supposed to \nmerge with, and push again if it worked. (If it failed, Bob fixes it, and \nthen pushes again.)\n\n> The result of this automerge needs to be checked for sanity, so\n> before this C (new reception repository master) is pulled into\n> the deployment repository, there is a validation step (this step\n> can do things other than validation; e.g. making tarballs for\n> distribution, automatic tagging).  While all that is happening,\n> other people can be pushing into their own reception branches,\n> waiting for their turn.  And we guarantee that what is moved to\n> the deployment repository has been tested \"clean\" (depending on\n> the quality of test, that is).\n> \n> If the central repository acceptance policy is simple enough,\n> namely, if it takes whatever an individiual developer with push\n> access says is good at the face value, then we do not need any\n> of the above, and a simple \"fast forward only\" is good enough,\n> far simpler to explain and understand.\n> \n> On the other hand, at places where management already has rules\n> that require any update to the central repository to first pass\n> a test suite, the acceptance test can take time to complete ---\n> which enlarges the race window --- and more importantly when a\n> push that passed a simple \"fast forward only\" rule fails, we\n> somehow need to prevent that failed head from leaking out to the\n> public.  That is cumbersome to arrange if we only use a single\n> reception branch.\n\nI think the right thing is to only allow pushes after something passes \ntesting, probably be having people push to tags, which the test server \ntests and then pushes to the common upstream. The developers have to wait \nfor the testing, but can go home when that passes.\n\nI think there is the possibility for something really clever where, when \nyou try to submit, if there's something in the testing area, it rejects \nyou, you merge with the thing in the testing area, wait for the test ahead \nof you to complete, and submit either the merge (if the previous thing \npassed) or your original (if the previous thing failed). That way, you can \noverlap the time that you spend waiting for the test farm to be free with \nthe time you spend merging against things that are getting in ahead of \nyou. (Of course, if the merge with the testing thing isn't automatic, you \nmight cancel it and do something else until you know whether that thing \nwill be rejected.)\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"13025","messageId":"m38xv5r50x.fsf@lugabout.cloos.reno.nv.us","threadId":"2698","inReplyTo":"7vbr051ad1.fsf@assigned-by-dhcp.cox.net","subject":"Re: keeping remote repo checked out?","fromName":"James Cloos","fromEmail":"cloos@jhcloos.com","sentAt":"2005-12-01T01:15:58Z","receivedAt":"2005-12-01T01:15:58Z","isPatch":false,"sender":{"key":"cloos@jhcloos.com","avatar":"https://gravatar.com/avatar/ec9a05787d29afe41e243e4b60bd0e2f69d757688e8f0bfe5e78bc185a3e317f?d=mp&s=160"},"body":">>>>> \"Junio\" == Junio C Hamano <junkio@cox.net> writes:\n\nJunio> Creative use of hooks/post-update would solve that.\n\nI'll have to look into that.\n\nJunio> However, you should be very careful if you sometimes edit on\nJunio> server and sometimes push from other machine to the server on\nJunio> the same branch on the server.\n\nI always pull before editing on the laptop....\n\nThanks,\n\n-JimC\n-- \nJames H. Cloos, Jr. <cloos@jhcloos.com>\n"},{"id":"13026","messageId":"7vacflmta9.fsf@assigned-by-dhcp.cox.net","threadId":"2698","inReplyTo":"m38xv5r50x.fsf@lugabout.cloos.reno.nv.us","subject":"Re: keeping remote repo checked out?","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-12-01T02:43:10Z","receivedAt":"2005-12-01T02:43:10Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"James Cloos <cloos@jhcloos.com> writes:\n\n>>>>>> \"Junio\" == Junio C Hamano <junkio@cox.net> writes:\n>\n> Junio> Creative use of hooks/post-update would solve that.\n>\n> I'll have to look into that.\n\nDocumentation/howto/rebuild-from-update-hook.txt may help.\n\nI push into the master repository, and its post-update hook\nchecks out the updated \"master\" head to rebuild the HTML\ndocumentation that is shown at\n\n\thttp://kernel.org/pub/software/scm/git/docs/\n\nThe checkout happens not in the master repository but in a\nseparate repository by pulling into the latter, since the master\nis a naked repository without a working tree associated with it.\n"}]}