I feel the existing answers don't accurately/clearly communicate the root cause. Although they may lead to arriving at a solution, I'm unsure they teach the viewer the lesson that should be learned. This answer is focused on answering from the angle of helping the viewer arrive at that understanding.
Quick answer
I thought of this method after writing up the original response, so leaving the detailed response below but here's the quick answer.
Your PS1
value is being stored as the substituted version because escaping was not used during input. You can validate it like this:
Original:
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\]\$
Escaped
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\]\$
As you can see, __git_ps1
is preserved in the second version whereas in the first it shows the value of __get_ps1 at the time of entry.
On with my original answer.
Explanation
The problem is when the shell executes your command, it performs substitution prior to insertion so the substituted values are inserted rather than your raw command.
In order to fix this, you simply need to use the escape char \
to prevent substitution prior to storing. This results in the unescaped executable version of the command being stored in memory so that bash will re-evaluate it upon each entered command.
The command being unescaped results in it being executed and substituted prior to storage in memory which in turn causes it to only show the command when ~/.bash_profile
was first executed/sourced.
Solutions
Original Command
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\]\\$ "
Original Stored value of $PS1
Includes string literal " (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\]\\$
Important: To avoid confusion, this stored value only represents the changes to __git_ps1
Fixed Command
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\]\\$ "
Fixed Stored value of $PS1
This time the command is left in-tact so that it will be substituted upon the next execution.
"\\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\]\\$ "
Backticks are unrelated - proof
As other answers have mentioned you may supply backticks with $(), however, that has nothing to do with the root cause of this issue. These issues should not be conflated.
Old [Not the problem]
`__git_ps1`
New [Not the problem]
$(__git_ps1)
Original command without backticks unescaped [Not the problem, equally broken]
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\]\\$ "
Original command without backticks escaped [Fixed same way, with escaping]
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\]\\$ "
Simplified proof
To simplify this, let's remove a lot of variables by making our custom shell command that does a similar thing to bash by merely echoing our current working directory to the console using a file sub_demo
as the storage medium to show the in-between state.
Unescaped $PWD [the problem]
[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
Notice that the substituted value of $PWD
has been stored in the file, thus destroying the information of what command was used to retrieve that directory. If we merely read out the contents of sub_demo from here on out, it will always result in the same rendered value of /c/Users/chadb/code
This is silly to do, but for illustration purposes I will read the contents of the file from multiple locations to prove the point that this is in fact not going to change the information stored within.
[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
Notice the value doesn't change, irrespective of the folder. The contents of ~/code/sub_demo
are from here on out /c/Users/chadb/code
until we change them.
Escaped $PWD [the solution]
Now consider if you instead escape the $
character via \$
.
[08:06 PM] ~/code $ echo \$PWD > sub_demo
[08:06 PM] ~/code $ cat sub_demo
$PWD
As you can see, the value is now stored as the command - the same one which is necessary to find our working directory. How is this useful? Well, bash executes whatever the stored value of $PS1 is. Let's simulate that by merely turning the contents of the file executable via adding echo to the beginning.
For completeness and contrast, I will show the unescaped and escaped versions.
[Unescaped]
[08:06 PM] ~/code $ echo "echo $PWD" > sub_demo
[08:11 PM] ~/code $ cat sub_demo
echo /c/Users/chadb/code
[Escaped]
[08:11 PM] ~/code $ echo "echo \$PWD" > sub_demo
[08:13 PM] ~/code $ cat sub_demo
echo $PWD
This isn't that exciting yet, but the real magic happens when you execute the output.
Final simplified proof
Unescaped - Does not work
[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
Observe that the output value is always /c/Users/chadb/code
Escaped - Does work
[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
Observe that now, every single time the command is executed it shows the correct current directory as desired.
__git_ps1
part so you don't need to fix escapes all through the prompt) so it isn't called/evaluated immediately and is left unexpanded for the shell to call at prompt display time.