Large .bash_profile increasing time for terminal to do things. Able to fix? I've got an almost 100 line .bash_profile which does things like check the git branch and colour certain text. This makes things like even starting a new line significantly slower compared to the instant speed of having an empty profile.

Is there any way around this or is it just because of the extra functionality that the profile has which is adding overhead? Why is it being so slow?

After testing it on another machine (on a Fedora distro, was using Mac), it doesn't have this issue at all. The Fedora machine is instant as expected, while the Mac has a noticeable delay when starting a new line, cd'ing into something etc.

Here is the profile: https://pastebin.com/UKWPPqKf

# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
    . /etc/bashrc
fi

# User specific environment
if ! [[ "$PATH" =~ "$HOME/.local/bin:$HOME/bin:" ]]
then
    PATH="$HOME/.local/bin:$HOME/bin:$PATH"
fi
export PATH

# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=

# User specific aliases and functions

#THIS MUST BE AT THE END OF THE FILE FOR SDKMAN TO WORK!!!
export SDKMAN_DIR="/home/USRNAME/.sdkman"
[[ -s "/home/USRNAME/.sdkman/bin/sdkman-init.sh" ]] &amp;&amp; source "/home/USRNAME/.sdkman/bin/sdkman-init.sh"

#Aliases
if [ -f ~/.bash_aliases ]; then
    source ~/.bash_aliases
fi

# get current branch in git repo
function parse_git_branch() {
    BRANCH=`git branch 2&gt; /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'`
    if [ ! "${BRANCH}" == "" ]
    then
        STAT=`parse_git_dirty`
        echo "[${BRANCH}${STAT}]"
    else
        echo ""
    fi
}
# get current branch in git repo
function parse_git_branch() {
    BRANCH=`git branch 2&gt; /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'`
    if [ ! "${BRANCH}" == "" ]
    then
        STAT=`parse_git_dirty`
        echo "[${BRANCH}${STAT}]"
    else
        echo ""
    fi
}

# get current status of git repo
function parse_git_dirty {
    status=`git status 2&gt;&amp;1 | tee`
    dirty=`echo -n "${status}" 2&gt; /dev/null | grep "modified:" &amp;&gt; /dev/null; echo "$?"`
    untracked=`echo -n "${status}" 2&gt; /dev/null | grep "Untracked files" &amp;&gt; /dev/null; echo "$?"`
    ahead=`echo -n "${status}" 2&gt; /dev/null | grep "Your branch is ahead of" &amp;&gt; /dev/null; echo "$?"`
    newfile=`echo -n "${status}" 2&gt; /dev/null | grep "new file:" &amp;&gt; /dev/null; echo "$?"`
    renamed=`echo -n "${status}" 2&gt; /dev/null | grep "renamed:" &amp;&gt; /dev/null; echo "$?"`
    deleted=`echo -n "${status}" 2&gt; /dev/null | grep "deleted:" &amp;&gt; /dev/null; echo "$?"`
    bits=''
    if [ "${renamed}" == "0" ]; then
        bits="&gt;${bits}"
    fi
    if [ "${ahead}" == "0" ]; then
        bits="*${bits}"
    fi
    if [ "${newfile}" == "0" ]; then
        bits="+${bits}"
    fi
    if [ "${untracked}" == "0" ]; then
        bits="?${bits}"
    fi
    if [ "${deleted}" == "0" ]; then
        bits="x${bits}"
    fi
    if [ "${dirty}" == "0" ]; then
        bits="!${bits}"
    fi
    if [ ! "${bits}" == "" ]; then
        echo " ${bits}"
    else
        echo ""
    fi
}

export PS1="\[$(tput bold)\]\u@\h:\[$(tput sgr0)\]\[\033[38;5;39m\]\w\[$(tput sgr0)\]\[$(tput sgr0)\]\[\033[38;5;15m\] \[$(tput sgr0)\]\[\033[38;5;11m\]\[$(tput bold)\]\`parse_git_branch\`\[\e[m\] \[$(tput sgr0)\]"
If you type set -x into the terminal, it will print every command it executes from that point on, so to find the culprit, type set -x and hit return, then - paying attention to the lines scrolling by on the screen - watch for whatever command takes a long time to run.

The number of + characters at the beginning of each line tell you how deeply nested the command is. If you scroll up a bit, you can find the "parent" command.

The commands you see when you hit return are all triggered by the last line of your bashrc, where you set the contents of the variable PS1. Every time you hit return, the contents of that variable are executed and the result is shown as the "prompt" (the bit before the cursor, e.g. something like user@box ~ $).

To get out of this mode, you can type set +x or just close that terminal window/tab (see What does set -x do?).



PS: I would hazard a guess that your git status commands are slowing down the prompt. If you install both git and bash-completion from Homebrew, you can use __git_ps1 to do this and get rid of all the git related functions from your bashrc. As an example, this is what it looks like on my machine:

if [[ -f /usr/local/etc/bash_completion ]]; then
    . /usr/local/etc/bash_completion
fi

GIT_PS1_SHOWDIRTYSTATE=1
GIT_PS1_SHOWUPSTREAM="auto"
GIT_PS1_SHOWUNTRACKEDFILES=1

PS1='\w \$ '
if type __git_ps1 &amp;&gt;/dev/null; then
    PS1='\w$(__git_ps1 | sed -e "s/=)$/)/") \$ '
fi