Reputation: 47051
I saw code snippets like this in git-stash
rm -f "$TMP-index" &&
GIT_INDEX_FILE="$TMP-index" git read-tree HEAD &&
# find out what the user wants
GIT_INDEX_FILE="$TMP-index" \
git add--interactive --patch=stash -- &&
# state of the working tree
w_tree=$(GIT_INDEX_FILE="$TMP-index" git write-tree) ||
die "$(gettext "Cannot save the current worktree state")"
git diff-tree -p HEAD $w_tree -- >"$TMP-patch" &&
test -s "$TMP-patch" ||
die "$(gettext "No changes selected")"
rm -f "$TMP-index" ||
die "$(gettext "Cannot remove temporary index (can't happen)")"
What I don't understand is the expression like this:
GIT_INDEX_FILE="$TMP-index" git read-tree HEAD
Does that mean assign the value of TMP-index
to GIT_INDEX_FILE
, and then execute command git read-tree HEAD
?
I'm not sure about that. So I tried to write a similar command like this.
A="1" ls
echo $A
The value of A
is still null
.
I also tried this:
echo $a
=> 1
k=$(a=100 echo $a)
=>
echo $k
=> 1
It looks that the value of a
is not changed at all. So the a=100
seems useless..
Does anyone have ideas about syntax like this?
Upvotes: 1
Views: 669
Reputation: 54143
Does that mean assign the value of
TMP-index
toGIT_INDEX_FILE
, and then execute commandgit read-tree HEAD
?
Not quite. The syntax:
VAR1=val1 VAR2=val2 somecommand arg1 arg2
tells the shell to execute the command somecommand
with arguments arg1
and arg2
, but somecommand
's environment will have VAR1
set to val1
and VAR2
set to val2
. The shell itself won't be affected by those assignments, only the environment of somecommand
. The effect is equivalent to:
env VAR1=val1 VAR2=val2 somecommand arg1 arg2
The only difference is that the former method does not require finding and executing the /usr/bin/env
utility (I'm assuming env
is not a shell built-in utility), so it's a hair faster.
It is also equivalent to:
(export VAR1=val1 VAR2=val2; somecommand arg1 arg2)
Notice the parentheses -- this causes the shell to execute the commands in a separate subshell. Any changes to a subshell (such as variable assignments) do not persist when the subshell ends.
#!/bin/sh
FOO=value1
printf %s\\n "In the shell, FOO is ${FOO} (before running python)"
FOO=value2 python -c 'import os; print "In python, FOO is", os.environ["FOO"]'
printf %s\\n "In the shell, FOO is ${FOO} (after running python)"
The above script prints the following output:
In the shell FOO is value1 (before running python)
In python, FOO is value2
In the shell, FOO is value1 (after running python)
In the snippet of Git shell code you provided, git stash
is temporarily changing GIT_INDEX_FILE
for a few invocations of git
so that stash
can perform some index-mutating operations without messing up your index:
git stash
uses git read-tree
to create the temporary index file and initialize its contents to whatever is in HEAD
.git stash
uses git add --interactive
to ask the user which parts to stash and saves the chosen changes in the temporary index file.git stash
uses git write-tree
to save the contents of the temporary index as a tree object in your Git repository.git stash
compares the tree object to HEAD
to make sure you actually selected something to stash.git stash
deletes the temporary index file it created.Upvotes: 1
Reputation: 1488
In BASH, there are some issues with defining a variable and running a new process afterward.
If you just define the variable, it is not 'inherited' by the new processes
Lets define a variable
$ VAR='value'
$ echo $VAR
value
And then go into a new process
$ bash
The var is undefined
$ echo $VAR
$
But once we get back
$ exit
the var is defined again
$ echo $VAR
value
$
the usual way around this is to use export
$ export VAR2='yep'
$ bash
$ echo $VAR2
yep
$
what you are seeing (seems to be) an alternate syntax for that, that assigns the variable in the child process, but not in the original process
$ var3='wow' bash #this line opens a new bash, and assigns the variable for this new bash
$ echo $var3
wow
$ exit
$ echo $var3
$
Upvotes: 1
Reputation: 146043
The answer to your question "Does that mean..." is yes.
However, the variable expansion happens when the command is parsed, which would be too early to see the result of setting an environment variable and then importing it into a shell, and that's why you aren't getting the results you expect.
There are various ways to see the result of a one-line environment variable expression; you could observe...
$ B=100 env | grep B
B=100
...or...
$ z=abc sh -c 'echo $z'
abc
Upvotes: 1