{"thread":{"id":"22250","subject":"[PATCH v4] Add push --set-upstream","startedAt":"2010-01-16T21:45:31Z","lastAt":"2010-01-18T03:27:53Z","messageCount":3,"participants":["Ilari Liusvaara","Junio C Hamano","Miles Bader"],"isPatch":true,"patchVersion":4,"patchTotal":null},"messages":[{"id":"131911","messageId":"1263678331-9794-1-git-send-email-ilari.liusvaara@elisanet.fi","threadId":"22250","inReplyTo":null,"subject":"[PATCH v4] Add push --set-upstream","fromName":"Ilari Liusvaara","fromEmail":"ilari.liusvaara@elisanet.fi","sentAt":"2010-01-16T21:45:31Z","receivedAt":"2010-01-16T21:45:31Z","isPatch":true,"sender":{"key":"ilari.liusvaara@elisanet.fi","avatar":null},"body":"Frequent complaint is lack of easy way to set up upstream (tracking)\nreferences for git pull to work as part of push command. So add switch\n--set-upstream (-u) to do just that.\n\nSigned-off-by: Jeff King <peff@peff.net>\nSigned-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>\n---\n Documentation/git-push.txt |    9 +++++-\n builtin-push.c             |    2 +\n t/t5523-push-upstream.sh   |   69 ++++++++++++++++++++++++++++++++++++++++++++\n transport.c                |   56 +++++++++++++++++++++++++++++++++++\n transport.h                |    1 +\n 5 files changed, 136 insertions(+), 1 deletions(-)\n create mode 100755 t/t5523-push-upstream.sh\n\ndiff --git a/Documentation/git-push.txt b/Documentation/git-push.txt\nindex e3eb1e8..2a5394b 100644\n--- a/Documentation/git-push.txt\n+++ b/Documentation/git-push.txt\n@@ -10,7 +10,7 @@ SYNOPSIS\n --------\n [verse]\n 'git push' [--all | --mirror | --tags] [-n | --dry-run] [--receive-pack=<git-receive-pack>]\n-\t   [--repo=<repository>] [-f | --force] [-v | --verbose]\n+\t   [--repo=<repository>] [-f | --force] [-v | --verbose] [-u | --set-upstream]\n \t   [<repository> <refspec>...]\n \n DESCRIPTION\n@@ -122,6 +122,13 @@ nor in any Push line of the corresponding remotes file---see below).\n \tthe name \"origin\" is used. For this latter case, this option\n \tcan be used to override the name \"origin\". In other words,\n \tthe difference between these two commands\n+\n+-u::\n+--set-upstream::\n+\tFor every branch that is up to date or successfully pushed, add\n+\tupstream (tracking) reference, used by argument-less\n+\tlinkgit:git-pull[1] and other commands. For more information,\n+\tsee 'branch.<name>.merge' in linkgit:git-config[1].\n +\n --------------------------\n git push public         #1\ndiff --git a/builtin-push.c b/builtin-push.c\nindex 28a26e7..5df6608 100644\n--- a/builtin-push.c\n+++ b/builtin-push.c\n@@ -218,6 +218,8 @@ int cmd_push(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOLEAN( 0 , \"thin\", &thin, \"use thin pack\"),\n \t\tOPT_STRING( 0 , \"receive-pack\", &receivepack, \"receive-pack\", \"receive pack program\"),\n \t\tOPT_STRING( 0 , \"exec\", &receivepack, \"receive-pack\", \"receive pack program\"),\n+\t\tOPT_BIT('u', \"set-upstream\", &flags, \"set upstream for git pull/status\",\n+\t\t\tTRANSPORT_PUSH_SET_UPSTREAM),\n \t\tOPT_END()\n \t};\n \ndiff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh\nnew file mode 100755\nindex 0000000..00da707\n--- /dev/null\n+++ b/t/t5523-push-upstream.sh\n@@ -0,0 +1,69 @@\n+#!/bin/sh\n+\n+test_description='push with --set-upstream'\n+. ./test-lib.sh\n+\n+test_expect_success 'setup bare parent' '\n+\tgit init --bare parent &&\n+\tgit remote add upstream parent\n+'\n+\n+test_expect_success 'setup local commit' '\n+\techo content >file &&\n+\tgit add file &&\n+\tgit commit -m one\n+'\n+\n+check_config() {\n+\t(echo $2; echo $3) >expect.$1\n+\t(git config branch.$1.remote\n+\t git config branch.$1.merge) >actual.$1\n+\ttest_cmp expect.$1 actual.$1\n+}\n+\n+test_expect_success 'push -u master:master' '\n+\tgit push -u upstream master:master &&\n+\tcheck_config master upstream refs/heads/master\n+'\n+\n+test_expect_success 'push -u master:other' '\n+\tgit push -u upstream master:other &&\n+\tcheck_config master upstream refs/heads/other\n+'\n+\n+test_expect_success 'push -u --dry-run master:otherX' '\n+\tgit push -u --dry-run upstream master:otherX &&\n+\tcheck_config master upstream refs/heads/other\n+'\n+\n+test_expect_success 'push -u master2:master2' '\n+\tgit branch master2 &&\n+\tgit push -u upstream master2:master2 &&\n+\tcheck_config master2 upstream refs/heads/master2\n+'\n+\n+test_expect_success 'push -u master2:other2' '\n+\tgit push -u upstream master2:other2 &&\n+\tcheck_config master2 upstream refs/heads/other2\n+'\n+\n+test_expect_success 'push -u :master2' '\n+\tgit push -u upstream :master2 &&\n+\tcheck_config master2 upstream refs/heads/other2\n+'\n+\n+test_expect_success 'push -u --all' '\n+\tgit branch all1 &&\n+\tgit branch all2 &&\n+\tgit push -u --all &&\n+\tcheck_config all1 upstream refs/heads/all1 &&\n+\tcheck_config all2 upstream refs/heads/all2\n+'\n+\n+test_expect_success 'push -u HEAD' '\n+\tgit checkout -b headbranch &&\n+\tgit push -u upstream HEAD &&\n+\tcheck_config headbranch upstream refs/heads/headbranch\n+'\n+\n+test_done\ndiff --git a/transport.c b/transport.c\nindex b5332c0..8cc287d 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -8,6 +8,7 @@\n #include \"bundle.h\"\n #include \"dir.h\"\n #include \"refs.h\"\n+#include \"branch.h\"\n \n /* rsync support */\n \n@@ -135,6 +136,53 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list)\n \t}\n }\n \n+static void set_upstreams(struct transport *transport, struct ref *refs,\n+\tint pretend)\n+{\n+\tstruct ref *ref;\n+\tfor (ref = refs; ref; ref = ref->next) {\n+\t\tconst char *localname;\n+\t\tconst char *tmp;\n+\t\tconst char *remotename;\n+\t\tunsigned char sha[20];\n+\t\tint flag = 0;\n+\t\t/*\n+\t\t * Check suitability for tracking. Must be successful /\n+\t\t * already up-to-date ref create/modify (not delete).\n+\t\t */\n+\t\tif (ref->status != REF_STATUS_OK &&\n+\t\t\tref->status != REF_STATUS_UPTODATE)\n+\t\t\tcontinue;\n+\t\tif (!ref->peer_ref)\n+\t\t\tcontinue;\n+\t\tif (!ref->new_sha1 || is_null_sha1(ref->new_sha1))\n+\t\t\tcontinue;\n+\n+\t\t/* Follow symbolic refs (mainly for HEAD). */\n+\t\tlocalname = ref->peer_ref->name;\n+\t\tremotename = ref->name;\n+\t\ttmp = resolve_ref(localname, sha, 1, &flag);\n+\t\tif (tmp && flag & REF_ISSYMREF &&\n+\t\t\t!prefixcmp(tmp, \"refs/heads/\"))\n+\t\t\tlocalname = tmp;\n+\n+\t\t/* Both source and destination must be local branches. */\n+\t\tif (!localname || prefixcmp(localname, \"refs/heads/\"))\n+\t\t\tcontinue;\n+\t\tif (!remotename || prefixcmp(remotename, \"refs/heads/\"))\n+\t\t\tcontinue;\n+\n+\t\tif (!pretend)\n+\t\t\tinstall_branch_config(BRANCH_CONFIG_VERBOSE,\n+\t\t\t\tlocalname + 11, transport->remote->name,\n+\t\t\t\tremotename);\n+\t\telse\n+\t\t\tprintf(\"Would set upstream of '%s' to '%s' of '%s'\\n\",\n+\t\t\t\tlocalname + 11, remotename + 11,\n+\t\t\t\ttransport->remote->name);\n+\t}\n+}\n+\n static const char *rsync_url(const char *url)\n {\n \treturn prefixcmp(url, \"rsync://\") ? skip_prefix(url, \"rsync:\") : url;\n@@ -974,6 +1022,10 @@ int transport_push(struct transport *transport,\n \tverify_remote_names(refspec_nr, refspec);\n \n \tif (transport->push) {\n+\t\t/* Maybe FIXME. But no important transport uses this case. */\n+\t\tif (flags & TRANSPORT_PUSH_SET_UPSTREAM)\n+\t\t\tdie(\"This transport does not support using --set-upstream\");\n+\n \t\treturn transport->push(transport, refspec_nr, refspec, flags);\n \t} else if (transport->push_refs) {\n \t\tstruct ref *remote_refs =\n@@ -983,6 +1035,7 @@ int transport_push(struct transport *transport,\n \t\tint verbose = flags & TRANSPORT_PUSH_VERBOSE;\n \t\tint quiet = flags & TRANSPORT_PUSH_QUIET;\n \t\tint porcelain = flags & TRANSPORT_PUSH_PORCELAIN;\n+\t\tint pretend = flags & TRANSPORT_PUSH_DRY_RUN;\n \t\tint ret;\n \n \t\tif (flags & TRANSPORT_PUSH_ALL)\n@@ -1002,6 +1055,9 @@ int transport_push(struct transport *transport,\n \t\t\t\t\tverbose | porcelain, porcelain,\n \t\t\t\t\tnonfastforward);\n \n+\t\tif (flags & TRANSPORT_PUSH_SET_UPSTREAM)\n+\t\t\tset_upstreams(transport, remote_refs, pretend);\n+\n \t\tif (!(flags & TRANSPORT_PUSH_DRY_RUN)) {\n \t\t\tstruct ref *ref;\n \t\t\tfor (ref = remote_refs; ref; ref = ref->next)\ndiff --git a/transport.h b/transport.h\nindex 97ba251..c4314dd 100644\n--- a/transport.h\n+++ b/transport.h\n@@ -91,6 +91,7 @@ struct transport {\n #define TRANSPORT_PUSH_VERBOSE 16\n #define TRANSPORT_PUSH_PORCELAIN 32\n #define TRANSPORT_PUSH_QUIET 64\n+#define TRANSPORT_PUSH_SET_UPSTREAM 128\n \n /* Returns a transport suitable for the url */\n struct transport *transport_get(struct remote *, const char *);\n-- \n1.6.6.199.gff4b0\n"},{"id":"131993","messageId":"7vwrzgweht.fsf@alter.siamese.dyndns.org","threadId":"22250","inReplyTo":"1263678331-9794-1-git-send-email-ilari.liusvaara@elisanet.fi","subject":"Re: [PATCH v4] Add push --set-upstream","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-01-17T22:30:54Z","receivedAt":"2010-01-17T22:30:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Looks good; thanks.  Will queue on 'next'.\n"},{"id":"132009","messageId":"buoska4jdmu.fsf@dhlpc061.dev.necel.com","threadId":"22250","inReplyTo":"7vwrzgweht.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v4] Add push --set-upstream","fromName":"Miles Bader","fromEmail":"miles@gnu.org","sentAt":"2010-01-18T03:27:53Z","receivedAt":"2010-01-18T03:27:53Z","isPatch":true,"sender":{"key":"miles@gnu.org","avatar":"https://gravatar.com/avatar/01069b69593af7bff28e2f97afeb3644ae6fe2f5f56cb3a8cf34c5fb8c36efe5?d=mp&s=160"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n> Looks good; thanks.  Will queue on 'next'.\n\nExcellent!  Can't wait to see it in a release someday...\n\nThanks, Ilari et al!!\n\n-miles\n\n-- \nNeighbor, n. One whom we are commanded to love as ourselves, and who does all\nhe knows how to make us disobedient.\n"}]}