Bashプロンプトの__git_ps1(現在のブランチ)は何とか常に古くなっています。

Bashプロンプトの__git_ps1(現在のブランチ)は何とか常に古くなっています。

PS1私の中に私のもの~/.bash_profile

export PS1="\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]`__git_ps1`\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$ "

(申し訳ありませんが、私のカラーコードにエイリアスはありません。このヒントはオンラインエディタを使用して作成しました。)

これは少し混乱しますが、非常に良いヒントを提供します。ここに画像の説明を入力してください。

しかし、切り替えると、現在表示されているブランチは常に間違っています。

間違ったポイント

なぜこれが起こるのかわかりません。コマンドのみを実行すると正しい値が得られます。

$ echo `__git_ps1`
(dev)

.bash_profileを取得すると、新しい値が表示されます(ただし、次回の切り替え時にエラーが発生します)。私は何が間違っていましたか?

答え1

export PS1="…`__git_ps1`…"

`__git_ps1`このコマンドは内部二重引用符を使用してコマンドを実行し__git_ps1、その出力(およびその他の周辺テキスト)を変数に割り当てますPS1。したがって、プロンプトには、.bash_profile実行時に決定された分岐が表示されます。

__git_ps1Bashがプロンプトを表示するたびにこのタスクを実行する必要があります。 (実際にgit情報が変わるまで再度実行する必要はありませんが、検出するのは難しいです。)これを行うには2つの方法があります。

  • `__git_ps1`変数にリテラルテキストを含めますPS1。以下を使用して、プロンプト文字列のシェル拡張を実行するように bash が構成されていることを確認します。promptvarsオプションオンはデフォルトで設定されていますが、を使用してオフにすることができますshopt -u promptvars

    PS1='\n\[…\]$(__git_ps1)\[…\]\$ '
    
  • 次のコマンドを実行してプロンプトの内容を更新します。PROMPT_COMMAND変える

    update_PS1 () {
      PS1="\\n\\[…\\]$(__git_ps1)\[…\]\\$ "
    }
    shopt -u promptvars
    PROMPT_COMMAND=update_PS1
    

しかし、プロンプトはグローバル設定ではなくシェル構成なので、~/.bashrc代わりにに設定する必要があります~/.bash_profile

答え2

ただ引用の問題にすぎません。バックティックを使用する必要がある場合は、または`__git_ps1`に変更してください。\$(__git_ps1)\`__git_ps1\`

確信を得るには、PS1を次のように変更します(以前の設定に完全に戻すには、新しいシェルインスタンスを開きます)。

$ PS1="$(date) >"
Thu Nov 26 20:02:34 EST 2015 >_

唯一の問題はそうなることだ。いいえアップデート(数秒待ってからEnterキーを押します)。

しかし、これは次のとおりです。

$ PS1="\$(date) >"
Thu Nov 26 20:06:20 EST 2015
Thu Nov 26 20:06:25 EST 2015

それはすべてです。書くexit。 (ヒントの更新)もう一度仕事を始めてください。

答え3

http://mediadoneright.com/content/ultimate-git-ps1-bash-prompt

下部に設定はありません。

PS1="\n... `__git_ps1 ... エクスポート

この嫌な創造物に設定してください:

export PS1=$IBlack$Time12h$Color_Off'$(git branch &>/dev/null;\

if [ $? -eq 0 ]; then \
  echo "$(echo `git status` | grep "nothing to commit" > /dev/null 2>&1; \
  if [ "$?" -eq "0" ]; then \
    # @4 - Clean repository - nothing to commit
    echo "'$Green'"$(__git_ps1 " (%s)"); \
  else \
    # @5 - Changes to working tree
    echo "'$IRed'"$(__git_ps1 " {%s}"); \
  fi) '$BYellow$PathShort$Color_Off'\$ "; \
else \
  # @2 - Prompt when not in GIT repo
  echo " '$Yellow$PathShort$Color_Off'\$ "; \
fi)'

関連ビットは "$(__git_ps1"(%s)" または "$(__git_ps1"{%s}") です。

答え4

既存の回答が根本原因を正確かつ明確に伝えることができないようです。解決策につながるかもしれませんが、聴衆に学ぶべき教訓を教えるかどうかはわかりません。この回答は、主に聴衆の理解を助けるという観点からのものです。

迅速な回答

もともと返事を書いた後、このようなアプローチが考えられ、以下に詳細な返信を残す予定ですが、ここに速い答えがあります。

入力中にエスケープが使用されなかったため、値PS1は代替バージョンとして保存されます。次のように確認できます。

オリジナル:

chadb@Chad-2in1 ~/code/videospeed-refactoring (master) 21:12:45  
$ export PS1="\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]`__git_ps1`\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$ "

chadb@Chad-2in1 ~/code/videospeed-refactoring (master) 21:13:03
$ env |grep PS1
PS1=\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\] (master)\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\$

脱出する

chadb@Chad-2in1 ~/code/videospeed-refactoring (master) 21:19:42
$ export PS1="\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]\`__git_ps1\`\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$ "

chadb@Chad-2in1 ~/code/videospeed-refactoring (master) 21:20:02
$ env |grep PS1
PS1=\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]`__git_ps1`\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\$

見てわかるように、__git_ps12番目のバージョンではこれが維持され、最初のバージョンでは入力時に__get_ps1の値が表示されます。

私の元の答えを続けます。

説明する

問題は、シェルがコマンドを実行するときに挿入する前に置換を実行するため、元のコマンドの代わりに置き換えられた値が挿入されることです。

この問題を解決するには、\置換を防ぐために保存する前にエスケープ文字を使用してください。これにより、コマンドのエスケープされていない実行可能バージョンがメモリに保存され、bashが入力された各コマンドでバージョンを再評価します。

コマンドをエスケープ解除すると、メモリに保存される前にコマンドが実行および置き換えられ、その結果、コマンドが最初に~/.bash_profile実行/インポートされたときにのみコマンドが表示されます。

解決策

オリジナルコマンド

export export PS1="\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]`__git_ps1`\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$ "

$ PS1の元の保存値

文字列リテラル「(master)」を含みます。

\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\] (master) \[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$

重要:混乱を避けるために、この保存された値は__git_ps1

固定コマンド

export export PS1="\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]\`__git_ps1\`\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$ "

$PS1の固定保存価値

今回はコマンドは変更されていないため、次回実行時に置き換えられます。

"\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]`__git_ps1`\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$ "

バックティックは関係ありません - 証明

他の回答で述べたように、$()を使用してバックティックを提供できますが、これはこの問題の根本的な原因とは関係ありません。これらの問題を混同しないでください。

老いたこと[問題ない]

`__git_ps1`

新しいもの[問題なし]

$(__git_ps1)

元のコマンドにはバックティックがなく、エスケープされません。 [問題ではなく同じ問題になります。]

export export PS1="\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]$(__git_ps1)\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$ "

バックティックなしでエスケープされるネイティブコマンド[エスケープを使用して同じ方法で修正されました]

export export PS1="\\n\[\033[38;5;246m\]\u@\[\033[38;5;245m\]\h\[\033[38;5;15m\] \[\033[38;5;28m\]\w\[\033[38;5;15m\]\[\033[38;5;2m\]\$(__git_ps1)\[\033[38;5;15m\] \[\033[38;5;90m\]\t\[\033[38;5;15m\] \[\033[38;5;232m\]\[\033[38;5;15m\] \n\[\033[38;5;0m\]\\$ "

簡略化された証明

sub_demoこれを簡単にするために、中間状態を表示するためにファイルを記憶媒体として使用して現在の作業ディレクトリをコンソールにエコーすることを除いて、bashに似た操作を実行するカスタムシェルコマンドを作成して多くの変数を削除します。

エスケープされていない $PWD [問題]

[07:18 PM] ~/code $ echo $PWD
/c/Users/chadb/code
[07:36 PM] ~/code $ echo $PWD > sub_demo
[07:36 PM] ~/code $ cat sub_demo
/c/Users/chadb/code

代替値が$PWDファイルに保存され、ディレクトリの検索に使用されたコマンドに関する情報が破損しています。これから sub_demo の内容を読み込むと、常に同じレンダリング値が生成されます。/c/Users/chadb/code

愚かなことですが、説明のために複数の場所からファイルの内容を読み取って、実際に保存された情報が変更されないことをお見せしましょう。

[08:01 PM] ~/code $ cat ~/code/sub_demo 
/c/Users/chadb/code
[08:01 PM] ~ $ cat ~/code/sub_demo
/c/Users/chadb/code
[08:01 PM] ~/code/sub_demo_folder $ cat ~/code/sub_demo 
/c/Users/chadb/code

この値はフォルダに関係なく変更されません。内容を変更するまで~/code/sub_demoこれから内容を確認してください。/c/Users/chadb/code

$PWD脱出[解決策]

次に、$エスケープ文字を渡すかどうかを検討します\$

[08:06 PM] ~/code $ echo \$PWD > sub_demo
[08:06 PM] ~/code $ cat sub_demo
$PWD

ご覧のとおり、値はコマンドとして保存されます。作業ディレクトリを見つけるために必要なのと同じコマンドです。何が役に立ちますか?さて、bashは$ PS1に格納されている値を実行します。ファイルの内容を実行可能ファイルに変換するために、最初にエコーを追加してこれをシミュレートしましょう。

完全性と比較のために、エスケープされていないバージョンとエスケープされたバージョンを紹介します。

[脱出しない]

[08:06 PM] ~/code $ echo "echo $PWD" > sub_demo
[08:11 PM] ~/code $ cat sub_demo
echo /c/Users/chadb/code

[脱出する]

[08:11 PM] ~/code $ echo "echo \$PWD" > sub_demo
[08:13 PM] ~/code $ cat sub_demo
echo $PWD

まだそれほど興味深いものではありませんが、出力を実行すると真の魔法が起こります。

最終簡略化された証明

エスケープされない - 動作しません
[08:15 PM] ~/code $ echo "echo $PWD" > sub_demo
[08:15 PM] ~/code $ cat sub_demo
echo /c/Users/chadb/code
[08:15 PM] ~/code $ cd sub_demo_folder/
[08:15 PM] ~/code/sub_demo_folder $ cat ~/code/sub_demo | bash -
/c/Users/chadb/code
[08:15 PM] ~/code/sub_demo_folder $ cd ~
[08:15 PM] ~ $ cat ~/code/sub_demo | bash -
/c/Users/chadb/code
[08:15 PM] ~ $ cd code
[08:15 PM] ~/code $ cat ~/code/sub_demo | bash -
/c/Users/chadb/code

観測された出力値は次のとおりです。いつも /c/Users/chadb/code

脱出 - 操作
[08:15 PM] ~/code $ echo "echo \$PWD" > sub_demo
[08:15 PM] ~/code $ cat sub_demo
echo $PWD
[08:16 PM] ~/code $ cd sub_demo_folder/
[08:19 PM] ~/code/sub_demo_folder $ cat ~/code/sub_demo | bash -
/c/Users/chadb/code/sub_demo_folder
[08:19 PM] ~/code/sub_demo_folder $ cd ~
[08:19 PM] ~ $ cat ~/code/sub_demo | bash -
/c/Users/chadb
[08:19 PM] ~ $ cd code/
[08:19 PM] ~/code $ cat ~/code/sub_demo | bash -
/c/Users/chadb/code

次に、コマンドが実行されるたびに正しいことを確認してください。現在の必要に応じてディレクトリ。

関連情報