[git] How can I see which Git branches are tracking which remote / upstream branch?

I know I can do git branch --all, and that shows me both local and remote branches, but it's not that useful in showing me the relationships between them.

How do I list branches in a way that shows which local branch is tracking which remote?

This question is related to git

The answer is


Based on Olivier Refalo's answer

if [ $# -eq 2 ] 
then
    echo "Setting tracking for branch " $1 " -> " $2
    git branch --set-upstream $1 $2
else
    echo "-- Local --" 
    git for-each-ref --shell --format="[ %(upstream:short) != '' ] && echo -e '\t%(refname:short) <--> %(upstream:short)'" refs/heads | sh
    echo "-- Remote --" 
    REMOTES=$(git remote -v) 
    if [ "$REMOTES" != '' ]
    then
        echo $REMOTES
    fi  
fi

It shows only local with track configured.

Write it on a script called git-track on your path an you will get a git track command

A more elaborated version on https://github.com/albfan/git-showupstream


git remote show origin

Replace 'origin' with whatever the name of your remote is.


For the current branch, here are two good choices:

% git rev-parse --abbrev-ref --symbolic-full-name @{u}
origin/mainline

or

% git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)
origin/mainline

That answer is also here, to a slightly different question which was (wrongly) marked as a duplicate.


In case anyone's reading this and wanting to protect master with client-side branch protection,

git branch -vv | grep "^\*" |grep -E '\* master |origin\/master'

will return 0 if either the local checked-out branch or its upstream remote branch is master.

Just put this in your .git/hooks directory's pre-commit and update files accordingly and Bob is your father's brother.


Here is a neat and simple one. Can check git remote -v, which shows you all the origin and upstream of current branch.


git config --get-regexp "branch\.$current_branch\.remote"

will give you the name of the remote that is being tracked

git config --get-regexp "branch\.$current_branch\.merge"

will give you the name of the remote branch that's being tracked.

You'll need to replace $current_branch with the name of your current branch. You can get that dynamically with git rev-parse --abbrev-ref HEAD

The following mini-script combines those things. Stick it in a file named git-tracking, make it executable, and make sure it's in your path.

then you can say

$ git  tracking
<current_branch_name>-><remote_repo_name>/<remote_branch_name>

note that the remote branch name can be different from your local branch name (although it usually isn't). For example:

$git tracking 
xxx_xls_xslx_thing -> origin/totally_bogus

as you can see in the code the key to this is extracting the data from the git config. I just use sed to clear out the extraneous data.

#!/bin/sh

current_branch=$(git rev-parse --abbrev-ref HEAD)
remote=$(git config --get-regexp "branch\.$current_branch\.remote" | sed -e "s/^.* //")
remote_branch=$(git config --get-regexp "branch\.$current_branch\.merge" | \
  sed -e "s/^.* //" -e "s/refs\/.*\///")

echo "$current_branch -> $remote/$remote_branch"

I use this alias

git config --global alias.track '!f() { ([ $# -eq 2 ] && ( echo "Setting tracking for branch " $1 " -> " $2;git branch --set-upstream $1 $2; ) || ( git for-each-ref --format="local: %(refname:short) <--sync--> remote: %(upstream:short)" refs/heads && echo --Remotes && git remote -v)); }; f'

then

git track

If you look at the man page for git-rev-parse, you'll see the following syntax is described:

<branchname>@{upstream}, e.g. master@{upstream}, @{u}

The suffix @{upstream} to a branchname (short form <branchname>@{u}) refers to the branch that the branch specified by branchname is set to build on top of. A missing branchname defaults to the current one.

Hence to find the upstream of the branch master, you would do:

git rev-parse --abbrev-ref master@{upstream}
# => origin/master

To print out the information for each branch, you could do something like:

while read branch; do
  upstream=$(git rev-parse --abbrev-ref $branch@{upstream} 2>/dev/null)
  if [[ $? == 0 ]]; then
    echo $branch tracks $upstream
  else
    echo $branch has no upstream configured
  fi
done < <(git for-each-ref --format='%(refname:short)' refs/heads/*)

# Output:
# master tracks origin/master
# ...

This is cleaner than parsing refs and config manually.


git for-each-ref --format='%(refname:short) <- %(upstream:short)' refs/heads

will show a line for each local branch. A tracking branch will look like:

master <- origin/master

A non-tracking one will look like:

test <- 

For the current branch, you could also say git checkout (w/o any branch). This is a no-op with a side-effects to show the tracking information, if exists, for the current branch.

$ git checkout 
Your branch is up-to-date with 'origin/master'.

An alternative to kubi's answer is to have a look at the .git/config file which shows the local repository configuration:

cat .git/config