[RFC PATCH 0/4] deny push to current branch of non-bare repo

DORMANTno replies

7 messages, 3 authors, 2016-06-15 · open the first message on its own page

[RFC PATCH 0/4] deny push to current branch of non-bare repo

From: Jeff King <hidden>
Date: 2016-06-15 22:45:37

The short of it is that it's dangerous, we see people confused by it
(there was another one just yesterday), and it's a FAQ:

  http://git.or.cz/gitwiki/GitFaq#head-b96f48bc9c925074be9f95c0fce69bcece5f6e73

The FAQ even says "don't do this until you know what you are doing." So
the safety valve is configurable, so that those who know what they are
doing can switch it off.

And it's even on Sam's "UI improvements" list. :)

Patch 4/4 is the interesting one. 1/4 is a cleanup I saw while fixing
tests. 2/4 is a cleanup to prepare for 3/4. And 3/4 fixes a bunch of
tests which were inadvertently doing such a push (but didn't care
because they didn't look at the working directory).

-Peff

[PATCH 1/4] t5400: expect success for denying deletion

From: Jeff King <hidden>
Date: 2016-06-15 22:45:37

Commit a240de11 introduced this test and the code to make it
successful.

Signed-off-by: Jeff King <redacted>
---
Reading over the mailing list postings which led to a240de11, I think it
is simply a case that Jan didn't fully understand what expect_failure
meant (it means "this is a test that is currently broken, but we hope to
fix in the future", and not anything to do with the test_must_fail in
the test itself).

 t/t5400-send-pack.sh |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh
index 6fe2f87..da69f08 100755
--- a/t/t5400-send-pack.sh
+++ b/t/t5400-send-pack.sh
@@ -103,7 +103,7 @@ unset GIT_CONFIG GIT_CONFIG_LOCAL
 HOME=`pwd`/no-such-directory
 export HOME ;# this way we force the victim/.git/config to be used.
 
-test_expect_failure \
+test_expect_success \
 	'pushing a delete should be denied with denyDeletes' '
 	cd victim &&
 	git config receive.denyDeletes true &&
-- 
1.6.0.3.866.gc189b

[PATCH 2/4] t5516: refactor oddball tests

From: Jeff King <hidden>
Date: 2016-06-15 22:45:37

t5516 sets up some utility functions for starting each test
with a clean slate. However, there were a few tests added
that do not use these functions, but instead make their own
repositories.

Let's bring these in line with the rest of the tests. Not
only do we reduce the number of lines, but these tests will
benefit from any further enhancements to the utility
scripts.

The conversion is pretty straightforward. Most of the tests
created a parent/child clone relationship, for which we now
use 'testrepo' as the parent.  One test looked in testrepo,
but relied on previous tests to have set it up; it now sets
up testrepo explicitly, which makes it a bit more robust to
changes in the script, as well.

Signed-off-by: Jeff King <redacted>
---
This is on top of 'next' to pick up the recent test from Clemens
Buchacher.

A few oddities here while I was digging in the history:

  - I actually introduced the first of these tests for local tracking
    refs in 09fba7a59 (and the others, being related, copied the style).
    But then I reverted them in 0673c96, because Alex had added other
    similar tests in t5404.  However, these tests ended up being
    re-added by Dscho in 28391a80, which adds a totally unrelated test.
    I think it's the result of a bad patch application (IIRC, he marked
    up my tests to avoid having them chdir for the whole test script.
    During application, Junio would see them going from tweaks to whole
    creation, and presumably just resolved the conflict that way).

    So my initial thought was to simply delete these tests. But since
    then, other related tests have been added to this script, and we do
    want to keep those. So I decided to keep them all, as they form a
    logical progression related to tracking refs. So while there is some
    duplication with t5404, I don't think it is a problem.

  - One of the tests called 'pwd', and I can't see that it would do
    anything useful. I assume it was just leftover debugging cruft
    (especially since it is from that same commit by Dscho).

 t/t5516-fetch-push.sh |   50 ++++++++++++++++++++----------------------------
 1 files changed, 21 insertions(+), 29 deletions(-)
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 598664c..3411107 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -39,6 +39,11 @@ mk_test () {
 	)
 }
 
+mk_child() {
+	rm -rf "$1" &&
+	git clone testrepo "$1"
+}
+
 check_push_result () {
 	(
 		cd testrepo &&
@@ -425,13 +430,10 @@ test_expect_success 'push with dry-run' '
 
 test_expect_success 'push updates local refs' '
 
-	rm -rf parent child &&
-	mkdir parent &&
-	(cd parent && git init &&
-		echo one >foo && git add foo && git commit -m one) &&
-	git clone parent child &&
+	mk_test heads/master &&
+	mk_child child &&
 	(cd child &&
-		echo two >foo && git commit -a -m two &&
+		git pull .. master &&
 		git push &&
 	test $(git rev-parse master) = $(git rev-parse remotes/origin/master))
 
@@ -439,15 +441,10 @@ test_expect_success 'push updates local refs' '
 
 test_expect_success 'push updates up-to-date local refs' '
 
-	rm -rf parent child &&
-	mkdir parent &&
-	(cd parent && git init &&
-		echo one >foo && git add foo && git commit -m one) &&
-	git clone parent child1 &&
-	git clone parent child2 &&
-	(cd child1 &&
-		echo two >foo && git commit -a -m two &&
-		git push) &&
+	mk_test heads/master &&
+	mk_child child1 &&
+	mk_child child2 &&
+	(cd child1 && git pull .. master && git push) &&
 	(cd child2 &&
 		git pull ../child1 master &&
 		git push &&
@@ -457,11 +454,8 @@ test_expect_success 'push updates up-to-date local refs' '
 
 test_expect_success 'push preserves up-to-date packed refs' '
 
-	rm -rf parent child &&
-	mkdir parent &&
-	(cd parent && git init &&
-		echo one >foo && git add foo && git commit -m one) &&
-	git clone parent child &&
+	mk_test heads/master &&
+	mk_child child &&
 	(cd child &&
 		git push &&
 	! test -f .git/refs/remotes/origin/master)
@@ -470,15 +464,13 @@ test_expect_success 'push preserves up-to-date packed refs' '
 
 test_expect_success 'push does not update local refs on failure' '
 
-	rm -rf parent child &&
-	mkdir parent &&
-	(cd parent && git init &&
-		echo one >foo && git add foo && git commit -m one &&
-		echo exit 1 >.git/hooks/pre-receive &&
-		chmod +x .git/hooks/pre-receive) &&
-	git clone parent child &&
+	mk_test heads/master &&
+	mk_child child &&
+	mkdir testrepo/.git/hooks &&
+	echo exit 1 >testrepo/.git/hooks/pre-receive &&
+	chmod +x testrepo/.git/hooks/pre-receive &&
 	(cd child &&
-		echo two >foo && git commit -a -m two &&
+		git pull .. master
 		test_must_fail git push &&
 		test $(git rev-parse master) != \
 			$(git rev-parse remotes/origin/master))
@@ -487,7 +479,7 @@ test_expect_success 'push does not update local refs on failure' '
 
 test_expect_success 'allow deleting an invalid remote ref' '
 
-	pwd &&
+	mk_test heads/master &&
 	rm -f testrepo/.git/objects/??/* &&
 	git push testrepo :refs/heads/master &&
 	(cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)
-- 
1.6.0.3.866.gc189b

[PATCH 3/4] tests: avoid pushing to current branch of non-bare repo

From: Jeff King <hidden>
Date: 2016-06-15 22:45:37

Many tests create a new repo, and then push into the master
branch (sometimes after making some commits on that branch).
After such a push the index and working tree of the
receiving repo are out of sync with the HEAD. This isn't a
problem for most tests, since they don't bother looking at
the working tree after such a push.  But this is generally a
dangerous behavior, and the tests would break if we later
decided to put in a safety valve.

Depending on the situation, this patch takes one of two
approaches:

  - creates the pushed-to repo as a bare repository. This
    works if we don't actually want to create our own
    commits in the repo.

  - switches the pushed-to repo to another branch before
    pushing. Since we never look at the working tree after
    the push anyway, this doesn't impact the test results.

Signed-off-by: Jeff King <redacted>
---
This is not the _most_ minimal patch, since when changing a non-bare
repo to a bare one, the name of the git dir changed (e.g.,
s{victim/.git}{victim}), causing a lot of textual changes. We could
technically call the bare clone "victim/.git", but I think this is less
confusing (if a bit harder to read the diff).

 t/t5400-send-pack.sh        |   30 ++++++++++++----------
 t/t5401-update-hooks.sh     |   58 +++++++++++++++++++++---------------------
 t/t5405-send-pack-rewind.sh |    3 +-
 t/t5516-fetch-push.sh       |    3 +-
 t/t5517-push-mirror.sh      |    2 +-
 5 files changed, 50 insertions(+), 46 deletions(-)
diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh
index da69f08..6bcb4df 100755
--- a/t/t5400-send-pack.sh
+++ b/t/t5400-send-pack.sh
@@ -31,7 +31,7 @@ test_expect_success setup '
 	    parent=$commit || return 1
 	done &&
 	git update-ref HEAD "$commit" &&
-	git clone ./. victim &&
+	git clone --bare ./. victim &&
 	cd victim &&
 	git log &&
 	cd .. &&
@@ -68,7 +68,7 @@ test_expect_success 'pack the destination repository' '
 test_expect_success \
         'pushing rewound head should not barf but require --force' '
 	# should not fail but refuse to update.
-	if git send-pack ./victim/.git/ master
+	if git send-pack ./victim/ master
 	then
 		# now it should fail with Pasky patch
 		echo >&2 Gaah, it should have failed.
@@ -77,7 +77,7 @@ test_expect_success \
 		echo >&2 Thanks, it correctly failed.
 		true
 	fi &&
-	if cmp victim/.git/refs/heads/master .git/refs/heads/master
+	if cmp victim/refs/heads/master .git/refs/heads/master
 	then
 		# should have been left as it was!
 		false
@@ -85,8 +85,8 @@ test_expect_success \
 		true
 	fi &&
 	# this should update
-	git send-pack --force ./victim/.git/ master &&
-	cmp victim/.git/refs/heads/master .git/refs/heads/master
+	git send-pack --force ./victim/ master &&
+	cmp victim/refs/heads/master .git/refs/heads/master
 '
 
 test_expect_success \
@@ -94,14 +94,14 @@ test_expect_success \
 	cd victim &&
 	git branch extra master &&
 	cd .. &&
-	test -f victim/.git/refs/heads/extra &&
-	git send-pack ./victim/.git/ :extra master &&
-	! test -f victim/.git/refs/heads/extra
+	test -f victim/refs/heads/extra &&
+	git send-pack ./victim/ :extra master &&
+	! test -f victim/refs/heads/extra
 '
 
 unset GIT_CONFIG GIT_CONFIG_LOCAL
 HOME=`pwd`/no-such-directory
-export HOME ;# this way we force the victim/.git/config to be used.
+export HOME ;# this way we force the victim/config to be used.
 
 test_expect_success \
 	'pushing a delete should be denied with denyDeletes' '
@@ -109,10 +109,10 @@ test_expect_success \
 	git config receive.denyDeletes true &&
 	git branch extra master &&
 	cd .. &&
-	test -f victim/.git/refs/heads/extra &&
-	test_must_fail git send-pack ./victim/.git/ :extra master
+	test -f victim/refs/heads/extra &&
+	test_must_fail git send-pack ./victim/ :extra master
 '
-rm -f victim/.git/refs/heads/extra
+rm -f victim/refs/heads/extra
 
 test_expect_success \
         'pushing with --force should be denied with denyNonFastforwards' '
@@ -120,14 +120,15 @@ test_expect_success \
 	git config receive.denyNonFastforwards true &&
 	cd .. &&
 	git update-ref refs/heads/master master^ || return 1
-	git send-pack --force ./victim/.git/ master && return 1
-	! test_cmp .git/refs/heads/master victim/.git/refs/heads/master
+	git send-pack --force ./victim/ master && return 1
+	! test_cmp .git/refs/heads/master victim/refs/heads/master
 '
 
 test_expect_success \
 	'pushing does not include non-head refs' '
 	mkdir parent && cd parent &&
 	git init && touch file && git add file && git commit -m add &&
+	git checkout -b otherbranch &&
 	cd .. &&
 	git clone parent child && cd child && git push --all &&
 	cd ../parent &&
@@ -139,6 +140,7 @@ rewound_push_setup() {
 	mkdir parent && cd parent &&
 	git init && echo one >file && git add file && git commit -m one &&
 	echo two >file && git commit -a -m two &&
+	git checkout -b otherbranch
 	cd .. &&
 	git clone parent child && cd child && git reset --hard HEAD^
 }
diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh
index 64f66c9..ae1aa77 100755
--- a/t/t5401-update-hooks.sh
+++ b/t/t5401-update-hooks.sh
@@ -17,22 +17,22 @@ test_expect_success setup '
 	commit1=$(echo modify | git commit-tree $tree1 -p $commit0) &&
 	git update-ref refs/heads/master $commit0 &&
 	git update-ref refs/heads/tofail $commit1 &&
-	git clone ./. victim &&
-	GIT_DIR=victim/.git git update-ref refs/heads/tofail $commit1 &&
+	git clone --bare ./. victim &&
+	GIT_DIR=victim git update-ref refs/heads/tofail $commit1 &&
 	git update-ref refs/heads/master $commit1 &&
 	git update-ref refs/heads/tofail $commit0
 '
 
-cat >victim/.git/hooks/pre-receive <<'EOF'
+cat >victim/hooks/pre-receive <<'EOF'
 #!/bin/sh
 printf %s "$@" >>$GIT_DIR/pre-receive.args
 cat - >$GIT_DIR/pre-receive.stdin
 echo STDOUT pre-receive
 echo STDERR pre-receive >&2
 EOF
-chmod u+x victim/.git/hooks/pre-receive
+chmod u+x victim/hooks/pre-receive
 
-cat >victim/.git/hooks/update <<'EOF'
+cat >victim/hooks/update <<'EOF'
 #!/bin/sh
 echo "$@" >>$GIT_DIR/update.args
 read x; printf %s "$x" >$GIT_DIR/update.stdin
@@ -40,77 +40,77 @@ echo STDOUT update $1
 echo STDERR update $1 >&2
 test "$1" = refs/heads/master || exit
 EOF
-chmod u+x victim/.git/hooks/update
+chmod u+x victim/hooks/update
 
-cat >victim/.git/hooks/post-receive <<'EOF'
+cat >victim/hooks/post-receive <<'EOF'
 #!/bin/sh
 printf %s "$@" >>$GIT_DIR/post-receive.args
 cat - >$GIT_DIR/post-receive.stdin
 echo STDOUT post-receive
 echo STDERR post-receive >&2
 EOF
-chmod u+x victim/.git/hooks/post-receive
+chmod u+x victim/hooks/post-receive
 
-cat >victim/.git/hooks/post-update <<'EOF'
+cat >victim/hooks/post-update <<'EOF'
 #!/bin/sh
 echo "$@" >>$GIT_DIR/post-update.args
 read x; printf %s "$x" >$GIT_DIR/post-update.stdin
 echo STDOUT post-update
 echo STDERR post-update >&2
 EOF
-chmod u+x victim/.git/hooks/post-update
+chmod u+x victim/hooks/post-update
 
 test_expect_success push '
-	test_must_fail git send-pack --force ./victim/.git \
+	test_must_fail git send-pack --force ./victim \
 		master tofail >send.out 2>send.err
 '
 
 test_expect_success 'updated as expected' '
-	test $(GIT_DIR=victim/.git git rev-parse master) = $commit1 &&
-	test $(GIT_DIR=victim/.git git rev-parse tofail) = $commit1
+	test $(GIT_DIR=victim git rev-parse master) = $commit1 &&
+	test $(GIT_DIR=victim git rev-parse tofail) = $commit1
 '
 
 test_expect_success 'hooks ran' '
-	test -f victim/.git/pre-receive.args &&
-	test -f victim/.git/pre-receive.stdin &&
-	test -f victim/.git/update.args &&
-	test -f victim/.git/update.stdin &&
-	test -f victim/.git/post-receive.args &&
-	test -f victim/.git/post-receive.stdin &&
-	test -f victim/.git/post-update.args &&
-	test -f victim/.git/post-update.stdin
+	test -f victim/pre-receive.args &&
+	test -f victim/pre-receive.stdin &&
+	test -f victim/update.args &&
+	test -f victim/update.stdin &&
+	test -f victim/post-receive.args &&
+	test -f victim/post-receive.stdin &&
+	test -f victim/post-update.args &&
+	test -f victim/post-update.stdin
 '
 
 test_expect_success 'pre-receive hook input' '
 	(echo $commit0 $commit1 refs/heads/master;
 	 echo $commit1 $commit0 refs/heads/tofail
-	) | test_cmp - victim/.git/pre-receive.stdin
+	) | test_cmp - victim/pre-receive.stdin
 '
 
 test_expect_success 'update hook arguments' '
 	(echo refs/heads/master $commit0 $commit1;
 	 echo refs/heads/tofail $commit1 $commit0
-	) | test_cmp - victim/.git/update.args
+	) | test_cmp - victim/update.args
 '
 
 test_expect_success 'post-receive hook input' '
 	echo $commit0 $commit1 refs/heads/master |
-	test_cmp - victim/.git/post-receive.stdin
+	test_cmp - victim/post-receive.stdin
 '
 
 test_expect_success 'post-update hook arguments' '
 	echo refs/heads/master |
-	test_cmp - victim/.git/post-update.args
+	test_cmp - victim/post-update.args
 '
 
 test_expect_success 'all hook stdin is /dev/null' '
-	! test -s victim/.git/update.stdin &&
-	! test -s victim/.git/post-update.stdin
+	! test -s victim/update.stdin &&
+	! test -s victim/post-update.stdin
 '
 
 test_expect_success 'all *-receive hook args are empty' '
-	! test -s victim/.git/pre-receive.args &&
-	! test -s victim/.git/post-receive.args
+	! test -s victim/pre-receive.args &&
+	! test -s victim/post-receive.args
 '
 
 test_expect_success 'send-pack produced no output' '
diff --git a/t/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh
index cb9aacc..2ad080f 100755
--- a/t/t5405-send-pack-rewind.sh
+++ b/t/t5405-send-pack-rewind.sh
@@ -16,7 +16,8 @@ test_expect_success setup '
 	) &&
 
 	>file2 && git add file2 && test_tick &&
-	git commit -m Second
+	git commit -m Second &&
+	git checkout -b otherbranch
 
 '
 
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 3411107..7070171 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -12,7 +12,8 @@ mk_empty () {
 	(
 		cd testrepo &&
 		git init &&
-		mv .git/hooks .git/hooks-disabled
+		mv .git/hooks .git/hooks-disabled &&
+		git symbolic-ref HEAD refs/heads/nonexistent
 	)
 }
 
diff --git a/t/t5517-push-mirror.sh b/t/t5517-push-mirror.sh
index ea49ded..5536077 100755
--- a/t/t5517-push-mirror.sh
+++ b/t/t5517-push-mirror.sh
@@ -19,7 +19,7 @@ mk_repo_pair () {
 	mkdir mirror &&
 	(
 		cd mirror &&
-		git init
+		git --bare init
 	) &&
 	mkdir master &&
 	(
-- 
1.6.0.3.866.gc189b

[PATCH 4/4] receive-pack: deny push to current branch of non-bare repo

From: Jeff King <hidden>
Date: 2016-06-15 22:45:37

Pushing into the currently checked out branch of a non-bare
repository can be dangerous; the HEAD then loses sync with
the index and working tree, and it looks in the receiving
repo as if the pushed changes have been reverted in the
index (since they were never there in the first place).

This patch adds a safety valve that checks for this
condition and denies the push. We trigger the check only on
a non-bare repository, since a bare does not have a working
tree (and in fact, pushing to the HEAD branch is a common
workflow for publishing repositories).

This behavior is still configurable, though, since some very
specific setups may want to allow such a push if they know
they will take action to reconcile the working tree and HEAD
afterwards (e.g., a post-receive hook that does "git reset
--hard").

Signed-off-by: Jeff King <redacted>
---
My feeling is that this is dangerous behavior that we see new users
confused by, so it is worth addressing. The other obvious route is to
at least _try_ the merge, and if it comes out cleanly, to allow it.

But it looks like Sam is promoting that as a hook, which makes a lot
more sense to me. And we can still support that, but the user of the
hook must now not only install the hook, but also set the config value.

I am open to comments on the name of the config value. Somebody at the
GitTogether suggested (possibly under the influence of beer) that it be
receive.PEBKAC (since you should only turn it off if you really know
what you're doing, you would set PEBKAC to "false"), but I didn't want
to give the impression that git wasn't user-friendly. ;)

One final issue: do we need to make a special exception for "branch yet
to be born"? I believe we do so for the analagous "fetch" situation.

 Documentation/config.txt |    8 ++++++++
 builtin-receive-pack.c   |   16 ++++++++++++++++
 t/t5516-fetch-push.sh    |   21 +++++++++++++++++++++
 3 files changed, 45 insertions(+), 0 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 965ed74..971f01e 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1198,6 +1198,14 @@ receive.denyNonFastForwards::
 	even if that push is forced. This configuration variable is
 	set when initializing a shared repository.
 
+receive.denyCurrentBranch::
+	If set to true, receive-pack will deny a ref update to the
+	currently checked out branch of a non-bare repository. Such a
+	push is potentially dangerous because it brings the HEAD out of
+	sync with the index and working tree; only set this to "false"
+	if you know what you are doing (e.g., you have a post-receive
+	hook which resets the working tree). Defaults to "true".
+
 transfer.unpackLimit::
 	When `fetch.unpackLimit` or `receive.unpackLimit` are
 	not set, the value of this variable is used instead.
diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c
index 7f9f134..06ad545 100644
--- a/builtin-receive-pack.c
+++ b/builtin-receive-pack.c
@@ -13,6 +13,7 @@ static const char receive_pack_usage[] = "git-receive-pack <git-dir>";
 
 static int deny_deletes = 0;
 static int deny_non_fast_forwards = 0;
+static int deny_current_branch = 1;
 static int receive_fsck_objects;
 static int receive_unpack_limit = -1;
 static int transfer_unpack_limit = -1;
@@ -49,6 +50,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
 		return 0;
 	}
 
+	if (!strcmp(var, "receive.denycurrentbranch")) {
+		deny_current_branch = git_config_bool(var, value);
+		return 0;
+	}
+
 	return git_default_config(var, value, cb);
 }
 
@@ -186,6 +192,16 @@ static const char *update(struct command *cmd)
 		return "funny refname";
 	}
 
+	if (deny_current_branch && !is_bare_repository()) {
+		unsigned char sha1[20];
+		const char *head = resolve_ref("HEAD", sha1, 0, NULL);
+		if (!strcmp(head, name)) {
+			error("refusing to update checked out branch: %s",
+				name);
+			return "branch is currently checked out";
+		}
+	}
+
 	if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {
 		error("unpack should have generated %s, "
 		      "but I can't find it!", sha1_to_hex(new_sha1));
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 7070171..579c3d8 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -487,4 +487,25 @@ test_expect_success 'allow deleting an invalid remote ref' '
 
 '
 
+test_expect_success 'deny push to HEAD to non-bare repository' '
+	mk_test heads/master
+	(cd testrepo && git checkout master) &&
+	test_must_fail git push testrepo master
+'
+
+test_expect_success 'allow push to HEAD of bare repository' '
+	mk_test heads/master
+	(cd testrepo && git checkout master && git config core.bare true) &&
+	git push testrepo master
+'
+
+test_expect_success 'allow push to HEAD of non-bare repository w/ config' '
+	mk_test heads/master
+	(cd testrepo &&
+		git checkout master &&
+		git config receive.denyCurrentBranch false
+	) &&
+	git push testrepo master
+'
+
 test_done
-- 
1.6.0.3.866.gc189b

Re: [RFC PATCH 0/4] deny push to current branch of non-bare repo

From: Mark Burton <hidden>
Date: 2016-06-15 22:45:37

Jeff King <peff <at> peff.net> writes:
The short of it is that it's dangerous, we see people confused by it
(there was another one just yesterday), and it's a FAQ:

  http://git.or.cz/gitwiki/GitFaq#head-b96f48bc9c925074be9f95c0fce69bcece5f6e73

The FAQ even says "don't do this until you know what you are doing." So
the safety valve is configurable, so that those who know what they are
doing can switch it off.
When I first tried to use git I was bitten by exactly this problem. I know,
RTFM, but when everything is new, it's easy to undervalue the words of wisdom
when you don't understand the bigger picture and the rational behind the advice.

I now happily work with non-bare repositories on my main machine that I push to
from my satellite development machines but, of course, I don't push to the head
branches but, instead, to remote branches and then merge on the main machine.

I wouldn't have wasted as much time getting my head around this if git had
refused to accept the push to the current branch but, instead, issued a suitable
message telling me I probably didn't want to be doing that.

So, from my own experience, I would say this would be a good feature to add.

Cheers,

Mark

Re: [PATCH 1/4] t5400: expect success for denying deletion

From: Jan Krüger <hidden>
Date: 2016-06-15 22:45:37

Hi,

On Fri, 7 Nov 2008 17:09:55 -0500, Jeff King [off-list ref] wrote:
Reading over the mailing list postings which led to a240de11, I think
it is simply a case that Jan didn't fully understand what
expect_failure meant

Yes, that's exactly what happened, and it won't likely happen again.
Thanks for fixing and for the Cc.

-Jan
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help