Skip to content

Commit e096683

Browse files
committed
Merge branch 'rj/branch-unborn-in-other-worktrees' into seen
* rj/branch-unborn-in-other-worktrees: branch: rename orphan branches in any worktree branch: description for orphan branch errors avoid unnecessary worktrees traversing
2 parents 7f60160 + ae750a0 commit e096683

File tree

3 files changed

+54
-20
lines changed

3 files changed

+54
-20
lines changed

builtin/branch.c

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -486,14 +486,17 @@ static void print_current_branch_name(void)
486486
die(_("HEAD (%s) points outside of refs/heads/"), refname);
487487
}
488488

489-
static void reject_rebase_or_bisect_branch(const char *target)
489+
static int ishead_and_reject_rebase_or_bisect_branch(const char *target)
490490
{
491491
struct worktree **worktrees = get_worktrees();
492-
int i;
492+
int i, ret = 0;
493493

494494
for (i = 0; worktrees[i]; i++) {
495495
struct worktree *wt = worktrees[i];
496496

497+
if (wt->head_ref && !strcmp(target, wt->head_ref))
498+
ret = 1 + (is_null_oid(&wt->head_oid) ? 1 : 0);
499+
497500
if (!wt->is_detached)
498501
continue;
499502

@@ -507,6 +510,7 @@ static void reject_rebase_or_bisect_branch(const char *target)
507510
}
508511

509512
free_worktrees(worktrees);
513+
return ret;
510514
}
511515

512516
static void copy_or_rename_branch(const char *oldname, const char *newname, int copy, int force)
@@ -515,7 +519,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
515519
struct strbuf oldsection = STRBUF_INIT, newsection = STRBUF_INIT;
516520
const char *interpreted_oldname = NULL;
517521
const char *interpreted_newname = NULL;
518-
int recovery = 0;
522+
int recovery = 0, ishead;
519523

520524
if (strbuf_check_branch_ref(&oldref, oldname)) {
521525
/*
@@ -528,12 +532,12 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
528532
die(_("Invalid branch name: '%s'"), oldname);
529533
}
530534

531-
if ((copy || strcmp(head, oldname)) && !ref_exists(oldref.buf)) {
532-
if (copy && !strcmp(head, oldname))
533-
die(_("No commit on branch '%s' yet."), oldname);
534-
else
535-
die(_("No branch named '%s'."), oldname);
536-
}
535+
ishead = ishead_and_reject_rebase_or_bisect_branch(oldref.buf);
536+
537+
if ((copy || !ishead) && !ref_exists(oldref.buf))
538+
die(ishead
539+
? _("No commit on branch '%s' yet.")
540+
: _("No branch named '%s'."), oldname);
537541

538542
/*
539543
* A command like "git branch -M currentbranch currentbranch" cannot
@@ -544,8 +548,6 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
544548
else
545549
validate_new_branchname(newname, &newref, force);
546550

547-
reject_rebase_or_bisect_branch(oldref.buf);
548-
549551
if (!skip_prefix(oldref.buf, "refs/heads/", &interpreted_oldname) ||
550552
!skip_prefix(newref.buf, "refs/heads/", &interpreted_newname)) {
551553
BUG("expected prefix missing for refs");
@@ -558,8 +560,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
558560
strbuf_addf(&logmsg, "Branch: renamed %s to %s",
559561
oldref.buf, newref.buf);
560562

561-
if (!copy &&
562-
(!head || strcmp(oldname, head) || !is_null_oid(&head_oid)) &&
563+
if (!copy && !(ishead > 1) &&
563564
rename_ref(oldref.buf, newref.buf, logmsg.buf))
564565
die(_("Branch rename failed"));
565566
if (copy && copy_existing_ref(oldref.buf, newref.buf, logmsg.buf))
@@ -574,7 +575,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
574575
interpreted_oldname);
575576
}
576577

577-
if (!copy &&
578+
if (!copy && ishead &&
578579
replace_each_worktree_head_symref(oldref.buf, newref.buf, logmsg.buf))
579580
die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
580581

@@ -806,7 +807,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
806807

807808
strbuf_addf(&branch_ref, "refs/heads/%s", branch_name);
808809
if (!ref_exists(branch_ref.buf))
809-
error((!argc || !strcmp(head, branch_name))
810+
error((!argc || branch_checked_out(branch_ref.buf))
810811
? _("No commit on branch '%s' yet.")
811812
: _("No branch named '%s'."),
812813
branch_name);
@@ -850,11 +851,10 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
850851
die(_("no such branch '%s'"), argv[0]);
851852
}
852853

853-
if (!ref_exists(branch->refname)) {
854-
if (!argc || !strcmp(head, branch->name))
855-
die(_("No commit on branch '%s' yet."), branch->name);
856-
die(_("branch '%s' does not exist"), branch->name);
857-
}
854+
if (!ref_exists(branch->refname))
855+
die((!argc || branch_checked_out(branch->refname))
856+
? _("No commit on branch '%s' yet.")
857+
: _("branch '%s' does not exist"), branch->name);
858858

859859
dwim_and_setup_tracking(the_repository, branch->name,
860860
new_upstream, BRANCH_TRACK_OVERRIDE,

t/t3200-branch.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,22 @@ test_expect_success 'git branch -M and -C fail on detached HEAD' '
280280
test_cmp expect err
281281
'
282282

283+
test_expect_success 'git branch -m should work with orphan branches' '
284+
test_when_finished git checkout - &&
285+
test_when_finished git worktree remove -f wt &&
286+
git worktree add wt --detach &&
287+
288+
# rename orphan in another worktreee
289+
git -C wt checkout --orphan orphan-foo-wt &&
290+
git branch -m orphan-foo-wt orphan-bar-wt &&
291+
test orphan-bar-wt=$(git -C orphan-worktree branch --show-current) &&
292+
293+
# rename orphan in the current worktree
294+
git checkout --orphan orphan-foo &&
295+
git branch -m orphan-foo orphan-bar &&
296+
test orphan-bar=$(git branch --show-current)
297+
'
298+
283299
test_expect_success 'git branch -d on orphan HEAD (merged)' '
284300
test_when_finished git checkout main &&
285301
git checkout --orphan orphan &&

t/t3202-show-branch.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,4 +221,22 @@ test_expect_success 'fatal descriptions on non-existent branch' '
221221
test_cmp expect actual
222222
'
223223

224+
test_expect_success 'error descriptions on orphan branch' '
225+
test_when_finished git worktree remove -f wt &&
226+
git worktree add wt --detach &&
227+
git -C wt checkout --orphan orphan-branch &&
228+
test_branch_op_in_wt() {
229+
test_orphan_error() {
230+
test_must_fail git $* 2>actual &&
231+
test_i18ngrep "No commit on branch .orphan-branch. yet.$" actual
232+
} &&
233+
test_orphan_error -C wt branch $1 $2 && # implicit branch
234+
test_orphan_error -C wt branch $1 orphan-branch $2 && # explicit branch
235+
test_orphan_error branch $1 orphan-branch $2 # different worktree
236+
} &&
237+
test_branch_op_in_wt --edit-description &&
238+
test_branch_op_in_wt --set-upstream-to=ne &&
239+
test_branch_op_in_wt -c new-branch
240+
'
241+
224242
test_done

0 commit comments

Comments
 (0)