threads / discuss / 41825

How to use @{-1} with push?

Subject: How to use @{-1} with push?

## tl;dr

6 messages between Mar 25, 2016 and Mar 28, 2016.

replies: 5people: 2as markdown or json

Robert Dailey· Mar 25, 2016, 14:40 UTC · lore
I have an alias that I'm working on to do a push and delete of a topic branch:
    # Push HEAD, delete branch local & remote
    #
    # $1 = remote name
    # $2 = branch name
    pushdel = "!f() { : git push ; git push \"$1\" HEAD \":$2\" && git
branch -d \"$2\" ; }; f"
I use it after I merge a topic branch, like so:
$ git pushdel origin my-topic-branch
What would be nice is if I could do one of the two:

$ git pushdel origin - $ git pushdel origin @{-1}

Both should refer to the last branch, but I know that these can't be used verbatim in a push command because it doesn't read it as a branch name normally like `git checkout` would. I'm not sure why, as I do not have knowledge of the underlying mechanics of these commands.

Is there a way I can use these "relative" branch shorthands in my push command? If not directly, perhaps there is a way I can update my alias to do an intermediate translation?

Thanks in advance.
Junio C Hamano· Mar 25, 2016, 17:45 UTC · re: Robert Dailey · lore

Re: How to use @{-1} with push?

Robert Dailey <rcdailey.lists@gmail.com> writes:
> Both should refer to the last branch, but I know that these can't be
> used verbatim in a push command because it doesn't read it as a branch
> name normally like `git checkout` would.

You can ask rev-parse to give you --symbolic-full-name, error out if it is empty (i.e. detached HEAD), and otherwise use the result, no?

    $ git checkout next
    $ git checkout master
    $ git rev-parse --symbolic-full-name @{-1}
    refs/heads/master
    $ git checkout HEAD^0
    $ git checkout master
    $ git rev-parse --symbolic-full-name @{-1}
    $ exit
And
    $ git push origin :refs/heads/master
would be the fully-spelled out way to remove that branch.
Robert Dailey· Mar 25, 2016, 18:02 UTC · re: Junio C Hamano · lore

Re: How to use @{-1} with push?

On Fri, Mar 25, 2016 at 12:45 PM, Junio C Hamano <gitster@pobox.com> wrote:
Show 17 quoted lines
> You can ask rev-parse to give you --symbolic-full-name, error out if
> it is empty (i.e. detached HEAD), and otherwise use the result, no?
>
>     $ git checkout next
>     $ git checkout master
>     $ git rev-parse --symbolic-full-name @{-1}
>     refs/heads/master
>     $ git checkout HEAD^0
>     $ git checkout master
>     $ git rev-parse --symbolic-full-name @{-1}
>     $ exit
>
> And
>
>     $ git push origin :refs/heads/master
>
> would be the fully-spelled out way to remove that branch.

Thanks Junio, I figured there was a command to do that. I tried to do this using '-' shorthand, but that didn't work. I guess because that's not really a revision, but a special function of git checkout only.

Robert Dailey· Mar 25, 2016, 18:11 UTC · re: Robert Dailey · lore

Re: How to use @{-1} with push?

On Fri, Mar 25, 2016 at 1:02 PM, Robert Dailey <rcdailey.lists@gmail.com> wrote:
Show 22 quoted lines
> On Fri, Mar 25, 2016 at 12:45 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> You can ask rev-parse to give you --symbolic-full-name, error out if
>> it is empty (i.e. detached HEAD), and otherwise use the result, no?
>>
>>     $ git checkout next
>>     $ git checkout master
>>     $ git rev-parse --symbolic-full-name @{-1}
>>     refs/heads/master
>>     $ git checkout HEAD^0
>>     $ git checkout master
>>     $ git rev-parse --symbolic-full-name @{-1}
>>     $ exit
>>
>> And
>>
>>     $ git push origin :refs/heads/master
>>
>> would be the fully-spelled out way to remove that branch.
>
> Thanks Junio, I figured there was a command to do that. I tried to do
> this using '-' shorthand, but that didn't work. I guess because that's
> not really a revision, but a special function of git checkout only.
So the push works with the fully-qualified ref, but not git branch:

$ git rev-parse --symbolic-full-name foo refs/heads/foo

$ git branch -d refs/heads/foo error: branch 'refs/heads/foo' not found.

Any reason for this? I'm using git 2.7.4 on windows
Junio C Hamano· Mar 25, 2016, 18:58 UTC · re: Robert Dailey · lore

Re: How to use @{-1} with push?

Robert Dailey <rcdailey.lists@gmail.com> writes:
> So the push works with the fully-qualified ref, but not git branch:

I thought these are clear from their documentation. "push" works on refnames, "branch" works on branch names. "push" takes an branch name as a short-hand and adds refs/heads/ when it makes sense, but because it does not make any sense for "git branch" to create a "branch" in a random place in refs/ (e.g. "refs/tags/foo" is not a branch), it takes "foo" (i.e. the name of the branch, whose underlying ref is "refs/heads/foo").

So
	ref=$(git rev-parse --symbolic-full-name "$2") &&
        case "$ref" in
        '') echo >&2 "No such thing $2"; exit 1 ;;
        refs/heads/*) ref=${ref#refs/heads/} ;;
        *) echo >&2 "That's not a branch $2"; exit 2 ;;
	esac &&
	git push "$1" "refs/heads/$ref" &&
        git branch -D "$ref"
or something?
Show 8 quoted lines
>
> $ git rev-parse --symbolic-full-name foo
> refs/heads/foo
>
> $ git branch -d refs/heads/foo
> error: branch 'refs/heads/foo' not found.
>
> Any reason for this? I'm using git 2.7.4 on windows
Robert Dailey· Mar 28, 2016, 14:53 UTC · re: Junio C Hamano · lore

Re: How to use @{-1} with push?

On Fri, Mar 25, 2016 at 1:58 PM, Junio C Hamano <gitster@pobox.com> wrote:
Show 20 quoted lines
> I thought these are clear from their documentation.  "push" works on
> refnames, "branch" works on branch names.  "push" takes an branch
> name as a short-hand and adds refs/heads/ when it makes sense, but
> because it does not make any sense for "git branch" to create a
> "branch" in a random place in refs/ (e.g. "refs/tags/foo" is not a
> branch), it takes "foo" (i.e. the name of the branch, whose
> underlying ref is "refs/heads/foo").
>
> So
>
>         ref=$(git rev-parse --symbolic-full-name "$2") &&
>         case "$ref" in
>         '') echo >&2 "No such thing $2"; exit 1 ;;
>         refs/heads/*) ref=${ref#refs/heads/} ;;
>         *) echo >&2 "That's not a branch $2"; exit 2 ;;
>         esac &&
>         git push "$1" "refs/heads/$ref" &&
>         git branch -D "$ref"
>
> or something?

Reading the git documentation feels a lot like reading the C++ standard. Not the best place to go to learn something. Some of the terminology is very detail-oriented. For example, until you explained the differences between push & branch, I always thought "ref" and "branch" were interchangeable. But now it's clear to me that a branch is just a type of ref, but refs are not branches. Also as a Windows developer, I am not as well-versed in bash scripting as I'd like to be.

So thanks for your explanation, it is clear now.

← back to recent threads