41

I want to create a Git alias to perform multiple commands, but I cant find documentation on how this is done.

  1. What is the syntax for Git aliases with multiple commands?
  2. Where is this documented?

From 'man git-config'

   alias.*

Command aliases for the git(1) command wrapper - e.g. after defining "alias.last = cat-file commit HEAD", the invocation "git last" is equivalent to "git cat-file commit HEAD". To avoid confusion and troubles with script usage, aliases that hide existing Git commands are ignored. Arguments are split by spaces, the usual shell quoting and escaping is supported. quote pair and a backslash can be used to quote them.

If the alias expansion is prefixed with an exclamation point, it will be treated as a shell command. For example, defining "alias.new = !gitk --all --not ORIG_HEAD", the invocation "git new" is equivalent to running the shell command "gitk --all --not ORIG_HEAD". Note that shell commands will be executed from the top-level directory of a repository, which may not necessarily be the current directory. GIT_PREFIX is set as returned by running git rev-parse --show-prefix from the original current directory. See git-rev-parse(1).

Bulwersator
  • 1,102
  • 2
  • 12
  • 30
Rylander
  • 19,449
  • 25
  • 93
  • 144
  • 1
    Are you referring to aliasing in general, or is there a special `git alias` set of commands I haven't heard of? – BlackVegetable Sep 17 '13 at 22:08
  • 3
    Does it have to be an alias, or could you just write a small shell script that executes the commands you want? – Roman Sep 17 '13 at 22:10
  • 2
    @BlackVegetable you can specify aliases in .gitconfig, which might have the same syntax as aliasing in general. – Rylander Sep 17 '13 at 22:35
  • 1
    @R0MANARMY I would like it to be a git alias. Mostly I want to know how the 'advanced' syntax for git alias works. I now believe the examples I have seen are shell scripts imbedded in git aliases. – Rylander Sep 17 '13 at 22:38
  • 2
    See [git alias with positional parameters](http://stackoverflow.com/q/3321492/1256452) – torek Sep 17 '13 at 22:49

4 Answers4

49
$ git config alias.q '!echo a; echo b'

$ git q

Output:

a
b

I think this is (rudimentarily) documented in man git-config under alias.*

Note that git commands should include git, unlike in normal aliases. It is caused by fact that it is treated as a shell command, not as a git command (see manpage quoted in the question). For example to chain

git init

and

git commit --allow-empty -m "empty initial commit"

it is necessary to create

"!git init; git commit --allow-empty -m \"empty initial commit\""

alias.

Robert Siemer
  • 32,405
  • 11
  • 84
  • 94
sehe
  • 374,641
  • 47
  • 450
  • 633
  • This did not work for me on Windows; I had to use `&&` instead of `;`. – TrueWill Sep 01 '17 at 19:50
  • 1
    @TrueWill probably depends on the shell. [CMD.EXE uses `&` to separate commands](https://ss64.com/nt/cmd.html): _`If /C or /K is specified, then the remainder of the command line is processed as an immediate command in the new shell. Multiple commands separated by the command separator '&' or '&&' are accepted if surrounded by quotes.`_ – sehe Sep 01 '17 at 20:07
26

Say the commands are echo a and echo b (not a and b), to add multiple commands for an alias q:

From the command line:
git config alias.q '!echo a; echo b'

Directly in the configuration file:

[alias]
    q = "!echo a; echo b"

For more complex things, define a shell function and call it:
'!f() { echo a ; echo b ; }; f'

For passing parameters to the commands see:
Git alias with positional parameters
Git Alias - Multiple Commands and Parameters

Based in Jonathan Wakely's comment

Community
  • 1
  • 1
brita_
  • 487
  • 7
  • 13
  • 3
    Thank you, `'!f() { echo a ; echo b ; }; f'` was the answer I was looking for. I wanted to iterate over the arguments provided to the alias, `'!f() { for arg in $@; do echo $arg; done; }; f'` – evanrs Mar 12 '14 at 03:11
2

Addendum Answer: Often I need more complex commands that decide what to do through positional parameters and branch on the parameters or loop through parameters or input files.

Such commands are too complex for single liners and they are hard to read and edit on one line. But I found a real simple method to do very complex commands from files:

Assume you have a file called alias/cmd in your repository:

!function f {
    if [ -z "$1" ]
    then echo "Please give me some argument!" 1>&2
        exit -1
    fi
    echo "Hello $1"
}; f

then you can simply say

git config alias.cmd "`cat alias/cmd`"

to define the alias cmd from the file and

git config --get alias.cmd > alias/cmd

to write the defined alias to the file.

ikrabbe
  • 1,909
  • 12
  • 25
0

I struggled to find a nice example for myself too. After some research, here's what I came up with:

git config --global alias.purge '!f() { if [ $(git ls-remote --heads origin $1 | wc -l) -eq 1 ]; then git branch -d $1 && git push origin --delete $1; else echo "remote branch not found"; fi } ; f'

Let's break that down from left to right, shall we?

git config --global alias. we know by now. It's the code we need in order to create an alias. Often referred to as [alias] on this site

purge is the shorthand name I decided to give to my alias

'f() { we start to write our function

if [ the start of our if-statement, closing it later on with ]

git ls-remote --heads origin $1 checks if there is a remote branch with the name we supplied. Return value would be nothing if there's no branch, otherwise, it'll return the reference tag. By enclosing it in $( ) we make sure it's known to Bash as a command

| wc -1 added as a suffix, converts the return value to 0 if there's no remote branch, 1 if there is

-eq 1 turns the whole enclosed command into a boolean, read as (returnValue == 1)

NOTE: because the commands are written on one line, instead of \n behind each, we need to type ; after each command

then is used to announce what our function should do if the boolean returns true

git branch -d $1 will delete the local branch of the parameter we entered

&& this logical operator will ensure both commands are carried out

git push origin –delete $1 will delete the remote branch of the parameter we entered

else does what the second half of an if-else should do

echo "remote branch not found" is a String I want to return in case there's no remote branch

fi announces the end of our if-else statement

} ; f' closes our function

'complex' git alias for my branch named "security"

Paul
  • 841
  • 13
  • 20