Hi, I'm adding people from the "git push --track" thread here, since this feature is related to what they want. (sorry for any line-wrap mangling in the patch.) -- Cheers, Ray Chuan On Sat, Jan 16, 2010 at 6:47 AM, Ilari Liusvaara <ilari.liusvaara@xxxxxxxxxxx> wrote: > Frequent complaint is lack of easy way to set up upstream (tracking) > references for git pull to work as part of push command. So add switch > --set-upstream (-u) to do just that. > > Signed-off-by: Jeff King <peff@xxxxxxxx> > Signed-off-by: Ilari Liusvaara <ilari.liusvaara@xxxxxxxxxxx> > --- > Changes from v1: > - Handle 'git push -u <remote> HEAD' correctly. > - Add testsuite (thanks Peff), with some additional tests to test delete. > - Modify documentation for push -u (thanks Matthieu Moy). > > Documentation/git-push.txt | 9 +++++- > builtin-push.c | 1 + > t/t5523-push-upstream.sh | 64 ++++++++++++++++++++++++++++++++++++++++++++ > transport.c | 49 +++++++++++++++++++++++++++++++++ > transport.h | 1 + > 5 files changed, 123 insertions(+), 1 deletions(-) > create mode 100755 t/t5523-push-upstream.sh > > diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt > index e3eb1e8..2a5394b 100644 > --- a/Documentation/git-push.txt > +++ b/Documentation/git-push.txt > @@ -10,7 +10,7 @@ SYNOPSIS > -------- > [verse] > 'git push' [--all | --mirror | --tags] [-n | --dry-run] [--receive-pack=<git-receive-pack>] > - [--repo=<repository>] [-f | --force] [-v | --verbose] > + [--repo=<repository>] [-f | --force] [-v | --verbose] [-u | --set-upstream] > [<repository> <refspec>...] > > DESCRIPTION > @@ -122,6 +122,13 @@ nor in any Push line of the corresponding remotes file---see below). > the name "origin" is used. For this latter case, this option > can be used to override the name "origin". In other words, > the difference between these two commands > + > +-u:: > +--set-upstream:: > + For every branch that is up to date or successfully pushed, add > + upstream (tracking) reference, used by argument-less > + linkgit:git-pull[1] and other commands. For more information, > + see 'branch.<name>.merge' in linkgit:git-config[1]. > + > -------------------------- > git push public #1 > diff --git a/builtin-push.c b/builtin-push.c > index 28a26e7..75ddaf4 100644 > --- a/builtin-push.c > +++ b/builtin-push.c > @@ -218,6 +218,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) > OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"), > OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"), > OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"), > + OPT_BIT('u', "set-upstream", &flags, "Set upstream for git pull", TRANSPORT_PUSH_SET_UPSTREAM), > OPT_END() > }; > > diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh > new file mode 100755 > index 0000000..e098d37 > --- /dev/null > +++ b/t/t5523-push-upstream.sh > @@ -0,0 +1,64 @@ > +#!/bin/sh > + > +test_description='push with --set-upstream' > +. ./test-lib.sh > + > +test_expect_success 'setup bare parent' ' > + git init --bare parent && > + git remote add upstream parent > +' > + > +test_expect_success 'setup local commit' ' > + echo content >file && > + git add file && > + git commit -m one > +' > + > +check_config() { > + (echo $2; echo $3) >expect.$1 > + (git config branch.$1.remote > + git config branch.$1.merge) >actual.$1 > + test_cmp expect.$1 actual.$1 > +} > + > +test_expect_success 'push -u master:master' ' > + git push -u upstream master:master && > + check_config master upstream refs/heads/master > +' > + > +test_expect_success 'push -u master:other' ' > + git push -u upstream master:other && > + check_config master upstream refs/heads/other > +' > + > +test_expect_success 'push -u master2:master2' ' > + git branch master2 && > + git push -u upstream master2:master2 && > + check_config master2 upstream refs/heads/master2 > +' > + > +test_expect_success 'push -u master2:other2' ' > + git push -u upstream master2:other2 && > + check_config master2 upstream refs/heads/other2 > +' > + > +test_expect_success 'push -u :master2' ' > + git push -u upstream :master2 && > + check_config master2 upstream refs/heads/other2 > +' > + > +test_expect_success 'push -u --all' ' > + git branch all1 && > + git branch all2 && > + git push -u --all && > + check_config all1 upstream refs/heads/all1 && > + check_config all2 upstream refs/heads/all2 > +' > + > +test_expect_success 'push -u HEAD' ' > + git checkout -b headbranch && > + git push -u upstream HEAD && > + check_config headbranch upstream refs/heads/headbranch > +' > + > +test_done > diff --git a/transport.c b/transport.c > index b5332c0..e5b462b 100644 > --- a/transport.c > +++ b/transport.c > @@ -8,6 +8,7 @@ > #include "bundle.h" > #include "dir.h" > #include "refs.h" > +#include "branch.h" > > /* rsync support */ > > @@ -135,6 +136,47 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list) > } > } > > +static void set_upstreams(struct transport *trans, struct ref *refs) > +{ > + struct ref *i; > + for (i = refs; i; i = i->next) { > + const char *localname; > + const char *tmp; > + const char *remotename; > + unsigned char sha[20]; > + int flag = 0; > + /* > + * Check suitability for tracking. Must be successful / > + * alreay up-to-date ref create/modify (not delete). > + */ > + if (i->status != REF_STATUS_OK && > + i->status != REF_STATUS_UPTODATE) > + continue; > + if (!i->peer_ref) > + continue; > + if (!i->new_sha1 || is_null_sha1(i->new_sha1)) > + continue; > + > + /* Chase symbolic refs (mainly for HEAD). */ > + localname = i->peer_ref->name; > + remotename = i->name; > + tmp = resolve_ref(localname, sha, 1, &flag); > + if (tmp && flag & REF_ISSYMREF && > + !prefixcmp(tmp, "refs/heads/")) > + localname = tmp; > + > + /* Both source and destination must be local branches. */ > + if (!localname || prefixcmp(localname, "refs/heads/")) > + continue; > + if (!remotename || prefixcmp(remotename, "refs/heads/")) > + continue; > + > + install_branch_config(BRANCH_CONFIG_VERBOSE, > + localname + 11, trans->remote->name, > + remotename); > + } > +} > + > static const char *rsync_url(const char *url) > { > return prefixcmp(url, "rsync://") ? skip_prefix(url, "rsync:") : url; > @@ -974,6 +1016,10 @@ int transport_push(struct transport *transport, > verify_remote_names(refspec_nr, refspec); > > if (transport->push) { > + /* Maybe FIXME. But no important transport uses this case. */ > + if (flags & TRANSPORT_PUSH_SET_UPSTREAM) > + die("This transport does not support using --set-upstream"); > + > return transport->push(transport, refspec_nr, refspec, flags); > } else if (transport->push_refs) { > struct ref *remote_refs = > @@ -1002,6 +1048,9 @@ int transport_push(struct transport *transport, > verbose | porcelain, porcelain, > nonfastforward); > > + if (flags & TRANSPORT_PUSH_SET_UPSTREAM) > + set_upstreams(transport, remote_refs); > + > if (!(flags & TRANSPORT_PUSH_DRY_RUN)) { > struct ref *ref; > for (ref = remote_refs; ref; ref = ref->next) > diff --git a/transport.h b/transport.h > index 97ba251..c4314dd 100644 > --- a/transport.h > +++ b/transport.h > @@ -91,6 +91,7 @@ struct transport { > #define TRANSPORT_PUSH_VERBOSE 16 > #define TRANSPORT_PUSH_PORCELAIN 32 > #define TRANSPORT_PUSH_QUIET 64 > +#define TRANSPORT_PUSH_SET_UPSTREAM 128 > > /* Returns a transport suitable for the url */ > struct transport *transport_get(struct remote *, const char *); > -- > 1.6.6.102.gd6f8f.dirty > > -- > To unsubscribe from this list: send the line "unsubscribe git" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html