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 정보가 바뀔 때까지 다시 실행할 필요는 없지만 감지하기 어렵습니다.) 이를 수행하는 방법에는 두 가지가 있습니다.

  • `__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_ps1두 번째 버전에서는 이것이 유지되는 반면, 첫 번째 버전에서는 입력 시 __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

이제 명령이 실행될 때마다 올바른지 관찰하십시오.현재의필요에 따라 디렉토리.

관련 정보