ChatGPT解决这个技术问题 Extra ChatGPT

Find out which remote branch a local branch is tracking

See also: How can I see which Git branches are tracking which remote / upstream branch?

How can I find out which remote branch a local branch is tracking?

Do I need to parse git config output, or is there a command that would do this for me?

Sheesh. This is not an exact duplicate. This is a subset of the other, but there are other ways to do the out question, like git remote show origin. The main answer in the other question is a bash script wrapped around the simple answer here, which might be useful to some. Hopefully this question will not be completely closed.
Agreed, this definitely shouldn't be a dupe. It's asking something completely different than the linked question

m
mtyurt

Here is a command that gives you all tracking branches (configured for 'pull'), see:

$ git branch -vv
  main   aaf02f0 [main/master: ahead 25] Some other commit
* master add0a03 [jdsumsion/master] Some commit

You have to wade through the SHA and any long-wrapping commit messages, but it's quick to type and I get the tracking branches aligned vertically in the 3rd column.

If you need info on both 'pull' and 'push' configuration per branch, see the other answer on git remote show origin.

Update

Starting in git version 1.8.5 you can show the upstream branch with git status and git status -sb


This output is more direct than git branch -av or git remote show origin, which give you a LOT of data, not just the tracked remote
BTW, the newest versions of git (1.8.5.x) also now show the upstream branch during git status and git status -sb -- so once you upgrade to 1.8.5.x, this question (and answer) is irrelevant.
While this give you information you want, I would disagree as it being the correct answer. It's an answer the same way giving someone a dictionary answers "how do you spell XYZ". case in point, you want to USE the resulting answer (the branch name) for some operation.. This answer only helps me visually see it... doesn't give you something usable in a subsequent command.
The output of this command can be misleading since a commit message may easily begin with for example "[my-feature] ...". Please see @cdunn2001 's answer that shows only the upstream branch (if any) and nothing else.
I agree with @jonas-berlin -- cdunn2001's answer is better if you want to parse the result -- my answer is good if you are looking for a simple command and are willing to visually scan the output
c
cdunn2001

Two 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

Nice! The first one gives ugly errors in case nothing is tracked, while the second is especially helpful for scripting. BTW %(refname:short) is the name of the current ref within --format.
git help revisions (one of the little-known but most useful parts of the docs) and search for upstream.
This answer is much better than the two answers above it, especially if you want to do something like git diff `git rev-parse --abbrev-ref --symbolic-full-name @{upstream}`
This is really useful echo 'git for-each-ref --format=\'%(refname:short) -> %(upstream:short)\' refs/heads/$1' > ~/bin/git-show-upstream; chmod +x ~/bin/git-show-upstream
If you want to find out the upstream for some other branch, a variant of the second choice is: git for-each-ref --format='%(upstream:short)' $(git rev-parse --symbolic-full-name SOMEBRANCH) replacing SOMEBRANCH with the branch name, or "HEAD" for current branch
A
Ajit George

I think git branch -av only tells you what branches you have and which commit they're at, leaving you to infer which remote branches the local branches are tracking.

git remote show origin explicitly tells you which branches are tracking which remote branches. Here's example output from a repository with a single commit and a remote branch called abranch:

$ git branch -av
* abranch                d875bf4 initial commit
  master                 d875bf4 initial commit
  remotes/origin/HEAD    -> origin/master
  remotes/origin/abranch d875bf4 initial commit
  remotes/origin/master  d875bf4 initial commit

versus

$ git remote show origin
* remote origin
  Fetch URL: /home/ageorge/tmp/d/../exrepo/
  Push  URL: /home/ageorge/tmp/d/../exrepo/
  HEAD branch (remote HEAD is ambiguous, may be one of the following):
    abranch
    master
  Remote branches:
    abranch tracked
    master  tracked
  Local branches configured for 'git pull':
    abranch merges with remote abranch
    master  merges with remote master
  Local refs configured for 'git push':
    abranch pushes to abranch (up to date)
    master  pushes to master  (up to date)

I need a command that discovers the upstream branch, so using 'origin' as input is making an assumption, so this does not work for me
But this DOES answer the OP. The command git remote show origin shows you local branches and what they track for both push and pull.
@dudewad I think the point was that this command assumes that the remote is called origin, while it could actually be anything (e.g. multiple remotes, with different branches tracking branches from different remotes).
A
Aaron Wells

Update: Well, it's been several years since I posted this! For my specific purpose of comparing HEAD to upstream, I now use @{u}, which is a shortcut that refers to the HEAD of the upstream tracking branch. (See https://git-scm.com/docs/gitrevisions#gitrevisions-emltbranchnamegtupstreamemegemmasterupstreamememuem ).

Original answer: I've run across this problem as well. I often use multiple remotes in a single repository, and it's easy to forget which one your current branch is tracking against. And sometimes it's handy to know that, such as when you want to look at your local commits via git log remotename/branchname..HEAD.

All this stuff is stored in git config variables, but you don't have to parse the git config output. If you invoke git config followed by the name of a variable, it will just print the value of that variable, no parsing required. With that in mind, here are some commands to get info about your current branch's tracking setup:

LOCAL_BRANCH=`git name-rev --name-only HEAD`
TRACKING_BRANCH=`git config branch.$LOCAL_BRANCH.merge`
TRACKING_REMOTE=`git config branch.$LOCAL_BRANCH.remote`
REMOTE_URL=`git config remote.$TRACKING_REMOTE.url`

In my case, since I'm only interested in finding out the name of my current remote, I do this:

git config branch.`git name-rev --name-only HEAD`.remote

This was very useful in making an alias to rebase whatever my current branch is. Thanks!
Likewise useful for our 'fastforward' alias which'll advance the local tracking branch to the remote as long as the operation is a fast-forward.
Actually I discovered this git name-rev --name-only HEAD won't tell you which branch you're actually on. For that I just used git branch | grep '^\*' | cut -d' ' -f2
Thanks! Other answers to similar questions didn't mention @{u} alias/shortcut and that's exactly what I was looking for! No reason to compare with master branch if you only want to determine whether you need to pull or not.
@{u} is the bomb. And has been around since 1.7.0, which means that if it's not available in a git that someone is using in 2018, they're probably due for an upgrade.
n
nikkypx

The local branches and their remotes.

git branch -vv 

All branches and tracking remotes.

git branch -a -vv

See where the local branches are explicitly configured for push and pull.

git remote show {remote_name}

This is the correct answer. For example git remote show origin actually does show the url of my remote.
@kingaj this requires you to know the name of your remote (origin). Are you 100% sure that when you type git push you are pushing to origin? This is not the case for me and I'm actually here looking for simple answers because so many of my aliases/shortcuts hardcode origin but sometimes I work with multiple remotes and so those are broken for me
@nhed the pattern in post below answer might help. I just tried it and it worked pretty well.
@the-typist Yeah I actually already up-voted that answer the same day. Its clean but would be nice if git could answer it without having to make multiple invocations. I went and rewrote several of my aliases/functions that used to hard-code origin
S
Sabyasachi Ghosh

git branch -vv | grep 'BRANCH_NAME'

git branch -vv : This part will show all local branches along with their upstream branch .

grep 'BRANCH_NAME' : It will filter the current branch from the branch list.


Thanks, I was using this to determine if the current branch was tracking a remote branch. Incase anyone else is doing the same thing... The output if there is no tracked branch will be * 'BRANCH_NAME' <commit-sha> 'commit message' if there is a tracked branch * 'BRANCH_NAME' <commit-sha> ['TRACKED_BRANCH_NAME']'commit message'
r
rubo77

This will show you the branch you are on:

$ git branch -vv

This will show only the current branch you are on:

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

for example:

myremote/mybranch

You can find out the URL of the remote that is used by the current branch you are on with:

$ git remote get-url $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)|cut -d/ -f1)

for example:

https://github.com/someone/somerepo.git

E
Eugene Yarmash

You can use git checkout, i.e. "check out the current 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'.

W
William Pursell

I don't know if this counts as parsing the output of git config, but this will determine the URL of the remote that master is tracking:

$ git config remote.$(git config branch.master.remote).url

Or git config branch.$(git symbolic-ref -q HEAD).remote if you just want the name of the remote being tracked of the current branch—git config remote.$(git config branch.$(git symbolic-ref -q HEAD).remote).url for the URL.
I needed to add --short option so it works. So for getting the remote name of current branch: git config branch.$(git symbolic-ref -q --short HEAD).remote and for getting the URL of the remote of current branch: git config remote.$(git config branch.$(git symbolic-ref -q --short HEAD).remote).url
F
FragLegs

Yet another way

git status -b --porcelain

This will give you

## BRANCH(...REMOTE)
modified and untracked files

A
AndiDog

git-status porcelain (machine-readable) v2 output looks like this:

$ git status -b --porcelain=v2
# branch.oid d0de00da833720abb1cefe7356493d773140b460
# branch.head the-branch-name
# branch.upstream gitlab/the-branch-name
# branch.ab +2 -2

And to get the branch upstream only:

$ git status -b --porcelain=v2 | grep -m 1 "^# branch.upstream " | cut -d " " -f 3-
gitlab/the-branch-name

If the branch has no upstream, the above command will produce an empty output (or fail with set -o pipefail).


I like this solution, because it allows detecting in the script if any upstream branch is configured for a local branch, without knowing anything about their names.
r
rayryeng

Another simple way is to use

cat .git/config in a git repo

This will list details for local branches


Works nicely on Linux. Will not work on Windows unless in a Unix-like prompt (e.g. cygwin or git bash).
In Windows simply use type .git/config instead of cat .git/config of course on plain command line..
W
Wayne Walker

Another method (thanks osse), if you just want to know whether or not it exists:

if git rev-parse @{u} > /dev/null 2>&1
then
  printf "has an upstream\n"
else
  printf "has no upstream\n"
fi

What language? This looks like a Linux shell script but gives no other information or context.
U
Undo
git branch -r -vv

will list all branches including remote.


A
Ahmed Ashour

You can try this :

git remote show origin | grep "branch_name"

branch_name needs to be replaced with your branch


What happens if your branch name also matches other branches? What happens your branch name matches some other text in the output of git remote show origin - if it's called merges or configure?
didn't get u. do you mean multiple branches having same names
Examples of "matches other branches": current branch is "foo" but there is also "foobar" that grep will match; current branch is "v3.4" but . in regexp means any character so will also match "v314"...
j
joseluisq

Lists both local and remote branches:

$ git branch -ra

Output:

  feature/feature1
  feature/feature2
  hotfix/hotfix1
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/develop
  remotes/origin/master

J
Jeremy Thomerson

If you want to find the upstream for any branch (as opposed to just the one you are on), here is a slight modification to @cdunn2001's answer:

git rev-parse --abbrev-ref --symbolic-full-name YOUR_LOCAL_BRANCH_NAME@{upstream}

That will give you the remote branch name for the local branch named YOUR_LOCAL_BRANCH_NAME.


git rev-parse --abbrev-ref --symbolic-full-name HEAD@{upstream} Did it for me :)
T
Tom Hale

Improving on this answer, I came up with these .gitconfig aliases:

branch-name = "symbolic-ref --short HEAD"
branch-remote-fetch = !"branch=$(git branch-name) && git config branch.\"$branch\".remote || echo origin #"
branch-remote-push  = !"branch=$(git branch-name) && git config branch.\"$branch\".pushRemote || git config remote.pushDefault || git branch-remote-fetch #"
branch-url-fetch = !"remote=$(git branch-remote-fetch) && git remote get-url        \"$remote\" #"  # cognizant of insteadOf
branch-url-push  = !"remote=$(git branch-remote-push ) && git remote get-url --push \"$remote\" #"  # cognizant of pushInsteadOf

which language is that?
@Dan Farrell: shell. Aliases starting with a ! use /bin/sh. The double quotes are quoted for git's config file.
E
Erik Aronesty

Having tried all of the solutions here, I realized none of them were good in all situations:

works on local branches

works on detached branches

works under CI

This command gets all names:

git branch -a --contains HEAD --list --format='%(refname:short)'

For my application, I had to filter out the HEAD & master refs, prefer remote refs, and strip off the word 'origin/'. and then if that wasn't found, use the first non HEAD ref that didn't have a / or a ( in it.


O
Olivier Refalo

I use this alias

git config --global alias.track '!sh -c "
if [ \$# -eq 2 ]
 then
   echo \"Setting tracking for branch \" \$1 \" -> \" \$2;
   git branch --set-upstream \$1 \$2;
 else
   git for-each-ref --format=\"local: %(refname:short) <--sync--> remote: %(upstream:short)\" refs/heads && echo --URLs && git remote -v;
fi  
" -'

then

git track

note that the script can also be used to setup tracking.

More great aliases at https://github.com/orefalo/bash-profiles


N
Nagaraja G Devadiga

Following command will remote origin current fork is referring to

git remote -v

For adding a remote path,

git remote add origin path_name


here you are not finding a remote path - you are adding
P
Peter Mortensen

If you are using Gradle,

def gitHash = new ByteArrayOutputStream()
    project.exec {
        commandLine 'git', 'rev-parse', '--short', 'HEAD'
        standardOutput = gitHash
    }

def gitBranch = new ByteArrayOutputStream()
    project.exec {
        def gitCmd = "git symbolic-ref --short -q HEAD || git branch -rq --contains "+getGitHash()+" | sed -e '2,\$d'  -e 's/\\(.*\\)\\/\\(.*\\)\$/\\2/' || echo 'master'"
        commandLine "bash", "-c", "${gitCmd}"
        standardOutput = gitBranch
    }

F
Fred Yang
git branch -vv | grep 'hardcode-branch-name'
# "git rev-parse --abbrev-ref head" will get your current branch name
# $(git rev-parse --abbrev-ref head) save it as string
#  find the tracking branch by grep filtering the current branch 
git branch -vv | grep $(git rev-parse --abbrev-ref head)

A good answer will always include an explanation why this would solve the issue, so that the OP and any future readers can learn from it.
P
PhillipMcCubbin

Display only current branch info without using grep:

git branch -vv --contains

This is short for:

git branch -vv --contains HEAD

and if your current HEAD's commit id is in other branches, those branches will display also.


N
Nathan Musoke

I use EasyGit (a.k.a. "eg") as a super lightweight wrapper on top of (or along side of) Git. EasyGit has an "info" subcommand that gives you all kinds of super useful information, including the current branches remote tracking branch. Here's an example (where the current branch name is "foo"):

pknotz@s883422: (foo) ~/workspace/bd
$ eg info
Total commits:      175
Local repository: .git
Named remote repositories: (name -> location)
  origin -> git://sahp7577/home/pknotz/bd.git
Current branch: foo
  Cryptographic checksum (sha1sum): bd248d1de7d759eb48e8b5ff3bfb3bb0eca4c5bf
  Default pull/push repository: origin
  Default pull/push options:
    branch.foo.remote = origin
    branch.foo.merge = refs/heads/aal_devel_1
  Number of contributors:        3
  Number of files:       28
  Number of directories:       20
  Biggest file size, in bytes: 32473 (pygooglechart-0.2.0/COPYING)
  Commits:       62