{"thread":{"id":"10490","subject":"[PATCH 5/8] push, send-pack: support pushing HEAD to real ref name","startedAt":"2007-10-27T16:49:59Z","lastAt":"2007-10-31T15:08:37Z","messageCount":36,"participants":["Steffen Prohaska","Daniel Barkalow","Junio C Hamano","Shawn O. Pearce","Brian Gernhardt"],"isPatch":true,"patchVersion":1,"patchTotal":8},"messages":[{"id":"57362","messageId":"119350380778-git-send-email-prohaska@zib.de","threadId":"10490","inReplyTo":null,"subject":"[PATCH 0/8 v2] improve push's refspec handling","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-27T16:49:59Z","receivedAt":"2007-10-27T16:49:59Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"This patch series improves the refspec handling in push.\n\nIt is a replacement for the series in sp/push-refspec\n(666df53d6868bf56ca6c9ed0a927d612c67fe68c).\n\nThe series addresses some issues that were recently discussed on the\nmailing list.\n- creating remote refs requires a more explicit command [1].\n- the current branch can be pushed as \"git push HEAD\" [2].\n- matching of refs use same rules as git rev-parse [3].\n- annoying error messages when working with shared repos are supressed [4].\n\n[1] http://marc.info/?l=git&m=119286893014690&w=2\n[2] http://marc.info/?l=git&m=119089831513994&w=2\n[3] http://marc.info/?l=git&m=119224567631084&w=2\n[4] http://marc.info/?t=119305127000001&r=1&w=2\n\n\nNote, existing setups may break. Therefore, we need to decide if this\nseries can be applied before git 1.6.\n\nAll tests pass.\n\n    Steffen\n\n Documentation/git-http-push.txt |    6 ++\n Documentation/git-push.txt      |    8 ++-\n Documentation/git-send-pack.txt |   18 ++++-\n builtin-push.c                  |    6 ++-\n builtin-rev-parse.c             |   27 +++++---\n cache.h                         |    2 +\n http-push.c                     |    9 ++-\n remote.c                        |   41 ++++++++----\n remote.h                        |    2 +-\n send-pack.c                     |   70 ++++++++++++++++-----\n sha1_name.c                     |   52 +++++++++++++----\n t/t5516-fetch-push.sh           |  127 ++++++++++++++++++++++++++++++++++++++-\n transport.c                     |    8 ++-\n transport.h                     |    1 +\n 14 files changed, 311 insertions(+), 66 deletions(-)\n\n [PATCH 1/8] push: change push to fail if short ref name does not exist\n [PATCH 2/8] push: teach push new flag --create\n    these two should be kept together.\n\n [PATCH 3/8] add get_sha1_with_real_ref() returning full name of ref on demand\n\n [PATCH 4/8] rev-parse: teach \"git rev-parse --symbolic\" to print the full ref name\n    This one is a bit off-topic and could be skipped.\n\n [PATCH 5/8] push, send-pack: support pushing HEAD to real ref name\n\n [PATCH 6/8] add ref_cmp_full_short() comparing full ref name with a short name\n [PATCH 7/8] push: use same rules as git-rev-parse to resolve refspecs\n\n [PATCH 8/8] push: teach push to be quiet if local ref is strict subset of remote ref\n"},{"id":"57367","messageId":"11935038081211-git-send-email-prohaska@zib.de","threadId":"10490","inReplyTo":"119350380778-git-send-email-prohaska@zib.de","subject":"[PATCH 1/8] push: change push to fail if short ref name does not exist","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-27T16:50:00Z","receivedAt":"2007-10-27T16:50:00Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"You can use a branch's shortname to push it. Push used to create\nthe branch on the remote side if it did not yet exist. If you\nspecified the wrong branch accidentally it was created. A safety\nvalve that pushes only existing branches may help to avoid\nerrors.\n\nThis commit changes push to fail if the remote ref does not yet\nexist and the refspec does not start with refs/. Remote refs must\nexplicitly be created with their full name.\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\n---\n remote.c              |    5 +++--\n t/t5516-fetch-push.sh |   34 ++++++++++++++++++++++++++++++++--\n 2 files changed, 35 insertions(+), 4 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex 170015a..ec992c9 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -611,6 +611,7 @@ static int match_explicit(struct ref *src, struct ref *dst,\n \tstruct ref *matched_src, *matched_dst;\n \n \tconst char *dst_value = rs->dst;\n+\tconst char * const orig_dst_value = rs->dst ? rs->dst : rs->src;\n \n \tif (rs->pattern)\n \t\treturn errs;\n@@ -647,12 +648,12 @@ static int match_explicit(struct ref *src, struct ref *dst,\n \tcase 1:\n \t\tbreak;\n \tcase 0:\n-\t\tif (!memcmp(dst_value, \"refs/\", 5))\n+\t\tif (!memcmp(orig_dst_value , \"refs/\", 5))\n \t\t\tmatched_dst = make_linked_ref(dst_value, dst_tail);\n \t\telse\n \t\t\terror(\"dst refspec %s does not match any \"\n \t\t\t      \"existing ref on the remote and does \"\n-\t\t\t      \"not start with refs/.\", dst_value);\n+\t\t\t      \"not start with refs/.\", orig_dst_value);\n \t\tbreak;\n \tdefault:\n \t\tmatched_dst = NULL;\ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex 4fbd5b1..5ba09e2 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -126,6 +126,36 @@ test_expect_success 'push with wildcard' '\n \t)\n '\n \n+test_expect_success 'push nonexisting (1)' '\n+\n+\tmk_test &&\n+\tif git push testrepo master\n+\tthen\n+\t\techo \"Oops, should have failed\"\n+\t\tfalse\n+\tfi\n+\n+'\n+\n+test_expect_success 'push nonexisting (2)' '\n+\n+\tmk_test &&\n+\tif git push testrepo heads/master\n+\tthen\n+\t\techo \"Oops, should have failed\"\n+\t\tfalse\n+\tfi\n+\n+'\n+\n+test_expect_success 'push nonexisting (3)' '\n+\n+\tmk_test &&\n+\tgit push testrepo refs/heads/master &&\n+\tcheck_push_result $the_commit heads/master\n+\n+'\n+\n test_expect_success 'push with matching heads' '\n \n \tmk_test heads/master &&\n@@ -225,7 +255,7 @@ test_expect_success 'push with colon-less refspec (3)' '\n \t\tgit tag -d frotz\n \tfi &&\n \tgit branch -f frotz master &&\n-\tgit push testrepo frotz &&\n+\tgit push testrepo refs/heads/frotz &&\n \tcheck_push_result $the_commit heads/frotz &&\n \ttest 1 = $( cd testrepo && git show-ref | wc -l )\n '\n@@ -238,7 +268,7 @@ test_expect_success 'push with colon-less refspec (4)' '\n \t\tgit branch -D frotz\n \tfi &&\n \tgit tag -f frotz &&\n-\tgit push testrepo frotz &&\n+\tgit push testrepo refs/tags/frotz &&\n \tcheck_push_result $the_commit tags/frotz &&\n \ttest 1 = $( cd testrepo && git show-ref | wc -l )\n \n-- \n1.5.3.4.1261.g626eb\n"},{"id":"57361","messageId":"11935038081650-git-send-email-prohaska@zib.de","threadId":"10490","inReplyTo":"11935038081211-git-send-email-prohaska@zib.de","subject":"[PATCH 2/8] push: teach push new flag --create","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-27T16:50:01Z","receivedAt":"2007-10-27T16:50:01Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"Refs that do not start with 'refs/' will only be created\nat the remote if --create is used.\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\n---\n Documentation/git-http-push.txt |    6 ++++++\n Documentation/git-push.txt      |    8 +++++++-\n Documentation/git-send-pack.txt |   14 +++++++++++---\n builtin-push.c                  |    6 +++++-\n http-push.c                     |    9 +++++++--\n remote.c                        |   18 +++++++++++++-----\n remote.h                        |    2 +-\n send-pack.c                     |    9 +++++++--\n t/t5516-fetch-push.sh           |    8 ++++++++\n transport.c                     |    8 ++++++--\n transport.h                     |    1 +\n 11 files changed, 72 insertions(+), 17 deletions(-)\n\ndiff --git a/Documentation/git-http-push.txt b/Documentation/git-http-push.txt\nindex 3a69b71..8753611 100644\n--- a/Documentation/git-http-push.txt\n+++ b/Documentation/git-http-push.txt\n@@ -30,6 +30,12 @@ OPTIONS\n \tthe remote repository can lose commits; use it with\n \tcare.\n \n+\\--create::\n+\tUsually, the command refuses to create a remote ref that is\n+\tnot specified by its full name, i.e. starting with 'refs/'.\n+\tThis flag tells the command to create the remote ref under\n+\tthe full name of the local matching ref.\n+\n --dry-run::\n \tDo everything except actually send the updates.\n \ndiff --git a/Documentation/git-push.txt b/Documentation/git-push.txt\nindex e5dd4c1..67b354b 100644\n--- a/Documentation/git-push.txt\n+++ b/Documentation/git-push.txt\n@@ -9,7 +9,7 @@ git-push - Update remote refs along with associated objects\n SYNOPSIS\n --------\n [verse]\n-'git-push' [--all] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>]\n+'git-push' [--all] [--dry-run] [--create] [--tags] [--receive-pack=<git-receive-pack>]\n            [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]\n \n DESCRIPTION\n@@ -86,6 +86,12 @@ the remote repository.\n \tThis flag disables the check.  This can cause the\n \tremote repository to lose commits; use it with care.\n \n+\\--create::\n+\tUsually, the command refuses to create a remote ref that is\n+\tnot specified by its full name, i.e. starting with 'refs/'.\n+\tThis flag tells the command to create the remote ref under\n+\tthe full name of the local matching ref.\n+\n \\--repo=<repo>::\n \tWhen no repository is specified the command defaults to\n \t\"origin\"; this overrides it.\ndiff --git a/Documentation/git-send-pack.txt b/Documentation/git-send-pack.txt\nindex 2fa01d4..01495df 100644\n--- a/Documentation/git-send-pack.txt\n+++ b/Documentation/git-send-pack.txt\n@@ -44,6 +44,12 @@ OPTIONS\n \tthe remote repository can lose commits; use it with\n \tcare.\n \n+\\--create::\n+\tUsually, the command refuses to create a remote ref that is\n+\tnot specified by its full name, i.e. starting with 'refs/'.\n+\tThis flag tells the command to create the remote ref under\n+\tthe full name of the local matching ref.\n+\n \\--verbose::\n \tRun verbosely.\n \n@@ -97,9 +103,11 @@ destination side.\n    * it has to start with \"refs/\"; <dst> is used as the\n      destination literally in this case.\n \n-   * <src> == <dst> and the ref that matched the <src> must not\n-     exist in the set of remote refs; the ref matched <src>\n-     locally is used as the name of the destination.\n+   * Only <src> is specified and the ref that matched\n+     <src> must not exist in the set of remote refs;\n+     and the '--create' flag is used;\n+     the ref matched <src> locally is used as the name of\n+     the destination.\n \n Without '--force', the <src> ref is stored at the remote only if\n <dst> does not exist, or <dst> is a proper subset (i.e. an\ndiff --git a/builtin-push.c b/builtin-push.c\nindex 4b39ef3..4ab1401 100644\n--- a/builtin-push.c\n+++ b/builtin-push.c\n@@ -8,7 +8,7 @@\n #include \"remote.h\"\n #include \"transport.h\"\n \n-static const char push_usage[] = \"git-push [--all] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]\";\n+static const char push_usage[] = \"git-push [--all] [--dry-run] [--create] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]\";\n \n static int thin, verbose;\n static const char *receivepack;\n@@ -113,6 +113,10 @@ int cmd_push(int argc, const char **argv, const char *prefix)\n \t\t\tflags |= TRANSPORT_PUSH_DRY_RUN;\n \t\t\tcontinue;\n \t\t}\n+\t\tif (!strcmp(arg, \"--create\")) {\n+\t\t\tflags |= TRANSPORT_PUSH_CREATE;\n+\t\t\tcontinue;\n+\t\t}\n \t\tif (!strcmp(arg, \"--tags\")) {\n \t\t\tadd_refspec(\"refs/tags/*\");\n \t\t\tcontinue;\ndiff --git a/http-push.c b/http-push.c\nindex c02a3af..4ad9f26 100644\n--- a/http-push.c\n+++ b/http-push.c\n@@ -13,7 +13,7 @@\n #include <expat.h>\n \n static const char http_push_usage[] =\n-\"git-http-push [--all] [--dry-run] [--force] [--verbose] <remote> [<head>...]\\n\";\n+\"git-http-push [--all] [--dry-run] [--create] [--force] [--verbose] <remote> [<head>...]\\n\";\n \n #ifndef XML_STATUS_OK\n enum XML_Status {\n@@ -81,6 +81,7 @@ static int push_verbosely;\n static int push_all;\n static int force_all;\n static int dry_run;\n+static int create;\n \n static struct object_list *objects;\n \n@@ -2307,6 +2308,10 @@ int main(int argc, char **argv)\n \t\t\t\tdry_run = 1;\n \t\t\t\tcontinue;\n \t\t\t}\n+\t\t\tif (!strcmp(arg, \"--create\")) {\n+\t\t\t\tcreate = 1;\n+\t\t\t\tcontinue;\n+\t\t\t}\n \t\t\tif (!strcmp(arg, \"--verbose\")) {\n \t\t\t\tpush_verbosely = 1;\n \t\t\t\tcontinue;\n@@ -2389,7 +2394,7 @@ int main(int argc, char **argv)\n \tif (!remote_tail)\n \t\tremote_tail = &remote_refs;\n \tif (match_refs(local_refs, remote_refs, &remote_tail,\n-\t\t       nr_refspec, refspec, push_all))\n+\t\t       nr_refspec, refspec, push_all, create))\n \t\treturn -1;\n \tif (!remote_refs) {\n \t\tfprintf(stderr, \"No refs in common and none specified; doing nothing.\\n\");\ndiff --git a/remote.c b/remote.c\nindex ec992c9..8908a19 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -606,7 +606,7 @@ static struct ref *make_linked_ref(const char *name, struct ref ***tail)\n static int match_explicit(struct ref *src, struct ref *dst,\n \t\t\t  struct ref ***dst_tail,\n \t\t\t  struct refspec *rs,\n-\t\t\t  int errs)\n+\t\t\t  int errs, int create)\n {\n \tstruct ref *matched_src, *matched_dst;\n \n@@ -650,6 +650,14 @@ static int match_explicit(struct ref *src, struct ref *dst,\n \tcase 0:\n \t\tif (!memcmp(orig_dst_value , \"refs/\", 5))\n \t\t\tmatched_dst = make_linked_ref(dst_value, dst_tail);\n+\t\telse if (!memcmp(dst_value, \"refs/\", 5))\n+\t\t\tif (create)\n+\t\t\t\tmatched_dst = make_linked_ref(dst_value, dst_tail);\n+\t\t\telse\n+\t\t\t\terror(\"dst refspec %s does not match any \"\n+\t\t\t\t      \"existing ref on the remote. \"\n+\t\t\t\t      \"If you want to create is use --create.\",\n+\t\t\t\t       orig_dst_value);\n \t\telse\n \t\t\terror(\"dst refspec %s does not match any \"\n \t\t\t      \"existing ref on the remote and does \"\n@@ -677,11 +685,11 @@ static int match_explicit(struct ref *src, struct ref *dst,\n \n static int match_explicit_refs(struct ref *src, struct ref *dst,\n \t\t\t       struct ref ***dst_tail, struct refspec *rs,\n-\t\t\t       int rs_nr)\n+\t\t\t       int rs_nr, int create)\n {\n \tint i, errs;\n \tfor (i = errs = 0; i < rs_nr; i++)\n-\t\terrs |= match_explicit(src, dst, dst_tail, &rs[i], errs);\n+\t\terrs |= match_explicit(src, dst, dst_tail, &rs[i], errs, create);\n \treturn -errs;\n }\n \n@@ -711,12 +719,12 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,\n  * without thinking.\n  */\n int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,\n-\t       int nr_refspec, char **refspec, int all)\n+\t       int nr_refspec, char **refspec, int all, int create)\n {\n \tstruct refspec *rs =\n \t\tparse_ref_spec(nr_refspec, (const char **) refspec);\n \n-\tif (match_explicit_refs(src, dst, dst_tail, rs, nr_refspec))\n+\tif (match_explicit_refs(src, dst, dst_tail, rs, nr_refspec, create))\n \t\treturn -1;\n \n \t/* pick the remainder */\ndiff --git a/remote.h b/remote.h\nindex c62636d..7d731b1 100644\n--- a/remote.h\n+++ b/remote.h\n@@ -57,7 +57,7 @@ void ref_remove_duplicates(struct ref *ref_map);\n struct refspec *parse_ref_spec(int nr_refspec, const char **refspec);\n \n int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,\n-\t       int nr_refspec, char **refspec, int all);\n+\t       int nr_refspec, char **refspec, int all, int create);\n \n /*\n  * Given a list of the remote refs and the specification of things to\ndiff --git a/send-pack.c b/send-pack.c\nindex e9b9a39..77acae1 100644\n--- a/send-pack.c\n+++ b/send-pack.c\n@@ -7,7 +7,7 @@\n #include \"remote.h\"\n \n static const char send_pack_usage[] =\n-\"git-send-pack [--all] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\\n\"\n+\"git-send-pack [--all] [--dry-run] [--create] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\\n\"\n \"  --all and explicit <ref> specification are mutually exclusive.\";\n static const char *receivepack = \"git-receive-pack\";\n static int verbose;\n@@ -15,6 +15,7 @@ static int send_all;\n static int force_update;\n static int use_thin_pack;\n static int dry_run;\n+static int create;\n \n /*\n  * Make a pack stream and spit it out into file descriptor fd\n@@ -201,7 +202,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha\n \tif (!remote_tail)\n \t\tremote_tail = &remote_refs;\n \tif (match_refs(local_refs, remote_refs, &remote_tail,\n-\t\t       nr_refspec, refspec, send_all))\n+\t\t       nr_refspec, refspec, send_all, create))\n \t\treturn -1;\n \n \tif (!remote_refs) {\n@@ -398,6 +399,10 @@ int main(int argc, char **argv)\n \t\t\t\tdry_run = 1;\n \t\t\t\tcontinue;\n \t\t\t}\n+\t\t\tif (!strcmp(arg, \"--create\")) {\n+\t\t\t\tcreate = 1;\n+\t\t\t\tcontinue;\n+\t\t\t}\n \t\t\tif (!strcmp(arg, \"--force\")) {\n \t\t\t\tforce_update = 1;\n \t\t\t\tcontinue;\ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex 5ba09e2..42ca0ff 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -156,6 +156,14 @@ test_expect_success 'push nonexisting (3)' '\n \n '\n \n+test_expect_success 'push nonexisting (4)' '\n+\n+\tmk_test &&\n+\tgit push testrepo --create master &&\n+\tcheck_push_result $the_commit heads/master\n+\n+'\n+\n test_expect_success 'push with matching heads' '\n \n \tmk_test heads/master &&\ndiff --git a/transport.c b/transport.c\nindex 400af71..fbdbd0d 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -385,7 +385,7 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons\n \tint argc;\n \tint err;\n \n-\targv = xmalloc((refspec_nr + 11) * sizeof(char *));\n+\targv = xmalloc((refspec_nr + 12) * sizeof(char *));\n \targv[0] = \"http-push\";\n \targc = 1;\n \tif (flags & TRANSPORT_PUSH_ALL)\n@@ -394,6 +394,8 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons\n \t\targv[argc++] = \"--force\";\n \tif (flags & TRANSPORT_PUSH_DRY_RUN)\n \t\targv[argc++] = \"--dry-run\";\n+\tif (flags & TRANSPORT_PUSH_CREATE)\n+\t\targv[argc++] = \"--create\";\n \targv[argc++] = transport->url;\n \twhile (refspec_nr--)\n \t\targv[argc++] = *refspec++;\n@@ -658,7 +660,7 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const\n \tint argc;\n \tint err;\n \n-\targv = xmalloc((refspec_nr + 11) * sizeof(char *));\n+\targv = xmalloc((refspec_nr + 12) * sizeof(char *));\n \targv[0] = \"send-pack\";\n \targc = 1;\n \tif (flags & TRANSPORT_PUSH_ALL)\n@@ -667,6 +669,8 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const\n \t\targv[argc++] = \"--force\";\n \tif (flags & TRANSPORT_PUSH_DRY_RUN)\n \t\targv[argc++] = \"--dry-run\";\n+\tif (flags & TRANSPORT_PUSH_CREATE)\n+\t\targv[argc++] = \"--create\";\n \tif (data->receivepack) {\n \t\tchar *rp = xmalloc(strlen(data->receivepack) + 16);\n \t\tsprintf(rp, \"--receive-pack=%s\", data->receivepack);\ndiff --git a/transport.h b/transport.h\nindex df12ea7..1d6a926 100644\n--- a/transport.h\n+++ b/transport.h\n@@ -30,6 +30,7 @@ struct transport {\n #define TRANSPORT_PUSH_ALL 1\n #define TRANSPORT_PUSH_FORCE 2\n #define TRANSPORT_PUSH_DRY_RUN 4\n+#define TRANSPORT_PUSH_CREATE 8\n \n /* Returns a transport suitable for the url */\n struct transport *transport_get(struct remote *, const char *);\n-- \n1.5.3.4.1261.g626eb\n"},{"id":"57366","messageId":"1193503808519-git-send-email-prohaska@zib.de","threadId":"10490","inReplyTo":"11935038081650-git-send-email-prohaska@zib.de","subject":"[PATCH 3/8] add get_sha1_with_real_ref() returning full name of ref on demand","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-27T16:50:02Z","receivedAt":"2007-10-27T16:50:02Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"Deep inside get_sha1() the name of the requested ref is matched\naccording to the rules documented in git-rev-parse. This patch\nintroduces a function that returns the full name of the matched\nref to the outside.\n\nFor example 'master' is typically returned as 'refs/heads/master'.\n\nThe new function can be used by \"git rev-parse\" to print the full\nname of the matched ref and can be used by \"git send-pack\" to expand\na local ref to its full name.\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\n---\n cache.h     |    1 +\n sha1_name.c |   38 +++++++++++++++++++++++++++-----------\n 2 files changed, 28 insertions(+), 11 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 27485d3..726948b 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -401,6 +401,7 @@ static inline unsigned int hexval(unsigned char c)\n \n extern int get_sha1(const char *str, unsigned char *sha1);\n extern int get_sha1_with_mode(const char *str, unsigned char *sha1, unsigned *mode);\n+extern int get_sha1_with_real_ref(const char *str, unsigned char *sha1, char **real_ref);\n extern int get_sha1_hex(const char *hex, unsigned char *sha1);\n extern char *sha1_to_hex(const unsigned char *sha1);\t/* static buffer result! */\n extern int read_ref(const char *filename, unsigned char *sha1);\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 2d727d5..b820909 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -306,7 +306,7 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)\n \treturn logs_found;\n }\n \n-static int get_sha1_basic(const char *str, int len, unsigned char *sha1)\n+static int get_sha1_basic(const char *str, int len, unsigned char *sha1, char **real_ref_out)\n {\n \tstatic const char *warning = \"warning: refname '%.*s' is ambiguous.\\n\";\n \tchar *real_ref = NULL;\n@@ -378,17 +378,21 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)\n \t\t}\n \t}\n \n-\tfree(real_ref);\n+\tif (real_ref_out) {\n+\t\t*real_ref_out = real_ref;\n+\t} else {\n+\t\tfree(real_ref);\n+\t}\n \treturn 0;\n }\n \n-static int get_sha1_1(const char *name, int len, unsigned char *sha1);\n+static int get_sha1_1(const char *name, int len, unsigned char *sha1, char **real_ref);\n \n static int get_parent(const char *name, int len,\n \t\t      unsigned char *result, int idx)\n {\n \tunsigned char sha1[20];\n-\tint ret = get_sha1_1(name, len, sha1);\n+\tint ret = get_sha1_1(name, len, sha1, /*real_ref=*/ 0);\n \tstruct commit *commit;\n \tstruct commit_list *p;\n \n@@ -418,7 +422,7 @@ static int get_nth_ancestor(const char *name, int len,\n \t\t\t    unsigned char *result, int generation)\n {\n \tunsigned char sha1[20];\n-\tint ret = get_sha1_1(name, len, sha1);\n+\tint ret = get_sha1_1(name, len, sha1, /*real_ref=*/ 0);\n \tif (ret)\n \t\treturn ret;\n \n@@ -471,7 +475,7 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)\n \telse\n \t\treturn -1;\n \n-\tif (get_sha1_1(name, sp - name - 2, outer))\n+\tif (get_sha1_1(name, sp - name - 2, outer, /*real_ref=*/ 0))\n \t\treturn -1;\n \n \to = parse_object(outer);\n@@ -531,7 +535,7 @@ static int get_describe_name(const char *name, int len, unsigned char *sha1)\n \treturn -1;\n }\n \n-static int get_sha1_1(const char *name, int len, unsigned char *sha1)\n+static int get_sha1_1(const char *name, int len, unsigned char *sha1, char **real_ref)\n {\n \tint ret, has_suffix;\n \tconst char *cp;\n@@ -569,7 +573,7 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1)\n \tif (!ret)\n \t\treturn 0;\n \n-\tret = get_sha1_basic(name, len, sha1);\n+\tret = get_sha1_basic(name, len, sha1, real_ref);\n \tif (!ret)\n \t\treturn 0;\n \n@@ -651,14 +655,14 @@ int get_sha1(const char *name, unsigned char *sha1)\n \treturn get_sha1_with_mode(name, sha1, &unused);\n }\n \n-int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)\n+int get_sha1_with_mode_real_ref(const char *name, unsigned char *sha1, unsigned *mode, char** real_ref)\n {\n \tint ret, bracket_depth;\n \tint namelen = strlen(name);\n \tconst char *cp;\n \n \t*mode = S_IFINVALID;\n-\tret = get_sha1_1(name, namelen, sha1);\n+\tret = get_sha1_1(name, namelen, sha1, real_ref);\n \tif (!ret)\n \t\treturn ret;\n \t/* sha1:path --> object name of path in ent sha1\n@@ -709,9 +713,21 @@ int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)\n \t}\n \tif (*cp == ':') {\n \t\tunsigned char tree_sha1[20];\n-\t\tif (!get_sha1_1(name, cp-name, tree_sha1))\n+\t\tif (!get_sha1_1(name, cp-name, tree_sha1, real_ref))\n \t\t\treturn get_tree_entry(tree_sha1, cp+1, sha1,\n \t\t\t\t\t      mode);\n \t}\n \treturn ret;\n }\n+\n+int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)\n+{\n+\treturn get_sha1_with_mode_real_ref(name, sha1, mode, 0);\n+}\n+\n+int get_sha1_with_real_ref(const char *name, unsigned char *sha1, char **real_ref)\n+{\n+\tunsigned unused;\n+\treturn get_sha1_with_mode_real_ref(name, sha1, &unused, real_ref);\n+}\n+\n-- \n1.5.3.4.1261.g626eb\n"},{"id":"57368","messageId":"11935038083369-git-send-email-prohaska@zib.de","threadId":"10490","inReplyTo":"1193503808519-git-send-email-prohaska@zib.de","subject":"[PATCH 4/8] rev-parse: teach \"git rev-parse --symbolic\" to print the full ref name","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-27T16:50:03Z","receivedAt":"2007-10-27T16:50:03Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\"git rev-parse --symbolic\" used to return the ref name as it was\nspecified on the command line. This is changed to returning the\nfull matched ref name, i.e. \"git rev-parse --symbolic master\"\nnow typically returns \"refs/heads/master\".\n\nNote, this changes output of an established command. It might\nbreak existing setups. I checked that it does not break scripts\nin git.git.\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\n---\n builtin-rev-parse.c |   27 +++++++++++++++++----------\n 1 files changed, 17 insertions(+), 10 deletions(-)\n\ndiff --git a/builtin-rev-parse.c b/builtin-rev-parse.c\nindex 8d78b69..e64abeb 100644\n--- a/builtin-rev-parse.c\n+++ b/builtin-rev-parse.c\n@@ -93,7 +93,7 @@ static void show(const char *arg)\n }\n \n /* Output a revision, only if filter allows it */\n-static void show_rev(int type, const unsigned char *sha1, const char *name)\n+static void show_rev(int type, const unsigned char *sha1, const char *name, const char* real_name)\n {\n \tif (!(filter & DO_REVS))\n \t\treturn;\n@@ -102,7 +102,9 @@ static void show_rev(int type, const unsigned char *sha1, const char *name)\n \n \tif (type != show_type)\n \t\tputchar('^');\n-\tif (symbolic && name)\n+\tif (symbolic && real_name)\n+\t\tshow(real_name);\n+\telse if (symbolic && name)\n \t\tshow(name);\n \telse if (abbrev)\n \t\tshow(find_unique_abbrev(sha1, abbrev));\n@@ -131,7 +133,7 @@ static void show_default(void)\n \n \t\tdef = NULL;\n \t\tif (!get_sha1(s, sha1)) {\n-\t\t\tshow_rev(NORMAL, sha1, s);\n+\t\t\tshow_rev(NORMAL, sha1, s, 0);\n \t\t\treturn;\n \t\t}\n \t}\n@@ -139,7 +141,7 @@ static void show_default(void)\n \n static int show_reference(const char *refname, const unsigned char *sha1, int flag, void *cb_data)\n {\n-\tshow_rev(NORMAL, sha1, refname);\n+\tshow_rev(NORMAL, sha1, refname, 0);\n \treturn 0;\n }\n \n@@ -187,8 +189,8 @@ static int try_difference(const char *arg)\n \tif (dotdot == arg)\n \t\tthis = \"HEAD\";\n \tif (!get_sha1(this, sha1) && !get_sha1(next, end)) {\n-\t\tshow_rev(NORMAL, end, next);\n-\t\tshow_rev(symmetric ? NORMAL : REVERSED, sha1, this);\n+\t\tshow_rev(NORMAL, end, next, 0);\n+\t\tshow_rev(symmetric ? NORMAL : REVERSED, sha1, this, 0);\n \t\tif (symmetric) {\n \t\t\tstruct commit_list *exclude;\n \t\t\tstruct commit *a, *b;\n@@ -198,7 +200,7 @@ static int try_difference(const char *arg)\n \t\t\twhile (exclude) {\n \t\t\t\tstruct commit_list *n = exclude->next;\n \t\t\t\tshow_rev(REVERSED,\n-\t\t\t\t\t exclude->item->object.sha1,NULL);\n+\t\t\t\t\t exclude->item->object.sha1, NULL, 0);\n \t\t\t\tfree(exclude);\n \t\t\t\texclude = n;\n \t\t\t}\n@@ -213,6 +215,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n {\n \tint i, as_is = 0, verify = 0;\n \tunsigned char sha1[20];\n+\tchar* real_name = 0;\n \n \tgit_config(git_default_config);\n \n@@ -393,12 +396,16 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t/* Not a flag argument */\n \t\tif (try_difference(arg))\n \t\t\tcontinue;\n-\t\tif (!get_sha1(arg, sha1)) {\n-\t\t\tshow_rev(NORMAL, sha1, arg);\n+\t\tif (!get_sha1_with_real_ref(arg, sha1, &real_name)) {\n+\t\t\tshow_rev(NORMAL, sha1, arg, real_name);\n+\t\t\tif(real_name) {\n+\t\t\t\tfree(real_name);\n+\t\t\t\treal_name = 0;\n+\t\t\t}\n \t\t\tcontinue;\n \t\t}\n \t\tif (*arg == '^' && !get_sha1(arg+1, sha1)) {\n-\t\t\tshow_rev(REVERSED, sha1, arg+1);\n+\t\t\tshow_rev(REVERSED, sha1, arg+1, 0);\n \t\t\tcontinue;\n \t\t}\n \t\tas_is = 1;\n-- \n1.5.3.4.1261.g626eb\n"},{"id":"57360","messageId":"11935038084055-git-send-email-prohaska@zib.de","threadId":"10490","inReplyTo":"11935038083369-git-send-email-prohaska@zib.de","subject":"[PATCH 5/8] push, send-pack: support pushing HEAD to real ref name","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-27T16:50:04Z","receivedAt":"2007-10-27T16:50:04Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"This teaches \"push <remote> HEAD\" to resolve HEAD on the local\nside to its real ref name, e.g. refs/heads/master, and then\nuse the real ref name on the remote side to search a matching\nremote ref.\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\n---\n remote.c              |   13 ++++++++++---\n t/t5516-fetch-push.sh |   29 +++++++++++++++++++++++++++++\n 2 files changed, 39 insertions(+), 3 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex 8908a19..1c96659 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -575,6 +575,8 @@ static struct ref *try_explicit_object_name(const char *name)\n \tunsigned char sha1[20];\n \tstruct ref *ref;\n \tint len;\n+\tchar *real_name = 0;\n+\tconst char *best_name;\n \n \tif (!*name) {\n \t\tref = alloc_ref(20);\n@@ -582,12 +584,17 @@ static struct ref *try_explicit_object_name(const char *name)\n \t\thashclr(ref->new_sha1);\n \t\treturn ref;\n \t}\n-\tif (get_sha1(name, sha1))\n+\tif (get_sha1_with_real_ref(name, sha1, &real_name))\n \t\treturn NULL;\n-\tlen = strlen(name) + 1;\n+\tbest_name = real_name ? real_name : name;\n+\tlen = strlen(best_name) + 1;\n \tref = alloc_ref(len);\n-\tmemcpy(ref->name, name, len);\n+\tmemcpy(ref->name, best_name, len);\n \thashcpy(ref->new_sha1, sha1);\n+\n+\tif (real_name) {\n+\t\tfree(real_name);\n+\t}\n \treturn ref;\n }\n \ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex 42ca0ff..0ff791a 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -282,6 +282,35 @@ test_expect_success 'push with colon-less refspec (4)' '\n \n '\n \n+test_expect_success 'push with HEAD' '\n+\n+\tmk_test heads/master &&\n+\tgit push testrepo HEAD &&\n+\tcheck_push_result $the_commit heads/master\n+\n+'\n+\n+test_expect_success 'push with HEAD (--create)' '\n+\n+\tmk_test &&\n+\tgit push --create testrepo HEAD &&\n+\tcheck_push_result $the_commit heads/master\n+\n+'\n+\n+test_expect_success 'push with HEAD nonexisting at remote' '\n+\n+\tmk_test heads/master &&\n+\tgit checkout -b local master &&\n+\tif git push testrepo HEAD\n+\tthen\n+\t\techo \"Oops, should have failed\"\n+\t\tfalse\n+\telse\n+\t\tcheck_push_result $the_first_commit heads/master\n+\tfi\n+'\n+\n test_expect_success 'push with dry-run' '\n \n \tmk_test heads/master &&\n-- \n1.5.3.4.1261.g626eb\n"},{"id":"57365","messageId":"11935038084130-git-send-email-prohaska@zib.de","threadId":"10490","inReplyTo":"11935038084055-git-send-email-prohaska@zib.de","subject":"[PATCH 6/8] add ref_cmp_full_short() comparing full ref name with a short name","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-27T16:50:05Z","receivedAt":"2007-10-27T16:50:05Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"ref_cmp_full_short(full_name, short_name) expands short_name according\nto the rules documented in git-rev-parse and compares the expanded\nname with full_name. It reports a match by returning 0.\n\nThis function makes the rules for resolving refs to sha1s available\nfor string comparison. Before this change, the rules were buried in\nget_sha1*() and dwim_ref().\n\nref_cmp_full_short() will be used for matching refspecs in git-send-pack.\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\n---\n cache.h     |    1 +\n sha1_name.c |   14 ++++++++++++++\n 2 files changed, 15 insertions(+), 0 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 726948b..e1385ac 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -406,6 +406,7 @@ extern int get_sha1_hex(const char *hex, unsigned char *sha1);\n extern char *sha1_to_hex(const unsigned char *sha1);\t/* static buffer result! */\n extern int read_ref(const char *filename, unsigned char *sha1);\n extern const char *resolve_ref(const char *path, unsigned char *sha1, int, int *);\n+extern int ref_cmp_full_short(const char *full_name, const char *short_name);\n extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref);\n extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);\n \ndiff --git a/sha1_name.c b/sha1_name.c\nindex b820909..2a1e093 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -249,6 +249,20 @@ static const char *ref_fmt[] = {\n \tNULL\n };\n \n+int ref_cmp_full_short(const char *full_name, const char *short_name)\n+{\n+\tconst char **p;\n+\tconst int short_name_len = strlen(short_name);\n+\n+\tfor (p = ref_fmt; *p; p++) {\n+\t\tif (strcmp(full_name, mkpath(*p, short_name_len, short_name)) == 0) {\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\n+\treturn -1;\n+}\n+\n int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)\n {\n \tconst char **p, *r;\n-- \n1.5.3.4.1261.g626eb\n"},{"id":"57364","messageId":"11935038083116-git-send-email-prohaska@zib.de","threadId":"10490","inReplyTo":"11935038084130-git-send-email-prohaska@zib.de","subject":"[PATCH 7/8] push: use same rules as git-rev-parse to resolve refspecs","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-27T16:50:06Z","receivedAt":"2007-10-27T16:50:06Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"This commit changes the rules for resolving refspecs to match the\nrules for resolving refs in rev-parse. git-rev-parse uses clear rules\nto resolve a short ref to its full name, which are well documented.\nThe rules for resolving refspecs documented in git-send-pack were\nless strict and harder to understand. This commit replaces them by\nthe rules of git-rev-parse.\n\nThe unified rules are easier to understand and better resolve ambiguous\ncases. You can now push from a repository containing several branches\nending on the same short name.\n\nNote, this breaks existing setups. For example \"master\" will no longer\nresolve to \"origin/master\".\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\n---\n Documentation/git-send-pack.txt |    4 +++-\n remote.c                        |    5 +----\n t/t5516-fetch-push.sh           |   12 +++++++++++-\n 3 files changed, 15 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/git-send-pack.txt b/Documentation/git-send-pack.txt\nindex 01495df..08bcc25 100644\n--- a/Documentation/git-send-pack.txt\n+++ b/Documentation/git-send-pack.txt\n@@ -91,7 +91,9 @@ Each pattern pair consists of the source side (before the colon)\n and the destination side (after the colon).  The ref to be\n pushed is determined by finding a match that matches the source\n side, and where it is pushed is determined by using the\n-destination side.\n+destination side. The rules used to match a ref are the same\n+rules used by gitlink:git-rev-parse[1] to resolve a symbolic ref\n+name.\n \n  - It is an error if <src> does not match exactly one of the\n    local refs.\ndiff --git a/remote.c b/remote.c\nindex 1c96659..176457c 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -519,10 +519,7 @@ static int count_refspec_match(const char *pattern,\n \t\tchar *name = refs->name;\n \t\tint namelen = strlen(name);\n \n-\t\tif (namelen < patlen ||\n-\t\t    memcmp(name + namelen - patlen, pattern, patlen))\n-\t\t\tcontinue;\n-\t\tif (namelen != patlen && name[namelen - patlen - 1] != '/')\n+\t\tif (ref_cmp_full_short(name, pattern))\n \t\t\tcontinue;\n \n \t\t/* A match is \"weak\" if it is with refs outside\ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex 0ff791a..9ec8216 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -183,11 +183,21 @@ test_expect_success 'push with no ambiguity (1)' '\n test_expect_success 'push with no ambiguity (2)' '\n \n \tmk_test remotes/origin/master &&\n-\tgit push testrepo master:master &&\n+\tgit push testrepo master:origin/master &&\n \tcheck_push_result $the_commit remotes/origin/master\n \n '\n \n+test_expect_success 'push with colon-less refspec, no ambiguity' '\n+\n+\tmk_test heads/master heads/t/master &&\n+\tgit branch -f t/master master &&\n+\tgit push testrepo master &&\n+\tcheck_push_result $the_commit heads/master &&\n+\tcheck_push_result $the_first_commit heads/t/master\n+\n+'\n+\n test_expect_success 'push with weak ambiguity (1)' '\n \n \tmk_test heads/master remotes/origin/master &&\n-- \n1.5.3.4.1261.g626eb\n"},{"id":"57363","messageId":"11935038083335-git-send-email-prohaska@zib.de","threadId":"10490","inReplyTo":"11935038083116-git-send-email-prohaska@zib.de","subject":"[PATCH 8/8] push: teach push to be quiet if local ref is strict subset of remote ref","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-27T16:50:07Z","receivedAt":"2007-10-27T16:50:07Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"git push reports errors if a remote ref is not a strict subset\nof a local ref. The push wouldn't be a fast-forward and is\ntherefore refused. This is in general a good idea.\n\nBut these messages can be annoying if you work with a shared\nremote repository. Branches at the remote may have advanced and\nyou haven't pulled to all of your local branches. In this\nsituation, local branches may be strict subsets of the remote\nheads. Pushing such branches wouldn't add any information to the\nremote. It would only reset the remote to an ancestor. A merge\nbetween the remote and the local branch is not very interested\neither because it would just be a fast forward of the local\nbranch. In these cases you're not interested in the error\nmessage.\n\nThis commit teaches git push to be quiet if the local is a strict\nsubset of the remote and no refspec is explicitly specified on\nthe command line. If the --verbose flag is used a \"note:\" is\nprinted for each ignored branch.\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\n---\n send-pack.c           |   61 +++++++++++++++++++++++++++++++++++++------------\n t/t5516-fetch-push.sh |   44 +++++++++++++++++++++++++++++++++++\n 2 files changed, 90 insertions(+), 15 deletions(-)\n\ndiff --git a/send-pack.c b/send-pack.c\nindex 77acae1..b95bed9 100644\n--- a/send-pack.c\n+++ b/send-pack.c\n@@ -259,24 +259,55 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha\n \t\t    !will_delete_ref &&\n \t\t    !is_null_sha1(ref->old_sha1) &&\n \t\t    !ref->force) {\n-\t\t\tif (!has_sha1_file(ref->old_sha1) ||\n-\t\t\t    !ref_newer(ref->peer_ref->new_sha1,\n-\t\t\t\t       ref->old_sha1)) {\n-\t\t\t\t/* We do not have the remote ref, or\n-\t\t\t\t * we know that the remote ref is not\n-\t\t\t\t * an ancestor of what we are trying to\n-\t\t\t\t * push.  Either way this can be losing\n-\t\t\t\t * commits at the remote end and likely\n-\t\t\t\t * we were not up to date to begin with.\n+\t\t\tif (!has_sha1_file(ref->old_sha1)) {\n+\t\t\t\t/* We do not have the remote ref.\n+\t\t\t\t * This can be losing commits at\n+\t\t\t\t * the remote end.\n \t\t\t\t */\n-\t\t\t\terror(\"remote '%s' is not a strict \"\n-\t\t\t\t      \"subset of local ref '%s'. \"\n-\t\t\t\t      \"maybe you are not up-to-date and \"\n-\t\t\t\t      \"need to pull first?\",\n-\t\t\t\t      ref->name,\n-\t\t\t\t      ref->peer_ref->name);\n+\t\t\t\terror(\"You don't have the commit\"\n+\t\t\t\t      \"for the remote ref '%s'.\"\n+\t\t\t\t      \"This may cause losing commits\"\n+\t\t\t\t      \"that cannot be recovered.\",\n+\t\t\t\t      ref->name);\n \t\t\t\tret = -2;\n \t\t\t\tcontinue;\n+\t\t\t} else if (!ref_newer(ref->peer_ref->new_sha1,\n+\t\t\t                      ref->old_sha1)) {\n+\t\t\t\t/* We know that the remote ref is not\n+\t\t\t\t * an ancestor of what we are trying to\n+\t\t\t\t * push. This can be losing commits at\n+\t\t\t\t * the remote end and likely we were not\n+\t\t\t\t * up to date to begin with.\n+\t\t\t\t *\n+\t\t\t\t * Therefore, we don't push.\n+\t\t\t\t *\n+\t\t\t\t * If no explicit refspec was passed on the\n+\t\t\t\t * commandline, then we only report an error\n+\t\t\t\t * if the local is not a strict subset of the\n+\t\t\t\t * remote.  If the local is a strict subset we\n+\t\t\t\t * don't have new commits for the remote.\n+\t\t\t\t * Pulling and pushing wouldn't add anything to\n+\t\t\t\t * the remote.\n+\t\t\t\t *\n+\t\t\t\t */\n+\t\t\t\tif (nr_refspec ||\n+\t\t\t\t    !ref_newer(ref->old_sha1, ref->peer_ref->new_sha1)) {\n+\t\t\t\t\terror(\"remote '%s' is not a strict \"\n+\t\t\t\t\t      \"subset of local ref '%s'. \"\n+\t\t\t\t\t      \"maybe you are not up-to-date and \"\n+\t\t\t\t\t      \"need to pull first?\",\n+\t\t\t\t\t      ref->name,\n+\t\t\t\t\t      ref->peer_ref->name);\n+\t\t\t\t\tret = -2;\n+\t\t\t\t} else if (verbose) {\n+\t\t\t\t\tfprintf(stderr,\n+\t\t\t\t\t        \"note: ignoring local ref '%s' \"\n+\t\t\t\t\t        \"because it is a strict \"\n+\t\t\t\t\t        \"subset of remote '%s'.\\n\",\n+\t\t\t\t\t        ref->peer_ref->name,\n+\t\t\t\t\t        ref->name);\n+\t\t\t\t}\n+\t\t\t\tcontinue;\n \t\t\t}\n \t\t}\n \t\thashcpy(ref->new_sha1, ref->peer_ref->new_sha1);\ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex 9ec8216..c8493f9 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -331,4 +331,48 @@ test_expect_success 'push with dry-run' '\n \tcheck_push_result $old_commit heads/master\n '\n \n+test_expect_success 'push with local is strict subset (must not report error)' '\n+\n+\tmk_test heads/foo &&\n+\tgit push testrepo $the_commit:refs/heads/foo &&\n+\tgit branch -f foo $old_commit &&\n+\tif git push testrepo 2>&1 | grep ^error\n+\tthen\n+\t\techo \"Oops, should not report error\"\n+\t\tfalse\n+\tfi\n+\n+'\n+\n+test_expect_success 'push with explicit refname, local is strict subset (must report error)' '\n+\n+\tmk_test heads/foo &&\n+\tgit push testrepo $the_commit:refs/heads/foo &&\n+\tgit branch -f foo $old_commit &&\n+\tif ! git push testrepo foo 2>&1 | grep ^error\n+\tthen\n+\t\techo \"Oops, should have reported error\"\n+\t\tfalse\n+\tfi\n+\n+'\n+\n+test_expect_success 'push with neither local nor remote is strict subset (must report error)' '\n+\n+\tmk_test heads/foo &&\n+\tgit push testrepo $the_commit:refs/heads/foo &&\n+\tgit branch -f foo $old_commit &&\n+\tgit checkout foo &&\n+\t: >path3 &&\n+\tgit add path3 &&\n+\ttest_tick &&\n+\tgit commit -a -m branched &&\n+\tif ! git push testrepo 2>&1 | grep ^error\n+\tthen\n+\t\techo \"Oops, should have reported error\"\n+\t\tfalse\n+\tfi\n+\n+'\n+\n test_done\n-- \n1.5.3.4.1261.g626eb\n"},{"id":"57376","messageId":"Pine.LNX.4.64.0710271716120.7345@iabervon.org","threadId":"10490","inReplyTo":"11935038081211-git-send-email-prohaska@zib.de","subject":"Re: [PATCH 1/8] push: change push to fail if short ref name does not exist","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2007-10-27T21:42:24Z","receivedAt":"2007-10-27T21:42:24Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sat, 27 Oct 2007, Steffen Prohaska wrote:\n\n> You can use a branch's shortname to push it. Push used to create\n> the branch on the remote side if it did not yet exist. If you\n> specified the wrong branch accidentally it was created. A safety\n> valve that pushes only existing branches may help to avoid\n> errors.\n> \n> This commit changes push to fail if the remote ref does not yet\n> exist and the refspec does not start with refs/. Remote refs must\n> explicitly be created with their full name.\n\nI agree with the change (and I think it's appropriate for master or next), \nbut your implementation is a bit too clever for my tastes.\n\n> Signed-off-by: Steffen Prohaska <prohaska@zib.de>\n> ---\n>  remote.c              |    5 +++--\n>  t/t5516-fetch-push.sh |   34 ++++++++++++++++++++++++++++++++--\n>  2 files changed, 35 insertions(+), 4 deletions(-)\n> \n> diff --git a/remote.c b/remote.c\n> index 170015a..ec992c9 100644\n> --- a/remote.c\n> +++ b/remote.c\n> @@ -611,6 +611,7 @@ static int match_explicit(struct ref *src, struct ref *dst,\n>  \tstruct ref *matched_src, *matched_dst;\n>  \n>  \tconst char *dst_value = rs->dst;\n> +\tconst char * const orig_dst_value = rs->dst ? rs->dst : rs->src;\n\n\"lit_dst_value\" would probably be a better description, and it might be \nworth handling the rs->dst == NULL case where it's handled for dst_value. \nTechnically, this variable, when it doesn't match the final value of \ndst_value, has a value that dst_value never had.\n\n>  \n>  \tif (rs->pattern)\n>  \t\treturn errs;\n> @@ -647,12 +648,12 @@ static int match_explicit(struct ref *src, struct ref *dst,\n>  \tcase 1:\n>  \t\tbreak;\n>  \tcase 0:\n> -\t\tif (!memcmp(dst_value, \"refs/\", 5))\n> +\t\tif (!memcmp(orig_dst_value , \"refs/\", 5))\n>  \t\t\tmatched_dst = make_linked_ref(dst_value, dst_tail);\n\nThis should also be orig_dst_value, too. I know that dst_value and \norig_dst_value must be the same in this case, but it takes a bunch of \nanalysis to demonstrate that, and it's more intuitive to use the value \nyou've just checked anyway, and also to have all of case 0 use the \ndifferently-computed destination.\n\n>  \t\telse\n>  \t\t\terror(\"dst refspec %s does not match any \"\n>  \t\t\t      \"existing ref on the remote and does \"\n> -\t\t\t      \"not start with refs/.\", dst_value);\n> +\t\t\t      \"not start with refs/.\", orig_dst_value);\n\nMaybe the error should provide a hint if dst_value is not the same as \norig_dst_value? (if (!rs->dst) error(\"Did you mean %s?\\n\", dst_value);)\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"57377","messageId":"Pine.LNX.4.64.0710271748440.7345@iabervon.org","threadId":"10490","inReplyTo":"11935038083369-git-send-email-prohaska@zib.de","subject":"Re: [PATCH 4/8] rev-parse: teach \"git rev-parse --symbolic\" to print the full ref name","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2007-10-27T21:53:10Z","receivedAt":"2007-10-27T21:53:10Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sat, 27 Oct 2007, Steffen Prohaska wrote:\n\n> \"git rev-parse --symbolic\" used to return the ref name as it was\n> specified on the command line. This is changed to returning the\n> full matched ref name, i.e. \"git rev-parse --symbolic master\"\n> now typically returns \"refs/heads/master\".\n> \n> Note, this changes output of an established command. It might\n> break existing setups. I checked that it does not break scripts\n> in git.git.\n\nI think this makes the --create option to push unnecessary, as interactive \nusers could use a suggested explicit value (or whatever they actually \nmeant), while scripts could replace $name with $(git rev-parse --symbolic \n$name) as easily as they could add --create, and by more explicit as to \nwhat they're doing.\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"57378","messageId":"Pine.LNX.4.64.0710271756140.7345@iabervon.org","threadId":"10490","inReplyTo":"11935038084055-git-send-email-prohaska@zib.de","subject":"Re: [PATCH 5/8] push, send-pack: support pushing HEAD to real ref name","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2007-10-27T22:03:18Z","receivedAt":"2007-10-27T22:03:18Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sat, 27 Oct 2007, Steffen Prohaska wrote:\n\n> This teaches \"push <remote> HEAD\" to resolve HEAD on the local\n> side to its real ref name, e.g. refs/heads/master, and then\n> use the real ref name on the remote side to search a matching\n> remote ref.\n\nI'd prefer this to be in set_refspecs in builtin-push. That way, it only \napplies to command-line arguments and matches your description better. (If \nyou use a symbolic name on the command line, it follows it, and acts \nexactly as if you used the name it points to).\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"57379","messageId":"Pine.LNX.4.64.0710271811260.7345@iabervon.org","threadId":"10490","inReplyTo":"11935038084130-git-send-email-prohaska@zib.de","subject":"Re: [PATCH 6/8] add ref_cmp_full_short() comparing full ref name with a short name","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2007-10-27T22:16:13Z","receivedAt":"2007-10-27T22:16:13Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Sat, 27 Oct 2007, Steffen Prohaska wrote:\n\n> ref_cmp_full_short(full_name, short_name) expands short_name according\n> to the rules documented in git-rev-parse and compares the expanded\n> name with full_name. It reports a match by returning 0.\n> \n> This function makes the rules for resolving refs to sha1s available\n> for string comparison. Before this change, the rules were buried in\n> get_sha1*() and dwim_ref().\n> \n> ref_cmp_full_short() will be used for matching refspecs in git-send-pack.\n\nI think this and ref_matches_abbrev in remote.c should be both be \nnamed to be more explicit as to which sets of rules they implement, and \nshould agree on order of arguments.\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"57391","messageId":"7v8x5ny9yg.fsf@gitster.siamese.dyndns.org","threadId":"10490","inReplyTo":"1193503808519-git-send-email-prohaska@zib.de","subject":"Re: [PATCH 3/8] add get_sha1_with_real_ref() returning full name of ref on demand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-28T07:28:23Z","receivedAt":"2007-10-28T07:28:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steffen Prohaska <prohaska@zib.de> writes:\n\n> The new function can be used by \"git rev-parse\" to print the full\n> name of the matched ref and can be used by \"git send-pack\" to expand\n> a local ref to its full name.\n\n\"can be\"?  \"will be used to implement git rev-parse --some-option\"?\n\n> +static int get_sha1_1(const char *name, int len, unsigned char *sha1, char **real_ref);\n>  \n>  static int get_parent(const char *name, int len,\n>  \t\t      unsigned char *result, int idx)\n>  {\n>  \tunsigned char sha1[20];\n> -\tint ret = get_sha1_1(name, len, sha1);\n> +\tint ret = get_sha1_1(name, len, sha1, /*real_ref=*/ 0);\n\nA null pointer constant in git sources is spelled as \"NULL\", not \"0\".\n"},{"id":"57392","messageId":"7v3avvy9yc.fsf@gitster.siamese.dyndns.org","threadId":"10490","inReplyTo":"11935038083369-git-send-email-prohaska@zib.de","subject":"Re: [PATCH 4/8] rev-parse: teach \"git rev-parse --symbolic\" to print the full ref name","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-28T07:28:27Z","receivedAt":"2007-10-28T07:28:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steffen Prohaska <prohaska@zib.de> writes:\n\n> \"git rev-parse --symbolic\" used to return the ref name as it was\n> specified on the command line. This is changed to returning the\n> full matched ref name, i.e. \"git rev-parse --symbolic master\"\n> now typically returns \"refs/heads/master\".\n\nThis is to expose \"dwim_ref\" logic, so it might be a good idea\nto introduce a new option --dwim-ref for this purpose.\n\n\tgit rev-parse --symbolic master^2\n\nis designed to give \"master^2\" or fail if \"master\" is not a\nmerge.  Similarly, you would diagnose a failure if somebody asks\nto show\n\n\tgit rev-parse --dwim-ref master~4\n\ninstead of giving \"refs/heads/master~4\".\n\n> +static void show_rev(int type, const unsigned char *sha1, const char *name, const char* real_name)\n> @@ -131,7 +133,7 @@ static void show_default(void)\n>  \n>  \t\tdef = NULL;\n>  \t\tif (!get_sha1(s, sha1)) {\n> -\t\t\tshow_rev(NORMAL, sha1, s);\n> +\t\t\tshow_rev(NORMAL, sha1, s, 0);\n\nA null pointer constant in git sources is spelled \"NULL\" not \"0\".\n\n> @@ -213,6 +215,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n>  {\n>  \tint i, as_is = 0, verify = 0;\n>  \tunsigned char sha1[20];\n> +\tchar* real_name = 0;\n\nPointer sign '*' in git sources go next to the name not the\ntype, as:\n\n\tchar *real_name = NULL;\n"},{"id":"57393","messageId":"7vwst7wvdr.fsf@gitster.siamese.dyndns.org","threadId":"10490","inReplyTo":"11935038084055-git-send-email-prohaska@zib.de","subject":"Re: [PATCH 5/8] push, send-pack: support pushing HEAD to real ref name","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-28T07:28:32Z","receivedAt":"2007-10-28T07:28:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steffen Prohaska <prohaska@zib.de> writes:\n\n> This teaches \"push <remote> HEAD\" to resolve HEAD on the local\n> side to its real ref name, e.g. refs/heads/master, and then\n> use the real ref name on the remote side to search a matching\n> remote ref.\n\nThis probably is a good idea.\n\n> +\tif (real_name) {\n> +\t\tfree(real_name);\n> +\t}\n\nExcess and unnecessary brace pair.\n"},{"id":"57394","messageId":"7vr6jfwvdn.fsf@gitster.siamese.dyndns.org","threadId":"10490","inReplyTo":"11935038084130-git-send-email-prohaska@zib.de","subject":"Re: [PATCH 6/8] add ref_cmp_full_short() comparing full ref name with a short name","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-28T07:28:36Z","receivedAt":"2007-10-28T07:28:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steffen Prohaska <prohaska@zib.de> writes:\n\n> diff --git a/sha1_name.c b/sha1_name.c\n> index b820909..2a1e093 100644\n> --- a/sha1_name.c\n> +++ b/sha1_name.c\n> @@ -249,6 +249,20 @@ static const char *ref_fmt[] = {\n>  \tNULL\n>  };\n>  \n> +int ref_cmp_full_short(const char *full_name, const char *short_name)\n> +{\n> +\tconst char **p;\n> +\tconst int short_name_len = strlen(short_name);\n> +\n> +\tfor (p = ref_fmt; *p; p++) {\n> +\t\tif (strcmp(full_name, mkpath(*p, short_name_len, short_name)) == 0) {\n\nWe usually say \"!strcmp()\" instead for readability.\n"},{"id":"57395","messageId":"7vlk9nwvdj.fsf@gitster.siamese.dyndns.org","threadId":"10490","inReplyTo":"11935038083116-git-send-email-prohaska@zib.de","subject":"Re: [PATCH 7/8] push: use same rules as git-rev-parse to resolve refspecs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-28T07:28:40Z","receivedAt":"2007-10-28T07:28:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steffen Prohaska <prohaska@zib.de> writes:\n\n> This commit changes the rules for resolving refspecs to match the\n> rules for resolving refs in rev-parse. git-rev-parse uses clear rules\n> to resolve a short ref to its full name, which are well documented.\n> The rules for resolving refspecs documented in git-send-pack were\n> less strict and harder to understand. This commit replaces them by\n> the rules of git-rev-parse.\n>\n> The unified rules are easier to understand and better resolve ambiguous\n> cases. You can now push from a repository containing several branches\n> ending on the same short name.\n>\n> Note, this breaks existing setups. For example \"master\" will no longer\n> resolve to \"origin/master\".\n\nIt may \"break\" but I think it is a good change.\n"},{"id":"57396","messageId":"7vfxzvwvde.fsf@gitster.siamese.dyndns.org","threadId":"10490","inReplyTo":"11935038083335-git-send-email-prohaska@zib.de","subject":"Re: [PATCH 8/8] push: teach push to be quiet if local ref is strict subset of remote ref","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-28T07:28:45Z","receivedAt":"2007-10-28T07:28:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steffen Prohaska <prohaska@zib.de> writes:\n\n> git push reports errors if a remote ref is not a strict subset\n> of a local ref. The push wouldn't be a fast-forward and is\n> therefore refused. This is in general a good idea.\n\n> This commit teaches git push to be quiet if the local is a strict\n> subset of the remote and no refspec is explicitly specified on\n> the command line. If the --verbose flag is used a \"note:\" is\n> printed for each ignored branch.\n\nWhat happens to the summary reporting after such a push?  Does\nit say \"branch foo was not pushed because you did not touch it\nsince you fetched and it is already stale with respect to the\nremote side which has updates since then\"?\n\nHow does this interact with the \"pretend we have fetched\nimmediately after we pushed by updating the corresponding remote\ntracking branch\" logic?\n"},{"id":"57397","messageId":"7vabq3wvd6.fsf@gitster.siamese.dyndns.org","threadId":"10490","inReplyTo":"11935038081211-git-send-email-prohaska@zib.de","subject":"Re: [PATCH 1/8] push: change push to fail if short ref name does not exist","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-28T07:28:53Z","receivedAt":"2007-10-28T07:28:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steffen Prohaska <prohaska@zib.de> writes:\n\n> You can use a branch's shortname to push it. Push used to create\n> the branch on the remote side if it did not yet exist. If you\n> specified the wrong branch accidentally it was created. A safety\n> valve that pushes only existing branches may help to avoid\n> errors.\n\nI do not agree with this change.\n\nIf you misspelled the branch name (by the way, it is not a\n\"shortname\", but what follows refs/heads/ is _the_ name of the\nbranch) \"frotz\" as \"frtoz\", and if a branch with the misspelled\nname did _not_ exist locally, it would fail, with or without\nthis change, which is a good thing.\n\nBut if you named \"nitfol\" that exists locally when you meant to\npush \"frotz\" out, if \"nitfol\" remotely existed, we will push\nthat anyway by mistake, even with this change.  It will prevent\nthe push only when \"nitfol\" did not happen to exist at the\nremote side.\n\nEarlier there was a discussion to introduce an optional\nconfiguration that makes \"git push\" without any parameter to\npush only the current branch out, in order to help people who\nwork with shared remote central repository.  That might be a\nbetter alternative to avoid pushing out wrong branch by\nmistake.  That approach would also make your 8/8 unnecessary.\n"},{"id":"57399","messageId":"79CE31EE-0975-48EB-8B3E-FC9D6A8EB3E4@zib.de","threadId":"10490","inReplyTo":"7v3avvy9yc.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 4/8] rev-parse: teach \"git rev-parse --symbolic\" to print the full ref name","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-28T07:58:22Z","receivedAt":"2007-10-28T07:58:22Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Oct 28, 2007, at 8:28 AM, Junio C Hamano wrote:\n\n> Steffen Prohaska <prohaska@zib.de> writes:\n>\n>> \"git rev-parse --symbolic\" used to return the ref name as it was\n>> specified on the command line. This is changed to returning the\n>> full matched ref name, i.e. \"git rev-parse --symbolic master\"\n>> now typically returns \"refs/heads/master\".\n>\n> This is to expose \"dwim_ref\" logic, so it might be a good idea\n> to introduce a new option --dwim-ref for this purpose.\n>\n> \tgit rev-parse --symbolic master^2\n>\n> is designed to give \"master^2\" or fail if \"master\" is not a\n> merge.\n\nSo the idea of --symbolic is really to return the argv as is?\nNo change whatsoever allowed. Why would someone need this?\nIs it only for convenience when writing shell code?\n\n\n> Similarly, you would diagnose a failure if somebody asks\n> to show\n>\n> \tgit rev-parse --dwim-ref master~4\n>\n> instead of giving \"refs/heads/master~4\".\n\nWhat I proposed is to teach git rev-parse to return a full\nsymbolic ref name. Maybe\n\n\tgit rev-parse --full-symbolic\n\tgit rev-parse --full-ref\n\nBut honestly, I don't care that much about this patch. Maybe\nwe just put it aside?\n\n\n>> +static void show_rev(int type, const unsigned char *sha1, const  \n>> char *name, const char* real_name)\n>> @@ -131,7 +133,7 @@ static void show_default(void)\n>>\n>>  \t\tdef = NULL;\n>>  \t\tif (!get_sha1(s, sha1)) {\n>> -\t\t\tshow_rev(NORMAL, sha1, s);\n>> +\t\t\tshow_rev(NORMAL, sha1, s, 0);\n>\n> A null pointer constant in git sources is spelled \"NULL\" not \"0\".\n\nOk. I'll fix this in all patches.\n\n\n>> @@ -213,6 +215,7 @@ int cmd_rev_parse(int argc, const char **argv,  \n>> const char *prefix)\n>>  {\n>>  \tint i, as_is = 0, verify = 0;\n>>  \tunsigned char sha1[20];\n>> +\tchar* real_name = 0;\n>\n> Pointer sign '*' in git sources go next to the name not the\n> type, as:\n>\n> \tchar *real_name = NULL;\n\nI know and I tried hard to follow this convention, although\nI think its the wrong choice ;)\n\n\tSteffen\n"},{"id":"57400","messageId":"C83C1B1F-99A9-4F47-9C1A-55170CF61338@zib.de","threadId":"10490","inReplyTo":"7vwst7wvdr.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 5/8] push, send-pack: support pushing HEAD to real ref name","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-28T08:03:16Z","receivedAt":"2007-10-28T08:03:16Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Oct 28, 2007, at 8:28 AM, Junio C Hamano wrote:\n\n> Steffen Prohaska <prohaska@zib.de> writes:\n>\n>> This teaches \"push <remote> HEAD\" to resolve HEAD on the local\n>> side to its real ref name, e.g. refs/heads/master, and then\n>> use the real ref name on the remote side to search a matching\n>> remote ref.\n>\n> This probably is a good idea.\n\nI'll think about Daniel's suggestion of implementing it\ndifferently.\n\n\n>> +\tif (real_name) {\n>> +\t\tfree(real_name);\n>> +\t}\n>\n> Excess and unnecessary brace pair.\n\nWhen are excess and unnecessary braces acceptable?\nIs\n\n\tif (something) {\n  \t\tprintf(\"text %d\"\n   \t\t       \"more text %d\"\n                        \"and even more %d\\n\"\n\t\t       , a, b, c);\n\t}\n\nok? Or should I avoid braces there, too?\n\n\tSteffen\n"},{"id":"57401","messageId":"20071028080654.GS14735@spearce.org","threadId":"10490","inReplyTo":"79CE31EE-0975-48EB-8B3E-FC9D6A8EB3E4@zib.de","subject":"Re: [PATCH 4/8] rev-parse: teach \"git rev-parse --symbolic\" to print the full ref name","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-10-28T08:06:55Z","receivedAt":"2007-10-28T08:06:55Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Steffen Prohaska <prohaska@zib.de> wrote:\n> On Oct 28, 2007, at 8:28 AM, Junio C Hamano wrote:\n> >Steffen Prohaska <prohaska@zib.de> writes:\n> >>@@ -213,6 +215,7 @@ int cmd_rev_parse(int argc, const char **argv,  \n> >>const char *prefix)\n> >> {\n> >> \tint i, as_is = 0, verify = 0;\n> >> \tunsigned char sha1[20];\n> >>+\tchar* real_name = 0;\n> >\n> >Pointer sign '*' in git sources go next to the name not the\n> >type, as:\n> >\n> >\tchar *real_name = NULL;\n> \n> I know and I tried hard to follow this convention, although\n> I think its the wrong choice ;)\n\nOh, hmm...\n\n  char* a, b;\n\nWhat's the type of b?  If you said \"char*\" you're wrong.\n\nGit's style of putting the * next to the name makes it far easier to\nspot these sort of typing problems.  At least that's my take on it.\n\n-- \nShawn.\n"},{"id":"57402","messageId":"F12160CA-1778-499F-A3D7-42711FB8B2CC@zib.de","threadId":"10490","inReplyTo":"7vfxzvwvde.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 8/8] push: teach push to be quiet if local ref is strict subset of remote ref","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-28T08:20:53Z","receivedAt":"2007-10-28T08:20:53Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Oct 28, 2007, at 8:28 AM, Junio C Hamano wrote:\n\n> Steffen Prohaska <prohaska@zib.de> writes:\n>\n>> git push reports errors if a remote ref is not a strict subset\n>> of a local ref. The push wouldn't be a fast-forward and is\n>> therefore refused. This is in general a good idea.\n>\n>> This commit teaches git push to be quiet if the local is a strict\n>> subset of the remote and no refspec is explicitly specified on\n>> the command line. If the --verbose flag is used a \"note:\" is\n>> printed for each ignored branch.\n>\n> What happens to the summary reporting after such a push?  Does\n> it say \"branch foo was not pushed because you did not touch it\n> since you fetched and it is already stale with respect to the\n> remote side which has updates since then\"?\n\nIt says nothing, it's quiet, as promised in the commit message ;)\nThat's the point of this patch.\n\nBut I see your point. Maybe it should say something like\n\"ignored 2 branches, which are strict subsets of remote.\"\n\"use --verbose for details.\"\n?\n\n> How does this interact with the \"pretend we have fetched\n> immediately after we pushed by updating the corresponding remote\n> tracking branch\" logic?\n\nI doesn't change a remote tracking branch. I'll add a test\nconfirming this.\n\n\tSteffen\n"},{"id":"57403","messageId":"7v640rwst5.fsf@gitster.siamese.dyndns.org","threadId":"10490","inReplyTo":"79CE31EE-0975-48EB-8B3E-FC9D6A8EB3E4@zib.de","subject":"Re: [PATCH 4/8] rev-parse: teach \"git rev-parse --symbolic\" to print the full ref name","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-28T08:24:06Z","receivedAt":"2007-10-28T08:24:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steffen Prohaska <prohaska@zib.de> writes:\n\n> So the idea of --symbolic is really to return the argv as is?\n> No change whatsoever allowed. Why would someone need this?\n> Is it only for convenience when writing shell code?\n\nrev-parse _is_ for convenience for writing shell scripts, to\nsift various parameters into \"rev-list arguments\" and \"non\nrev-list arguments\".\n"},{"id":"57404","messageId":"9C8E1C6D-8DC1-4B32-AB78-1D97D3F44447@zib.de","threadId":"10490","inReplyTo":"7vabq3wvd6.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 1/8] push: change push to fail if short ref name does not exist","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-28T08:43:13Z","receivedAt":"2007-10-28T08:43:13Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Oct 28, 2007, at 8:28 AM, Junio C Hamano wrote:\n\n> Steffen Prohaska <prohaska@zib.de> writes:\n>\n>> You can use a branch's shortname to push it. Push used to create\n>> the branch on the remote side if it did not yet exist. If you\n>> specified the wrong branch accidentally it was created. A safety\n>> valve that pushes only existing branches may help to avoid\n>> errors.\n>\n> I do not agree with this change.\n>\n> If you misspelled the branch name (by the way, it is not a\n> \"shortname\", but what follows refs/heads/ is _the_ name of the\n> branch)\n\nTrue. Is \"short refname\" the correct wording?\n\n\n> \"frotz\" as \"frtoz\", and if a branch with the misspelled\n> name did _not_ exist locally, it would fail, with or without\n> this change, which is a good thing.\n>\n> But if you named \"nitfol\" that exists locally when you meant to\n> push \"frotz\" out, if \"nitfol\" remotely existed, we will push\n> that anyway by mistake, even with this change.  It will prevent\n> the push only when \"nitfol\" did not happen to exist at the\n> remote side.\n\nMy proposed change is more defensive than the current\nimplementation. It allows distinguishing between \"push existing\nbranch\" and \"create new branch on the remote side\", which I\nbelieve is a good thing. The current implementation uses\nthe same command line in both cases.\n\nDaniel suggested that git push should print a recommendation\nwhat full ref to use. This would make it easy to correct\nthe command. Ot you could use the '--create' flag to make\nyour intention explicit.\n\nIf we take the \"push origin HEAD\" patch, the existence check is\neven more important. If you're on the wrong branch and push HEAD\nyou may be surprised if a new branch is created. This can be\navoided by requiring either a full ref or the '--create' flag.\n\n\n> Earlier there was a discussion to introduce an optional\n> configuration that makes \"git push\" without any parameter to\n> push only the current branch out, in order to help people who\n> work with shared remote central repository.  That might be a\n> better alternative to avoid pushing out wrong branch by\n> mistake.  That approach would also make your 8/8 unnecessary.\n\nI didn't have the impression that the discussion went in\nthis direction. There were quite a few people who just said\n\"git push\" is the counter-part of \"git fetch\". Therefore\n\"git push\" pushes _all_ branches. Period.\n\nWith \"git push HEAD\" 5/8 you could now push only the current branch\n(its existence would be verified if 1/8 is also accepted).\n\n8/8 solves a different issue, too. I never advance local branches if\nI do not intend to push them. Therefore I can always say \"git push\"\nwithout any argument. It does always the right thing for me; except\nfor the annoying error messages that are avoided by 8/8. With 8/8\nI can push several local branches while ignoring the ones that I'm\nnot interested in.\n\n\tSteffen\n"},{"id":"57406","messageId":"30641295-495B-4E5E-9D44-5CAF7C480DF2@zib.de","threadId":"10490","inReplyTo":"20071028080654.GS14735@spearce.org","subject":"Re: [PATCH 4/8] rev-parse: teach \"git rev-parse --symbolic\" to print the full ref name","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-28T08:56:20Z","receivedAt":"2007-10-28T08:56:20Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Oct 28, 2007, at 9:06 AM, Shawn O. Pearce wrote:\n\n> Steffen Prohaska <prohaska@zib.de> wrote:\n>> On Oct 28, 2007, at 8:28 AM, Junio C Hamano wrote:\n>>> Steffen Prohaska <prohaska@zib.de> writes:\n>>>> @@ -213,6 +215,7 @@ int cmd_rev_parse(int argc, const char **argv,\n>>>> const char *prefix)\n>>>> {\n>>>> \tint i, as_is = 0, verify = 0;\n>>>> \tunsigned char sha1[20];\n>>>> +\tchar* real_name = 0;\n>>>\n>>> Pointer sign '*' in git sources go next to the name not the\n>>> type, as:\n>>>\n>>> \tchar *real_name = NULL;\n>>\n>> I know and I tried hard to follow this convention, although\n>> I think its the wrong choice ;)\n>\n> Oh, hmm...\n>\n>   char* a, b;\n>\n> What's the type of b?  If you said \"char*\" you're wrong.\n\nI know. Obviously, you need a combination of conventions.\n\n- '*' is part of the type; put it there.\n- Only define a single variable per statement.\n\nMy combined rule avoids your question. I typically use C++,\nwhich make the second rule easier to follow, because you\ndefer defining variables until you really need them. There's\nno need to save space at the start of the function block by\ndefining several variables in a single line.\n\n\n> Git's style of putting the * next to the name makes it far easier to\n> spot these sort of typing problems.  At least that's my take on it.\n\nLet's stop this discussion here. I'm not proposing to change the\nrules. I'll follow the git coding conventions when submitting\npatches to git, even if it's sometimes hard for me. I already packed\nas much as possible in my editor configuration. Unfortunately,\nI can't teach vim to always place the '*' correctly. At least I\ndon't know how to do this.\n\n\tSteffen\n"},{"id":"57425","messageId":"A4E7AC63-8EFF-4078-985D-4582BB8D528C@zib.de","threadId":"10490","inReplyTo":"Pine.LNX.4.64.0710271748440.7345@iabervon.org","subject":"Re: [PATCH 4/8] rev-parse: teach \"git rev-parse --symbolic\" to print the full ref name","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-28T13:49:28Z","receivedAt":"2007-10-28T13:49:28Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Oct 27, 2007, at 11:53 PM, Daniel Barkalow wrote:\n\n> On Sat, 27 Oct 2007, Steffen Prohaska wrote:\n>\n>> \"git rev-parse --symbolic\" used to return the ref name as it was\n>> specified on the command line. This is changed to returning the\n>> full matched ref name, i.e. \"git rev-parse --symbolic master\"\n>> now typically returns \"refs/heads/master\".\n>>\n>> Note, this changes output of an established command. It might\n>> break existing setups. I checked that it does not break scripts\n>> in git.git.\n>\n> I think this makes the --create option to push unnecessary, as  \n> interactive\n> users could use a suggested explicit value (or whatever they actually\n> meant), while scripts could replace $name with $(git rev-parse -- \n> symbolic\n> $name) as easily as they could add --create, and by more explicit  \n> as to\n> what they're doing.\n\nI'll remove 4/8 (git rev-parse --symbolic) from the patch\nseries. It is not directly related to the push behaviour\nand Junio pointed out that the old behavior of git rev-parse\nmust be maintained as is.  I'm not particularly interested in\nmodifying git rev-parse. If someone else is, feel free to take\nover my patch.\n\nI'll keep the '--create' flag. Its intention is obvious and easy\nto explain to users. Much easier than\n\"git rev-parse --dwim_ref ...\" or something similar.\n\n\tSteffen\n"},{"id":"57428","messageId":"3849CD8A-A86C-4297-899F-F1B7C1E81F2C@silverinsanity.com","threadId":"10490","inReplyTo":"30641295-495B-4E5E-9D44-5CAF7C480DF2@zib.de","subject":"Re: [PATCH 4/8] rev-parse: teach \"git rev-parse --symbolic\" to print the full ref name","fromName":"Brian Gernhardt","fromEmail":"benji@silverinsanity.com","sentAt":"2007-10-28T15:10:15Z","receivedAt":"2007-10-28T15:10:15Z","isPatch":true,"sender":{"key":"benji@silverinsanity.com","avatar":"https://gravatar.com/avatar/e06c101dbc25c68114d859b4a9ec7cf8a2c52fd2b0270ef0eac0e2e63ff22311?d=mp&s=160"},"body":"\nOn Oct 28, 2007, at 4:56 AM, Steffen Prohaska wrote:\n\n> I can't teach vim to always place the '*' correctly. At least I\n> don't know how to do this.\n\nI did some research (I was curious), and the following in your .vimrc  \nwill do it:  (Mildly tested)\n\n-----8<-----\n\n\" Needed to avoid 'char * '\nfunc s:Eatchar(pat)\nlet c = nr2char(getchar(0))\nreturn (c =~ a:pat) ? '' : c\nendfunc\n\n\" Make creating the abbreviation for multiple types easier\nfunc s:FixPointer(type)\nexec \"iabbr \" . a:type . \"* \" . a:type . \" *<C-R>=<SID>Eatchar('\\ \n\\s')<CR>\"\nendfunc\ncommand -nargs=1 FixPointer call <SID>FixPointer(<args>)\n\n\" Change the following pointer types (char* var -> char *var)\nFixPointer 'char'\nFixPointer 'int'\nFixPointer 'void'\n\n-----8<-----\n\nRepeating the last line for each type you want to fix the pointers  \nfor.  There may be a simpler way to do some of this, but I don't know  \nit.  But once it's set up each time you type in \"char* var\", Vim will  \nauto-correct to \"char *var\".\n\nChanging this to operate only in C, or only if you're starting in your  \ngit repository is left as an exercise for the reader.  ;-)\n\n~~ Brian\n"},{"id":"57429","messageId":"722152C5-299C-435E-B720-D2D331D16249@zib.de","threadId":"10490","inReplyTo":"7vwst7wvdr.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 5/8] push, send-pack: support pushing HEAD to real ref name","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-28T15:10:44Z","receivedAt":"2007-10-28T15:10:44Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Oct 28, 2007, at 8:28 AM, Junio C Hamano wrote:\n\n> Steffen Prohaska <prohaska@zib.de> writes:\n>\n>> This teaches \"push <remote> HEAD\" to resolve HEAD on the local\n>> side to its real ref name, e.g. refs/heads/master, and then\n>> use the real ref name on the remote side to search a matching\n>> remote ref.\n>\n> This probably is a good idea.\n\nI'll add an even shorter shorthand: \"git push HEAD\" will push\nthe current branch to its default remote.\n\n\tSteffen\n"},{"id":"57430","messageId":"7vd4uzuu1g.fsf@gitster.siamese.dyndns.org","threadId":"10490","inReplyTo":"722152C5-299C-435E-B720-D2D331D16249@zib.de","subject":"Re: [PATCH 5/8] push, send-pack: support pushing HEAD to real ref name","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-28T15:40:27Z","receivedAt":"2007-10-28T15:40:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steffen Prohaska <prohaska@zib.de> writes:\n\n> On Oct 28, 2007, at 8:28 AM, Junio C Hamano wrote:\n>\n>> Steffen Prohaska <prohaska@zib.de> writes:\n>>\n>>> This teaches \"push <remote> HEAD\" to resolve HEAD on the local\n>>> side to its real ref name, e.g. refs/heads/master, and then\n>>> use the real ref name on the remote side to search a matching\n>>> remote ref.\n>>\n>> This probably is a good idea.\n>\n> I'll add an even shorter shorthand: \"git push HEAD\" will push\n> the current branch to its default remote.\n\nUgh, that looks way too magicky.  The first parameter to push if\none ever exists has _always_ been the remote, and the above\nbreaks it.\n\nPlease don't.\n"},{"id":"57431","messageId":"EE8B843C-5276-4FEC-ABDD-FC456EFD3D75@zib.de","threadId":"10490","inReplyTo":"7vd4uzuu1g.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 5/8] push, send-pack: support pushing HEAD to real ref name","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-28T15:59:37Z","receivedAt":"2007-10-28T15:59:37Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Oct 28, 2007, at 4:40 PM, Junio C Hamano wrote:\n\n> Steffen Prohaska <prohaska@zib.de> writes:\n>\n>> On Oct 28, 2007, at 8:28 AM, Junio C Hamano wrote:\n>>\n>>> Steffen Prohaska <prohaska@zib.de> writes:\n>>>\n>>>> This teaches \"push <remote> HEAD\" to resolve HEAD on the local\n>>>> side to its real ref name, e.g. refs/heads/master, and then\n>>>> use the real ref name on the remote side to search a matching\n>>>> remote ref.\n>>>\n>>> This probably is a good idea.\n>>\n>> I'll add an even shorter shorthand: \"git push HEAD\" will push\n>> the current branch to its default remote.\n>\n> Ugh, that looks way too magicky.  The first parameter to push if\n> one ever exists has _always_ been the remote, and the above\n> breaks it.\n\nYes. It breaks setups that have a remote named HEAD.\n\n\n> Please don't.\n\nI already did it -- it was too easy. But it's a separate patch.\nSo it can easily be skipped.\n\nWhat would you propose for pushing only the current branch to\nits default remote repository? All information is there. Only\na way to tell push to restrict push to the current branch\nis missing. Would you prefer something like\n\"git push --only-current-branch\"?\n\n\tSteffen\n"},{"id":"57432","messageId":"7v7il7usyx.fsf@gitster.siamese.dyndns.org","threadId":"10490","inReplyTo":"7vd4uzuu1g.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 5/8] push, send-pack: support pushing HEAD to real ref name","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-28T16:03:34Z","receivedAt":"2007-10-28T16:03:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Steffen Prohaska <prohaska@zib.de> writes:\n>\n>> On Oct 28, 2007, at 8:28 AM, Junio C Hamano wrote:\n>>\n>>> Steffen Prohaska <prohaska@zib.de> writes:\n>>>\n>>>> This teaches \"push <remote> HEAD\" to resolve HEAD on the local\n>>>> side to its real ref name, e.g. refs/heads/master, and then\n>>>> use the real ref name on the remote side to search a matching\n>>>> remote ref.\n>>>\n>>> This probably is a good idea.\n>>\n>> I'll add an even shorter shorthand: \"git push HEAD\" will push\n>> the current branch to its default remote.\n>\n> Ugh, that looks way too magicky.  The first parameter to push if\n> one ever exists has _always_ been the remote, and the above\n> breaks it.\n>\n> Please don't.\n\nAn alternative, just to let me keep my nicer public image by\npretending to be constructive ;-)\n\nIntroduce a configuration \"remote.$name.push_default\" whose\nvalue can be a list of refs.  Teach the push command without\nrefspecs:\n\n\t$ git push\n\t$ git push $remote\n\nto pretend as if the listed refspecs are given, instead of the\ntraditional \"matching branches\" behaviour.\n\nThen, introduce another option\n\n\t$ git push --matching\n\t$ git push --matching $remote\n\nto override that configuration, if set, so that the user who\nusually pushes only the selected branches can use the \"matching\nbranches\" behaviour when needed.\n\nAlong with your earlier \"git push $remote HEAD\" patch, this will\nallow you to say:\n\n\t[remote \"origin\"]\n        \tpush_default = HEAD\n\nand your\n\n\t$ git push\n\nwill push only the current branch.\n"},{"id":"57434","messageId":"55CCFD12-C10F-46A6-8D65-544231DEBF3F@zib.de","threadId":"10490","inReplyTo":"7v7il7usyx.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 5/8] push, send-pack: support pushing HEAD to real ref name","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-28T16:30:44Z","receivedAt":"2007-10-28T16:30:44Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Oct 28, 2007, at 5:03 PM, Junio C Hamano wrote:\n\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>> Steffen Prohaska <prohaska@zib.de> writes:\n>>\n>>> On Oct 28, 2007, at 8:28 AM, Junio C Hamano wrote:\n>>>\n>>>> Steffen Prohaska <prohaska@zib.de> writes:\n>>>>\n>>>>> This teaches \"push <remote> HEAD\" to resolve HEAD on the local\n>>>>> side to its real ref name, e.g. refs/heads/master, and then\n>>>>> use the real ref name on the remote side to search a matching\n>>>>> remote ref.\n>>>>\n>>>> This probably is a good idea.\n>>>\n>>> I'll add an even shorter shorthand: \"git push HEAD\" will push\n>>> the current branch to its default remote.\n>>\n>> Ugh, that looks way too magicky.  The first parameter to push if\n>> one ever exists has _always_ been the remote, and the above\n>> breaks it.\n>>\n>> Please don't.\n>\n> An alternative, just to let me keep my nicer public image by\n> pretending to be constructive ;-)\n>\n> Introduce a configuration \"remote.$name.push_default\" whose\n> value can be a list of refs.  Teach the push command without\n> refspecs:\n>\n> \t$ git push\n> \t$ git push $remote\n>\n> to pretend as if the listed refspecs are given, instead of the\n> traditional \"matching branches\" behaviour.\n>\n> Then, introduce another option\n>\n> \t$ git push --matching\n> \t$ git push --matching $remote\n>\n> to override that configuration, if set, so that the user who\n> usually pushes only the selected branches can use the \"matching\n> branches\" behaviour when needed.\n>\n> Along with your earlier \"git push $remote HEAD\" patch, this will\n> allow you to say:\n>\n> \t[remote \"origin\"]\n>         \tpush_default = HEAD\n>\n> and your\n>\n> \t$ git push\n>\n> will push only the current branch.\n\nSounds reasonable; but it is more work. I'm not starting to\nimplement this today.\n\n\tSteffen\n"},{"id":"57454","messageId":"7v1wbfufbo.fsf@gitster.siamese.dyndns.org","threadId":"10490","inReplyTo":"55CCFD12-C10F-46A6-8D65-544231DEBF3F@zib.de","subject":"Re: [PATCH 5/8] push, send-pack: support pushing HEAD to real ref name","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-28T20:58:19Z","receivedAt":"2007-10-28T20:58:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steffen Prohaska <prohaska@zib.de> writes:\n\n> On Oct 28, 2007, at 5:03 PM, Junio C Hamano wrote:\n> ...\n>> An alternative, just to let me keep my nicer public image by\n>> pretending to be constructive ;-)\n>>\n>> Introduce a configuration \"remote.$name.push_default\" whose\n>> value can be a list of refs.  Teach the push command without\n>> refspecs:\n>>\n>> \t$ git push\n>> \t$ git push $remote\n>>\n>> to pretend as if the listed refspecs are given, instead of the\n>> traditional \"matching branches\" behaviour.\n>>\n>> Then, introduce another option\n>>\n>> \t$ git push --matching\n>> \t$ git push --matching $remote\n>>\n>> to override that configuration, if set, so that the user who\n>> usually pushes only the selected branches can use the \"matching\n>> branches\" behaviour when needed.\n>>\n>> Along with your earlier \"git push $remote HEAD\" patch, this will\n>> allow you to say:\n>>\n>> \t[remote \"origin\"]\n>>         \tpush_default = HEAD\n>>\n>> and your\n>>\n>> \t$ git push\n>>\n>> will push only the current branch.\n>\n> Sounds reasonable; but it is more work. I'm not starting to\n> implement this today.\n\nTake your time; nobody is in a hurry.\n\nIf somebody usually uses \"matching\" behaviour, i.e. without\nremote.$name.push_default configuration, but wants to push only\nthe current branch as a one-shot operation, we can obviously use\n\"git push $remote HEAD\".  But to be complete, it may make sense\nto have another option\n\n\t$ git push --current\n\nthat lets you omit $remote (and default to the value configured\nwith branch.$name.remote).\n"},{"id":"57706","messageId":"104D272D-AD9E-49D7-A503-E9402766CF6F@zib.de","threadId":"10490","inReplyTo":"7v1wbfufbo.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 5/8] push, send-pack: support pushing HEAD to real ref name","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-10-31T15:08:37Z","receivedAt":"2007-10-31T15:08:37Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Oct 28, 2007, at 9:58 PM, Junio C Hamano wrote:\n\n> Steffen Prohaska <prohaska@zib.de> writes:\n>\n>> On Oct 28, 2007, at 5:03 PM, Junio C Hamano wrote:\n>> ...\n>>> An alternative, just to let me keep my nicer public image by\n>>> pretending to be constructive ;-)\n>>>\n>>> Introduce a configuration \"remote.$name.push_default\" whose\n>>> value can be a list of refs.  Teach the push command without\n>>> refspecs:\n>>>\n>>> \t$ git push\n>>> \t$ git push $remote\n>>>\n>>> to pretend as if the listed refspecs are given, instead of the\n>>> traditional \"matching branches\" behaviour.\n>>>\n>>> Then, introduce another option\n>>>\n>>> \t$ git push --matching\n>>> \t$ git push --matching $remote\n>>>\n>>> to override that configuration, if set, so that the user who\n>>> usually pushes only the selected branches can use the \"matching\n>>> branches\" behaviour when needed.\n>>>\n>>> Along with your earlier \"git push $remote HEAD\" patch, this will\n>>> allow you to say:\n>>>\n>>> \t[remote \"origin\"]\n>>>         \tpush_default = HEAD\n>>>\n>>> and your\n>>>\n>>> \t$ git push\n>>>\n>>> will push only the current branch.\n>>\n>> Sounds reasonable; but it is more work. I'm not starting to\n>> implement this today.\n>\n> Take your time; nobody is in a hurry.\n>\n> If somebody usually uses \"matching\" behaviour, i.e. without\n> remote.$name.push_default configuration, but wants to push only\n> the current branch as a one-shot operation, we can obviously use\n> \"git push $remote HEAD\".  But to be complete, it may make sense\n> to have another option\n>\n> \t$ git push --current\n>\n> that lets you omit $remote (and default to the value configured\n> with branch.$name.remote).\n\nHere is an alternative proposal.\n\nThe idea is that in a workflow based on a shared repository\ngit pull and git push should be 'more' symmetric than they are\nin a pull-only based workflow. The integration of changes is\n'more' direct. Working against a shared repository may require\nto integrate new changes before pushing. Changes are also\npushed directly to the remote branch you originally branched\noff. Both is different from a pull-only workflow, where I first\npush my changes to a privately owned but publicly readable repo\nand someone else does the integration by pulling from there.\n\nThe branch in the shared repository serves as the single\n'integration' branch. One can use 'git branch --track' to set\nup local branches that automatically merge changes from the\nshared 'integration' branch. That is git pull without further\narguments is the right command to integrate changes from the\nshared branch to the local branch. (git provides more advanced\nways, but git pull is simple and in principle does the right\nthing.)\n\nWhat is missing is a simple way to 'push' local changes back\nto shared integration branch in the remote repository. This\ncan be seen as a 'symmetric' operation to pulling. So, git push\nshould do the right thing. And the right thing is pushing the\ncurrent branch to the shared 'integration' branch.\n\nThe automerge behaviour stores information in branch.$name.remote\nand branch.$name.merge that provide sufficient information to\nmake \"git pull\" the equivalent of\n\n    git pull <remoteURL> <remoteref>\n\nwhere <remoteURL> is the full URL of the remote stored in\nbranch.$name.remote, and <remoteref> is the value of\nbranch.$name.merge.\n\nA 'symmetric' push command would push the current branch to the\nremote head it originally was branched off, that is\n\n    git push <remoteURL> <currentbranch>:<remoteref>\n\nNow, the proposal is\n\n- add a configuration variable branch.$name.push\n\n- change git push to check if the push configuration variable\n   is set for the current branch $name, and if so run the\n   equivalent of\n\n     git push branch.$name.remote $name:branch.$name.push\n\n\n- teach git branch a flag --push/--no-push that sets up\n   branch.$name.push. Add branch.autosetuppush configuration\n   flag to configure if --push or --no-push is the default.\n   (maybe we need better names here).\n\n\nThis breaks the symmetry between git fetch/git push and\nreplaces it with a symmetry between git pull/git push for some\nbranches. I believe this might be the right thing to do for\na workflow based on shared repos.\n\n\tSteffen\n"}]}