Is it possible to override git command by git alias?

my ~/.gitconfig is:

[alias]
        commit = "!sh commit.sh"

However, when I type git commit, script is not called.

Is it possible, or I have to use another alias name?


Solution 1:

It is NOT POSSIBLE

This is from my clone of git.git:

static int run_argv(int *argcp, const char ***argv)
{
    int done_alias = 0;

    while (1) {
        /* See if it's an internal command */
        handle_internal_command(*argcp, *argv);

        /* .. then try the external ones */
        execv_dashed_external(*argv);

        /* It could be an alias -- this works around the insanity
         * of overriding "git log" with "git show" by having
         * alias.log = show
         */
        if (done_alias || !handle_alias(argcp, argv))
            break;
        done_alias = 1;
    }

    return done_alias;
}

So its not possible. (handle_internal_command calls exit if it finds the command).

You could fix this in your sources by changing the order of the lines and making handle_alias call exit if it finds the alias.

Solution 2:

I opted to solve this with a bash function. If I call git clone, it will redirect the call to git cl, which is my alias with some added switches.

function git {
  if [[ "$1" == "clone" && "$@" != *"--help"* ]]; then
    shift 1
    command git cl "$@"
  else
    command git "$@"
  fi
}

Solution 3:

As already mentioned, it is not possible to use a git alias to override a git command. However, it is possible to override a git command using a shell alias. For any POSIXy shell (i.e. not MS cmd), write a simple executable script that performs the desired modified behavior and set a shell alias. In my .bashrc (Linux) and .bash_profile (Mac) I have

export PATH="~/bin:$PATH"
...
alias git='my-git'

In my ~/bin folder I have an executable Perl script called my-git that checks if the first argument (i.e. the git command) is clone. It looks essentially like this:

#!/usr/bin/env perl
use strict;
use warnings;
my $path_to_git = '/usr/local/bin/git';
exit(system($path_to_git, @ARGV))
    if @ARGV < 2 or $ARGV[0] ne 'clone';
# Override git-clone here...

Mine is a little more configurable, but you get the idea.

Solution 4:

Not only not possible, but also WONTFIX

In 2009 http://git.661346.n2.nabble.com/allowing-aliases-to-override-builtins-to-support-default-options-td2438491.html

Hamano replies:

Currently git does not allow aliases to override builtins. I understand the reasoning behind this, but I wonder if it's overly conservative.

It is not.

Most shells support overriding commands with aliases, and I'm not sure why git needs to be more conservative than the shell.

Because sane shells do not expand aliases when used in a script, and gives a handy way to defeat the alias even from the command line.

$ alias ls='ls -aF'
$ echo ls >script
$ chmod +x script

and compare:

$ ./script
$ ls
$ /bin/ls