1

I want to automate the many version control steps of Git. I was successful until I used git commit -S -m ${var} in my Bash script. This line gives me (pathspec errors x # of word) - 1... unless I use eval. How does eval make my script work?

I thought this article had the answer, but my issue involves a string, not an array.

Gif video of the broken vs. working Bash script

Broken code

brokenCommitCode () {
  # Give it a multi-word, space-separated message
  read -p 'Commit message (use quotes): ' commitMsg
  commitMsg="'${commitMsg}'"
  echo ${commitMsg}
  git add -A &&
  git commit -S -m ${commitMsg} 
}

Working code

workingCommitCode () {
  read -p 'Commit message (use quotes): ' commitMsg
  commitMsg="'${commitMsg}'"
  echo ${commitMsg}
  git add -A &&
  eval git commit -S -m ${commitMsg} 
}

I expected the brokenCommitCode to commit properly with the message I enter on the prompt. The actual result is a pathspec error when it reaches git commit -S -m ${commitMsg}. How does eval make this work?

I'm using GNU bash, version 4.4.19(1)-release (x86_64-pc-msys) with git version 2.16.2.windows.1 on a Windows 8.1 PC.

  • 4
    `eval` not recommended except you know what it does because may execute aribtray code, the single quotes are not needed in variable definition ~`commitMsg="'${commitMsg}'"`~ and do not prevent argument split on space, correct syntax is to double quote variable expansion in last command : `git commit -S -m "${commitMsg}"` – Nahuel Fouilleul Jul 15 '19 at 10:06
  • This looks vaguely like [When to wrap quotes around a shell variable?](https://stackoverflow.com/questions/10067266/when-to-wrap-quotes-around-a-shell-variable) – tripleee Jul 15 '19 at 10:26
  • 1
    Concur that `eval` is almost certainly the wrong solution here, and quite possibly create a much worse problem. – tripleee Jul 15 '19 at 10:27
  • 1
    To get an idea what's wrong with the `eval` approach (and why @NahuelFouilleul's suggestion is better), try your "working" code with the commit message "What is 6 * 9". I think the results will surprise you. – Gordon Davisson Jul 15 '19 at 10:37
  • @GordonDavisson Wow! That did surprise me! I expected `... 54`. The result: `'What is 6 babel.config.js backend config dist firebase-debug.log index.js node_modules package.json package-lock.json public README.md scratch.txt src test.js test-require.js tests views vue.config.js 9'` –  Jul 15 '19 at 10:41
  • `eval` is no bueno and @NahuelFouilleul's solution is confirmed working. –  Jul 15 '19 at 10:41

1 Answers1

0

Correct fix is

funname() {
    read -p 'Commit message (use quotes): ' commitMsg
    echo "${commitMsg}"
    git add -A &&
    git commit -S -m "${commitMsg}"
}

Why eval seems to fix:

  • single quotes where added to commitMsg variable (seems intent was to prevent message argument to be split on a whitespace)

looking what happens with the following message:

commitMsg="this is a message"

git commit -S -m ${commitMsg} 
git commit -S -m this is a message
[error because "is" "a" "message" are taken as different additional arguments]
  • however it doesn't prevent because single quote is not re-interpreted but is like any other character in variable content

following with the example

git commit -S -m ${commitMsg} 
git commit -S -m \'this is a message\' 
[error "is" "a" "message'" are taken as different additional arguments]

with eval the single quotes are re-interpreted but also any other character which has a particular meaning in bash (;, &, ${..}, ..)

Suppose for example the following commit message which can inject arbitrary command.

commitMsg="message'; ls -l; echo 'done"
git commit -S -m 'message'; ls -l; echo 'done'
Nahuel Fouilleul
  • 18,726
  • 2
  • 31
  • 36
  • When your suggestion to use "${commitMsg}" worked, I knew the single quotes behaved differently than I expected. –  Jul 15 '19 at 11:08
  • 1
    this is not specific to single quote character but how command line is process and expansion sequence in bash but also in other posix shells. the variable is expanded after the command parsing see manual for more details – Nahuel Fouilleul Jul 15 '19 at 11:09
  • The reason 'clicked' when I saw the `\'`. –  Jul 15 '19 at 11:14