branch: make create_branch() always create a branch
With the previous commit, there are no more invocations of create_branch() that do not create a branch because: * BRANCH_TRACK_OVERRIDE is no longer passed * clobber_head_ok = true and force = false is never passed Assert these situations, delete dead code and ensure that we're handling clobber_head_ok and force correctly by introducing tests for `git branch --force`. As a result, create_branch() now always creates a branch. Helped-by: Jonathan Tan <jonathantanmy@google.com> Signed-off-by: Glen Choo <chooglen@google.com> Reviewed-by: Jonathan Tan <jonathantanmy@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Glen Choo committed
Jan 28, 2022 at 16:04 UTC
bc0893cf3b0ee376ef5b6ed293b1525480a9d720
3 files changed
+46
-32
branch.c
+27
-30
@@ -429,15 +429,19 @@ void create_branch(struct repository *r,
429
char *real_ref;
430
struct strbuf ref = STRBUF_INIT;
431
int forcing = 0;
432
- int dont_change_ref = 0;
433
-
434
- if ((track == BRANCH_TRACK_OVERRIDE || clobber_head_ok)
435
- ? validate_branchname(name, &ref)
436
- : validate_new_branchname(name, &ref, force)) {
437
- if (!force)
438
- dont_change_ref = 1;
439
- else
440
- forcing = 1;
432
+ struct ref_transaction *transaction;
433
+ struct strbuf err = STRBUF_INIT;
434
+ char *msg;
435
+
436
+ if (track == BRANCH_TRACK_OVERRIDE)
437
+ BUG("'track' cannot be BRANCH_TRACK_OVERRIDE. Did you mean to call dwim_and_setup_tracking()?");
438
+ if (clobber_head_ok && !force)
439
+ BUG("'clobber_head_ok' can only be used with 'force'");
440
+
441
+ if (clobber_head_ok ?
442
+ validate_branchname(name, &ref) :
443
+ validate_new_branchname(name, &ref, force)) {
444
+ forcing = 1;
445
}
446
447
dwim_branch_start(r, start_name, track, &real_ref, &oid);
@@ -445,27 +449,20 @@ void create_branch(struct repository *r,
449
if (reflog)
450
log_all_ref_updates = LOG_REFS_NORMAL;
451
448
- if (!dont_change_ref) {
449
- struct ref_transaction *transaction;
450
- struct strbuf err = STRBUF_INIT;
451
- char *msg;
452
-
453
- if (forcing)
454
- msg = xstrfmt("branch: Reset to %s", start_name);
455
- else
456
- msg = xstrfmt("branch: Created from %s", start_name);
457
-
458
- transaction = ref_transaction_begin(&err);
459
- if (!transaction ||
460
- ref_transaction_update(transaction, ref.buf,
461
- &oid, forcing ? NULL : null_oid(),
462
- 0, msg, &err) ||
463
- ref_transaction_commit(transaction, &err))
464
- die("%s", err.buf);
465
- ref_transaction_free(transaction);
466
- strbuf_release(&err);
467
- free(msg);
468
- }
452
+ if (forcing)
453
+ msg = xstrfmt("branch: Reset to %s", start_name);
454
+ else
455
+ msg = xstrfmt("branch: Created from %s", start_name);
456
+ transaction = ref_transaction_begin(&err);
457
+ if (!transaction ||
458
+ ref_transaction_update(transaction, ref.buf,
459
+ &oid, forcing ? NULL : null_oid(),
460
+ 0, msg, &err) ||
461
+ ref_transaction_commit(transaction, &err))
462
+ die("%s", err.buf);
463
+ ref_transaction_free(transaction);
464
+ strbuf_release(&err);
465
+ free(msg);
466
467
if (real_ref && track)
468
setup_tracking(ref.buf + 11, real_ref, track, quiet);
branch.h
+2
-2
@@ -52,8 +52,8 @@ void dwim_and_setup_tracking(struct repository *r, const char *new_ref,
52
*
53
* - force enables overwriting an existing (non-head) branch
54
*
55
- * - clobber_head_ok allows the currently checked out (hence existing)
56
- * branch to be overwritten; without 'force', it has no effect.
55
+ * - clobber_head_ok, when enabled with 'force', allows the currently
56
+ * checked out (head) branch to be overwritten
57
*
58
* - reflog creates a reflog for the branch
59
*
t/t3200-branch.sh
+17
@@ -42,6 +42,23 @@ test_expect_success 'git branch abc should create a branch' '
42
git branch abc && test_path_is_file .git/refs/heads/abc
43
'
44
45
+test_expect_success 'git branch abc should fail when abc exists' '
46
+ test_must_fail git branch abc
47
+'
48
+
49
+test_expect_success 'git branch --force abc should fail when abc is checked out' '
50
+ test_when_finished git switch main &&
51
+ git switch abc &&
52
+ test_must_fail git branch --force abc HEAD~1
53
+'
54
+
55
+test_expect_success 'git branch --force abc should succeed when abc exists' '
56
+ git rev-parse HEAD~1 >expect &&
57
+ git branch --force abc HEAD~1 &&
58
+ git rev-parse abc >actual &&
59
+ test_cmp expect actual
60
+'
61
+
62
test_expect_success 'git branch a/b/c should create a branch' '
63
git branch a/b/c && test_path_is_file .git/refs/heads/a/b/c
64
'