Merge branch 'il/branch-set-upstream'
* il/branch-set-upstream: branch: warn and refuse to set a branch as a tracking branch of itself. Add branch --set-upstream
This commit is contained in:
commit
1a545d0b5f
@ -11,7 +11,7 @@ SYNOPSIS
|
|||||||
'git branch' [--color | --no-color] [-r | -a]
|
'git branch' [--color | --no-color] [-r | -a]
|
||||||
[-v [--abbrev=<length> | --no-abbrev]]
|
[-v [--abbrev=<length> | --no-abbrev]]
|
||||||
[(--merged | --no-merged | --contains) [<commit>]]
|
[(--merged | --no-merged | --contains) [<commit>]]
|
||||||
'git branch' [--track | --no-track] [-l] [-f] <branchname> [<start-point>]
|
'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]
|
||||||
'git branch' (-m | -M) [<oldbranch>] <newbranch>
|
'git branch' (-m | -M) [<oldbranch>] <newbranch>
|
||||||
'git branch' (-d | -D) [-r] <branchname>...
|
'git branch' (-d | -D) [-r] <branchname>...
|
||||||
|
|
||||||
@ -129,6 +129,12 @@ start-point is either a local or remote branch.
|
|||||||
Do not set up "upstream" configuration, even if the
|
Do not set up "upstream" configuration, even if the
|
||||||
branch.autosetupmerge configuration variable is true.
|
branch.autosetupmerge configuration variable is true.
|
||||||
|
|
||||||
|
--set-upstream::
|
||||||
|
If specified branch does not exist yet or if '--force' has been
|
||||||
|
given, acts exactly like '--track'. Otherwise sets up configuration
|
||||||
|
like '--track' would when creating the branch, except that where
|
||||||
|
branch points to is not changed.
|
||||||
|
|
||||||
--contains <commit>::
|
--contains <commit>::
|
||||||
Only list branches which contain the specified commit.
|
Only list branches which contain the specified commit.
|
||||||
|
|
||||||
|
35
branch.c
35
branch.c
@ -49,9 +49,19 @@ static int should_setup_rebase(const char *origin)
|
|||||||
|
|
||||||
void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
|
void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
|
||||||
{
|
{
|
||||||
|
const char *shortname = remote + 11;
|
||||||
|
int remote_is_branch = !prefixcmp(remote, "refs/heads/");
|
||||||
struct strbuf key = STRBUF_INIT;
|
struct strbuf key = STRBUF_INIT;
|
||||||
int rebasing = should_setup_rebase(origin);
|
int rebasing = should_setup_rebase(origin);
|
||||||
|
|
||||||
|
if (remote_is_branch
|
||||||
|
&& !strcmp(local, shortname)
|
||||||
|
&& !origin) {
|
||||||
|
warning("Not setting branch %s as its own upstream.",
|
||||||
|
local);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
strbuf_addf(&key, "branch.%s.remote", local);
|
strbuf_addf(&key, "branch.%s.remote", local);
|
||||||
git_config_set(key.buf, origin ? origin : ".");
|
git_config_set(key.buf, origin ? origin : ".");
|
||||||
|
|
||||||
@ -71,8 +81,8 @@ void install_branch_config(int flag, const char *local, const char *origin, cons
|
|||||||
strbuf_addstr(&key, origin ? "remote" : "local");
|
strbuf_addstr(&key, origin ? "remote" : "local");
|
||||||
|
|
||||||
/* Are we tracking a proper "branch"? */
|
/* Are we tracking a proper "branch"? */
|
||||||
if (!prefixcmp(remote, "refs/heads/")) {
|
if (remote_is_branch) {
|
||||||
strbuf_addf(&key, " branch %s", remote + 11);
|
strbuf_addf(&key, " branch %s", shortname);
|
||||||
if (origin)
|
if (origin)
|
||||||
strbuf_addf(&key, " from %s", origin);
|
strbuf_addf(&key, " from %s", origin);
|
||||||
}
|
}
|
||||||
@ -108,6 +118,7 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,
|
|||||||
switch (track) {
|
switch (track) {
|
||||||
case BRANCH_TRACK_ALWAYS:
|
case BRANCH_TRACK_ALWAYS:
|
||||||
case BRANCH_TRACK_EXPLICIT:
|
case BRANCH_TRACK_EXPLICIT:
|
||||||
|
case BRANCH_TRACK_OVERRIDE:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 1;
|
return 1;
|
||||||
@ -128,18 +139,25 @@ void create_branch(const char *head,
|
|||||||
const char *name, const char *start_name,
|
const char *name, const char *start_name,
|
||||||
int force, int reflog, enum branch_track track)
|
int force, int reflog, enum branch_track track)
|
||||||
{
|
{
|
||||||
struct ref_lock *lock;
|
struct ref_lock *lock = NULL;
|
||||||
struct commit *commit;
|
struct commit *commit;
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
char *real_ref, msg[PATH_MAX + 20];
|
char *real_ref, msg[PATH_MAX + 20];
|
||||||
struct strbuf ref = STRBUF_INIT;
|
struct strbuf ref = STRBUF_INIT;
|
||||||
int forcing = 0;
|
int forcing = 0;
|
||||||
|
int dont_change_ref = 0;
|
||||||
|
int explicit_tracking = 0;
|
||||||
|
|
||||||
|
if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
|
||||||
|
explicit_tracking = 1;
|
||||||
|
|
||||||
if (strbuf_check_branch_ref(&ref, name))
|
if (strbuf_check_branch_ref(&ref, name))
|
||||||
die("'%s' is not a valid branch name.", name);
|
die("'%s' is not a valid branch name.", name);
|
||||||
|
|
||||||
if (resolve_ref(ref.buf, sha1, 1, NULL)) {
|
if (resolve_ref(ref.buf, sha1, 1, NULL)) {
|
||||||
if (!force)
|
if (!force && track == BRANCH_TRACK_OVERRIDE)
|
||||||
|
dont_change_ref = 1;
|
||||||
|
else if (!force)
|
||||||
die("A branch named '%s' already exists.", name);
|
die("A branch named '%s' already exists.", name);
|
||||||
else if (!is_bare_repository() && !strcmp(head, name))
|
else if (!is_bare_repository() && !strcmp(head, name))
|
||||||
die("Cannot force update the current branch.");
|
die("Cannot force update the current branch.");
|
||||||
@ -153,12 +171,12 @@ void create_branch(const char *head,
|
|||||||
switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
|
switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
|
||||||
case 0:
|
case 0:
|
||||||
/* Not branching from any existing branch */
|
/* Not branching from any existing branch */
|
||||||
if (track == BRANCH_TRACK_EXPLICIT)
|
if (explicit_tracking)
|
||||||
die("Cannot setup tracking information; starting point is not a branch.");
|
die("Cannot setup tracking information; starting point is not a branch.");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
/* Unique completion -- good, only if it is a real ref */
|
/* Unique completion -- good, only if it is a real ref */
|
||||||
if (track == BRANCH_TRACK_EXPLICIT && !strcmp(real_ref, "HEAD"))
|
if (explicit_tracking && !strcmp(real_ref, "HEAD"))
|
||||||
die("Cannot setup tracking information; starting point is not a branch.");
|
die("Cannot setup tracking information; starting point is not a branch.");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -170,9 +188,11 @@ void create_branch(const char *head,
|
|||||||
die("Not a valid branch point: '%s'.", start_name);
|
die("Not a valid branch point: '%s'.", start_name);
|
||||||
hashcpy(sha1, commit->object.sha1);
|
hashcpy(sha1, commit->object.sha1);
|
||||||
|
|
||||||
|
if (!dont_change_ref) {
|
||||||
lock = lock_any_ref_for_update(ref.buf, NULL, 0);
|
lock = lock_any_ref_for_update(ref.buf, NULL, 0);
|
||||||
if (!lock)
|
if (!lock)
|
||||||
die_errno("Failed to lock ref for update");
|
die_errno("Failed to lock ref for update");
|
||||||
|
}
|
||||||
|
|
||||||
if (reflog)
|
if (reflog)
|
||||||
log_all_ref_updates = 1;
|
log_all_ref_updates = 1;
|
||||||
@ -180,13 +200,14 @@ void create_branch(const char *head,
|
|||||||
if (forcing)
|
if (forcing)
|
||||||
snprintf(msg, sizeof msg, "branch: Reset from %s",
|
snprintf(msg, sizeof msg, "branch: Reset from %s",
|
||||||
start_name);
|
start_name);
|
||||||
else
|
else if (!dont_change_ref)
|
||||||
snprintf(msg, sizeof msg, "branch: Created from %s",
|
snprintf(msg, sizeof msg, "branch: Created from %s",
|
||||||
start_name);
|
start_name);
|
||||||
|
|
||||||
if (real_ref && track)
|
if (real_ref && track)
|
||||||
setup_tracking(name, real_ref, track);
|
setup_tracking(name, real_ref, track);
|
||||||
|
|
||||||
|
if (!dont_change_ref)
|
||||||
if (write_ref_sha1(lock, sha1, msg) < 0)
|
if (write_ref_sha1(lock, sha1, msg) < 0)
|
||||||
die_errno("Failed to write ref");
|
die_errno("Failed to write ref");
|
||||||
|
|
||||||
|
@ -564,6 +564,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
|
|||||||
OPT__VERBOSE(&verbose),
|
OPT__VERBOSE(&verbose),
|
||||||
OPT_SET_INT('t', "track", &track, "set up tracking mode (see git-pull(1))",
|
OPT_SET_INT('t', "track", &track, "set up tracking mode (see git-pull(1))",
|
||||||
BRANCH_TRACK_EXPLICIT),
|
BRANCH_TRACK_EXPLICIT),
|
||||||
|
OPT_SET_INT( 0, "set-upstream", &track, "change upstream info",
|
||||||
|
BRANCH_TRACK_OVERRIDE),
|
||||||
OPT_BOOLEAN( 0 , "color", &branch_use_color, "use colored output"),
|
OPT_BOOLEAN( 0 , "color", &branch_use_color, "use colored output"),
|
||||||
OPT_SET_INT('r', NULL, &kinds, "act on remote-tracking branches",
|
OPT_SET_INT('r', NULL, &kinds, "act on remote-tracking branches",
|
||||||
REF_REMOTE_BRANCH),
|
REF_REMOTE_BRANCH),
|
||||||
|
1
cache.h
1
cache.h
@ -553,6 +553,7 @@ enum branch_track {
|
|||||||
BRANCH_TRACK_REMOTE,
|
BRANCH_TRACK_REMOTE,
|
||||||
BRANCH_TRACK_ALWAYS,
|
BRANCH_TRACK_ALWAYS,
|
||||||
BRANCH_TRACK_EXPLICIT,
|
BRANCH_TRACK_EXPLICIT,
|
||||||
|
BRANCH_TRACK_OVERRIDE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum rebase_setup_type {
|
enum rebase_setup_type {
|
||||||
|
@ -89,4 +89,25 @@ test_expect_success 'status when tracking annotated tags' '
|
|||||||
grep "set up to track" actual &&
|
grep "set up to track" actual &&
|
||||||
git checkout heavytrack
|
git checkout heavytrack
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'setup tracking with branch --set-upstream on existing branch' '
|
||||||
|
git branch from-master master &&
|
||||||
|
test_must_fail git config branch.from-master.merge > actual &&
|
||||||
|
git branch --set-upstream from-master master &&
|
||||||
|
git config branch.from-master.merge > actual &&
|
||||||
|
grep -q "^refs/heads/master$" actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success '--set-upstream does not change branch' '
|
||||||
|
git branch from-master2 master &&
|
||||||
|
test_must_fail git config branch.from-master2.merge > actual &&
|
||||||
|
git rev-list from-master2 &&
|
||||||
|
git update-ref refs/heads/from-master2 from-master2^ &&
|
||||||
|
git rev-parse from-master2 >expect2 &&
|
||||||
|
git branch --set-upstream from-master2 master &&
|
||||||
|
git config branch.from-master.merge > actual &&
|
||||||
|
git rev-parse from-master2 >actual2 &&
|
||||||
|
grep -q "^refs/heads/master$" actual &&
|
||||||
|
cmp expect2 actual2
|
||||||
|
'
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user