{"thread":{"id":"16215","subject":"[RFC PATCH 0/4] deny push to current branch of non-bare repo","startedAt":"2008-11-07T22:07:30Z","lastAt":"2008-12-02T03:08:01Z","messageCount":25,"participants":["Jeff King","Mark Burton","Junio C Hamano","Johannes Schindelin","Jan Krüger","Kyle Moffett","Leo Razoumov"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"95152","messageId":"20081107220730.GA15942@coredump.intra.peff.net","threadId":"16215","inReplyTo":null,"subject":"[RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-11-07T22:07:30Z","receivedAt":"2008-11-07T22:07:30Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"The short of it is that it's dangerous, we see people confused by it\n(there was another one just yesterday), and it's a FAQ:\n\n  http://git.or.cz/gitwiki/GitFaq#head-b96f48bc9c925074be9f95c0fce69bcece5f6e73\n\nThe FAQ even says \"don't do this until you know what you are doing.\" So\nthe safety valve is configurable, so that those who know what they are\ndoing can switch it off.\n\nAnd it's even on Sam's \"UI improvements\" list. :)\n\nPatch 4/4 is the interesting one. 1/4 is a cleanup I saw while fixing\ntests. 2/4 is a cleanup to prepare for 3/4. And 3/4 fixes a bunch of\ntests which were inadvertently doing such a push (but didn't care\nbecause they didn't look at the working directory).\n\n-Peff\n"},{"id":"95161","messageId":"20081107220955.GA16058@coredump.intra.peff.net","threadId":"16215","inReplyTo":"20081107220730.GA15942@coredump.intra.peff.net","subject":"[PATCH 1/4] t5400: expect success for denying deletion","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-11-07T22:09:55Z","receivedAt":"2008-11-07T22:09:55Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Commit a240de11 introduced this test and the code to make it\nsuccessful.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nReading over the mailing list postings which led to a240de11, I think it\nis simply a case that Jan didn't fully understand what expect_failure\nmeant (it means \"this is a test that is currently broken, but we hope to\nfix in the future\", and not anything to do with the test_must_fail in\nthe test itself).\n\n t/t5400-send-pack.sh |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh\nindex 6fe2f87..da69f08 100755\n--- a/t/t5400-send-pack.sh\n+++ b/t/t5400-send-pack.sh\n@@ -103,7 +103,7 @@ unset GIT_CONFIG GIT_CONFIG_LOCAL\n HOME=`pwd`/no-such-directory\n export HOME ;# this way we force the victim/.git/config to be used.\n \n-test_expect_failure \\\n+test_expect_success \\\n \t'pushing a delete should be denied with denyDeletes' '\n \tcd victim &&\n \tgit config receive.denyDeletes true &&\n-- \n1.6.0.3.866.gc189b\n"},{"id":"95162","messageId":"20081107222033.GB16058@coredump.intra.peff.net","threadId":"16215","inReplyTo":"20081107220730.GA15942@coredump.intra.peff.net","subject":"[PATCH 2/4] t5516: refactor oddball tests","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-11-07T22:20:33Z","receivedAt":"2008-11-07T22:20:33Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"t5516 sets up some utility functions for starting each test\nwith a clean slate. However, there were a few tests added\nthat do not use these functions, but instead make their own\nrepositories.\n\nLet's bring these in line with the rest of the tests. Not\nonly do we reduce the number of lines, but these tests will\nbenefit from any further enhancements to the utility\nscripts.\n\nThe conversion is pretty straightforward. Most of the tests\ncreated a parent/child clone relationship, for which we now\nuse 'testrepo' as the parent.  One test looked in testrepo,\nbut relied on previous tests to have set it up; it now sets\nup testrepo explicitly, which makes it a bit more robust to\nchanges in the script, as well.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nThis is on top of 'next' to pick up the recent test from Clemens\nBuchacher.\n\nA few oddities here while I was digging in the history:\n\n  - I actually introduced the first of these tests for local tracking\n    refs in 09fba7a59 (and the others, being related, copied the style).\n    But then I reverted them in 0673c96, because Alex had added other\n    similar tests in t5404.  However, these tests ended up being\n    re-added by Dscho in 28391a80, which adds a totally unrelated test.\n    I think it's the result of a bad patch application (IIRC, he marked\n    up my tests to avoid having them chdir for the whole test script.\n    During application, Junio would see them going from tweaks to whole\n    creation, and presumably just resolved the conflict that way).\n\n    So my initial thought was to simply delete these tests. But since\n    then, other related tests have been added to this script, and we do\n    want to keep those. So I decided to keep them all, as they form a\n    logical progression related to tracking refs. So while there is some\n    duplication with t5404, I don't think it is a problem.\n\n  - One of the tests called 'pwd', and I can't see that it would do\n    anything useful. I assume it was just leftover debugging cruft\n    (especially since it is from that same commit by Dscho).\n\n t/t5516-fetch-push.sh |   50 ++++++++++++++++++++----------------------------\n 1 files changed, 21 insertions(+), 29 deletions(-)\n\ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex 598664c..3411107 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -39,6 +39,11 @@ mk_test () {\n \t)\n }\n \n+mk_child() {\n+\trm -rf \"$1\" &&\n+\tgit clone testrepo \"$1\"\n+}\n+\n check_push_result () {\n \t(\n \t\tcd testrepo &&\n@@ -425,13 +430,10 @@ test_expect_success 'push with dry-run' '\n \n test_expect_success 'push updates local refs' '\n \n-\trm -rf parent child &&\n-\tmkdir parent &&\n-\t(cd parent && git init &&\n-\t\techo one >foo && git add foo && git commit -m one) &&\n-\tgit clone parent child &&\n+\tmk_test heads/master &&\n+\tmk_child child &&\n \t(cd child &&\n-\t\techo two >foo && git commit -a -m two &&\n+\t\tgit pull .. master &&\n \t\tgit push &&\n \ttest $(git rev-parse master) = $(git rev-parse remotes/origin/master))\n \n@@ -439,15 +441,10 @@ test_expect_success 'push updates local refs' '\n \n test_expect_success 'push updates up-to-date local refs' '\n \n-\trm -rf parent child &&\n-\tmkdir parent &&\n-\t(cd parent && git init &&\n-\t\techo one >foo && git add foo && git commit -m one) &&\n-\tgit clone parent child1 &&\n-\tgit clone parent child2 &&\n-\t(cd child1 &&\n-\t\techo two >foo && git commit -a -m two &&\n-\t\tgit push) &&\n+\tmk_test heads/master &&\n+\tmk_child child1 &&\n+\tmk_child child2 &&\n+\t(cd child1 && git pull .. master && git push) &&\n \t(cd child2 &&\n \t\tgit pull ../child1 master &&\n \t\tgit push &&\n@@ -457,11 +454,8 @@ test_expect_success 'push updates up-to-date local refs' '\n \n test_expect_success 'push preserves up-to-date packed refs' '\n \n-\trm -rf parent child &&\n-\tmkdir parent &&\n-\t(cd parent && git init &&\n-\t\techo one >foo && git add foo && git commit -m one) &&\n-\tgit clone parent child &&\n+\tmk_test heads/master &&\n+\tmk_child child &&\n \t(cd child &&\n \t\tgit push &&\n \t! test -f .git/refs/remotes/origin/master)\n@@ -470,15 +464,13 @@ test_expect_success 'push preserves up-to-date packed refs' '\n \n test_expect_success 'push does not update local refs on failure' '\n \n-\trm -rf parent child &&\n-\tmkdir parent &&\n-\t(cd parent && git init &&\n-\t\techo one >foo && git add foo && git commit -m one &&\n-\t\techo exit 1 >.git/hooks/pre-receive &&\n-\t\tchmod +x .git/hooks/pre-receive) &&\n-\tgit clone parent child &&\n+\tmk_test heads/master &&\n+\tmk_child child &&\n+\tmkdir testrepo/.git/hooks &&\n+\techo exit 1 >testrepo/.git/hooks/pre-receive &&\n+\tchmod +x testrepo/.git/hooks/pre-receive &&\n \t(cd child &&\n-\t\techo two >foo && git commit -a -m two &&\n+\t\tgit pull .. master\n \t\ttest_must_fail git push &&\n \t\ttest $(git rev-parse master) != \\\n \t\t\t$(git rev-parse remotes/origin/master))\n@@ -487,7 +479,7 @@ test_expect_success 'push does not update local refs on failure' '\n \n test_expect_success 'allow deleting an invalid remote ref' '\n \n-\tpwd &&\n+\tmk_test heads/master &&\n \trm -f testrepo/.git/objects/??/* &&\n \tgit push testrepo :refs/heads/master &&\n \t(cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)\n-- \n1.6.0.3.866.gc189b\n"},{"id":"95164","messageId":"20081107222241.GC16058@coredump.intra.peff.net","threadId":"16215","inReplyTo":"20081107220730.GA15942@coredump.intra.peff.net","subject":"[PATCH 3/4] tests: avoid pushing to current branch of non-bare repo","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-11-07T22:22:41Z","receivedAt":"2008-11-07T22:22:41Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Many tests create a new repo, and then push into the master\nbranch (sometimes after making some commits on that branch).\nAfter such a push the index and working tree of the\nreceiving repo are out of sync with the HEAD. This isn't a\nproblem for most tests, since they don't bother looking at\nthe working tree after such a push.  But this is generally a\ndangerous behavior, and the tests would break if we later\ndecided to put in a safety valve.\n\nDepending on the situation, this patch takes one of two\napproaches:\n\n  - creates the pushed-to repo as a bare repository. This\n    works if we don't actually want to create our own\n    commits in the repo.\n\n  - switches the pushed-to repo to another branch before\n    pushing. Since we never look at the working tree after\n    the push anyway, this doesn't impact the test results.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nThis is not the _most_ minimal patch, since when changing a non-bare\nrepo to a bare one, the name of the git dir changed (e.g.,\ns{victim/.git}{victim}), causing a lot of textual changes. We could\ntechnically call the bare clone \"victim/.git\", but I think this is less\nconfusing (if a bit harder to read the diff).\n\n t/t5400-send-pack.sh        |   30 ++++++++++++----------\n t/t5401-update-hooks.sh     |   58 +++++++++++++++++++++---------------------\n t/t5405-send-pack-rewind.sh |    3 +-\n t/t5516-fetch-push.sh       |    3 +-\n t/t5517-push-mirror.sh      |    2 +-\n 5 files changed, 50 insertions(+), 46 deletions(-)\n\ndiff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh\nindex da69f08..6bcb4df 100755\n--- a/t/t5400-send-pack.sh\n+++ b/t/t5400-send-pack.sh\n@@ -31,7 +31,7 @@ test_expect_success setup '\n \t    parent=$commit || return 1\n \tdone &&\n \tgit update-ref HEAD \"$commit\" &&\n-\tgit clone ./. victim &&\n+\tgit clone --bare ./. victim &&\n \tcd victim &&\n \tgit log &&\n \tcd .. &&\n@@ -68,7 +68,7 @@ test_expect_success 'pack the destination repository' '\n test_expect_success \\\n         'pushing rewound head should not barf but require --force' '\n \t# should not fail but refuse to update.\n-\tif git send-pack ./victim/.git/ master\n+\tif git send-pack ./victim/ master\n \tthen\n \t\t# now it should fail with Pasky patch\n \t\techo >&2 Gaah, it should have failed.\n@@ -77,7 +77,7 @@ test_expect_success \\\n \t\techo >&2 Thanks, it correctly failed.\n \t\ttrue\n \tfi &&\n-\tif cmp victim/.git/refs/heads/master .git/refs/heads/master\n+\tif cmp victim/refs/heads/master .git/refs/heads/master\n \tthen\n \t\t# should have been left as it was!\n \t\tfalse\n@@ -85,8 +85,8 @@ test_expect_success \\\n \t\ttrue\n \tfi &&\n \t# this should update\n-\tgit send-pack --force ./victim/.git/ master &&\n-\tcmp victim/.git/refs/heads/master .git/refs/heads/master\n+\tgit send-pack --force ./victim/ master &&\n+\tcmp victim/refs/heads/master .git/refs/heads/master\n '\n \n test_expect_success \\\n@@ -94,14 +94,14 @@ test_expect_success \\\n \tcd victim &&\n \tgit branch extra master &&\n \tcd .. &&\n-\ttest -f victim/.git/refs/heads/extra &&\n-\tgit send-pack ./victim/.git/ :extra master &&\n-\t! test -f victim/.git/refs/heads/extra\n+\ttest -f victim/refs/heads/extra &&\n+\tgit send-pack ./victim/ :extra master &&\n+\t! test -f victim/refs/heads/extra\n '\n \n unset GIT_CONFIG GIT_CONFIG_LOCAL\n HOME=`pwd`/no-such-directory\n-export HOME ;# this way we force the victim/.git/config to be used.\n+export HOME ;# this way we force the victim/config to be used.\n \n test_expect_success \\\n \t'pushing a delete should be denied with denyDeletes' '\n@@ -109,10 +109,10 @@ test_expect_success \\\n \tgit config receive.denyDeletes true &&\n \tgit branch extra master &&\n \tcd .. &&\n-\ttest -f victim/.git/refs/heads/extra &&\n-\ttest_must_fail git send-pack ./victim/.git/ :extra master\n+\ttest -f victim/refs/heads/extra &&\n+\ttest_must_fail git send-pack ./victim/ :extra master\n '\n-rm -f victim/.git/refs/heads/extra\n+rm -f victim/refs/heads/extra\n \n test_expect_success \\\n         'pushing with --force should be denied with denyNonFastforwards' '\n@@ -120,14 +120,15 @@ test_expect_success \\\n \tgit config receive.denyNonFastforwards true &&\n \tcd .. &&\n \tgit update-ref refs/heads/master master^ || return 1\n-\tgit send-pack --force ./victim/.git/ master && return 1\n-\t! test_cmp .git/refs/heads/master victim/.git/refs/heads/master\n+\tgit send-pack --force ./victim/ master && return 1\n+\t! test_cmp .git/refs/heads/master victim/refs/heads/master\n '\n \n test_expect_success \\\n \t'pushing does not include non-head refs' '\n \tmkdir parent && cd parent &&\n \tgit init && touch file && git add file && git commit -m add &&\n+\tgit checkout -b otherbranch &&\n \tcd .. &&\n \tgit clone parent child && cd child && git push --all &&\n \tcd ../parent &&\n@@ -139,6 +140,7 @@ rewound_push_setup() {\n \tmkdir parent && cd parent &&\n \tgit init && echo one >file && git add file && git commit -m one &&\n \techo two >file && git commit -a -m two &&\n+\tgit checkout -b otherbranch\n \tcd .. &&\n \tgit clone parent child && cd child && git reset --hard HEAD^\n }\ndiff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh\nindex 64f66c9..ae1aa77 100755\n--- a/t/t5401-update-hooks.sh\n+++ b/t/t5401-update-hooks.sh\n@@ -17,22 +17,22 @@ test_expect_success setup '\n \tcommit1=$(echo modify | git commit-tree $tree1 -p $commit0) &&\n \tgit update-ref refs/heads/master $commit0 &&\n \tgit update-ref refs/heads/tofail $commit1 &&\n-\tgit clone ./. victim &&\n-\tGIT_DIR=victim/.git git update-ref refs/heads/tofail $commit1 &&\n+\tgit clone --bare ./. victim &&\n+\tGIT_DIR=victim git update-ref refs/heads/tofail $commit1 &&\n \tgit update-ref refs/heads/master $commit1 &&\n \tgit update-ref refs/heads/tofail $commit0\n '\n \n-cat >victim/.git/hooks/pre-receive <<'EOF'\n+cat >victim/hooks/pre-receive <<'EOF'\n #!/bin/sh\n printf %s \"$@\" >>$GIT_DIR/pre-receive.args\n cat - >$GIT_DIR/pre-receive.stdin\n echo STDOUT pre-receive\n echo STDERR pre-receive >&2\n EOF\n-chmod u+x victim/.git/hooks/pre-receive\n+chmod u+x victim/hooks/pre-receive\n \n-cat >victim/.git/hooks/update <<'EOF'\n+cat >victim/hooks/update <<'EOF'\n #!/bin/sh\n echo \"$@\" >>$GIT_DIR/update.args\n read x; printf %s \"$x\" >$GIT_DIR/update.stdin\n@@ -40,77 +40,77 @@ echo STDOUT update $1\n echo STDERR update $1 >&2\n test \"$1\" = refs/heads/master || exit\n EOF\n-chmod u+x victim/.git/hooks/update\n+chmod u+x victim/hooks/update\n \n-cat >victim/.git/hooks/post-receive <<'EOF'\n+cat >victim/hooks/post-receive <<'EOF'\n #!/bin/sh\n printf %s \"$@\" >>$GIT_DIR/post-receive.args\n cat - >$GIT_DIR/post-receive.stdin\n echo STDOUT post-receive\n echo STDERR post-receive >&2\n EOF\n-chmod u+x victim/.git/hooks/post-receive\n+chmod u+x victim/hooks/post-receive\n \n-cat >victim/.git/hooks/post-update <<'EOF'\n+cat >victim/hooks/post-update <<'EOF'\n #!/bin/sh\n echo \"$@\" >>$GIT_DIR/post-update.args\n read x; printf %s \"$x\" >$GIT_DIR/post-update.stdin\n echo STDOUT post-update\n echo STDERR post-update >&2\n EOF\n-chmod u+x victim/.git/hooks/post-update\n+chmod u+x victim/hooks/post-update\n \n test_expect_success push '\n-\ttest_must_fail git send-pack --force ./victim/.git \\\n+\ttest_must_fail git send-pack --force ./victim \\\n \t\tmaster tofail >send.out 2>send.err\n '\n \n test_expect_success 'updated as expected' '\n-\ttest $(GIT_DIR=victim/.git git rev-parse master) = $commit1 &&\n-\ttest $(GIT_DIR=victim/.git git rev-parse tofail) = $commit1\n+\ttest $(GIT_DIR=victim git rev-parse master) = $commit1 &&\n+\ttest $(GIT_DIR=victim git rev-parse tofail) = $commit1\n '\n \n test_expect_success 'hooks ran' '\n-\ttest -f victim/.git/pre-receive.args &&\n-\ttest -f victim/.git/pre-receive.stdin &&\n-\ttest -f victim/.git/update.args &&\n-\ttest -f victim/.git/update.stdin &&\n-\ttest -f victim/.git/post-receive.args &&\n-\ttest -f victim/.git/post-receive.stdin &&\n-\ttest -f victim/.git/post-update.args &&\n-\ttest -f victim/.git/post-update.stdin\n+\ttest -f victim/pre-receive.args &&\n+\ttest -f victim/pre-receive.stdin &&\n+\ttest -f victim/update.args &&\n+\ttest -f victim/update.stdin &&\n+\ttest -f victim/post-receive.args &&\n+\ttest -f victim/post-receive.stdin &&\n+\ttest -f victim/post-update.args &&\n+\ttest -f victim/post-update.stdin\n '\n \n test_expect_success 'pre-receive hook input' '\n \t(echo $commit0 $commit1 refs/heads/master;\n \t echo $commit1 $commit0 refs/heads/tofail\n-\t) | test_cmp - victim/.git/pre-receive.stdin\n+\t) | test_cmp - victim/pre-receive.stdin\n '\n \n test_expect_success 'update hook arguments' '\n \t(echo refs/heads/master $commit0 $commit1;\n \t echo refs/heads/tofail $commit1 $commit0\n-\t) | test_cmp - victim/.git/update.args\n+\t) | test_cmp - victim/update.args\n '\n \n test_expect_success 'post-receive hook input' '\n \techo $commit0 $commit1 refs/heads/master |\n-\ttest_cmp - victim/.git/post-receive.stdin\n+\ttest_cmp - victim/post-receive.stdin\n '\n \n test_expect_success 'post-update hook arguments' '\n \techo refs/heads/master |\n-\ttest_cmp - victim/.git/post-update.args\n+\ttest_cmp - victim/post-update.args\n '\n \n test_expect_success 'all hook stdin is /dev/null' '\n-\t! test -s victim/.git/update.stdin &&\n-\t! test -s victim/.git/post-update.stdin\n+\t! test -s victim/update.stdin &&\n+\t! test -s victim/post-update.stdin\n '\n \n test_expect_success 'all *-receive hook args are empty' '\n-\t! test -s victim/.git/pre-receive.args &&\n-\t! test -s victim/.git/post-receive.args\n+\t! test -s victim/pre-receive.args &&\n+\t! test -s victim/post-receive.args\n '\n \n test_expect_success 'send-pack produced no output' '\ndiff --git a/t/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh\nindex cb9aacc..2ad080f 100755\n--- a/t/t5405-send-pack-rewind.sh\n+++ b/t/t5405-send-pack-rewind.sh\n@@ -16,7 +16,8 @@ test_expect_success setup '\n \t) &&\n \n \t>file2 && git add file2 && test_tick &&\n-\tgit commit -m Second\n+\tgit commit -m Second &&\n+\tgit checkout -b otherbranch\n \n '\n \ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex 3411107..7070171 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -12,7 +12,8 @@ mk_empty () {\n \t(\n \t\tcd testrepo &&\n \t\tgit init &&\n-\t\tmv .git/hooks .git/hooks-disabled\n+\t\tmv .git/hooks .git/hooks-disabled &&\n+\t\tgit symbolic-ref HEAD refs/heads/nonexistent\n \t)\n }\n \ndiff --git a/t/t5517-push-mirror.sh b/t/t5517-push-mirror.sh\nindex ea49ded..5536077 100755\n--- a/t/t5517-push-mirror.sh\n+++ b/t/t5517-push-mirror.sh\n@@ -19,7 +19,7 @@ mk_repo_pair () {\n \tmkdir mirror &&\n \t(\n \t\tcd mirror &&\n-\t\tgit init\n+\t\tgit --bare init\n \t) &&\n \tmkdir master &&\n \t(\n-- \n1.6.0.3.866.gc189b\n"},{"id":"95167","messageId":"20081107222830.GD16058@coredump.intra.peff.net","threadId":"16215","inReplyTo":"20081107220730.GA15942@coredump.intra.peff.net","subject":"[PATCH 4/4] receive-pack: deny push to current branch of non-bare repo","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-11-07T22:28:30Z","receivedAt":"2008-11-07T22:28:30Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Pushing into the currently checked out branch of a non-bare\nrepository can be dangerous; the HEAD then loses sync with\nthe index and working tree, and it looks in the receiving\nrepo as if the pushed changes have been reverted in the\nindex (since they were never there in the first place).\n\nThis patch adds a safety valve that checks for this\ncondition and denies the push. We trigger the check only on\na non-bare repository, since a bare does not have a working\ntree (and in fact, pushing to the HEAD branch is a common\nworkflow for publishing repositories).\n\nThis behavior is still configurable, though, since some very\nspecific setups may want to allow such a push if they know\nthey will take action to reconcile the working tree and HEAD\nafterwards (e.g., a post-receive hook that does \"git reset\n--hard\").\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nMy feeling is that this is dangerous behavior that we see new users\nconfused by, so it is worth addressing. The other obvious route is to\nat least _try_ the merge, and if it comes out cleanly, to allow it.\n\nBut it looks like Sam is promoting that as a hook, which makes a lot\nmore sense to me. And we can still support that, but the user of the\nhook must now not only install the hook, but also set the config value.\n\nI am open to comments on the name of the config value. Somebody at the\nGitTogether suggested (possibly under the influence of beer) that it be\nreceive.PEBKAC (since you should only turn it off if you really know\nwhat you're doing, you would set PEBKAC to \"false\"), but I didn't want\nto give the impression that git wasn't user-friendly. ;)\n\nOne final issue: do we need to make a special exception for \"branch yet\nto be born\"? I believe we do so for the analagous \"fetch\" situation.\n\n Documentation/config.txt |    8 ++++++++\n builtin-receive-pack.c   |   16 ++++++++++++++++\n t/t5516-fetch-push.sh    |   21 +++++++++++++++++++++\n 3 files changed, 45 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 965ed74..971f01e 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -1198,6 +1198,14 @@ receive.denyNonFastForwards::\n \teven if that push is forced. This configuration variable is\n \tset when initializing a shared repository.\n \n+receive.denyCurrentBranch::\n+\tIf set to true, receive-pack will deny a ref update to the\n+\tcurrently checked out branch of a non-bare repository. Such a\n+\tpush is potentially dangerous because it brings the HEAD out of\n+\tsync with the index and working tree; only set this to \"false\"\n+\tif you know what you are doing (e.g., you have a post-receive\n+\thook which resets the working tree). Defaults to \"true\".\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/builtin-receive-pack.c b/builtin-receive-pack.c\nindex 7f9f134..06ad545 100644\n--- a/builtin-receive-pack.c\n+++ b/builtin-receive-pack.c\n@@ -13,6 +13,7 @@ static const char receive_pack_usage[] = \"git-receive-pack <git-dir>\";\n \n static int deny_deletes = 0;\n static int deny_non_fast_forwards = 0;\n+static int deny_current_branch = 1;\n static int receive_fsck_objects;\n static int receive_unpack_limit = -1;\n static int transfer_unpack_limit = -1;\n@@ -49,6 +50,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb)\n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(var, \"receive.denycurrentbranch\")) {\n+\t\tdeny_current_branch = git_config_bool(var, value);\n+\t\treturn 0;\n+\t}\n+\n \treturn git_default_config(var, value, cb);\n }\n \n@@ -186,6 +192,16 @@ static const char *update(struct command *cmd)\n \t\treturn \"funny refname\";\n \t}\n \n+\tif (deny_current_branch && !is_bare_repository()) {\n+\t\tunsigned char sha1[20];\n+\t\tconst char *head = resolve_ref(\"HEAD\", sha1, 0, NULL);\n+\t\tif (!strcmp(head, name)) {\n+\t\t\terror(\"refusing to update checked out branch: %s\",\n+\t\t\t\tname);\n+\t\t\treturn \"branch is currently checked out\";\n+\t\t}\n+\t}\n+\n \tif (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {\n \t\terror(\"unpack should have generated %s, \"\n \t\t      \"but I can't find it!\", sha1_to_hex(new_sha1));\ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex 7070171..579c3d8 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -487,4 +487,25 @@ test_expect_success 'allow deleting an invalid remote ref' '\n \n '\n \n+test_expect_success 'deny push to HEAD to non-bare repository' '\n+\tmk_test heads/master\n+\t(cd testrepo && git checkout master) &&\n+\ttest_must_fail git push testrepo master\n+'\n+\n+test_expect_success 'allow push to HEAD of bare repository' '\n+\tmk_test heads/master\n+\t(cd testrepo && git checkout master && git config core.bare true) &&\n+\tgit push testrepo master\n+'\n+\n+test_expect_success 'allow push to HEAD of non-bare repository w/ config' '\n+\tmk_test heads/master\n+\t(cd testrepo &&\n+\t\tgit checkout master &&\n+\t\tgit config receive.denyCurrentBranch false\n+\t) &&\n+\tgit push testrepo master\n+'\n+\n test_done\n-- \n1.6.0.3.866.gc189b\n"},{"id":"95168","messageId":"loom.20081107T222744-932@post.gmane.org","threadId":"16215","inReplyTo":"20081107220730.GA15942@coredump.intra.peff.net","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Mark Burton","fromEmail":"markb@ordern.com","sentAt":"2008-11-07T22:39:26Z","receivedAt":"2008-11-07T22:39:26Z","isPatch":true,"sender":{"key":"markb@ordern.com","avatar":null},"body":"Jeff King <peff <at> peff.net> writes:\n\n> \n> The short of it is that it's dangerous, we see people confused by it\n> (there was another one just yesterday), and it's a FAQ:\n> \n>   http://git.or.cz/gitwiki/GitFaq#head-b96f48bc9c925074be9f95c0fce69bcece5f6e73\n> \n> The FAQ even says \"don't do this until you know what you are doing.\" So\n> the safety valve is configurable, so that those who know what they are\n> doing can switch it off.\n\nWhen I first tried to use git I was bitten by exactly this problem. I know,\nRTFM, but when everything is new, it's easy to undervalue the words of wisdom\nwhen you don't understand the bigger picture and the rational behind the advice.\n\nI now happily work with non-bare repositories on my main machine that I push to\nfrom my satellite development machines but, of course, I don't push to the head\nbranches but, instead, to remote branches and then merge on the main machine.\n\nI wouldn't have wasted as much time getting my head around this if git had\nrefused to accept the push to the current branch but, instead, issued a suitable\nmessage telling me I probably didn't want to be doing that.\n\nSo, from my own experience, I would say this would be a good feature to add.\n\nCheers,\n\nMark\n"},{"id":"95173","messageId":"7v3ai3f7oa.fsf@gitster.siamese.dyndns.org","threadId":"16215","inReplyTo":"20081107220730.GA15942@coredump.intra.peff.net","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-11-07T23:16:53Z","receivedAt":"2008-11-07T23:16:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> The FAQ even says \"don't do this until you know what you are doing.\" So\n> the safety valve is configurable, so that those who know what they are\n> doing can switch it off.\n\n\"We are breaking your existing working setup but you can add a new\nconfiguration to unbreak it\" should not be done lightly.  I think as the\nend result it is a reasonable thing to aim for for this particular\nfeature, but we do need a transition plan patch in between that introduces\na step that warns but not forbids.  We can ship 1.6.1 with it and then\nswitch the default to forbid in 1.6.3, for example.\n\n> Patch 4/4 is the interesting one. 1/4 is a cleanup I saw while fixing\n> tests. 2/4 is a cleanup to prepare for 3/4. And 3/4 fixes a bunch of\n> tests which were inadvertently doing such a push (but didn't care\n> because they didn't look at the working directory).\n\nI wonder if you can use the tests 3/4 touches as the test for your \"keep\nexisting setup\" configuration variable, pretending that they are old\ntimer's repositories?\n"},{"id":"95216","messageId":"20081108142756.GC17100@coredump.intra.peff.net","threadId":"16215","inReplyTo":"7v3ai3f7oa.fsf@gitster.siamese.dyndns.org","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-11-08T14:27:56Z","receivedAt":"2008-11-08T14:27:56Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Nov 07, 2008 at 03:16:53PM -0800, Junio C Hamano wrote:\n\n> > The FAQ even says \"don't do this until you know what you are doing.\" So\n> > the safety valve is configurable, so that those who know what they are\n> > doing can switch it off.\n> \n> \"We are breaking your existing working setup but you can add a new\n> configuration to unbreak it\" should not be done lightly.  I think as the\n> end result it is a reasonable thing to aim for for this particular\n> feature, but we do need a transition plan patch in between that introduces\n> a step that warns but not forbids.  We can ship 1.6.1 with it and then\n> switch the default to forbid in 1.6.3, for example.\n\nYeah, I was kind of hoping we could assume that anybody relying on this\nbehavior was somewhat insane, and wouldn't be too upset when it broke.\nBut you're probably right that we should be more conservative. I'll\nrework it with a \"yes/no/warn\" option for the config, and we can set it\nto \"warn\" (and those who really do want it can shut off the warning with\n\"no\"). Or we can even start with just leaving it on \"no\", but I think\nthe deprecation period should begin when we switch it to \"warn\".\n\n> > Patch 4/4 is the interesting one. 1/4 is a cleanup I saw while fixing\n> > tests. 2/4 is a cleanup to prepare for 3/4. And 3/4 fixes a bunch of\n> > tests which were inadvertently doing such a push (but didn't care\n> > because they didn't look at the working directory).\n> \n> I wonder if you can use the tests 3/4 touches as the test for your \"keep\n> existing setup\" configuration variable, pretending that they are old\n> timer's repositories?\n\nYes, they do break with 4/4 applied without 3/4 (that was how I found\nthem, but \"git rebase -i\" let me pretend I had the proper foresight. ;)\n). We can keep 3/4 back until the switch from \"warn\" to \"yes\", if that's\nwhat you are suggesting.\n\n-Peff\n"},{"id":"95219","messageId":"alpine.DEB.1.00.0811081609530.30769@pacific.mpi-cbg.de","threadId":"16215","inReplyTo":"20081108142756.GC17100@coredump.intra.peff.net","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-11-08T15:12:26Z","receivedAt":"2008-11-08T15:12:26Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 8 Nov 2008, Jeff King wrote:\n\n> On Fri, Nov 07, 2008 at 03:16:53PM -0800, Junio C Hamano wrote:\n> \n> > > The FAQ even says \"don't do this until you know what you are doing.\" \n> > > So the safety valve is configurable, so that those who know what \n> > > they are doing can switch it off.\n> > \n> > \"We are breaking your existing working setup but you can add a new \n> > configuration to unbreak it\" should not be done lightly.  I think as \n> > the end result it is a reasonable thing to aim for for this particular \n> > feature, but we do need a transition plan patch in between that \n> > introduces a step that warns but not forbids.  We can ship 1.6.1 with \n> > it and then switch the default to forbid in 1.6.3, for example.\n> \n> Yeah, I was kind of hoping we could assume that anybody relying on this\n> behavior was somewhat insane, and wouldn't be too upset when it broke.\n\nI think I have a repository with \"git read-tree -u -m HEAD\" as update hook \nfor that kind of behavior.\n\nBut I will not be the person responsible to keep that behavior, if I am \nthe only one relying on it.\n\nI very much like the approach of defaulting to \"warn\" for quite some time \n(but setting the variable to \"refuse\" in git-init) and then adapt the \ndefault after some time.\n\nCiao,\nDscho\n"},{"id":"95238","messageId":"7vwsfeaqpa.fsf@gitster.siamese.dyndns.org","threadId":"16215","inReplyTo":"20081108142756.GC17100@coredump.intra.peff.net","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-11-08T20:49:21Z","receivedAt":"2008-11-08T20:49:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> Yes, they do break with 4/4 applied without 3/4 (that was how I found\n> them, but \"git rebase -i\" let me pretend I had the proper foresight. ;)\n> ). We can keep 3/4 back until the switch from \"warn\" to \"yes\", if that's\n> what you are suggesting.\n\nI meant to suggest that change contained in 3/4 can instead be \"set the\nconfiguration to allow such a dangerous push upfront, and make sure the\npushes the current tests perform actually are still allowed\", _if_ you are\nchanging the default to forbid.\n\nI think the default should be to warn for two release cycles during which\nwe will give deprecation notice, and then switch the default to forbid\n(and we do not touch \"git init/git clone\" at all --- changing the default\nto forbid in newly created repositories earlier than existing repositories\nwould be changing the behaviour of the command between old and new\nrepositories, which is madness).  If we are going this route, I think we\ncan modify the tests 3/4 touches to set the configuration to allow such a\npush and make sure that such a push is still allowed.\n"},{"id":"95246","messageId":"20081109014926.GA31276@coredump.intra.peff.net","threadId":"16215","inReplyTo":"7vwsfeaqpa.fsf@gitster.siamese.dyndns.org","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-11-09T01:49:27Z","receivedAt":"2008-11-09T01:49:27Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Nov 08, 2008 at 12:49:21PM -0800, Junio C Hamano wrote:\n\n> I meant to suggest that change contained in 3/4 can instead be \"set the\n> configuration to allow such a dangerous push upfront, and make sure the\n> pushes the current tests perform actually are still allowed\", _if_ you are\n> changing the default to forbid.\n\nAh, I see. I did think about using the config variable for those tests,\nbut it felt too much like testing two things at once. That is, it is\nnicer to debug if each test breaks only when the thing it is testing for\nis broken, not some other random unrelated feature. Obviously that isn't\nalways possible, but it seemed kind of clumsy to me.\n\nAnyway, with a default of \"warn\" the tests don't need any update at all\n(and do serve as a test that we still haven't broken people), and I can\npass the decision off to whoever changes it to \"refuse\" after the\ndeprecation period. :)\n\n> I think the default should be to warn for two release cycles during which\n> we will give deprecation notice, and then switch the default to forbid\n\nOK, the patch is below, replacing 4/4. 3/4 can simply be dropped at this\npoint (and I think 1/4 is a no-brainer to apply, and 2/4 is probably\nworth it as cleanup).\n\nI worded the warning to explain what happened so that the Frequently\nAsking users might have a clue that something bad has happened. But\nmaybe it should also:\n\n  - suggest \"git reset --hard\"; of course, then we need to explain that\n    you would be losing your work, so we have to warn about that, too.\n\n  - more explicitly warn that the behavior is deprecated.\n\nAlso, we could potentially note the deprecation in the documentation for\nthe config option.\n\n> (and we do not touch \"git init/git clone\" at all --- changing the default\n> to forbid in newly created repositories earlier than existing repositories\n> would be changing the behaviour of the command between old and new\n> repositories, which is madness).  If we are going this route, I think we\n\nI agree. I suggested that for another config option recently, and I now\nthink I was wrong. It really doesn't dodge the \"things are changing\"\nbullet. It just makes them change at a slightly different time, which\ncan be even more confusing (i.e., \"this breaks in my repo, but when I\nmake a test repo it works\" or vice versa).\n\nI do feel like we made a config change like that at some point long ago,\nbut I can't recall for what, or the reasoning. Maybe\ncore.logallrefupdates, which does have clone-specific behavior.\n\n> can modify the tests 3/4 touches to set the configuration to allow such a\n> push and make sure that such a push is still allowed.\n\nAgain, I am not sure that is best, as above. But I tried to cover all\ncases explicitly with my tests, so I think we should get good coverage\neither way (and my tests don't depend on any particular default config\nsetting).\n\n-- >8 --\nreceive-pack: detect push to current branch of non-bare repo\n\nPushing into the currently checked out branch of a non-bare\nrepository can be dangerous; the HEAD then loses sync with\nthe index and working tree, and it looks in the receiving\nrepo as if the pushed changes have been reverted in the\nindex (since they were never there in the first place).\n\nThis patch adds a safety valve that checks for this\ncondition and either generates a warning or denies the\nupdate. We trigger the check only on a non-bare repository,\nsince a bare repo does not have a working tree (and in fact,\npushing to the HEAD branch is a common workflow for\npublishing repositories).\n\nThe behavior is configurable via receive.denyCurrentBranch,\ndefaulting to \"warn\" so as not to break existing setups\n(though it may, after a deprecation period, switch to\n\"refuse\" by default). For users who know what they are doing\nand want to silence the warning (e.g., because they have a\npost-receive hook that reconciles the HEAD and working\ntree), they can turn off the warning by setting it to false\nor \"ignore\".\n\nSigned-off-by: Jeff King <peff@peff.net>\n\n---\n Documentation/config.txt |    9 +++++++\n builtin-receive-pack.c   |   59 ++++++++++++++++++++++++++++++++++++++++++++++\n t/t5516-fetch-push.sh    |   37 ++++++++++++++++++++++++++++\n 3 files changed, 105 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 965ed74..32dcd64 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -1198,6 +1198,15 @@ receive.denyNonFastForwards::\n \teven if that push is forced. This configuration variable is\n \tset when initializing a shared repository.\n \n+receive.denyCurrentBranch::\n+\tIf set to true or \"refuse\", receive-pack will deny a ref update\n+\tto the currently checked out branch of a non-bare repository.\n+\tSuch a push is potentially dangerous because it brings the HEAD\n+\tout of sync with the index and working tree. If set to \"warn\",\n+\tprint a warning of such a push to stderr, but allow the push to\n+\tproceed. If set to false or \"ignore\", allow such pushes with no\n+\tmessage. Defaults to \"warn\".\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/builtin-receive-pack.c b/builtin-receive-pack.c\nindex 7f9f134..db67c31 100644\n--- a/builtin-receive-pack.c\n+++ b/builtin-receive-pack.c\n@@ -11,8 +11,15 @@\n \n static const char receive_pack_usage[] = \"git-receive-pack <git-dir>\";\n \n+enum deny_action {\n+\tDENY_IGNORE,\n+\tDENY_WARN,\n+\tDENY_REFUSE,\n+};\n+\n static int deny_deletes = 0;\n static int deny_non_fast_forwards = 0;\n+static enum deny_action deny_current_branch = DENY_WARN;\n static int receive_fsck_objects;\n static int receive_unpack_limit = -1;\n static int transfer_unpack_limit = -1;\n@@ -22,6 +29,21 @@ static int report_status;\n static char capabilities[] = \" report-status delete-refs \";\n static int capabilities_sent;\n \n+static enum deny_action parse_deny_action(const char *var, const char *value)\n+{\n+\tif (value) {\n+\t\tif (!strcasecmp(value, \"ignore\"))\n+\t\t\treturn DENY_IGNORE;\n+\t\tif (!strcasecmp(value, \"warn\"))\n+\t\t\treturn DENY_WARN;\n+\t\tif (!strcasecmp(value, \"refuse\"))\n+\t\t\treturn DENY_REFUSE;\n+\t}\n+\tif (git_config_bool(var, value))\n+\t\treturn DENY_REFUSE;\n+\treturn DENY_IGNORE;\n+}\n+\n static int receive_pack_config(const char *var, const char *value, void *cb)\n {\n \tif (strcmp(var, \"receive.denydeletes\") == 0) {\n@@ -49,6 +71,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb)\n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(var, \"receive.denycurrentbranch\")) {\n+\t\tdeny_current_branch = parse_deny_action(var, value);\n+\t\treturn 0;\n+\t}\n+\n \treturn git_default_config(var, value, cb);\n }\n \n@@ -173,6 +200,20 @@ static int run_update_hook(struct command *cmd)\n \treturn hook_status(run_command(&proc), update_hook);\n }\n \n+static int is_ref_checked_out(const char *ref)\n+{\n+\tunsigned char sha1[20];\n+\tconst char *head;\n+\n+\tif (is_bare_repository())\n+\t\treturn 0;\n+\n+\thead = resolve_ref(\"HEAD\", sha1, 0, NULL);\n+\tif (!head)\n+\t\treturn 0;\n+\treturn !strcmp(head, ref);\n+}\n+\n static const char *update(struct command *cmd)\n {\n \tconst char *name = cmd->ref_name;\n@@ -186,6 +227,24 @@ static const char *update(struct command *cmd)\n \t\treturn \"funny refname\";\n \t}\n \n+\tswitch (deny_current_branch) {\n+\tcase DENY_IGNORE:\n+\t\tbreak;\n+\tcase DENY_WARN:\n+\t\tif (!is_ref_checked_out(name))\n+\t\t\tbreak;\n+\t\twarning(\"updating the currently checked out branch; this may\"\n+\t\t\t\" cause confusion,\\n\"\n+\t\t\t\"as the index and working tree do not reflect changes\"\n+\t\t\t\" that are now in HEAD.\");\n+\t\tbreak;\n+\tcase DENY_REFUSE:\n+\t\tif (!is_ref_checked_out(name))\n+\t\t\tbreak;\n+\t\terror(\"refusing to update checked out branch: %s\", name);\n+\t\treturn \"branch is currently checked out\";\n+\t}\n+\n \tif (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {\n \t\terror(\"unpack should have generated %s, \"\n \t\t      \"but I can't find it!\", sha1_to_hex(new_sha1));\ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex 3411107..a6532cb 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -486,4 +486,41 @@ test_expect_success 'allow deleting an invalid remote ref' '\n \n '\n \n+test_expect_success 'warn on push to HEAD of non-bare repository' '\n+\tmk_test heads/master\n+\t(cd testrepo &&\n+\t\tgit checkout master &&\n+\t\tgit config receive.denyCurrentBranch warn) &&\n+\tgit push testrepo master 2>stderr &&\n+\tgrep \"warning.*this may cause confusion\" stderr\n+'\n+\n+test_expect_success 'deny push to HEAD of non-bare repository' '\n+\tmk_test heads/master\n+\t(cd testrepo &&\n+\t\tgit checkout master &&\n+\t\tgit config receive.denyCurrentBranch true) &&\n+\ttest_must_fail git push testrepo master\n+'\n+\n+test_expect_success 'allow push to HEAD of bare repository (bare)' '\n+\tmk_test heads/master\n+\t(cd testrepo &&\n+\t\tgit checkout master &&\n+\t\tgit config receive.denyCurrentBranch true &&\n+\t\tgit config core.bare true) &&\n+\tgit push testrepo master 2>stderr &&\n+\t! grep \"warning.*this may cause confusion\" stderr\n+'\n+\n+test_expect_success 'allow push to HEAD of non-bare repository (config)' '\n+\tmk_test heads/master\n+\t(cd testrepo &&\n+\t\tgit checkout master &&\n+\t\tgit config receive.denyCurrentBranch false\n+\t) &&\n+\tgit push testrepo master 2>stderr &&\n+\t! grep \"warning.*this may cause confusion\" stderr\n+'\n+\n test_done\n"},{"id":"95251","messageId":"20081109113841.1382380a@perceptron","threadId":"16215","inReplyTo":"20081107220955.GA16058@coredump.intra.peff.net","subject":"Re: [PATCH 1/4] t5400: expect success for denying deletion","fromName":"Jan Krüger","fromEmail":"jk@jk.gs","sentAt":"2008-11-09T10:38:41Z","receivedAt":"2008-11-09T10:38:41Z","isPatch":true,"sender":{"key":"jk@jk.gs","avatar":"https://avatars.githubusercontent.com/u/1774?v=4"},"body":"Hi,\n\nOn Fri, 7 Nov 2008 17:09:55 -0500, Jeff King <peff@peff.net> wrote:\n> Reading over the mailing list postings which led to a240de11, I think\n> it is simply a case that Jan didn't fully understand what\n> expect_failure meant\n\n\nYes, that's exactly what happened, and it won't likely happen again.\nThanks for fixing and for the Cc.\n\n-Jan\n"},{"id":"95290","messageId":"7v1vxka6r4.fsf@gitster.siamese.dyndns.org","threadId":"16215","inReplyTo":"20081109014926.GA31276@coredump.intra.peff.net","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-11-09T22:12:31Z","receivedAt":"2008-11-09T22:12:31Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thanks; will be in 'next'.\n"},{"id":"95513","messageId":"f73f7ab80811111644y14f0e0ccweed44440356a6508@mail.gmail.com","threadId":"16215","inReplyTo":"20081109014926.GA31276@coredump.intra.peff.net","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Kyle Moffett","fromEmail":"kyle@moffetthome.net","sentAt":"2008-11-12T00:44:06Z","receivedAt":"2008-11-12T00:44:06Z","isPatch":true,"sender":{"key":"kyle@moffetthome.net","avatar":null},"body":"On Sat, Nov 8, 2008 at 8:49 PM, Jeff King <peff@peff.net> wrote:\n> The behavior is configurable via receive.denyCurrentBranch,\n> defaulting to \"warn\" so as not to break existing setups\n> (though it may, after a deprecation period, switch to\n> \"refuse\" by default). For users who know what they are doing\n> and want to silence the warning (e.g., because they have a\n> post-receive hook that reconciles the HEAD and working\n> tree), they can turn off the warning by setting it to false\n> or \"ignore\".\n\nHmm, I wonder if it would be possible to also add a \"detach\" variant;\nwhich would create a detached-HEAD at the current commit when\nautomatically receiving a push to the working branch.  I have a\npost-receive script that does so right now on a couple repositories.\nIt's still a little confusing to someone actively working in the\nrepository being pushed to, but it's much easier to explain than the\ncurrent default behavior.\n\nCheers,\nKyle Moffett\n"},{"id":"95543","messageId":"20081112084412.GA3860@coredump.intra.peff.net","threadId":"16215","inReplyTo":"f73f7ab80811111644y14f0e0ccweed44440356a6508@mail.gmail.com","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-11-12T08:44:13Z","receivedAt":"2008-11-12T08:44:13Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Nov 11, 2008 at 07:44:06PM -0500, Kyle Moffett wrote:\n\n> Hmm, I wonder if it would be possible to also add a \"detach\" variant;\n> which would create a detached-HEAD at the current commit when\n> automatically receiving a push to the working branch.  I have a\n> post-receive script that does so right now on a couple repositories.\n> It's still a little confusing to someone actively working in the\n> repository being pushed to, but it's much easier to explain than the\n> current default behavior.\n\nA neat idea, but I'm not sure what workflow that is meant to support.\n\nBefore you had:\n\n  1. git push non-bare-remote theirHEAD\n  2a. echo Oops, I've just screwed myself.\n    3a. ssh remote 'git reset --soft HEAD@{1}'\n  2b. echo Oops, I just screwed somebody else.\n    3b. echo sorry | mail somebody.else\n\nWith \"refuse\" you have:\n\n  1. git push non-bare-remote theirHEAD\n  2. echo Oops, rejected.\n  3. git push non-bare-remote theirHEAD:elsewhere\n  4a. ssh remote 'git merge elsewhere'\n  4b. echo 'please merge elsewhere' | mail somebody.else\n\nwhich is an improvement. With \"detach\" you have:\n\n  1. git push non-bare-remote theirHEAD\n  2. echo Oh, now we've detached on the remote.\n  3a. ssh remote 'git checkout theirHEAD'\n  3b. echo 'please merge theirHEAD. BTW, you have been detached without\n            realizing it, so make sure you didn't lose any commits.' |\n            mail somebody.else\n\nSo I think in the case that you are working by yourself, you haven't\nreally saved much effort (you didn't have to repeat your push, but you\nstill have to go to the remote and checkout instead of merge). But if\nyou are pushing into somebody _else_'s repo, you have just mightily\nconfused them as they start to make commits on top of the detached HEAD.\n\nStill, there may be some instances where moving to the detached HEAD is\npreferable. But, like the \"try to merge if we can\" strategy, I think it\nis better implemented by setting denyCurrentBranch to ignore and using a\nhook for those instances. And if either hook becomes ubiquitous, maybe\nit will be worth implementing within git itself (but I doubt it for\neither, as the desired behavior is highly dependent on your personal\nworkflow).\n\n-Peff\n"},{"id":"95664","messageId":"f73f7ab80811122122i4ae3ba6dn2ceb314b86660a70@mail.gmail.com","threadId":"16215","inReplyTo":"20081112084412.GA3860@coredump.intra.peff.net","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Kyle Moffett","fromEmail":"kyle@moffetthome.net","sentAt":"2008-11-13T05:22:20Z","receivedAt":"2008-11-13T05:22:20Z","isPatch":true,"sender":{"key":"kyle@moffetthome.net","avatar":null},"body":"On Wed, Nov 12, 2008 at 3:44 AM, Jeff King <peff@peff.net> wrote:\n> On Tue, Nov 11, 2008 at 07:44:06PM -0500, Kyle Moffett wrote:\n>> Hmm, I wonder if it would be possible to also add a \"detach\" variant;\n>> which would create a detached-HEAD at the current commit when\n>> automatically receiving a push to the working branch.  I have a\n>> post-receive script that does so right now on a couple repositories.\n>> It's still a little confusing to someone actively working in the\n>> repository being pushed to, but it's much easier to explain than the\n>> current default behavior.\n>\n> A neat idea, but I'm not sure what workflow that is meant to support.\n\nBasically, I have a remote tree on a fast multicore box used for runs\nof a test suite on various peoples different branches.  When I want\nsomebody to push something for me to test, they push directly to that\nrepo, and when I'm done playing with a previous run I just do:\n\n$ git checkout new/branch/to/test\n$ make clean\n$ ./configure\n$ make\n$ make check\n\nOccasionally I notice a bug which I want to temporarily fix to let the\nbuild continue, even though I will need to have the author merge that\nfix as a part of his original buggy patch.  If nobody pushes the\nbranch I'm currently testing again, I can \"git diff\" just fine to see\nwhat I had to fix.  If somebody pushes to a different branch than the\none I'm testing, it's also fine.  The inconsistency is pushing to the\nbranch I'm on.\n\nSo it would be handy to be able to mark that repository as\n\"detach-HEAD-on-push-of-current-branch\", which would let me remember\nwhere I was, even if that's not where that branch is anymore.\n\nThere are other ways I could probably do something very similar, but\nsince the config option was being added it seemed it would probably be\neasy to extend.  If nobody else is interested in that behavior, I will\njust keep maintaining my own hook, but I thought I'd mention it.\n\nCheers,\nKyle Moffett\n"},{"id":"95665","messageId":"20081113053735.GA5343@coredump.intra.peff.net","threadId":"16215","inReplyTo":"f73f7ab80811122122i4ae3ba6dn2ceb314b86660a70@mail.gmail.com","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-11-13T05:37:35Z","receivedAt":"2008-11-13T05:37:35Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Nov 13, 2008 at 12:22:20AM -0500, Kyle Moffett wrote:\n\n> somebody to push something for me to test, they push directly to that\n> repo, and when I'm done playing with a previous run I just do:\n> \n> $ git checkout new/branch/to/test\n> $ make clean\n> $ ./configure\n> $ make\n> $ make check\n\nOK, I see how using a detached HEAD makes sense. But I think just going\nstraight to a detached HEAD might make even more sense. With your\nproposed behavior, you need to be prepared to unexpectedly and\nasynchronously move to a detached HEAD at any time, so why not just\nstart there in the first place?\n\nAnd then the \"push to current branch\" problem is neatly solved: you have\nno current branch.\n\nSo:\n\n  $ git checkout new/branch/to/test^0\n  $ make, configure, etc\n\n-Peff\n"},{"id":"95667","messageId":"7vhc6ci24o.fsf@gitster.siamese.dyndns.org","threadId":"16215","inReplyTo":"20081113053735.GA5343@coredump.intra.peff.net","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-11-13T06:14:15Z","receivedAt":"2008-11-13T06:14:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> And then the \"push to current branch\" problem is neatly solved: you have\n> no current branch.\n>\n> So:\n>\n>   $ git checkout new/branch/to/test^0\n>   $ make, configure, etc\n\nExactly.\n\nI keep a handful pseudo worktrees around (created with git-new-workdir on\ntop of a single repository) for quick patch test and build purposes.  I do\nnot push into them but pushing into a non-bare repository and checking out\nthe same branch twice in such a setup share exactly the same issue, and I\nkeep their HEADs all detached for exactly the same reason.\n"},{"id":"95686","messageId":"f73f7ab80811130558h34cb1220q76ef5536e853151c@mail.gmail.com","threadId":"16215","inReplyTo":"7vhc6ci24o.fsf@gitster.siamese.dyndns.org","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Kyle Moffett","fromEmail":"kyle@moffetthome.net","sentAt":"2008-11-13T13:58:50Z","receivedAt":"2008-11-13T13:58:50Z","isPatch":true,"sender":{"key":"kyle@moffetthome.net","avatar":null},"body":"On Thu, Nov 13, 2008 at 1:14 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Jeff King <peff@peff.net> writes:\n>> And then the \"push to current branch\" problem is neatly solved: you have\n>> no current branch.\n>>\n>> So:\n>>\n>>   $ git checkout new/branch/to/test^0\n>>   $ make, configure, etc\n>\n> Exactly.\n>\n> I keep a handful pseudo worktrees around (created with git-new-workdir on\n> top of a single repository) for quick patch test and build purposes.  I do\n> not push into them but pushing into a non-bare repository and checking out\n> the same branch twice in such a setup share exactly the same issue, and I\n> keep their HEADs all detached for exactly the same reason.\n\nI guess the issue comes down to a UI complication.  It would very easy\nfor me to tell somebody how to check out and test their branch in my\ntestbed if I'm not around, except for that little bit of arcane\nsyntax.  Moreover, the consequences if they forget are really\nfrustrating and hard to figure out.  It's also very easy with a GUI to\ndo the simple *rightclick branch, click \"Checkout\"*, but would be much\nharder to do the detached HEAD checkout correctly.\n\nIf it didn't involve reconfiguring a lot of other people's\nrepositories, I might consider having them push to \"refs/remotes/*\".\nIn theory that's actually much closer to what I'm doing anyways.  That\nwould force any checkouts to be bare, but it would require lots of\ngit-foo on the pushing side.  Perhaps some way to \"git push\" which\nasks the remote repository where it wants the stuff?\n\nAlternatively, it might be possible to add ref attributes or a config\noption to force detached HEAD checkouts.\n\nCheers,\nKyle Moffett\n"},{"id":"95765","messageId":"20081114063740.GA12001@coredump.intra.peff.net","threadId":"16215","inReplyTo":"f73f7ab80811130558h34cb1220q76ef5536e853151c@mail.gmail.com","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-11-14T06:37:41Z","receivedAt":"2008-11-14T06:37:41Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Nov 13, 2008 at 08:58:50AM -0500, Kyle Moffett wrote:\n\n> I guess the issue comes down to a UI complication.  It would very easy\n> for me to tell somebody how to check out and test their branch in my\n> testbed if I'm not around, except for that little bit of arcane\n> syntax.  Moreover, the consequences if they forget are really\n\nIf the problem is merely the syntax, then perhaps that argues for \"git\ncheckout -d\" to force detaching.\n\n> frustrating and hard to figure out.  It's also very easy with a GUI to\n> do the simple *rightclick branch, click \"Checkout\"*, but would be much\n> harder to do the detached HEAD checkout correctly.\n\nAnd again, perhaps this argues for a \"Detach\" option in the GUI.\n\nBut I have to admit, this is a pretty infrequently-used use-case. I\ndetach all the time when looking at non-branches, but I can't think of\nthe last time I used \"ref^0\" to detach intentionally.\n\n> If it didn't involve reconfiguring a lot of other people's\n> repositories, I might consider having them push to \"refs/remotes/*\".\n> In theory that's actually much closer to what I'm doing anyways.  That\n> would force any checkouts to be bare, but it would require lots of\n> git-foo on the pushing side.  Perhaps some way to \"git push\" which\n> asks the remote repository where it wants the stuff?\n\nOr git-receive could even just silently munge the incoming refs when\nwriting them out (i.e., it exposes \"refs/test/*\" as \"refs/heads/*\", and\nwhen you ask to write \"refs/heads/foo\" it writes \"refs/test/foo\"\ninstead).\n\nThough that sort of lying feels a little wrong to me, since the pushing\nside will incorrectly update its tracking branches. It wouldn't so bad\nif the \"fetch\" side respected the munging, too.\n\nBut again, this seems uncommon enough that it is not worth trying to\nimplement something too clever.\n\n> Alternatively, it might be possible to add ref attributes or a config\n> option to force detached HEAD checkouts.\n\nI think that is a more sensible solution. Your workflow is not about\n\"sometimes I want to detach the HEAD\" but rather \"in this particular\nrepo, we should _always_ detach the HEAD.\" Which a config option\nrepresents very nicely.\n\n-Peff\n"},{"id":"96912","messageId":"ee2a733e0812011822r4cef6a44ra68d6e84f9e30a90@mail.gmail.com","threadId":"16215","inReplyTo":"20081108142756.GC17100@coredump.intra.peff.net","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Leo Razoumov","fromEmail":"slonik.az@gmail.com","sentAt":"2008-12-02T02:22:43Z","receivedAt":"2008-12-02T02:22:43Z","isPatch":true,"sender":{"key":"slonik.az@gmail.com","avatar":null},"body":"On 11/8/08, Jeff King <peff@peff.net> wrote:\n> On Fri, Nov 07, 2008 at 03:16:53PM -0800, Junio C Hamano wrote:\n>\n>  > > The FAQ even says \"don't do this until you know what you are doing.\" So\n>  > > the safety valve is configurable, so that those who know what they are\n>  > > doing can switch it off.\n>  >\n>  > \"We are breaking your existing working setup but you can add a new\n>  > configuration to unbreak it\" should not be done lightly.  I think as the\n>  > end result it is a reasonable thing to aim for for this particular\n>  > feature, but we do need a transition plan patch in between that introduces\n>  > a step that warns but not forbids.  We can ship 1.6.1 with it and then\n>  > switch the default to forbid in 1.6.3, for example.\n>\n>\n> Yeah, I was kind of hoping we could assume that anybody relying on this\n>  behavior was somewhat insane, and wouldn't be too upset when it broke.\n\nI do not think that having a work-flow different from yours deserves a\n\"somewhat insane\" label. But let us consider the consequences of\nbanning push into a (current branch) non-bare repo. To propagate\nchanges to such a non-bare repo there are two remaining alternatives\nneither of which is fully satisfactory:\n\n(1) Switch target's current branch to something else (prevent a\nconflict) before pushing and then restore it back after the push\n\n(2) Use git-fetch from the target.\n\nMethod (1) is no better than what is available today with \"git reset\n--hard\" to sync working directory.\nMethod (2) is even worse, because git-fetch provides no control of\nwhat branches/tags to fetch, it sucks everything in from all branches.\n\"git-push\", OTOH, can be instructed to be very selective.\n\nHere is an example of such a work-flow\n\nFoo.git -- main bare repo of the project\nFoo.wip -- everyday \"work in progress\" repo. Cloned from Foo.git.\nPushes to Foo.git\nFoo.wip.insane -- experimental \"crazy\" stuff cloned from Foo.wip.\nPushed to Foo.wip\n\nProposed patch makes this work flow impossible (cannot push from\nFoo.wip.insane to Foo.wip)\n\n--Leo--\n"},{"id":"96915","messageId":"7vtz9npawn.fsf@gitster.siamese.dyndns.org","threadId":"16215","inReplyTo":"ee2a733e0812011822r4cef6a44ra68d6e84f9e30a90@mail.gmail.com","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-12-02T02:29:28Z","receivedAt":"2008-12-02T02:29:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Leo Razoumov\" <slonik.az@gmail.com> writes:\n\n> On 11/8/08, Jeff King <peff@peff.net> wrote:\n>> On Fri, Nov 07, 2008 at 03:16:53PM -0800, Junio C Hamano wrote:\n>>\n>>  > > The FAQ even says \"don't do this until you know what you are doing.\" So\n>>  > > the safety valve is configurable, so that those who know what they are\n>>  > > doing can switch it off.\n>>  >\n>>  > \"We are breaking your existing working setup but you can add a new\n>>  > configuration to unbreak it\" should not be done lightly.  I think as the\n>>  > end result it is a reasonable thing to aim for for this particular\n>>  > feature, but we do need a transition plan patch in between that introduces\n>>  > a step that warns but not forbids.  We can ship 1.6.1 with it and then\n>>  > switch the default to forbid in 1.6.3, for example.\n>>\n>>\n>> Yeah, I was kind of hoping we could assume that anybody relying on this\n>>  behavior was somewhat insane, and wouldn't be too upset when it broke.\n>\n> I do not think that having a work-flow different from yours deserves a\n> \"somewhat insane\" label. But let us consider the consequences of\n> banning push into a (current branch) non-bare repo. To propagate\n> changes to such a non-bare repo there are two remaining alternatives\n> neither of which is fully satisfactory:\n>\n> (1) Switch target's current branch to something else (prevent a\n> conflict) before pushing and then restore it back after the push\n>\n> (2) Use git-fetch from the target.\n\n(3) set the config in the target repository to allow such a push\n    regardless of the git version.\n\nRemember, I am in the third camp in this topic myself.\n"},{"id":"96918","messageId":"ee2a733e0812011841l73fc046dra6434340702fc282@mail.gmail.com","threadId":"16215","inReplyTo":"7vtz9npawn.fsf@gitster.siamese.dyndns.org","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Leo Razoumov","fromEmail":"slonik.az@gmail.com","sentAt":"2008-12-02T02:41:53Z","receivedAt":"2008-12-02T02:41:53Z","isPatch":true,"sender":{"key":"slonik.az@gmail.com","avatar":null},"body":"On 12/1/08, Junio C Hamano <gitster@pobox.com> wrote:\n> \"Leo Razoumov\" <slonik.az@gmail.com> writes:\n>\n>  > On 11/8/08, Jeff King <peff@peff.net> wrote:\n>  >> On Fri, Nov 07, 2008 at 03:16:53PM -0800, Junio C Hamano wrote:\n>  >>\n>  >>  > > The FAQ even says \"don't do this until you know what you are doing.\" So\n>  >>  > > the safety valve is configurable, so that those who know what they are\n>  >>  > > doing can switch it off.\n>  >>  >\n>  >>  > \"We are breaking your existing working setup but you can add a new\n>  >>  > configuration to unbreak it\" should not be done lightly.  I think as the\n>  >>  > end result it is a reasonable thing to aim for for this particular\n>  >>  > feature, but we do need a transition plan patch in between that introduces\n>  >>  > a step that warns but not forbids.  We can ship 1.6.1 with it and then\n>  >>  > switch the default to forbid in 1.6.3, for example.\n>  >>\n>  >>\n>  >> Yeah, I was kind of hoping we could assume that anybody relying on this\n>  >>  behavior was somewhat insane, and wouldn't be too upset when it broke.\n>  >\n>  > I do not think that having a work-flow different from yours deserves a\n>  > \"somewhat insane\" label. But let us consider the consequences of\n>  > banning push into a (current branch) non-bare repo. To propagate\n>  > changes to such a non-bare repo there are two remaining alternatives\n>  > neither of which is fully satisfactory:\n>  >\n>  > (1) Switch target's current branch to something else (prevent a\n>  > conflict) before pushing and then restore it back after the push\n>  >\n>  > (2) Use git-fetch from the target.\n>\n>\n> (3) set the config in the target repository to allow such a push\n>     regardless of the git version.\n>\n>  Remember, I am in the third camp in this topic myself.\n\nJunio,\nthanks for supporting the \"third way\". I am not sure whether I\ninterpret it correctly but in the same thread several message earlier\nyou wrote \"We can ship 1.6.1 with it and then switch the default to\nforbid in 1.6.3, for example\". With the default set to \"deny\" it would\nbe useful if the git-push error message will indicate what config\nvariable to set in order to reverse the denial.\n\n--Leo--\n"},{"id":"96921","messageId":"20081202024837.GB6804@coredump.intra.peff.net","threadId":"16215","inReplyTo":"ee2a733e0812011822r4cef6a44ra68d6e84f9e30a90@mail.gmail.com","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-12-02T02:48:37Z","receivedAt":"2008-12-02T02:48:37Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Dec 01, 2008 at 09:22:43PM -0500, Leo Razoumov wrote:\n\n> I do not think that having a work-flow different from yours deserves a\n> \"somewhat insane\" label. But let us consider the consequences of\n\n  a) you are responding to a nearly month-old message. Please read the\n     rest of the thread where we decide that it is not so insane, and\n     that the behavior should be configurable with a default of \"warn\"\n     at least for now.\n\n  b) My comment was not that it is insane simply because it is different\n     from mine. It is because it creates a dangerous situation (where\n     dangerous implies changes might be silently lost) which requires\n     manual intervention to fix, and which the user was given no warning\n     whatsoever about. It is a direct response to frequent complaints on\n     the list about users getting bit by this.\n\n> (1) Switch target's current branch to something else (prevent a\n> conflict) before pushing and then restore it back after the push\n> \n> (2) Use git-fetch from the target.\n\n(3) Use git-reset --hard, but set a config variable that says \"I know\nwhat I'm doing.\" You don't even have to do it per-repo, you can do it\nper-user.\n\n(4) Push into a non-current branch and merge from the target.\n\n> Method (2) is even worse, because git-fetch provides no control of\n> what branches/tags to fetch, it sucks everything in from all branches.\n> \"git-push\", OTOH, can be instructed to be very selective.\n\nEr, what? git-fetch takes a refspec very similar to the ones used by\ngit-push. The real reason that (2) is not an acceptable solution is that\nyou can't necessarily connect to the source repo (e.g., it is on your\nworkstation with no ssh or git server running).\n\n-Peff\n"},{"id":"96926","messageId":"ee2a733e0812011908p3310cda4h46815264efee2588@mail.gmail.com","threadId":"16215","inReplyTo":"20081202024837.GB6804@coredump.intra.peff.net","subject":"Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo","fromName":"Leo Razoumov","fromEmail":"slonik.az@gmail.com","sentAt":"2008-12-02T03:08:01Z","receivedAt":"2008-12-02T03:08:01Z","isPatch":true,"sender":{"key":"slonik.az@gmail.com","avatar":null},"body":"On 12/1/08, Jeff King <peff@peff.net> wrote:\n> [..snip..]\n>  >\n> Er, what? git-fetch takes a refspec very similar to the ones used by\n>  git-push. The real reason that (2) is not an acceptable solution is that\n>  you can't necessarily connect to the source repo (e.g., it is on your\n>  workstation with no ssh or git server running).\n>\n>  -Peff\n\nI am sorry, I had to be more accurate in my wording. \"git fetch\" with\nno explicit refspecs fetches everything in. It is quite cumbersome to\nform a refspec for git-fetch operation if you are  not logged in into\nthe \"source repo\" machine. git-fetch does not have a --dry-run option\nto help discover all the branch/tag names on the source side needed\nfor a meaningful refspec. \"git-push -v --dry-run\" allows one to\nexperiment and see what branches/tags exist at the destination and\nform refspecs selectively. To the best of my knowledge, git-fetch does\nnot provide such discovery tools.\n\n--Leo--\n"}]}