35

I'm trying to use to use the same name for an alias as the existing command, so that the alias shadows the original command (preventing me from deleting files off the working tree).

[alias]
   rm = rm --cached
   diff = diff --color

Unfortunatly this is not working. Does anyone know a workaround? Thanks.

Edit Setting color.diff = true gives colored output as default.

M.Hebot
  • 353
  • 3
  • 7

4 Answers4

25

As a workaround, you can define aliases in Bash to get the result you want. Here's something I just knocked up for a pet peeve of mine - that 'git add' is not verbose by default. (And there's no config setting for it).

Put this in your ~/.bash_profile or ~/.bash_rc

function do_git {
  cmd=$1
  shift
  extra=""
  if [ "$cmd" == "add" ]; then
    extra="-v"
  elif [ "$cmd" == "rm" ]; then
    extra="--cached"
  fi
  git="$(which git)"
  ex="$git $cmd $extra $@"
  ${ex}
}
alias  git='do_git'

Then just call it like normal:

$ git add .
add 'foo'
Benjamin W.
  • 38,596
  • 16
  • 96
  • 104
Steve Bennett
  • 98,925
  • 29
  • 148
  • 200
24

For commands like rm --cached that don't have configurable options, your best bet is to just make an alias named differently. For example:

[alias]
        rmc = rm --cached

You may have already figured this out, but Git aliases cannot shadow existing Git commands. From the git-config man page:

To avoid confusion and troubles with script usage, aliases that hide existing git commands are ignored.

Michael
  • 7,248
  • 5
  • 56
  • 81
mipadi
  • 380,288
  • 84
  • 512
  • 473
  • [The git mailing list had a discussion about the rationale behind this](http://git.661346.n2.nabble.com/allowing-aliases-to-override-builtins-to-support-default-options-td2438491.html). tl;dr KISS – Bengt Mar 09 '13 at 19:37
  • 4
    Ugh. What a stupid, obnoxious conclusion that thread has. It is not very easy to defend, because it prevents me making `git clone` recursive by default. Idiotic. – Jez Mar 18 '16 at 15:47
1

Steve Bennett's answer works for simple commands, but breaks when you have quoted arguments like the following:

$ git commit -m "foo bar" --allow-empty
error: pathspec 'bar' did not match any file(s) known to git.

Preserving the full list of arguments as an array seems to work:

function do_git {
  cmd=$1
  shift
  myArgs=( "$@" )

  if [ "$cmd" == "add" ]; then
    myArgs=( "-v" "${myArgs[@]}" )
  elif [ "$cmd" == "rm" ]; then
    myArgs=( "--cached" "${myArgs[@]}" )
  fi
  myArgs=( "$cmd" "${myArgs[@]}" )
  $(which git) "${myArgs[@]}"
}
alias  git='do_git'

Now the command succeeds:

$ git commit -m "foo bar" --allow-empty
/usr/bin/git commit -m foo bar --allow-empty
[master 699af14] foo bar
Lucas Wiman
  • 8,375
  • 2
  • 33
  • 39
  • Only thing that could make this better is using a Bash v4.4+ associative array to define `cmd: extra,args` if you want to add multiple like `--recursive` and `--shallow-fetch` to make `git clone` against huge repositories really snappy. – dragon788 May 10 '22 at 17:57
0

This is the answer of Steve Bennett translated for oh-my-zsh

function do_git {
  cmd=$1
  shift
  extra=""
  if [ "$cmd" '==' "add" ]; then
    extra="-v"
  elif [ "$cmd" '==' "rm" ]; then
    extra="--cached"
  fi
  "`whence -p git`" "$cmd" "$extra" "$@"
}
alias  git='do_git'

The equals sign needs to be wrapped in quotes. And which doesn't work as it just return that 'git' is an alias.

Tom Maeckelberghe
  • 1,949
  • 3
  • 21
  • 24