linux - 如何创建一个 git 别名以递归地在所有子模块上运行命令?

标签 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. 递归地对所有子模块执行相同的命令。

我尝试创建一个别名来执行此操作:

[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

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

最佳答案

这应该有效:

[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 命令,比如 git r checkout master。我试着写一个 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"

关于linux - 如何创建一个 git 别名以递归地在所有子模块上运行命令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45306543/

相关文章:

Git - 选择性分支

linux - 在 Linux 系统调用序列中区分 execve() 的解释器

linux - ptrace 防止信号在跟踪进程中中断 pselect()

linux - 将更多文件的行数与文件名组合起来

git - 如何查看 git 子模块库的状态?

git - pod 安装返回 fatal error : SSL certificate issue?

linux - 如何使用expect只记录命令的输出

ios - 通过命令行构建并运行iOS7应用

linux - 仅在成功时将命令的输出导出到变量(Bash set -e)

c - Linux 和 Windows 上结构的不同值