是否可以通过git别名覆盖git命令?

noi*_*isy 48 git alias

我的〜/ .gitconfig是:

[alias]
        commit = "!sh commit.sh"
Run Code Online (Sandbox Code Playgroud)

但是,当我输入git commit时,不会调用脚本.

是否可能,或者我必须使用另一个别名?

alt*_*ive 43

这不可能

这是我的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;
}
Run Code Online (Sandbox Code Playgroud)

所以它不可能.(如果找到命令则handle_internal_command调用exit).

您可以通过更改行的顺序并在找到别名时进行handle_alias调用来解决此问题exit.

  • 如果尝试创建一个与内部/外部命令相同的别名,git config可能会发出某种警告......具有讽刺意味的是,我找不到报告git-scm本身问题的位置.谷歌和Stack Overflow结果似乎都被用于管理Git问题的工具所笼罩. (14认同)
  • @Daniel git邮件列表 (2认同)

Dav*_*ens 23

如前所述,不可能使用git别名来覆盖git命令.但是,可以使用shell别名覆盖git命令.对于任何POSIXy shell(即不是MS cmd),编写一个简单的可执行脚本,执行所需的修改行为并设置shell别名.在我的.bashrc(Linux)和.bash_profile(Mac)我有

export PATH="~/bin:$PATH"
...
alias git='my-git'
Run Code Online (Sandbox Code Playgroud)

在我的~/bin文件夹中,我有一个可执行的Perl脚本,它调用my-git了第一个参数(即git命令)clone.看起来基本上是这样的:

#!/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...
Run Code Online (Sandbox Code Playgroud)

我的可配置性更强一些,但你明白了.

  • 这应该是公认的答案.用黑客版本替换`git`对许多用户来说不是一个可行的解决方案. (4认同)
  • 作为别名的替代方法,您可以将“git”符号链接到“PATH”早期目录中的包装脚本。显然,确保脚本不会执行自己而不是真正的“git”。 (2认同)
  • 提高这个作为答案。人们很可能尝试创建别名。 (2认同)
  • 从某种意义上来说这是正确的,但是拥有一个代码与上游不同的“git”可能会变得非常有问题或完全站不住脚,而一个简单的包装器可以让您在方便时从上游拉取更新通常相当健壮,并且避免了固有的问题一把叉子。 (2认同)

ste*_*din 22

我选择用bash函数来解决这个问题.如果我打电话git clone,它会将呼叫重定向到git cl,这是我的别名与一些添加的开关.

function git {
  if [[ "$1" == "clone" && "$@" != *"--help"* ]]; then
    shift 1
    command git cl "$@"
  else
    command git "$@"
  fi
}
Run Code Online (Sandbox Code Playgroud)


Cir*_*四事件 16

不仅不可能,还有WONTFIX

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

Hamano回复:

目前git不允许别名覆盖内置.我理解这背后的原因,但我想知道它是否过于保守.

它不是.

大多数shell支持使用别名覆盖命令,我不确定为什么git需要比shell更保守.

因为在脚本中使用时,理智的shell不会扩展别名,并且提供了一种方便的方法来甚至从命令行中击败别名.

$ alias ls='ls -aF'
$ echo ls >script
$ chmod +x script
Run Code Online (Sandbox Code Playgroud)

并比较:

$ ./script
$ ls
$ /bin/ls
Run Code Online (Sandbox Code Playgroud)

  • 对死尸帖子感到抱歉,但我注意到 Mamano 对贝壳行为的感知存在潜在问题。可以通过几种方法来击败别名。这样做: `$ alias ls='ls -aF'` 然后比较这些: `$ ls` `$ \ls` `$ /bin/ls` `$builtin ls` 首先调用别名,它指向 shell内置“ls”或外部 bin。其次绕过别名,直接调用 shell 的内置 `ls` 或外部 bin。第三种方法通过明确调用外部二进制文件“/bin/ls”来绕过别名。第四,假设有一个内置的“ls”,则必须调用它。 (2认同)
  • @马斯塔兄弟。哇。你不知道我想知道这个精确信息多久了——或者即使同样的信息是可能的。毫不夸张地说,我在这里偶然发现了你的答案,并且已经在心里更新了 15 或 20 个脚本,如果我已经了解了这些知识,这些脚本会写得更好。谢谢你!我是认真的:谢谢!如果你来堪萨斯城,我欠你一杯啤酒。 (2认同)