refspec: make @ a synonym of HEAD

Since commit 9ba89f484e git learned how to push to a remote branch using the source @, for example: git push origin @:master However, if the right-hand side is missing, the push fails: git push origin @ It is obvious what is the desired behavior, and allowing the push makes things more consistent. Additionally, @:master now has the same semantics as HEAD:master. Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Felipe Contreras committed Nov 25, 2020 at 18:16 UTC 374fbaef3df8f05acf9968fc38c6da72a62bcfc2
3 files changed +62 -52
refspec.c
+4 -1
@@ -71,7 +71,10 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet
71 }
72
73 item->pattern = is_glob;
74 - item->src = xstrndup(lhs, llen);
74 + if (llen == 1 && *lhs == '@')
75 + item->src = xstrdup("HEAD");
76 + else
77 + item->src = xstrndup(lhs, llen);
78 flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);
79
80 if (item->negative) {
t/t5511-refspec.sh
+2
@@ -58,6 +58,8 @@ test_refspec fetch 'HEAD~4:refs/remotes/frotz/new' invalid
58
59 test_refspec push 'HEAD'
60 test_refspec fetch 'HEAD'
61 +test_refspec push '@'
62 +test_refspec fetch '@'
63 test_refspec push 'refs/heads/ nitfol' invalid
64 test_refspec fetch 'refs/heads/ nitfol' invalid
65
t/t5516-fetch-push.sh
+56 -51
@@ -436,71 +436,76 @@ test_expect_success 'push ref expression with non-existent, incomplete dest' '
436
437 '
438
439 -test_expect_success 'push with HEAD' '
439 +for head in HEAD @
440 +do
441
441 - mk_test testrepo heads/master &&
442 - git checkout master &&
443 - git push testrepo HEAD &&
444 - check_push_result testrepo $the_commit heads/master
442 + test_expect_success "push with $head" '
443
446 -'
444 + mk_test testrepo heads/master &&
445 + git checkout master &&
446 + git push testrepo $head &&
447 + check_push_result testrepo $the_commit heads/master
448
448 -test_expect_success 'push with HEAD nonexisting at remote' '
449 + '
450
450 - mk_test testrepo heads/master &&
451 - git checkout -b local master &&
452 - test_when_finished "git checkout master; git branch -D local" &&
453 - git push testrepo HEAD &&
454 - check_push_result testrepo $the_commit heads/local
455 -'
451 + test_expect_success "push with $head nonexisting at remote" '
452
457 -test_expect_success 'push with +HEAD' '
453 + mk_test testrepo heads/master &&
454 + git checkout -b local master &&
455 + test_when_finished "git checkout master; git branch -D local" &&
456 + git push testrepo $head &&
457 + check_push_result testrepo $the_commit heads/local
458 + '
459
459 - mk_test testrepo heads/master &&
460 - git checkout -b local master &&
461 - test_when_finished "git checkout master; git branch -D local" &&
462 - git push testrepo master local &&
463 - check_push_result testrepo $the_commit heads/master &&
464 - check_push_result testrepo $the_commit heads/local &&
460 + test_expect_success "push with +$head" '
461
466 - # Without force rewinding should fail
467 - git reset --hard HEAD^ &&
468 - test_must_fail git push testrepo HEAD &&
469 - check_push_result testrepo $the_commit heads/local &&
462 + mk_test testrepo heads/master &&
463 + git checkout -b local master &&
464 + test_when_finished "git checkout master; git branch -D local" &&
465 + git push testrepo master local &&
466 + check_push_result testrepo $the_commit heads/master &&
467 + check_push_result testrepo $the_commit heads/local &&
468
471 - # With force rewinding should succeed
472 - git push testrepo +HEAD &&
473 - check_push_result testrepo $the_first_commit heads/local
469 + # Without force rewinding should fail
470 + git reset --hard $head^ &&
471 + test_must_fail git push testrepo $head &&
472 + check_push_result testrepo $the_commit heads/local &&
473
475 -'
474 + # With force rewinding should succeed
475 + git push testrepo +$head &&
476 + check_push_result testrepo $the_first_commit heads/local
477
477 -test_expect_success 'push HEAD with non-existent, incomplete dest' '
478 + '
479
479 - mk_test testrepo &&
480 - git checkout master &&
481 - git push testrepo HEAD:branch &&
482 - check_push_result testrepo $the_commit heads/branch
480 + test_expect_success "push $head with non-existent, incomplete dest" '
481
484 -'
482 + mk_test testrepo &&
483 + git checkout master &&
484 + git push testrepo $head:branch &&
485 + check_push_result testrepo $the_commit heads/branch
486
486 -test_expect_success 'push with config remote.*.push = HEAD' '
487 + '
488
488 - mk_test testrepo heads/local &&
489 - git checkout master &&
490 - git branch -f local $the_commit &&
491 - test_when_finished "git branch -D local" &&
492 - (
493 - cd testrepo &&
494 - git checkout local &&
495 - git reset --hard $the_first_commit
496 - ) &&
497 - test_config remote.there.url testrepo &&
498 - test_config remote.there.push HEAD &&
499 - test_config branch.master.remote there &&
500 - git push &&
501 - check_push_result testrepo $the_commit heads/master &&
502 - check_push_result testrepo $the_first_commit heads/local
503 -'
489 + test_expect_success "push with config remote.*.push = $head" '
490 +
491 + mk_test testrepo heads/local &&
492 + git checkout master &&
493 + git branch -f local $the_commit &&
494 + test_when_finished "git branch -D local" &&
495 + (
496 + cd testrepo &&
497 + git checkout local &&
498 + git reset --hard $the_first_commit
499 + ) &&
500 + test_config remote.there.url testrepo &&
501 + test_config remote.there.push $head &&
502 + test_config branch.master.remote there &&
503 + git push &&
504 + check_push_result testrepo $the_commit heads/master &&
505 + check_push_result testrepo $the_first_commit heads/local
506 + '
507 +
508 +done
509
510 test_expect_success 'push with remote.pushdefault' '
511 mk_test up_repo heads/master &&