44

How can it possible to get all names of some remote origin branches?

I started from --remote --list options, but got redundant origin/HEAD -> origin/master message and branches from the another origin.

$> git branch --remote --list
  origin/HEAD -> origin/master
  origin1/develop
  origin1/feature/1
  origin1/feature/2
  origin1/feature/3
  origin1/master
  origin2/develop
  origin2/feature/1
  origin2/feature/2
  origin2/master

Branches of specific origin could be matched with <pattern> option, but redundant message is still there. Actually that pattern is not really correct, because some origin's name could be a substring of another origin name, or even some branch.

$> git branch --remote --list origin1*
  origin1/HEAD -> origin/master
  origin1/develop
  origin1/feature/1
  origin1/feature/2
  origin1/feature/3
  origin1/master

What am I looking for is a list of branch names of origin1, any of them I could use for git checkout command. Something like that:

develop
feature/1
feature/2
feature/3
master

It's important that it should be done without grep, sed, tail or even ghc -e wrappers, only with true git power, because of their unsafeness and variation.

4 Answers4

51

It's important that it should be done without grep, sed, tail or even ghc -e wrappers, only with true git power, because of their unsafeness and variation.

That is only true for git porcelain commands (see "What does the term porcelain mean in Git?")

Use the plumbing command ls-remote, and then you will be able to filter its output.

ls-remote without parameter would still list the remote HEAD:

git@vonc-VirtualBox:~/ce/ce6/.git$ git ls-remote origin
8598d26b4a4bbe416f46087815734d49ba428523    HEAD
8598d26b4a4bbe416f46087815734d49ba428523    refs/heads/master
38325f657380ddef07fa32063c44d7d6c601c012    refs/heads/test_trap

But if you ask only for the heads of said remote:

git@vonc-VirtualBox:~/ce/ce6/.git$ git ls-remote --heads origin
8598d26b4a4bbe416f46087815734d49ba428523    refs/heads/master
38325f657380ddef07fa32063c44d7d6c601c012    refs/heads/test_trap

Final answer:

git@vonc-VirtualBox:~/ce/ce6/.git$ git ls-remote --heads origin  | sed 's?.*refs/heads/??'
master
test_trap

(Yes, it uses sed, but the output of a plumbing command is supposed to be stable enough to be parsed)


See also Git 2.23 (Q3 2019) which documents an example:

git branch -r -l '<remote>/<pattern>'
git for-each-ref 'refs/remotes/<remote>/<pattern>'
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 1
    Looks great. Thanks for exhaustive answer. – ДМИТРИЙ МАЛИКОВ Apr 09 '12 at 17:33
  • 4
    I could've answer this too, but what happend with the "no sed" rule? lol, whatever – KurzedMetal Apr 09 '12 at 19:10
  • 3
    @KurzedMetal true, but I carefully justified the use of `sed` by using only plumbing command, instead of a porcelain command like `git branch`. See for instance http://stackoverflow.com/questions/2978947/how-to-list-all-the-log-for-current-project-in-git/2979124#2979124 or http://stackoverflow.com/questions/2976665/git-changelog-day-by-day/2976776#2976776 – VonC Apr 09 '12 at 21:06
  • 6
    Note that this requires network access (which git branch --remote --list does not) – Johan Lundberg Nov 14 '13 at 19:58
10

An alternate method, after some research into the same problem, is:

git for-each-ref --format='%(refname:strip=2)' refs/remotes/<remote_name>

This will give a sorted list of your local refs for the named remote at the point you last fetched.

You can adjust this for their tags etc.

Philip Oakley
  • 13,333
  • 9
  • 48
  • 71
  • 1
    Also have a look at [this](https://stackoverflow.com/a/30076212/3679900) even more enhanced solution based on `for-each-ref` – y2k-shubham Aug 08 '20 at 03:37
3

The existing answer both uses something explicitly not wanted in the question (sed) and is a remote command.

I found this that avoids both those issues, uses only local git commands and a pipe:

git rev-parse --remotes=origin | git name-rev --name-only --stdin

Update: Not really optimal either, but keeping it if someone knows how to improve it. It lists the full remote including the /remotes/origin prefix if you have no local branch, but only the local name if you have. In addition it seem to skip some refs if there are several pointing to the same SHA1.

Zitrax
  • 19,036
  • 20
  • 88
  • 110
  • For me `git rev-parse --remotes=upstream | git name-rev --name-only --annotate-stdin` prints local branches that do not exist in `upstream`, and does not print, like, half the branches that are present in `git branch -r | grep upstream` output. – Hi-Angel Feb 17 '23 at 08:09
0

Actually that pattern is not really correct, because some origin's name could be a substring of another origin name, or even some branch.

This is partially incorrect, the matching in git branch seems to require a full match, so origin* will not match my_origin/my_branch_name. To avoid matching against origin_two/my_branch_name you can add a trailing slash to your pattern, so you instead match against origin1/*.

As other answerers are saying, I don't see any problem with further parsing the output - so this is the final solution I came up with: using awk to get only the branch name by specifying / as the delimiter and printing the second field.

git branch --remote --list 'remote_name/*' | awk -F '/' '{print $2}'
h33925
  • 38
  • 5