What due to the way git handles aliases:
Given an alias
[alias]
myalias =! string
where string is any string representing some code when calling git myalias args , where args is a (possibly empty) argument list, git will do:
sh -c 'string "$ @"' 'string' args
For example:
[alias] banana = !echo "$1,$2,SNIP "
and challenge
git banana one 'two two' three
git will do:
sh -c 'echo "$1,$2,SNIP " "$@"' 'echo "$1,$2,SNIP "' one 'two two' three
and therefore the output will be:
one,two two,SNIP one two two three
In your case
[alias] encrypt-for = "!g(){ echo \"once\";};$1;"
and challenge
git encrypt-for g
git will do:
sh -c 'g(){ echo "once";};$1;"$@"' 'g(){ echo "once";};$1;' g
For clarity, let me rewrite this in equivalent form:
sh -c 'g(){ echo "once";};$1;"$@"' - g
I replaced only the part of 'g(){ echo "once";};$1;' (which will be <positional) sh $0 and will not play any role here) dummy argument - . It should be clear that this is similar to doing:
g(){ echo "once";};g;g
so you see:
once once
To fix this: do not use the parameters! just use:
[alias] encrypt-for = "!g(){ echo "once";};"
Now, if you really want to use the parameters, make sure that the specified trailing parameters are not executed at all. One possibility is to add the following comment character like this:
[alias] encrypt-for = "!g(){ echo "once";};$1 #"
In your complete example, wrapping everything in a function could also be a cleaner way:
[alias] encrypt-for = "!main() {\ case $1 in \ (github) echo github;; \ (twitter) echo twitter;; \ (facebook) echo facebook;; \ (*) echo >&2 \"error, unknown $1"\; exit 1;; \ esac \ }; main"
I hope you understand what git does under the hood with aliases! it really adds "$@" to the alias line and calls sh -c with that line and given arguments.