Skip to content

Commit

Permalink
refspec: make @ a synonym of HEAD
Browse files Browse the repository at this point in the history
Since commit 9ba89f4 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>
  • Loading branch information
Felipe Contreras authored and gitster committed Nov 30, 2020
1 parent e7f80ea commit 374fbae
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 52 deletions.
5 changes: 4 additions & 1 deletion refspec.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ static int parse_refspec(struct refspec_item *item, const char *refspec, int fet
}

item->pattern = is_glob;
item->src = xstrndup(lhs, llen);
if (llen == 1 && *lhs == '@')
item->src = xstrdup("HEAD");
else
item->src = xstrndup(lhs, llen);
flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);

if (item->negative) {
Expand Down
2 changes: 2 additions & 0 deletions t/t5511-refspec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ test_refspec fetch 'HEAD~4:refs/remotes/frotz/new' invalid

test_refspec push 'HEAD'
test_refspec fetch 'HEAD'
test_refspec push '@'
test_refspec fetch '@'
test_refspec push 'refs/heads/ nitfol' invalid
test_refspec fetch 'refs/heads/ nitfol' invalid

Expand Down
107 changes: 56 additions & 51 deletions t/t5516-fetch-push.sh
Original file line number Diff line number Diff line change
Expand Up @@ -436,71 +436,76 @@ test_expect_success 'push ref expression with non-existent, incomplete dest' '
'

test_expect_success 'push with HEAD' '
for head in HEAD @
do

mk_test testrepo heads/master &&
git checkout master &&
git push testrepo HEAD &&
check_push_result testrepo $the_commit heads/master
test_expect_success "push with $head" '
'
mk_test testrepo heads/master &&
git checkout master &&
git push testrepo $head &&
check_push_result testrepo $the_commit heads/master
test_expect_success 'push with HEAD nonexisting at remote' '
'

mk_test testrepo heads/master &&
git checkout -b local master &&
test_when_finished "git checkout master; git branch -D local" &&
git push testrepo HEAD &&
check_push_result testrepo $the_commit heads/local
'
test_expect_success "push with $head nonexisting at remote" '
test_expect_success 'push with +HEAD' '
mk_test testrepo heads/master &&
git checkout -b local master &&
test_when_finished "git checkout master; git branch -D local" &&
git push testrepo $head &&
check_push_result testrepo $the_commit heads/local
'

mk_test testrepo heads/master &&
git checkout -b local master &&
test_when_finished "git checkout master; git branch -D local" &&
git push testrepo master local &&
check_push_result testrepo $the_commit heads/master &&
check_push_result testrepo $the_commit heads/local &&
test_expect_success "push with +$head" '
# Without force rewinding should fail
git reset --hard HEAD^ &&
test_must_fail git push testrepo HEAD &&
check_push_result testrepo $the_commit heads/local &&
mk_test testrepo heads/master &&
git checkout -b local master &&
test_when_finished "git checkout master; git branch -D local" &&
git push testrepo master local &&
check_push_result testrepo $the_commit heads/master &&
check_push_result testrepo $the_commit heads/local &&
# With force rewinding should succeed
git push testrepo +HEAD &&
check_push_result testrepo $the_first_commit heads/local
# Without force rewinding should fail
git reset --hard $head^ &&
test_must_fail git push testrepo $head &&
check_push_result testrepo $the_commit heads/local &&
'
# With force rewinding should succeed
git push testrepo +$head &&
check_push_result testrepo $the_first_commit heads/local
test_expect_success 'push HEAD with non-existent, incomplete dest' '
'

mk_test testrepo &&
git checkout master &&
git push testrepo HEAD:branch &&
check_push_result testrepo $the_commit heads/branch
test_expect_success "push $head with non-existent, incomplete dest" '
'
mk_test testrepo &&
git checkout master &&
git push testrepo $head:branch &&
check_push_result testrepo $the_commit heads/branch
test_expect_success 'push with config remote.*.push = HEAD' '
'

mk_test testrepo heads/local &&
git checkout master &&
git branch -f local $the_commit &&
test_when_finished "git branch -D local" &&
(
cd testrepo &&
git checkout local &&
git reset --hard $the_first_commit
) &&
test_config remote.there.url testrepo &&
test_config remote.there.push HEAD &&
test_config branch.master.remote there &&
git push &&
check_push_result testrepo $the_commit heads/master &&
check_push_result testrepo $the_first_commit heads/local
'
test_expect_success "push with config remote.*.push = $head" '
mk_test testrepo heads/local &&
git checkout master &&
git branch -f local $the_commit &&
test_when_finished "git branch -D local" &&
(
cd testrepo &&
git checkout local &&
git reset --hard $the_first_commit
) &&
test_config remote.there.url testrepo &&
test_config remote.there.push $head &&
test_config branch.master.remote there &&
git push &&
check_push_result testrepo $the_commit heads/master &&
check_push_result testrepo $the_first_commit heads/local
'

done

test_expect_success 'push with remote.pushdefault' '
mk_test up_repo heads/master &&
Expand Down

0 comments on commit 374fbae

Please sign in to comment.