Issue
If I wanted to set the value of foo
to equal "bar" every time I used git status
, how would I proceed to do this? My first thought would be to set an alias for status="status && foo=bar"
but when I attempt that and echo $foo
, I do not get "bar" echoed; however, if I type it all out manually as git status && foo=baz
and then echo $foo
, my output is "baz'. Why can't I declare the variable inside the alias?
I've observed that if I were to switch the order up and for some reason do this alias git="foo=bar && git"
and if I tried any git command and echo foo
it equals "bar".
Solution
Git aliases are run by:
- Git itself, if the alias does not start with
!
: in this case you cannot set new environment variables; or - a POSIX-compatible shell, if the alias starts with
!
.
POSIX-compatible shells allow setting environment variables in two ways:
VAR=value command
or:
VAR=value; export VAR; command1; command2; ...; commandN
This second variant can be written as:
export VAR=value; command1; ...; commandN
The explicitly exported variable is set for all the commands invoked this way—versus the VAR=value command
, which sets it just for the one command—because this setting is done in the shell, and persists until the shell itself exits, and then the setting disappears with the shell that has exited. So if x
is a Git alias:
git x
runs that alias, which can set an environment variable setting for the duration of any commands the alias itself runs. Then the shell that is running those commands exits, and all settings evaporate.
It's therefore literally impossible for a Git alias to set any environment variable in the command-line shell you use to run that alias. This is true for all commands, not just Git commands: no command can set environment variables in any "outer" shell.
There is one escape hatch, which is this: when you write a shell command yourself, you have control. For instance, you can write the rather silly shell command:
export VAR=$(echo value)
where the parenthesized $(echo value)
is evaluated and then its output is substituted in. But this does mean that if some program prints some value you would like to save, you can write:
var=$(command)
which sets the local shell variable var
to the output, or:
export VAR=$(command)
which sets the shell variable and exports it. (Note: the uppercase here is merely convention: local shell variables that are exported are conventionally written in all uppercase, while local shell variables that are not exported are conventionally written in all lowercase.)
There is a second escape hatch as well, but using it is risky: POSIX shells have an eval
command which feeds text back to the shell interpreter. We can use this with programs that print export VAR1=value1; export VAR2=value2
as their output:
eval `ssh-agent -s`
Here, the ssh-agent
program sets up the agent and then prints several appropriate export
commands. However, should the ssh-agent
program print rm -rf /
, using eval ssh-agent -s
will proceed to remove every file it can: this means you are placing a tremendous amount of trust on that ssh-agent
command.
You can use a shell alias to make some easy-to-type-in command, such as gst
, consist of both a variable-setting operation and a Git command:
alias gst='foo=bar && git status'
This is not a Git alias. This is a shell alias. POSIX now requires shell aliases (thanks to KamilCuk for the pointer). Bash always has them, though some very old non-bash shells might not have them.
Answered By - torek Answer Checked By - Cary Denson (WPSolving Admin)