Add --set-upstream option to branch that works like --track, except that
when branch exists already, its upstream info is changed without changing
the ref value.

Based-on-patch-from: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Ilari Liusvaara 2010-01-18 22:44:11 +02:00 коммит произвёл Junio C Hamano
Родитель ff6d26a0e1
Коммит 4fc5006676
5 изменённых файлов: 52 добавлений и 11 удалений

Просмотреть файл

@ -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.

Просмотреть файл

@ -108,6 +108,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 +129,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 +161,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 +178,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);
lock = lock_any_ref_for_update(ref.buf, NULL, 0); if (!dont_change_ref) {
if (!lock) lock = lock_any_ref_for_update(ref.buf, NULL, 0);
die_errno("Failed to lock ref for update"); if (!lock)
die_errno("Failed to lock ref for update");
}
if (reflog) if (reflog)
log_all_ref_updates = 1; log_all_ref_updates = 1;
@ -180,15 +190,16 @@ 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 (write_ref_sha1(lock, sha1, msg) < 0) if (!dont_change_ref)
die_errno("Failed to write ref"); if (write_ref_sha1(lock, sha1, msg) < 0)
die_errno("Failed to write ref");
strbuf_release(&ref); strbuf_release(&ref);
free(real_ref); free(real_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),

Просмотреть файл

@ -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