Skip to content

Commit 1da6d98

Browse files
committed
Merge branch 'ci/forbid-unwanted-current-branch-update'
* ci/forbid-unwanted-current-branch-update: Show interpreted branch name in error messages Prevent force-updating of the current branch
2 parents 67c116b + 587a9ee commit 1da6d98

File tree

6 files changed

+65
-24
lines changed

6 files changed

+65
-24
lines changed

branch.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,26 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,
135135
return 0;
136136
}
137137

138+
int validate_new_branchname(const char *name, struct strbuf *ref, int force)
139+
{
140+
const char *head;
141+
unsigned char sha1[20];
142+
143+
if (strbuf_check_branch_ref(ref, name))
144+
die("'%s' is not a valid branch name.", name);
145+
146+
if (!ref_exists(ref->buf))
147+
return 0;
148+
else if (!force)
149+
die("A branch named '%s' already exists.", ref->buf + strlen("refs/heads/"));
150+
151+
head = resolve_ref("HEAD", sha1, 0, NULL);
152+
if (!is_bare_repository() && head && !strcmp(head, ref->buf))
153+
die("Cannot force update the current branch.");
154+
155+
return 1;
156+
}
157+
138158
void create_branch(const char *head,
139159
const char *name, const char *start_name,
140160
int force, int reflog, enum branch_track track)
@@ -151,17 +171,11 @@ void create_branch(const char *head,
151171
if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
152172
explicit_tracking = 1;
153173

154-
if (strbuf_check_branch_ref(&ref, name))
155-
die("'%s' is not a valid branch name.", name);
156-
157-
if (resolve_ref(ref.buf, sha1, 1, NULL)) {
158-
if (!force && track == BRANCH_TRACK_OVERRIDE)
174+
if (validate_new_branchname(name, &ref, force || track == BRANCH_TRACK_OVERRIDE)) {
175+
if (!force)
159176
dont_change_ref = 1;
160-
else if (!force)
161-
die("A branch named '%s' already exists.", name);
162-
else if (!is_bare_repository() && head && !strcmp(head, name))
163-
die("Cannot force update the current branch.");
164-
forcing = 1;
177+
else
178+
forcing = 1;
165179
}
166180

167181
real_ref = NULL;

branch.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@
1515
void create_branch(const char *head, const char *name, const char *start_name,
1616
int force, int reflog, enum branch_track track);
1717

18+
/*
19+
* Validates that the requested branch may be created, returning the
20+
* interpreted ref in ref, force indicates whether (non-head) branches
21+
* may be overwritten. A non-zero return value indicates that the force
22+
* parameter was non-zero and the branch already exists.
23+
*/
24+
int validate_new_branchname(const char *name, struct strbuf *ref, int force);
25+
1826
/*
1927
* Remove information about the state of working on the current
2028
* branch. (E.g., MERGE_HEAD)

builtin/branch.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -566,11 +566,7 @@ static void rename_branch(const char *oldname, const char *newname, int force)
566566
die(_("Invalid branch name: '%s'"), oldname);
567567
}
568568

569-
if (strbuf_check_branch_ref(&newref, newname))
570-
die(_("Invalid branch name: '%s'"), newname);
571-
572-
if (resolve_ref(newref.buf, sha1, 1, NULL) && !force)
573-
die(_("A branch named '%s' already exists."), newref.buf + 11);
569+
validate_new_branchname(newname, &newref, force);
574570

575571
strbuf_addf(&logmsg, "Branch: renamed %s to %s",
576572
oldref.buf, newref.buf);

builtin/checkout.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,15 +1072,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
10721072

10731073
if (opts.new_branch) {
10741074
struct strbuf buf = STRBUF_INIT;
1075-
if (strbuf_check_branch_ref(&buf, opts.new_branch))
1076-
die(_("git checkout: we do not like '%s' as a branch name."),
1077-
opts.new_branch);
1078-
if (ref_exists(buf.buf)) {
1079-
opts.branch_exists = 1;
1080-
if (!opts.new_branch_force)
1081-
die(_("git checkout: branch %s already exists"),
1082-
opts.new_branch);
1083-
}
1075+
1076+
opts.branch_exists = validate_new_branchname(opts.new_branch, &buf, !!opts.new_branch_force);
1077+
10841078
strbuf_release(&buf);
10851079
}
10861080

t/t2018-checkout-branch.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,15 @@ test_expect_success 'checkout -b to an existing branch fails' '
118118
test_must_fail do_checkout branch2 $HEAD2
119119
'
120120

121+
test_expect_success 'checkout -b to @{-1} fails with the right branch name' '
122+
git reset --hard HEAD &&
123+
git checkout branch1 &&
124+
git checkout branch2 &&
125+
echo >expect "fatal: A branch named '\''branch1'\'' already exists." &&
126+
test_must_fail git checkout -b @{-1} 2>actual &&
127+
test_cmp expect actual
128+
'
129+
121130
test_expect_success 'checkout -B to an existing branch resets branch to HEAD' '
122131
git checkout branch1 &&
123132
@@ -180,4 +189,12 @@ test_expect_success 'checkout -b <describe>' '
180189
test_cmp expect actual
181190
'
182191

192+
test_expect_success 'checkout -B to the current branch fails before merging' '
193+
git checkout branch1 &&
194+
setup_dirty_mergeable &&
195+
git commit -mfooble &&
196+
test_must_fail git checkout -B branch1 initial &&
197+
test_must_fail test_dirty_mergeable
198+
'
199+
183200
test_done

t/t3200-branch.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,18 @@ test_expect_success 'git branch -m q r/q should fail when r exists' '
9898
test_must_fail git branch -m q r/q
9999
'
100100

101+
test_expect_success 'git branch -M foo bar should fail when bar is checked out' '
102+
git branch bar &&
103+
git checkout -b foo &&
104+
test_must_fail git branch -M bar foo
105+
'
106+
107+
test_expect_success 'git branch -M baz bam should succeed when baz is checked out' '
108+
git checkout -b baz &&
109+
git branch bam &&
110+
git branch -M baz bam
111+
'
112+
101113
mv .git/config .git/config-saved
102114

103115
test_expect_success 'git branch -m q q2 without config should succeed' '

0 commit comments

Comments
 (0)