• Modern UX

    Edit and navigate faster in the terminal with Warp's IDE-like input editor.

  • Warp AI

    AI suggests what commands to run and learns from your documentation.

  • Agent Mode

    Delegate tasks to AI and use natural language on the command line.

  • Warp Drive

    Save and share interactive notebooks, workflows, and environment variables.

  • All Features

Prompt Show Git Branch In Prompt

Thumbnail for Gabriel ManricksGabriel Manricks

Gabriel Manricks

Chief Architect, ClearX

Published: 5/20/2024

About Terminus

The short answer

The appearance of the terminal prompt is controlled by an environment variable named PS1, which the shell evaluates each time the prompt is displayed.

To change your prompt to include the current Git branch, you can start by opening your shell's configuration file using your favorite text editor; for Bash, it is ~/.bashrc, and for Zsh, it is ~/.zshrc:

 $ vim ~/.zshrc

Run in Warp

Define the following getBranch function into it:

 getBranch() {
    git rev-parse --abbrev-ref HEAD 2> /dev/null
}

Run in Warp

Where:

  • The git rev-parse --abbrev-ref HEAD command fetches the name of the current branch.
  • The 2> /dev/null redirection is used to discard any error messages, for example, if the current directory is not a Git repository.

Integrate this function into the PS1 environment variable:

 export PS1="$PS1 \$(getBranch) "

Run in Warp

Where:

  • The export command sets an environment variable.
  • The $PS1 variable contains the current prompt settings.
  • The $(getBranch) expression will be replaced by the getBranch command output.
  • The \ ensures that the $(getBranch) expression evaluates dynamically each time the prompt is displayed rather than being pre-evaluated and stored as a string on terminal' start up.

Note that if you are using Zsh as your terminal, you will need to enable command substitution within the prompt using the setopt command as follows:

 setopt PROMPT_SUBST;

Run in Warp

After editing your shell config file, you will need to reload your shell’s configuration by opening a new terminal or by running the following source command:

$ source path/to/shell_config

Run in Warp

Easily change the prompt using the Warp Context Chips feature

If you’re using Warp as your terminal, you can easily change your terminal's prompt using the Warp Context Chips feature:

Thumbnail for

The Warp Custom Prompt is a GUI-based feature that allows you to customize your shell using a list of pre-configured prompts that you can easily combine through a system of drag and drop, including timestamp, remote login, git branch, and more.

Just right-click your prompt and click on “Edit Prompt” to bring up the visual custom prompt editor. 

These prompt chips are context-aware, so for example, if you add the “uncommitted files” chip, then only when inside a git directory you will have a section on the number of uncommitted files, or if you add the Kubernetes context it will only appear when running a kubectl command.

Extending your Git prompt

The goal of a good Git prompt is to provide as much helpful context about the repository you are currently in without requiring you to run any commands manually, like how a prompt displays the current working directory so that you don’t need to check where you are manually.

In the context of Git, some relevant contextual information is:

  • The branch name - to make sure you are working on the correct branch
  • The status of the branch - to allow you to know if you need to commit something
  • The difference in commits between the local and remote repositories - to see if you need to pull or push any changes

Commits ahead or behind upstream

To get the number of commits you are ahead or behind the remote branch, you can use:

 $ git rev-list --count --left-right @{upstream}...HEAD
12    6

Run in Warp

The command will output two columns: the first will be the number of commits the upstream (origin) is ahead of your local branch, and the second is the number of commits you are ahead of the remote branch. 

Using this, you can create a function in your shell’s config file (~/.zshrc):

gitUpstreamPosition() {
    local commitCount=$(git rev-list --count --left-right @{upstream}...HEAD 2> /dev/null)
    if [ -n "$commitCount" ]; then
       local behindCount=$(echo -n "$commitCount" | cut -f1)
       local aheadCount=$(echo -n "$commitCount" | cut -f2)
       if [ "$behindCount" != "0" ]; then
           echo -n " ${behindCount}↓"
       fi
       if [ "$aheadCount" != "0" ]; then
          echo -n " ${aheadCount}↑"
       fi
    fi
}

Run in Warp

Where:

  • local commitCount=$(...) runs the command and stores the results in a local variable called commitCount
  • if [ -n "$commitCount" ]; checks if the value is not an empty string
  • echo -n $commitCount | cut -f1 will cut the first column, which is the number of commits behind the remote branch. The value is stored in a variable called behindCount
  • local aheadCount=$(...) same is done for the second column, which is the number of commits ahead of the remote branch.
  • if [ "$behindCount" != "0" ]; check only to display something if the value is different than zero.
  • echo -n " ${behindCount}↓" print out the number plus a down arrow as a symbol for commits that need to be pulled.

Working Tree Status

Another common use case is to display the status of your work tree to see if there are changes to commit or if you are in a clean state. The command to get the status of the working tree is:

 $ git status --porcelain
A  file.txt
MM demo.bin
D  README.md

Run in Warp

Many git commands have a --porcelain flag, which outputs the data in an easier-to-parse format. For git status, the porcelain flag will cause the output only to include changed files without any extra text, and for each line, you will have two letters describing the change followed by a space and the file name.

The first letter is the staged change status, and the second is the unstaged change status. The exception to this is new files that have never been tracked (added) to Git; they will have a question mark in each column.

So, to see if there are any staged changes, you can simply check to see if, in any of the rows, there is a line with a letter (other than a question mark) in the first character space:

 $ git status --porcelain | grep '^[^? ]'

Run in Warp

Where the grep regular expression is:

  • ^ - means the match must start at the beginning of a line
  • [^? ] - brackets specify a group of characters to match, and the ^ reverses the selection, so any character not matching a question mark or space.

A prompt function to display symbols for these different kinds of changes would look something like the following:

gitStatusSymbols() {
    local gitstatus=$(git status --porcelain 2> /dev/null)
    if [ -n "$gitstatus" ]; then
         local statusString="";
         if [ -n "$(echo "$gitstatus" | grep '^[^? ]')" ]; then
                statusString="$statusString$GREEN+$BLANK"
         fi
         if [ -n "$(echo "$gitstatus" | grep '^.[^? ]')" ]; then
                statusString="$statusString$RED*$BLANK"
         fi
         if [ -n "$(echo "$gitstatus" | grep '^[?][?]')" ]; then
                statusString="$statusString?"
         fi
         echo -e " $statusString"
    fi
}
RED='%F{red}'
GREEN='%F{green}'
BLANK='%f'

Run in Warp

Where:

  • The first line gets the status output, handling errors
  • if [ -n "$gitstatus" ]; checks if the value is not empty
  • local statusString=""; prepares a variable to hold the statuses
  • The function then checks for three kinds of changes using grep and a regular expression to test for staged changes, unstaged changes, and new files
  • For each of these cases, the function appends the desired symbol to the output variable
  • echo -e " $statusString" outputs the final results, prepending the value with a space to fit well with the rest of the prompt.
  • The last three lines hold variables with the escape sequence for adding color to the terminal output.

For Bash instead of Zsh, the variables for color should be:

GREEN='\033[32m'
RED='\033[31m'
BLANK='\033[0m'

Run in Warp

Tying it all together

To wrap the above two functions into a single string along with the branch name you can create another function like the following:

 gitPrompt() {
    local branchName=$(git rev-parse --abbrev-ref HEAD 2> /dev/null)
    if [ -n "$branchName" ]; then
       echo -e " [🌱 ${branchName}$(gitStatusSymbols)$(gitUpstreamPosition)]"
    fi
}

Run in Warp

This function gets the current branch name, and if the value isn’t blank (i.e., we are in a Git directory), it will output the branch name between square brackets along with the output of the two other functions. It is worth noting the ${} with curly braces prints out a variable, whereas $() with parentheses runs a command/function and outputs the results.

This function can then be used by adding to your shell’s config file:

 export PS1="\u@\h \w\$(gitPrompt)> "

Run in Warp

Where:

  • \u prints the current user
  • \h prints the hostname
  • \w prints the current working directory
  • $(gitPrompt) prints the output of the gitPrompt[.inline-code] function

For Zsh, you will also need to enable prompt substitution as described above:

 setopt  PROMPT_SUBST

Run in Warp

Git Prompt Script

Git has released an official utility that can be used to add Git info easily into your terminal prompt. To get started, you need to download the script itself:

$ curl https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh -o ~/git-prompt.sh

Run in Warp

And then edit your shells configuration (~/.zshrc) with the following:

 source ~/.git-prompt.sh

Run in Warp

That loads in a shell function called __git_ps1, which prints out git information primarily to be used in prompts. To add it to your prompt, you can include it in your PS1 variable:

 export PS1="$PS1\$(__git_ps1 \" (%s)\")> "

Run in Warp

The __git_ps1 function accepts an optional format string parameter used to style the output. The example above sends ” (%s)” where we will get a string that starts with a space and then parenthesis, and within the parenthesis, the %s will be replaced by the __git_ps1 results. The advantage to using a format string instead of just hard coding the space and parenthesis is that if you are not in a Git repository, it will be omitted completely.

For Zsh, you will also need to enable prompt substitutions:

 setopt PROMPT_SUBST;

Run in Warp

By default, this script will only display the git branch, but you can enable other features by setting specific environment variables.

GIT_PS1_SHOWDIRTYSTATE will cause the prompt to include the working tree statusGIT_PS1_SHOWUNTRACKEDFILES will show if there are new untracked filesGIT_PS1_SHOWUPSTREAM can be used to show commits ahead and behind your upstream

For example, add to your ~/.zshrc

 export GIT_PS1_SHOWDIRTYSTATE=true

Run in Warp

These are just a few of the options. You can view more info in the script comments here.

Advanced Prompt Toolkits

Designing a truly dynamic and interactive prompt that reacts to different tools like Docker, Git, Python, Node.js, etc., is a complex task. Each tool has nuances and design decisions (not to mention supporting multiple terminals like bash/zsh). Luckily, there are very popular projects that work on just this.

Starship

One such project is called Starship, which supports over 80 different tools, smart defaults out of the box, and the ability to customize many different settings in each.

To install Starship, you can run:

$ curl -sS https://starship.rs/install.sh | sh

Run in Warp

Then, to get it running in Bash, add the following to your ~/.bashrc:

 eval "$(starship init bash)"

Run in Warp

And for Zsh, you would add to your ~/.zshrc:

 eval "$(starship init bash)"

Run in Warp

It is also recommended to install a NerdFont from here, which are regular fonts with the symbols replaced with popular development icons from icon frameworks like Devicons, Font Awesome, Material Design, and more.

Customising Starship

To customize Starship prompt, create a file ~/.config/starship.toml with your configuration. Starship has both high-level settings for designing the prompt's format and granular per-tool options.

For example, if you would like to add the current Kubernetes context to your prompt, you can add the following to your ~/.config/starship.toml file:

[kubernetes]
disabled = false
format = '[${symbol}k8s $context]($style) in '

Run in Warp

Each tool in Starship has its own settings and variables. For Kubernetes, you have variables like context, namespace, user, and cluster; in the example above, we display the current Kubernetes context.

There are also configuration variables per tool, like symbol and style, which we used here; symbol defaults to a Kubernetes icon, and the style defaults to “cyan bold”. In Starship, to customize colors of text, you use the format [<text to color>](<style>); everything between the square brackets will receive the style defined in the parentheses.

You can find more info about starship configuration for Kubernetes and other tools here.

There are also presets that are like themes; these are complete starship.toml configurations you can just copy and use. You can find some presets on the official Starship site here.

Powerlevel10K (P10K)

If you are using ZSH, another popular off-the-shelf prompt is PowerLevel10K; like Starship, it has extensive support for many different tools and contexts.

To install P10K, you can run:

 $ git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ~/powerlevel10k
$ echo 'source ~/powerlevel10k/powerlevel10k.zsh-theme' >>~/.zshrc

Run in Warp

The first line clones the repository into your HOME directory, and the second command adds a line to your ~/.zshrc file to load P10K.

Unlike other prompt kits like Starship, where you start off with the defaults and then customize it later, with P10K, you are greeted with a setup wizard the first time P10K is loaded. This setup wizard visually guides you through the different customization options, allowing you to get it set up just how you like it very quickly.

You can get back to this setup wizard at any time by running p10k configure

Written by

Thumbnail for Gabriel ManricksGabriel Manricks

Gabriel Manricks

Chief Architect, ClearX

Filed Under

Related Articles

Undo A Git Pull

How to effectively remove the commits introduced by a pull in Git using git-reset and preserve your local changes using git-stash. Also, how to cancel an unmerged pull request on GitHub.

Git
Thumbnail for Glory KimGlory Kim

Undo a Git Merge

How to rollback the changes introduced by a merge in Git by adding new opposite commits using git-revert and effectively removing commits using git-reset.

Git
Thumbnail for Philip WilkinsonPhilip Wilkinson

How To Remove Secrets From The Git History Remove Secrets From The Git History

Learn how to remove secrets from the Git history using the BFG and git-filter-repo command-line tools.

Git
Thumbnail for Utsav PoudelUtsav Poudel

Adding a Submodule in Git

This post will show you how to simply add a submodule to a local repository, clone a repository with a submodule, and work within a repository that has a submodule.

Git
Thumbnail for Philip WilkinsonPhilip Wilkinson

Undo a git push

This post will show you had to simply undo a git push three different ways.

Git
Thumbnail for Philip WilkinsonPhilip Wilkinson

Undo Git Add

Learn how to effectively use 'git add' to stage files in Git for committing, and discover two powerful methods to undo accidental stagings.

Git
Thumbnail for Glory KimGlory Kim

Undo a Git Rebase

This post will show you how to undo a rebase using git reset, git rebase and git revert

Git
Thumbnail for Philip WilkinsonPhilip Wilkinson

Git Push Origin

A breakdown of git push origin

Git
Thumbnail for Amanda KhooAmanda Khoo

Create Folder In GitHub Repository

Learn how to create and push one or more empty directories in a Git repository using `.placeholder` and `README.md` files using both the CLI and the GitHub interface.

Git
Thumbnail for Razvan LudosanuRazvan Ludosanu

Git Push Tags

This post will show you how to push a single tag, multiple tags, all tags, and tags with commits.

Git
Thumbnail for Philip WilkinsonPhilip Wilkinson

Undoing Git Commits

Explore ways to undo a commit, including git reset, git checkout, and git revert with git while preserving commit history.

Git
Thumbnail for Philip WilkinsonPhilip Wilkinson

Delete Local Git Branch

Learn how to delete local branches from your git repository, including ones with unmerged changes, as well as local remote-tracking branches.

Git
Thumbnail for Philip WilkinsonPhilip Wilkinson

Trusted by hundreds of thousands of professional developers

Download Warp to get started

Download for Mac
Thumbnail for null