如何创建一个git别名来递归运行所有子模块上的命令?

时间:2017-07-25 14:40:23

标签: linux git shell

我手动运行以下命令:

$ git fetch --all && git reset --hard @{u} && git submodule foreach --recursive "git fetch --all && git reset --hard @{u}"

我正在使用Git v2.13.0。我的目标是:

  1. 首先在父(当前)存储库上运行指定的命令。
  2. 以递归方式对所有子模块执行相同的命令。
  3. 我尝试创建一个别名来执行此操作:

    [alias]
        run = !f() { \"$@\" && git submodule foreach --recursive \"$@\"; }; f"
    

    哪个会像这样运行(使用前面的例子):

    $ git run "git fetch --all && git reset --hard @{u}"
    

    但是我收到以下错误(为诊断启用了git trace):

    09:38:31.170812 git.c:594               trace: exec: 'git-run' 'git fetch --all && git reset --hard @{u}'
    09:38:31.170899 run-command.c:369       trace: run_command: 'git-run' 'git fetch --all && git reset --hard @{u}'
    09:38:31.172819 run-command.c:369       trace: run_command: 'f() { "$@" && git submodule foreach --recursive "$@"; }; f' 'git fetch --all && git reset --hard @{u}'
    09:38:31.173268 run-command.c:228       trace: exec: '/bin/sh' '-c' 'f() { "$@" && git submodule foreach --recursive "$@"; }; f "$@"' 'f() { "$@" && git submodule foreach --recursive "$@"; }; f' 'git fetch --all && git reset --hard @{u}'
    f() { "$@" && git submodule foreach --recursive "$@"; }; f: git fetch --all && git reset --hard @{u}: command not found
    fatal: While expanding alias 'run': 'f() { "$@" && git submodule foreach --recursive "$@"; }; f': No such file or directory
    

    如何让别名按我的意愿工作?

1 个答案:

答案 0 :(得分:1)

这应该有效:

[alias]
    # Forcefully perform a git command in the current repo and recursively in all submodules (regardless of exit status).
    # NOTE: The command (after `git run`) must be in quotes
    # Example: git run "git checkout master"
    run = !sh -c '\
        $@ && \
        git submodule foreach --recursive \"$@ || :\" && \
    :' -

我倾向于只使用!sh -c编写命令。发现更复杂的命令要容易一些。这种方法最棘手的部分通常与转义引号和参数有关。

在相关说明中,我真的很想写一个别名,像git r checkout master这样递归地运行git命令。我尝试编写git别名,例如:

[alias]
    r = !sh -c '\
        git $@ && \
        git submodule foreach --recursive \"git $@ || :\" && \
    :' -

这对于单参数git命令(例如git r status)非常有用,但是当尝试运行多参数git命令时,它会中断。例如,运行git r checkout master会产生以下输出:

Already on 'master'
Your branch is up-to-date with 'origin/master'.
Entering 'submodules/MY_SUBMODULE'
/usr/local/git/libexec/git-core/git-submodule: line 360: git checkout: command not found
Stopping at 'submodules/MY_SUBMODULE'; script returned non-zero status.

解决方法是将其余参数以字符串形式传递,例如git r "checkout master"