git alias: multiple commands, variadic parameters

I often find myself typing this:

git push remote1 branch1 branch2 tag1 tag2 tag3..
git push remote2 branch1 branch2 tag1 tag2 tag3..

I would prefer an alias where I can type this instead:

git pushall branch1 branch2 tag1 tag2 tag3 ..

Note: I am aware I could create a new remote "all" with multiple urls. Let's not discuss this here, but focus on the alias instead!

I am ok to hardcode the remote names, because I have a number of projects with the same multiple remote names (usually "drupal" and "github").

Progress so far

I already figured out a non-variadic version:

[alias]
pushall = "!git push github $1; git push drupal $1; #"

Two tricks here were

  • using double quotes to prevent ';' from having a special meaning in .ini files
  • # to ignore the rest of the line.
  • But this only pushes one branch (or tag) at a time. So I would have to type this:

    git pushall branch1
    git pushall branch2
    git pushall tag1
    git pushall tag2
    git pushall tag3
    ...
    

    I would prefer an alias where I can type this:

    git pushall branch1 branch2 tag1 tag2 tag3 ..
    

    Why not a new remote "all" with multiple push urls?

    As said, let's focus on the aliases, so that readers find what they are looking for.

    Anyway, here is why I am not creating a remote "all":

  • I would have to do this once per project, and could not do it globally. In my case, hardcoding the remote names in a global alias is actually fine!
  • Afaik, I would pollute my history with refs like "all/branch1" instead of or in addition to "remote1/branch1" and "remote2/branch1".
  • The correct place to discuss this would be here, pull/push from multiple remote locations

    See also

    The following are related, but they do not address variadic parameters:

  • Git Alias - Multiple Commands and Parameters
  • Syntax for Git aliases with multiple commands
  • Git alias with positional parameters
  • The following might be helpful, but it addresses pure shell script, not specifically git aliases:

  • How to iterate over arguments in a Bash script

  • This really is answered by the other questions which you linked to, but for clarity:

    [alias]
        pushall = "!git push github "$@"; git push drupal "$@"; :"
    

    Or setting from the command line:

    git config --global alias.pushall '!git push github "$@"; git push drupal "$@"; :'
    

    By extending your initial attempt:

    [alias]
    pushall = "!git push github $@; git push drupal"
    

    This way, git pushall branch1 branch2 branch3 expands to:

    git push github branch1 branch2 branch3; git push drupal branch1 branch2 branch3
    #                  |               |                        |               |
    #                  +-------+-------+                        +-------+-------+
    # these arguments were     |                                        |
    # expanded from $@ --------+                                        |
    #                                                                   |
    #                  these are the arguments of the original command -+
    

    $@ expands to all command line arguments.
    There is no need for # at the end of line; the fragment git pushall is replaced by the value of the alias, the rest of the argument

    If you have a bigger list of remote repositories you can write it this way:

    [alias]
    pushall = "!for repo in github drupal bitbucket; do git push $repo $@; done #"
    #                         |               |
    #                         +-------+-------+
    # put all your repos here         |
    # separated by spaces ------------+
    

    This time the # sign is required. It turns the original arguments into a comment; otherwise the command has syntax errors and it doesn't run.

    If you want to push to all the remotes of the repository then you can write a smarter alias:

    pushall = "! for repo in $(git remote); do git push $repo $@; done #"
    

    It runs git remote to find all the remotes and uses command substitution to replace $(...) with the output of the git remote command before continuing.

    You can define it as a global alias using:

    $ git config alias.pusha '! for repo in $(git remote); do git push $repo $@; done #'
    

    If you have some repos where you don't want to push to all remotes, you can define it as a local alias and customize the list of remotes in each repo using thi command while you are in the repository:

    $ git config --local alias.pusha '! for repo in github drupal; do git push $repo $@; done #'
    

    The idiom to package an arbitrary script into a git alias is to put it inside a shell function:

    pushall = "! f() { git push github "$@"; git push drupal "$@"; }; f"
    

    I want to point out that the correct use of $@ is to place it inside double-quotes: "$@" .

    链接地址: http://www.djcxy.com/p/8768.html

    上一篇: git:推送一个提交

    下一篇: git别名:多个命令,可变参数