From c7133f5a79bf58ee9d22eff621b97a42d1bccb95 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Fri, 30 Aug 2013 19:11:23 -0500 Subject: [PATCH] Add concept of 'publish' branch The publish branch is the branch the user wants to push to, akin to the upstream branch, which is the branch the user wants to use as a baseline. It overrides other configurations, such as push.default, and remote..push. The upstream branch is: branch.$name.remote branch.$name.merge The publish branch is: branch.$name.pushremote branch.$name.push Signed-off-by: Felipe Contreras --- Documentation/config.txt | 7 ++++++ builtin/push.c | 9 +++++++- remote.c | 11 ++++++++- remote.h | 2 ++ t/t5516-fetch-push.sh | 49 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 76 insertions(+), 2 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 2cd6bdd7d2..d7918acca6 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -869,6 +869,13 @@ branch..mergeOptions:: option values containing whitespace characters are currently not supported. +branch..push:: + Defines, together with branch..pushremote, the publish branch for + the given branch. It tells 'git push' which branch to push to, and + overrides any other configurations, such as push.default. It also tells + commands such as 'git status' and 'git branch' which remote branch to + use for tracking information (commits ahead and behind). + branch..rebase:: When true, rebase the branch on top of the fetched branch, instead of merging the default branch from the default remote when diff --git a/builtin/push.c b/builtin/push.c index 4e9e4dbab2..1d23c68143 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -394,7 +394,14 @@ static int do_push(const char *repo, int flags) } if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) { - if (remote->push_refspec_nr) { + struct branch *branch = branch_get(NULL); + /* Is there a publish branch */ + if (branch && branch->pushremote_name && !strcmp(remote->name, branch->pushremote_name) && + branch->push_name) { + struct strbuf refspec = STRBUF_INIT; + strbuf_addf(&refspec, "%s:%s", branch->name, branch->push_name); + add_refspec(refspec.buf); + } else if (remote->push_refspec_nr) { refspec = remote->push_refspec; refspec_nr = remote->push_refspec_nr; } else if (!(flags & TRANSPORT_PUSH_MIRROR)) diff --git a/remote.c b/remote.c index fc02698587..c153e8bc2f 100644 --- a/remote.c +++ b/remote.c @@ -334,7 +334,8 @@ static int handle_config(const char *key, const char *value, void *cb) if (!value) return config_error_nonbool(key); add_merge(branch, xstrdup(value)); - } + } else if (!strcmp(subkey, "push")) + return git_config_string(&branch->push_name, key, value); return 0; } if (parse_config_key(key, "url", &name, &namelen, &subkey) >= 0) { @@ -1642,6 +1643,14 @@ struct branch *branch_get(const char *name) else ret = make_branch(name, 0); set_merge(ret); + if (ret && ret->pushremote_name && ret->push_name) { + struct remote *pushremote; + pushremote = pushremote_get(ret->pushremote_name); + ret->push.src = xstrdup(ret->push_name); + if (remote_find_tracking(pushremote, &ret->push) + && !strcmp(ret->pushremote_name, ".")) + ret->push.dst = xstrdup(ret->push_name); + } return ret; } diff --git a/remote.h b/remote.h index c21fd3788c..ccbecf6356 100644 --- a/remote.h +++ b/remote.h @@ -213,6 +213,8 @@ struct branch { int merge_alloc; const char *push_tracking_ref; + const char *push_name; + struct refspec push; }; struct branch *branch_get(const char *name); diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index cbe34d6a37..35a9fa0f33 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -1616,4 +1616,53 @@ test_expect_success 'updateInstead with push-to-checkout hook' ' ) ' +mk_publish_test () { + mk_test up_repo heads/master && + mk_test down_repo heads/master && + test_config remote.up.url up_repo && + test_config remote.down.url down_repo && + test_config branch.master.pushremote down && + test_config branch.master.push for-john && + test_config branch.master.remote up && + test_config branch.master.merge master +} + +test_expect_success 'push with publish branch' ' + mk_publish_test && + git push && + check_push_result up_repo $the_first_commit heads/master && + check_push_result down_repo $the_commit heads/for-john +' + +test_expect_success 'push with publish branch for different remote' ' + mk_publish_test && + test_must_fail git push up && + git push up HEAD:master && + check_push_result up_repo $the_commit heads/master && + check_push_result down_repo $the_first_commit heads/master +' + +test_expect_success 'push with publish branch with pushdefault' ' + mk_publish_test && + test_config remote.pushdefault up && + git push && + check_push_result up_repo $the_first_commit heads/master && + check_push_result down_repo $the_commit heads/for-john +' + +test_expect_success 'push with publish branch with remote refspec' ' + mk_publish_test && + test_config remote.down.push refs/heads/master:refs/heads/bad && + git push && + check_push_result up_repo $the_first_commit heads/master && + check_push_result down_repo $the_commit heads/for-john +' + +test_expect_success 'push with publish branch with manual refspec' ' + mk_publish_test && + git push down master:good && + check_push_result up_repo $the_first_commit heads/master && + check_push_result down_repo $the_commit heads/good +' + test_done -- 2.32.0.93.g670b81a890