Git for Windows 2.xでプロンプトの設定(PS1)にブランチ名と改行を入れるとsyntax errorになる

f:id:orangeclover:20170218215924p:plain

Git for Widnows 2系に上げてから、設定(PS1)にブランチ名と改行を入れるとsyntax errorに
なるようになった。 対処方法がわからなかったので、しばらく、改行を外していて放置してた。

現象

bash: command substitution: line 1: syntax error near unexpected token `)'
bash: command substitution: line 1: `__git_ps1)'

条件

  1. Git for Widnows 2.xを使用してる。
  2. PS1に__git_ps1でブランチ名を設定してる。
  3. PS1に改行(\n)を設定している。


export PS1='\w$(__git_ps1)\n\$ '

問題にならない条件

  • Git for Widnows 2.xでも以下の条件ではsyntax errorにならない

    • ブランチ名がない場合
      export PS1='\w\n\$ '
    • 改行の設定がない場合
      export PS1='\w$(__git_ps1)\$ '
  • Git for Widnows 1.xを使っている場合はsyntax errorにならない

  • Linuxで、Gitを使ってる場合はsyntax errorにならない

環境

以下の環境だとsyntax errorになる。

  • Windows 10 1608(ビルド 14393.693)
  • git version 2.11.1.windows.1
  • bash 4.3.46(2)-release (x86_64-pc-msys)

調査

LinuxではGit 1.x、2.xでも発生しないから、Git for Widnowsの問題だろう。
WindowsだとGit 1.xでは問題なかった。
2.xになってから、なにか変更があったっぽい。

ぐぐったら事例は出てきた。
PS1 bash command substitution not working on windows 10

'\n$'$'\n$ 'にすればいいみたい。

なんで?
Cygwinの事例なら、原因が書いてあった。
Cygwin のプロンプトに Git のブランチを表示する(シンタックスエラーが発生した場合の対策あり)

構文解析でエラー

Cygwin 環境では $PS1 のコマンド置換でシンタックスエラーが出ることがあります。

-bash: command substitution: line 1: syntax error near unexpected token `)'
-bash: command substitution: line 1: `__git_ps1)'
これは改行コード CR を無視する Cygwin 独自のシェルオプション igncr による影響の
ようです。igncr が設定されている場合,$PS1 内で $( ) 形式のコマンド置換の後に
\n が続くと構文解析に失敗してしまいます。バッククォートによる旧式のコマンド置換
ではこの現象は発生しません。

CRが悪さしてるのか。
igncrの設定がGit for Widnows 2.xから変わった?

確認してみる。

Git for Windows 1.9.4の環境

 $ git --version
 git version 1.9.4.msysgit.1
 $ bash --version
 GNU bash, version 3.1.0(1)-release (i686-pc-msys)
 Copyright (C) 2005 Free Software Foundation, Inc.
 $ set -o
 allexport       off
 braceexpand     on
 emacs           on
 errexit         off
 errtrace        off
 functrace       off
 hashall         on
 histexpand      on
 history         on
 ignoreeof       off
 interactive-comments    on
 keyword         off
 monitor         on
 noclobber       off
 noexec          off
 noglob          off
 nolog           off
 notify          off
 nounset         off
 onecmd          off
 physical        off
 pipefail        off
 posix           off
 privileged      off
 verbose         off
 vi              off
 xtrace          off

igncrの項目は無い。無いけど有効になっているのか?

Git for Windows 2.11.1

$ set -o |grep igncr
igncr           off

offだな。

2.xでなにが変更になったかは、確認できず。。。

対処

対処は、Cygwin のプロンプトに Git のブランチを表示する(シンタックスエラーが発生した場合の対策あり)に載っているもののうちの以下の2つ。

  • バッククォート形式にする
    export PS1='\w`__git_ps1`\n\$ '

  • 改行を$'\n'にする
    export PS1='\w$(__git_ps1)'$'\n$ '

後者を選択。

$'\n'ってなに?

BASHより

$'string' の形式を持つ単語は特殊な扱いを受けます。 この単語は string に展開され、
それから ANSI C 標準で仕様が決められている、 バックスラッシュでエスケープされている
文字に置き換えられます。 バックスラッシュエスケープシーケンスは、 (もし存在すれば)
以下のようにデコードされます:

(省略)

  • \n
    改行