receive-pack: explain what to do when push updates the current branch
authorJunio C Hamano <gitster@pobox.com>
Sun, 1 Feb 2009 01:34:05 +0000 (17:34 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 3 Feb 2009 08:39:18 +0000 (00:39 -0800)
This makes "git push" issue a more detailed instruction when a user pushes
into the current branch of a non-bare repository without having an
explicit configuration set to receive.denycurrentbranch.  In such a case,
it will also tell the user that the default will change to refusal in a
future version of git.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin-receive-pack.c
t/t5516-fetch-push.sh

index 6564a97cefe9061ec94f5db6eb945a405376d02f..6f61c45fdd039b20688bedb91b6470c5ae105dad 100644 (file)
@@ -12,6 +12,7 @@
 static const char receive_pack_usage[] = "git-receive-pack <git-dir>";
 
 enum deny_action {
+       DENY_UNCONFIGURED,
        DENY_IGNORE,
        DENY_WARN,
        DENY_REFUSE,
@@ -19,7 +20,7 @@ enum deny_action {
 
 static int deny_deletes = 0;
 static int deny_non_fast_forwards = 0;
-static enum deny_action deny_current_branch = DENY_WARN;
+static enum deny_action deny_current_branch = DENY_UNCONFIGURED;
 static int receive_fsck_objects;
 static int receive_unpack_limit = -1;
 static int transfer_unpack_limit = -1;
@@ -214,6 +215,35 @@ static int is_ref_checked_out(const char *ref)
        return !strcmp(head, ref);
 }
 
+static char *warn_unconfigured_deny_msg[] = {
+       "Updating the currently checked out branch may cause confusion,",
+       "as the index and work tree do not reflect changes that are in HEAD.",
+       "As a result, you may see the changes you just pushed into it",
+       "reverted when you run 'git diff' over there, and you may want",
+       "to run 'git reset --hard' before starting to work to recover.",
+       "",
+       "You can set 'receive.denyCurrentBranch' configuration variable to",
+       "'refuse' in the remote repository to forbid pushing into its",
+       "current branch."
+       "",
+       "To allow pushing into the current branch, you can set it to 'ignore';",
+       "but this is not recommended unless you arranged to update its work",
+       "tree to match what you pushed in some other way.",
+       "",
+       "To squelch this message, you can set it to 'warn'.",
+       "",
+       "Note that the default will change in a future version of git",
+       "to refuse updating the current branch unless you have the",
+       "configuration variable set to either 'ignore' or 'warn'."
+};
+
+static void warn_unconfigured_deny(void)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(warn_unconfigured_deny_msg); i++)
+               warning(warn_unconfigured_deny_msg[i]);
+}
+
 static const char *update(struct command *cmd)
 {
        const char *name = cmd->ref_name;
@@ -227,22 +257,20 @@ static const char *update(struct command *cmd)
                return "funny refname";
        }
 
-       switch (deny_current_branch) {
-       case DENY_IGNORE:
-               break;
-       case DENY_WARN:
-               if (!is_ref_checked_out(name))
+       if (is_ref_checked_out(name)) {
+               switch (deny_current_branch) {
+               case DENY_IGNORE:
                        break;
-               warning("updating the currently checked out branch; this may"
-                       " cause confusion,\n"
-                       "as the index and working tree do not reflect changes"
-                       " that are now in HEAD.");
-               break;
-       case DENY_REFUSE:
-               if (!is_ref_checked_out(name))
+               case DENY_UNCONFIGURED:
+               case DENY_WARN:
+                       warning("updating the current branch");
+                       if (deny_current_branch == DENY_UNCONFIGURED)
+                               warn_unconfigured_deny();
                        break;
-               error("refusing to update checked out branch: %s", name);
-               return "branch is currently checked out";
+               case DENY_REFUSE:
+                       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)) {
index 4426df9226535c55eacff80217c4ab70f77639b6..89649e7a9b2dc138bb9618d4e5770e76f62dc7e0 100755 (executable)
@@ -492,7 +492,7 @@ test_expect_success 'warn on push to HEAD of non-bare repository' '
                git checkout master &&
                git config receive.denyCurrentBranch warn) &&
        git push testrepo master 2>stderr &&
-       grep "warning.*this may cause confusion" stderr
+       grep "warning: updating the current branch" stderr
 '
 
 test_expect_success 'deny push to HEAD of non-bare repository' '
@@ -510,7 +510,7 @@ test_expect_success 'allow push to HEAD of bare repository (bare)' '
                git config receive.denyCurrentBranch true &&
                git config core.bare true) &&
        git push testrepo master 2>stderr &&
-       ! grep "warning.*this may cause confusion" stderr
+       ! grep "warning: updating the current branch" stderr
 '
 
 test_expect_success 'allow push to HEAD of non-bare repository (config)' '
@@ -520,7 +520,7 @@ test_expect_success 'allow push to HEAD of non-bare repository (config)' '
                git config receive.denyCurrentBranch false
        ) &&
        git push testrepo master 2>stderr &&
-       ! grep "warning.*this may cause confusion" stderr
+       ! grep "warning: updating the current branch" stderr
 '
 
 test_expect_success 'fetch with branches' '