Junio C Hamano <gitster@xxxxxxxxx> 于2021年3月31日周三 上午1:14写道: > > ZheNing Hu <adlternative@xxxxxxxxx> writes: > > > The `prepare_shell_cmd()` in "run-command.c" seem to use "$@" to pass > > shell args. > > Yes. "$@" is a way to write "$1" "$2" "$3"... > Since you are passing only one, > > echo "$@" > > and > > echo "$1" > > would be the equivalent. > > I am not sure what program you fed to the gdb (and remote debugging > over e-mail is not my forte ;-), but let's see. > > > Before exec: > > > > (gdb) print argv.v[1] > > $22 = 0x5555558edfd0 "/bin/sh" > > (gdb) print argv.v[2] > > $23 = 0x5555558f4c80 "-c" > > (gdb) print argv.v[3] > > $24 = 0x5555558ed4b0 "echo \"123\" \"$@\"" > > (gdb) print argv.v[4] > > $25 = 0x5555558f5980 "echo \"123\"" > > (gdb) print argv.v[5] > > $26 = 0x5555558edab0 "abc" > > (gdb) print argv.v[6] > > $27 = 0x0 > > > > Some unexpected things happened here. > > Maybe "abc" was wrongly used as the parameter of "echo"? > > Looking forward to your reply. > > Observe > > $ sh -c ' > echo "\$0 == $0" > count=0 > for arg in "$@" > do > count=$(( $count + 1 )) > echo "\$$count == $arg" > done > ' 0 1 2 > $0 == 0 > $1 == 1 > $2 == 2 > > i.e. the first arg after > > argv[1] = "/bin/sh" > argv[2] = "-c" > argv[3] = "script" > > is used to give the script the name of the program ($0). Are we > getting hit by this common confusion? > > It is customery to write such an invocation with '-' as the "name of > the program" thing, so that ordinary positional parameters are > available starting at $1, not $0, like so: > > sh -c 'script' - arg1 arg2 ... The configuration is like this: trailer.bug.key=BUG: trailer.bug.ifexists=add trailer.bug.cmd=echo "123" And use: $ git interpret-trailers --trailer="bug:456" --trailer="bug:789"<<-EOF EOF BUG: 123 BUG: 123 456 BUG: 123 789 I just want three "BUG: 123", but "456" and "789" appeared... In fact, I think about this problem like this way: When we execute a child process that runs the shell, the function`prepare_shell_cmd()` will actively add "$@" to the end of our shell command when we have more than zero args , e.g. "echo \"123\"" "abc" will turn to "echo \"123\" \"$@\"" "echo \"123\"" "abc" Normally, $@ should not cause any problems because it passes arguments to the script what we provide. But now, what we actually want is take any $1 that appears in the script as an argument, the automatically added $@ causes $1 to be implicitly included. And the original $ARG does not have this problem, Or if we pass environment variables, this kind of problem will not occur. Or If we want to avoid this problem, should we add one new options in `struct child_process` , such as: "shell_no_implicit_args" , let git not add extra "$@" before we run the shell script? Thanks. -- ZheNing Hu