{"thread":{"id":"12821","subject":"[PATCH 1/2] Introduce receive.guardCurrentBranch","startedAt":"2008-03-23T20:43:43Z","lastAt":"2008-03-24T22:31:34Z","messageCount":11,"participants":["Johannes Schindelin","Junio C Hamano","Miklos Vajna","Daniel Barkalow"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"72808","messageId":"alpine.LSU.1.00.0803232142460.4353@racer.site","threadId":"12821","inReplyTo":null,"subject":"[PATCH 1/2] Introduce receive.guardCurrentBranch","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-23T20:43:43Z","receivedAt":"2008-03-23T20:43:43Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nSetting this config variable to \"true\" makes git-receive-pack refuse\nto update whatever happens to be the current branch.\n\nThis option can be used to avoid havoc in a non-bare repository into\nwhich somebody pushes.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tI thought about this a while (see also\n\thttp://thread.gmane.org/gmane.comp.version-control.git/66490),\n\tand I think it is time to push for this change.\n\n\tOn the one hand, of course, it is nice to have so many users\n\tthat not all of them know the Git source intimately.  On the\n\tother hand, we will have to introduce many more safeguards\n\tlike this now.  Sigh...\n\n\tMaybe this is even 1.5.5 material.  I'm undecided.\n\n Documentation/config.txt           |    5 +++++\n Documentation/git-receive-pack.txt |    3 +++\n receive-pack.c                     |   18 ++++++++++++++++++\n t/t5400-send-pack.sh               |   13 +++++++++++++\n 4 files changed, 39 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 5df8ea9..efde54d 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -1006,6 +1006,11 @@ receive.denyNonFastForwards::\n \teven if that push is forced. This configuration variable is\n \tset when initializing a shared repository.\n \n+receive.guardCurrentBranch::\n+\tIf set to true, git-receive-pack will deny to update the ref that\n+\tHEAD points to, if HEAD is not detached.  This configuration\n+\tvariable is set when initializing a non-bare repository.\n+\n transfer.unpackLimit::\n \tWhen `fetch.unpackLimit` or `receive.unpackLimit` are\n \tnot set, the value of this variable is used instead.\ndiff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt\nindex 4111434..0c82af9 100644\n--- a/Documentation/git-receive-pack.txt\n+++ b/Documentation/git-receive-pack.txt\n@@ -32,6 +32,9 @@ git-receive-pack honours the receive.denyNonFastForwards config\n option, which tells it if updates to a ref should be denied if they\n are not fast-forwards.\n \n+git-receive-pack honors the receive.guardCurrentBranch config options,\n+which tells it if it is okay to update the branch HEAD points to.\n+\n OPTIONS\n -------\n <directory>::\ndiff --git a/receive-pack.c b/receive-pack.c\nindex 828d490..6423c7c 100644\n--- a/receive-pack.c\n+++ b/receive-pack.c\n@@ -15,6 +15,7 @@ static int receive_unpack_limit = -1;\n static int transfer_unpack_limit = -1;\n static int unpack_limit = 100;\n static int report_status;\n+static char *guard_current_branch;\n \n static char capabilities[] = \" report-status delete-refs \";\n static int capabilities_sent;\n@@ -41,6 +42,19 @@ static int receive_pack_config(const char *var, const char *value)\n \t\treturn 0;\n \t}\n \n+\tif (strcmp(var, \"receive.guardhead\") == 0) {\n+\t\tguard_current_branch = NULL;\n+\t\tif (git_config_bool(var, value)) {\n+\t\t\tunsigned char sha1[20];\n+\t\t\tint flag;\n+\t\t\tconst char *head = resolve_ref(\"HEAD\", sha1, 0, &flag);\n+\t\t\tif (flag & REF_ISSYMREF)\n+\t\t\t\tguard_current_branch = xstrdup(head);\n+\t\t}\n+\n+\t\treturn 0;\n+\t}\n+\n \treturn git_default_config(var, value);\n }\n \n@@ -183,6 +197,10 @@ static const char *update(struct command *cmd)\n \t\t      \"but I can't find it!\", sha1_to_hex(new_sha1));\n \t\treturn \"bad pack\";\n \t}\n+\tif (guard_current_branch && !strcmp(name, guard_current_branch)) {\n+\t\terror(\"refusing to update current branch: '%s'\", name);\n+\t\treturn \"current branch\";\n+\t}\n \tif (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&\n \t    !is_null_sha1(old_sha1) &&\n \t    !prefixcmp(name, \"refs/heads/\")) {\ndiff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh\nindex 2b6b6e3..af8d5a3 100755\n--- a/t/t5400-send-pack.sh\n+++ b/t/t5400-send-pack.sh\n@@ -171,4 +171,17 @@ test_expect_success \\\n \trewound_push_succeeded\n '\n \n+test_expect_success 'receive.guardCurrentBranch' '\n+\n+\trewound_push_setup &&\n+\t(cd ../parent &&\n+\t git config receive.guardCurrentBranch true) &&\n+\ttest_must_fail git-send-pack ../parent/.git refs/heads/master &&\n+\trewound_push_failed &&\n+\t(cd ../parent &&\n+\t git config receive.guardCurrentBranch false) &&\n+\tgit-send-pack ../parent/.git +refs/heads/*:refs/heads/* &&\n+\trewound_push_succeeded\n+'\n+\n test_done\n-- \n1.5.5.rc1.174.g591a9\n"},{"id":"72809","messageId":"alpine.LSU.1.00.0803232144070.4353@racer.site","threadId":"12821","inReplyTo":"alpine.LSU.1.00.0803232142460.4353@racer.site","subject":"[PATCH 2/2] git-init: set receive.guardCurrentBranch = true for non-bare repositories","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-23T20:44:20Z","receivedAt":"2008-03-23T20:44:20Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nWhen initializing a non-bare repositories, you most likely want to avoid\npushing into the current branch (because a push does not touch the\nworking tree at all).\n\nLet's be nice to those users who have not read that part of the\nmanual, and just outright refuse updating the current branch.\n\nTo be nice to those users who wrote that part of the manual, let's do\nthat in git-init, so that existing repositories are not affected.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n Documentation/git-init.txt |    4 ++++\n builtin-init-db.c          |    1 +\n 2 files changed, 5 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/git-init.txt b/Documentation/git-init.txt\nindex 62914da..03a4f0e 100644\n--- a/Documentation/git-init.txt\n+++ b/Documentation/git-init.txt\n@@ -56,6 +56,10 @@ By default, the configuration flag receive.denyNonFastForwards is enabled\n in shared repositories, so that you cannot force a non fast-forwarding push\n into it.\n \n+If you are initializing a non-bare repository, the config variable\n+`receive.guardCurrentBranch` is set to true.  This avoids problems with\n+pushing into the current branch, which does not touch the working tree.\n+\n --\n \n \ndiff --git a/builtin-init-db.c b/builtin-init-db.c\nindex 4f93d03..4542054 100644\n--- a/builtin-init-db.c\n+++ b/builtin-init-db.c\n@@ -243,6 +243,7 @@ static int create_default_files(const char *template_path)\n \telse {\n \t\tconst char *work_tree = get_git_work_tree();\n \t\tgit_config_set(\"core.bare\", \"false\");\n+\t\tgit_config_set(\"receive.guardCurrentBranch\", \"true\");\n \t\t/* allow template config file to override the default */\n \t\tif (log_all_ref_updates == -1)\n \t\t    git_config_set(\"core.logallrefupdates\", \"true\");\n-- \n1.5.5.rc1.174.g591a9\n"},{"id":"72835","messageId":"7v4pax3r6l.fsf@gitster.siamese.dyndns.org","threadId":"12821","inReplyTo":"alpine.LSU.1.00.0803232144070.4353@racer.site","subject":"Re: [PATCH 2/2] git-init: set receive.guardCurrentBranch = true for non-bare repositories","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-24T00:24:02Z","receivedAt":"2008-03-24T00:24:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> When initializing a non-bare repositories, you most likely want to avoid\n> pushing into the current branch (because a push does not touch the\n> working tree at all).\n\nAs I described in my other message, I suspect that treating the current\nbranch specially like this is a wrong approach.  The configuration might\nbe a good idea, but shouldn't it prevent any local branch from getting\nupdated?  Push into non-bare repository is simply a fetch run in reverse\ndirection.\n"},{"id":"72839","messageId":"20080324012139.GV14567@genesis.frugalware.org","threadId":"12821","inReplyTo":"alpine.LSU.1.00.0803232142460.4353@racer.site","subject":"Re: [PATCH 1/2] Introduce receive.guardCurrentBranch","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2008-03-24T01:21:39Z","receivedAt":"2008-03-24T01:21:39Z","isPatch":true,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"On Sun, Mar 23, 2008 at 09:43:43PM +0100, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> +receive.guardCurrentBranch::\n> +\tIf set to true, git-receive-pack will deny to update the ref that\n> +\tHEAD points to, if HEAD is not detached.  This configuration\n> +\tvariable is set when initializing a non-bare repository.\n\nprobably i want too much, but it would be really nice if receive-pack\ncould just make HEAD detached. so that the user later can do a 'git\ncheckout -m master' to resolve possible conflicts.\n"},{"id":"72873","messageId":"alpine.LSU.1.00.0803241158301.4353@racer.site","threadId":"12821","inReplyTo":"7v4pax3r6l.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 2/2] git-init: set receive.guardCurrentBranch = true for non-bare repositories","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-24T11:00:25Z","receivedAt":"2008-03-24T11:00:25Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 23 Mar 2008, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > When initializing a non-bare repositories, you most likely want to \n> > avoid pushing into the current branch (because a push does not touch \n> > the working tree at all).\n> \n> As I described in my other message, I suspect that treating the current \n> branch specially like this is a wrong approach.  The configuration might \n> be a good idea, but shouldn't it prevent any local branch from getting \n> updated?  Push into non-bare repository is simply a fetch run in reverse \n> direction.\n\nThat would break this work flow:\n\n\t# machine A\n\t$ git push B master:refs/heads/tmp\n\n\t# machine B\n\t$ git merge tmp\n\t$ git branch -d tmp\n\nBesides, there is a _vital_ difference between the current branch, and any \nother local branch: pushing into other local branches cannot make your \nworking tree stale.\n\nCiao,\nDscho\n"},{"id":"72874","messageId":"alpine.LSU.1.00.0803241200560.4353@racer.site","threadId":"12821","inReplyTo":"20080324012139.GV14567@genesis.frugalware.org","subject":"Re: [PATCH 1/2] Introduce receive.guardCurrentBranch","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-24T11:01:33Z","receivedAt":"2008-03-24T11:01:33Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 24 Mar 2008, Miklos Vajna wrote:\n\n> On Sun, Mar 23, 2008 at 09:43:43PM +0100, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> > +receive.guardCurrentBranch::\n> > +\tIf set to true, git-receive-pack will deny to update the ref that\n> > +\tHEAD points to, if HEAD is not detached.  This configuration\n> > +\tvariable is set when initializing a non-bare repository.\n> \n> probably i want too much, but it would be really nice if receive-pack \n> could just make HEAD detached. so that the user later can do a 'git \n> checkout -m master' to resolve possible conflicts.\n\nAs I wrote earlier, you can do that with a hook.\n\nI do not want any official support for this, since I think it is an \nabsolutely horrible idea.  I think I said that earlier, too.\n\nCiao,\nDscho\n"},{"id":"72892","messageId":"20080324141009.GB14567@genesis.frugalware.org","threadId":"12821","inReplyTo":"alpine.LSU.1.00.0803241200560.4353@racer.site","subject":"Re: [PATCH 1/2] Introduce receive.guardCurrentBranch","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2008-03-24T14:10:09Z","receivedAt":"2008-03-24T14:10:09Z","isPatch":true,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"On Mon, Mar 24, 2008 at 12:01:33PM +0100, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> As I wrote earlier, you can do that with a hook.\n> \n> I do not want any official support for this, since I think it is an \n> absolutely horrible idea.  I think I said that earlier, too.\n\nhm that makes sense. thanks for mentioning that it's possible via hooks,\nin the \"i know what i'm doing\" case :)\n"},{"id":"72915","messageId":"7v4pawvzgg.fsf@gitster.siamese.dyndns.org","threadId":"12821","inReplyTo":"alpine.LSU.1.00.0803241158301.4353@racer.site","subject":"Re: [PATCH 2/2] git-init: set receive.guardCurrentBranch = true for non-bare repositories","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-24T16:50:07Z","receivedAt":"2008-03-24T16:50:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> On Sun, 23 Mar 2008, Junio C Hamano wrote:\n> ...\n>> As I described in my other message, I suspect that treating the current \n>> branch specially like this is a wrong approach.  The configuration might \n>> be a good idea, but shouldn't it prevent any local branch from getting \n>> updated?  Push into non-bare repository is simply a fetch run in reverse \n>> direction.\n>\n> That would break this work flow:\n>\n> \t# machine A\n> \t$ git push B master:refs/heads/tmp\n>\n> \t# machine B\n> \t$ git merge tmp\n> \t$ git branch -d tmp\n\nI am afraid that the above is irrelevant.\n\n(1) You can push the temporary into anywhere outside refs/heads/ if that\n    becomes the problem;\n\n(2) Your change to forbid current branch already \"breaks\" another workflow\n    (which I happen to use everyday) anyway:\n\n\t# machine A (primary development repository)\n        $ git push k.org ;# master->master, next->next, ...\n\n        # machine B (build test repository)\n        $ git reset --hard\n        $ for b in master maint next pu\n          do git checkout $b && make clean test || break\n\t  done\n\n(3) Because the proposed new feature is dependent on a configuration, both\n    of the above can be \"worked around\" equally easily by disabling it.\n\n> Besides, there is a _vital_ difference between the current branch,...\n\nActually that is exactly I used to think until I realized how flawed that\nline of reasoning was.\n\nSuppose you started treating the current branch any specially.  A few\nissues immediately arise:\n\n * \"I can update any other branches, but git rejected my push saying it\n   does not want to update the current branch. why?\"\n\n * \"how do I know what branch is checked out currently over there to work\n   around this limitation?\"\n\n * \"more importantly, how would I fix this?  do I ask the repository owner\n   to check out different branch?\"\n\nThe process of coming up with answers to these questions made me realize\nthat treating the current branch specially was just a hack to work around\nonly immediately observable effects of pushing into a live repository, and\nnot solving the real issue.  IOW, any of the answers I came up with\nsounded like lame excuses.\n\nStep back a bit and think _why_ you wanted to prevent current branch tip\nfrom getting updated in the first place.  There are two issues:\n\n * Why is it _current_ branch, and not _these branches_, that can be\n   configured by the user to be protected from a push from sideways?\n\n * Why is it undesirable for the work tree and the index to go out of sync\n   with respect to the branch tip to begin with?\n\nThe latter is simpler to answer, so let's deal with it first.  The reason\nwhy it is bad is because allowing a push to the current branch interferes\nwith the work actively being done in the repository, using the work tree\ncontents.  There is a person, you, who is actively editing the work tree\nin order to advance the tip of the branch by making commits.  If the\nbranch tip moves without your knowing, that destabilizes your working\nenvironment.  Your work tree wanted to make a new commit on top of some\nknown state, but that state was moved underneath you.  Not good.\n\nWhen you are using the repository for real work (i.e. advance the tips of\nits branches), you want a stable environment.  You do not want its HEAD\nbobbing around outside your control, and silently detaching to cause your\nlater commits to go to unnamed branch without your knowing is just as bad\n(which you already correctly objected to).\n\nNow think.  What if one of these operations you do in the repository to\nadvance the tip was to merge from one of _your_ local branches?  Yes, you\nend up merging something you did not expect to merge if you allowed a push\nfrom sideways to affect that local branch, only because the branch\nhappened to be un-checked-out and you implemented this protection to\nforbid only to current branch.  Allowing a push from sideways to any local\nbranch destabilizes your work environment, not just the current one.\n\nThe former question becomes easier to answer once you realize this.  It\nwas only because you were too narrowly focused on the immediately visible\neffect of pushing into a live repository, and that is apparent in your\n\"there is a _vital_ difference\" statement (again, I used to think the same\nway, so it is not just you).  The difference is not _vital_ at all.  It\nmerely is being immediately observable.  The stability of the environment\nyou do real work in is more than just the branch currently checked out.\nAt least you would want \"I do not want these refs to silently change\nwithout me knowing\".\n\nPushing to non-bare repository can happen in number of ways, and there are\na few _useful_ use cases to push into local branches of a live repository,\nbut the sane usage that allows such push has one common precondition: No\ninteresting edit is ever outstanding in the non-bare repository when push\nhappens.\n\nFor example, you could have a repository and its checkout of html branch\nof git.git, and serve the former via dumb protocol for git-fetch clients,\nwhile the latter is fed directly to web browsers.  Even if you push into\nits html branch (that is checked out), you would not suffer, as _you\nalready know what you are doing_ and that is the reason you can even\narrange its post-update hook to run \"reset --hard\" for you.\n\nThe earlier \"build test repository\" example is the same way.  I might have\nto debug problems that only manifest on the k.org machine, so it is unlike\nI am forbidden from doing any \"interesting edits\" there, but when I do a\npush from the primary machine, I know I am done with any edit on the k.org\nrepository (otherwise I'd still be logged in and working there, not\npushing from home), so I am sure \"reset --hard\" is safe and good.\n\nThese use cases share the precondition \"no interesting edit is ever\noutstanding\".  But it is just an extension of a more general idea: Usually\nnobody works in the work tree to advance its branches with commits made\nthere.  Instead, advancement of its branches always happen by push from\nelsewhere.\n\nIf a real person works in the work tree, the story is different.  There\nneeds a boundary that defines his stable working environment that should\nnot be disrupted by a push from sideways.  You _could_ define it as \"the\ncurrently checked out branch, the index and the work tree\".  I think it is\ntoo narrow.  We could allow the user to define \"this subset of local\nbranches\", but I think it is one too many knob to tweak, and a reasonable\nboundary is to define the boundary to include \"local branches\" into that\nset, as they are also the ones you would update with the regular working\ninside that work tree (i.e. checkout-hack-commit cycle).\n\nIn such a live repository, treating \"git push\" initiated from elsewhere\ninto it exactly the same way \"git fetch\" initiated in the repository in\nthe reverse direction would be the cleanest way to explain a non-confusing\nworkflow to the end users.  You are always in control of all of your local\nbranches, and you decide when to merge the tip of such a pushed-in ref\n(this is the mothership-satellite configuration suggested in the FAQ entry\nmentioned in the other thread).\n\nI am not married to the idea of using refs/remotes/* for that purpose, and\nit might turn out to be a good idea to have more elaborate setup, for\nexample, using refs/pushed/<branch-name>/ hierarchy to keep other's pushed\nrefs in there.  But one thing I am reasonably sure is that pushes should\nnot go to refs/heads/ directly whether the branch is checked out or not,\nif the user of that pushed-into live repository wants to keep his sanity.\n"},{"id":"72918","messageId":"alpine.LSU.1.00.0803241807210.4353@racer.site","threadId":"12821","inReplyTo":"7v4pawvzgg.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 2/2] git-init: set receive.guardCurrentBranch = true for non-bare repositories","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-24T17:10:38Z","receivedAt":"2008-03-24T17:10:38Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 24 Mar 2008, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > On Sun, 23 Mar 2008, Junio C Hamano wrote:\n> > ...\n> >> As I described in my other message, I suspect that treating the \n> >> current branch specially like this is a wrong approach.  The \n> >> configuration might be a good idea, but shouldn't it prevent any \n> >> local branch from getting updated?  Push into non-bare repository is \n> >> simply a fetch run in reverse direction.\n> >\n> > That would break this work flow:\n> >\n> > \t# machine A\n> > \t$ git push B master:refs/heads/tmp\n> >\n> > \t# machine B\n> > \t$ git merge tmp\n> > \t$ git branch -d tmp\n> \n> I am afraid that the above is irrelevant.\n> \n> (1) You can push the temporary into anywhere outside refs/heads/ if that\n>     becomes the problem;\n\nOkay, didn't think about that one.\n\n> (2) Your change to forbid current branch already \"breaks\" another workflow\n>     (which I happen to use everyday) anyway:\n> \n> \t# machine A (primary development repository)\n>         $ git push k.org ;# master->master, next->next, ...\n> \n>         # machine B (build test repository)\n>         $ git reset --hard\n>         $ for b in master maint next pu\n>           do git checkout $b && make clean test || break\n> \t  done\n\nIt would not, because it is not activated by default.  Only newly \ninitialised repositories will have that config variable set.\n\n> > Besides, there is a _vital_ difference between the current branch,...\n> \n> [...]\n>\n> Now think.  What if one of these operations you do in the repository to \n> advance the tip was to merge from one of _your_ local branches?  Yes, \n> you end up merging something you did not expect to merge if you allowed \n> a push from sideways to affect that local branch, only because the \n> branch happened to be un-checked-out and you implemented this protection \n> to forbid only to current branch.  Allowing a push from sideways to any \n> local branch destabilizes your work environment, not just the current \n> one.\n\nOkay, I am starting to see the light.\n\nHow about\n\n\treceive.localBranches = (refuse | allow)\n\nwith a default \"allow\"?  Then we could add more rope later with the \n\"update\" option, which would run \"git read-tree -u -m HEAD\" if the current \nbranch is updated, and simply allow all other branches being updated.\n\nHmm?\n\nCiao,\nDscho\n"},{"id":"72959","messageId":"alpine.LNX.1.00.0803241714520.19665@iabervon.org","threadId":"12821","inReplyTo":"alpine.LSU.1.00.0803241807210.4353@racer.site","subject":"Re: [PATCH 2/2] git-init: set receive.guardCurrentBranch = true for non-bare repositories","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2008-03-24T22:08:08Z","receivedAt":"2008-03-24T22:08:08Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Mon, 24 Mar 2008, Johannes Schindelin wrote:\n\n> Hi,\n> \n> On Mon, 24 Mar 2008, Junio C Hamano wrote:\n> \n> > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> > \n> > > On Sun, 23 Mar 2008, Junio C Hamano wrote:\n> > > ...\n> > >> As I described in my other message, I suspect that treating the \n> > >> current branch specially like this is a wrong approach.  The \n> > >> configuration might be a good idea, but shouldn't it prevent any \n> > >> local branch from getting updated?  Push into non-bare repository is \n> > >> simply a fetch run in reverse direction.\n> > >\n> > > That would break this work flow:\n> > >\n> > > \t# machine A\n> > > \t$ git push B master:refs/heads/tmp\n> > >\n> > > \t# machine B\n> > > \t$ git merge tmp\n> > > \t$ git branch -d tmp\n> > \n> > I am afraid that the above is irrelevant.\n> > \n> > (1) You can push the temporary into anywhere outside refs/heads/ if that\n> >     becomes the problem;\n> \n> Okay, didn't think about that one.\n> \n> > (2) Your change to forbid current branch already \"breaks\" another workflow\n> >     (which I happen to use everyday) anyway:\n> > \n> > \t# machine A (primary development repository)\n> >         $ git push k.org ;# master->master, next->next, ...\n> > \n> >         # machine B (build test repository)\n> >         $ git reset --hard\n> >         $ for b in master maint next pu\n> >           do git checkout $b && make clean test || break\n> > \t  done\n> \n> It would not, because it is not activated by default.  Only newly \n> initialised repositories will have that config variable set.\n> \n> > > Besides, there is a _vital_ difference between the current branch,...\n> > \n> > [...]\n> >\n> > Now think.  What if one of these operations you do in the repository to \n> > advance the tip was to merge from one of _your_ local branches?  Yes, \n> > you end up merging something you did not expect to merge if you allowed \n> > a push from sideways to affect that local branch, only because the \n> > branch happened to be un-checked-out and you implemented this protection \n> > to forbid only to current branch.  Allowing a push from sideways to any \n> > local branch destabilizes your work environment, not just the current \n> > one.\n> \n> Okay, I am starting to see the light.\n> \n> How about\n> \n> \treceive.localBranches = (refuse | allow)\n> \n> with a default \"allow\"?  Then we could add more rope later with the \n> \"update\" option, which would run \"git read-tree -u -m HEAD\" if the current \n> branch is updated, and simply allow all other branches being updated.\n\nThe use cases I've seen for pushing into a non-bare repository seem to be \ncases in which \"refs/heads/\" isn't really local; it's only updated by push \nfrom elsewhere, and it's named \"refs/heads/\" because that's where public \nbranches are served from. This suggests we could have:\n\n\tcore.noLocalBranches: true\n\nwith the implications:\n\n - it's definitely okay to push to refs/heads/\n - HEAD is always detached.\n\nThat seems to me to accurately describe a repository used to hold branches \nfor public consumption and where there's a work tree for testing and \nbuilding, rather than development. (I.e., work tree operations only read \nthe repository.)\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"72964","messageId":"alpine.LSU.1.00.0803242329550.4353@racer.site","threadId":"12821","inReplyTo":"alpine.LNX.1.00.0803241714520.19665@iabervon.org","subject":"Re: [PATCH 2/2] git-init: set receive.guardCurrentBranch = true for non-bare repositories","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-03-24T22:31:34Z","receivedAt":"2008-03-24T22:31:34Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 24 Mar 2008, Daniel Barkalow wrote:\n\n> On Mon, 24 Mar 2008, Johannes Schindelin wrote:\n> \n> > How about\n> > \n> > \treceive.localBranches = (refuse | allow)\n> > \n> > with a default \"allow\"?  Then we could add more rope later with the \n> > \"update\" option, which would run \"git read-tree -u -m HEAD\" if the \n> > current branch is updated, and simply allow all other branches being \n> > updated.\n> \n> The use cases I've seen for pushing into a non-bare repository seem to \n> be cases in which \"refs/heads/\" isn't really local; it's only updated by \n> push from elsewhere, and it's named \"refs/heads/\" because that's where \n> public branches are served from. This suggests we could have:\n> \n> \tcore.noLocalBranches: true\n> \n> with the implications:\n> \n>  - it's definitely okay to push to refs/heads/\n>  - HEAD is always detached.\n> \n> That seems to me to accurately describe a repository used to hold \n> branches for public consumption and where there's a work tree for \n> testing and building, rather than development. (I.e., work tree \n> operations only read the repository.)\n\nFunny.  I thought bare repositories were meant for public consumption.  \nAnd for testing, you still can have a (non-public) repository with a \nwork-tree.\n\nI'd rather not try to tell users that it is okay to mix the two.\n\nCiao,\nDscho\n"}]}