16

I'm trying to write an alias to delete both a local and remote branch at the same time, but I can't figure out why the syntax is not working. In ~/.gitconfig, I've tried the following aliases, but each produces the same result, which is unexpected:

[alias]
     nuke = !sh -c 'git branch -D $1 && git push origin :$1'

and

[alias]
     nuke = !git branch -D $1 && git push origin :$1

both produce:

$> git branch
  * master
  mybranch
$> git nuke mybranch
Everything up-to-date
$> git branch
  * master
  mybranch

Switching the order of the commands produces a different result, but also not entirely what I'm looking for:

[alias]
    nuke = !git push origin :$1 && git branch -D $1

...

$> git branch
  * master
  mybranch
$> git nuke mybranch
Everything up-to-date
Deleted branch mybranch (was d719895)
$> git branch
  * master
$> git push origin :mybranch
To git@github.com:biegel/repo.git
 - [deleted]         mybranch

When I run that command directly on the shell, it works nicely:

$> git branch
* master
  mybranch
$> git branch -D mybranch && git push origin :mybranch
Deleted branch mybranch (was d719895
To git@github.com:biegel/repo.git
 - [deleted]         mybranch
$> git branch
* master

I've tried creating an alias in ~/.bashrc, using git push origin --delete $1 and using a shell function with !f() { }; and nothing seems to take!

I'm ready to give up. Any thoughts on what I'm missing here?

Thanks.

biegel
  • 570
  • 5
  • 12

3 Answers3

43

You can make this work just fine. You just need to add a missing command name at the end of your definition. The command name will become $0 and everything after will get assigned to $1, $2, etc. In this case, I simply used - as the command name:

[alias]
     nuke = !sh -c 'git branch -D $1 && git push origin :$1' -

From the command line, switch to another branch, then run the command:

git nuke branch-name

Alternately… If you are unable to add the above to your .gitconfig file for some reason, but have access to the .bashrc, .bash_profile, etc… you can add the following:

git config --global alias.nuke '!sh -c "git branch -D $1 && git push origin :$1" -'

You can read more about sh and how it's expected to work here.

John Szakmeister
  • 44,691
  • 9
  • 89
  • 79
  • 1
    This is a good answer, but the explanation is incorrect. When calling `sh`, the first positional argument is the name of the script being executed. (The shell puts this value into `$0`.) When `-c` is used, there is no script, so — by convention — `-` is used in its place. – smammy Jun 30 '23 at 17:49
  • @smammy You're absolutely right. Updated. – John Szakmeister Jul 17 '23 at 11:21
3

If you create a bin called git-nuke and place it in a directory anywhere on your $PATH, you will achieve the same effect. The advantage with this approach is the ability to write a command with a bit more clarity and robustness.

Example, in my bash profile I have: export PATH="$HOME/.bin:$PATH".

And in ~/.bin/git-nuke, I have:

#!/bin/bash
set -eu

#
# git nuke <branch-name>
#
# Delete a branch (irrespective of its merged status) and
# remove from origin.
#

echo "Nuking $1 ..."

if git show-branch "$1" > /dev/null 2>&1
then
  git branch -D "$1"
else
  echo "No local branch to delete"
fi

git remote prune origin
if git show-branch "origin/$1" > /dev/null 2>&1
then
  echo "Deleting remote $1 ..."
  git push origin ":$1"
else
  echo "No remote branch to delete"
fi
Doug
  • 655
  • 2
  • 6
  • 15
  • 1
    Another advantage of this is you can add autocompletion. – Oliver Joseph Ash Jul 20 '16 at 14:42
  • Can I make git complete this as a new subcommand `nuke` as if it where defined as an alias or do I have to type `git-nuke`? in the shell? – Nordlöw Aug 20 '20 at 19:13
  • The `git-mycmd` trick means you now have a `mycmd` subcommand and will be called via `git mycmd` and tab completion will work with using `git my[tab]` – Doug Mar 03 '21 at 16:22
1

You cannot use $1 in an alias. Create a script called git-nuke somewhere in your path so you have access to proper shell scripting.

You could also just install git-extras. That’s a script compilation that contains the git delete-branch script, which does exactly what you want.

Chronial
  • 66,706
  • 14
  • 93
  • 99
  • 1
    Ah, thanks for the pointer. I'll probably go with git-extras. – biegel May 24 '13 at 17:28
  • 4
    Please see [jszakmeister's answer](http://stackoverflow.com/a/16740731/456814), you **can** use `$1` in an alias. –  May 25 '13 at 05:37
  • While jszakmeister’s answer is an nice solution indeed, you still can not use `$1` in an alias. `sh` is doing the `$1` handling there. The arguments to an alias are always appended to it. – Chronial May 25 '13 at 10:20