Get Git Default Branch from the Command Line (Powershell or Bash/Zsh)
Tags: git, github, programming, productivity
Published: 2021-01-29 12:40:42

On occasion, one needs to know the default branch for a given Git repo. Below I have compiled methods that fit a variety of use cases, and cover specific platforms (Github and Gitlab) as well as methods that work universally regardless of remote platform.

## Github API method

Given a repo `username/reponame`, the following script will work in Bash, Dash/Ash, or Zsh, provided you have the `wget` tool, and `sed`:

```sh
wget -q -O - "https://api.github.com/repos/username/reponame" | sed -nE 's/^\s+"default_branch": "([^"]+).+$/\1/p'
```

If you have `jq` it is even simpler:

```sh
wget -q -O - "https://api.github.com/repos/username/reponame" | jq -r '.default_branch'
```

Or for those who prefer `curl`:

```sh
curl -s "https://api.github.com/repos/username/reponame" | jq -r '.default_branch'
```

This is pretty easy in Powershell, as well:

```powershell
iwr -useb https://api.github.com/repos/username/reponame | ConvertFrom-Json | select -exp default_branch
```

In summary, we first query information about the given repo, then parse the JSON that is returned, extracting the value of the `default_branch` key.

Is this something you might use repeatedly? Consider building a function and placing the following in your shell config (such as `.bashrc`):

```sh
defbranch () {
  REPO=$1
  wget -q -O - "https://api.github.com/repos/$REPO" | sed -nE 's/^\s+"default_branch": "([^"]+).+$/\1/p'
}
```

Feel free to [use this gist](https://gist.github.com/bowmanjd/d72e2e89996087f71ffe3e9777dea5a2/)

Or, for Windows Powershell, place the following in your `Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`:

```powershell
function defbranch {
  Param ([string]$repo)
  iwr -useb https://api.github.com/repos/$repo | ConvertFrom-Json | select -exp default_branch
}
```

Feel free to [use this gist](https://gist.github.com/bowmanjd/08ccc1af6419d3388aa919aee3497e06)

## Similar functionality on Gitlab

The above is specific to Github, because it is specifically a Github setting. In Github, even an empty repo can have a default branch that is different than `master`.

Gitlab, another popular "social coding" service, has different but similar functionality. A populated repo can have a default branch. An empty one will not.

Here is an example function that uses the Gitlab API ([see gist](https://gist.github.com/bowmanjd/33c34f105302288e667d3105efea297a)):

```sh
gldefbranch () {
  REPO=$(echo $1 | sed "s/\//%2F/g")
  BRANCH=$(wget -q -O - "https://gitlab.com/api/v4/projects/$REPO" | sed -nE 's/.*"default_branch":"([^"]+).*/\1/p')
  [ "$BRANCH" == null ] && echo master || echo $BRANCH
}
```

and the Powershell equivalent:

```powershell
function gldefbranch {
  Param ([string]$repo)
  $repo = $repo.replace("/","%2F")
  $branch = (iwr -useb "https://gitlab.com/api/v4/projects/$repo" | ConvertFrom-Json | select -exp default_branch)
  if ($branch) {
    echo $branch
  } else {
    echo "master"
  }
}
```

## A better, universal approach if repo is non-empty

My original intent was to read a Github setting on a repo, new or old, empty or not. However, if desiring to simply get the default branch on an existing repo, an API call is unnecessary. We can use `git ls-remote`.

Thanks to [u/Cyberbeni in this Reddit discussion](https://www.reddit.com/r/github/comments/l7rn3j/get_github_default_branch_from_the_command_line/) for these suggestions.

To query the default branch on a remote repository, try this, with your repository URL assigned to or substituted for `$REPO_URL`:

```sh
git ls-remote --symref "$REPO_URL" HEAD | sed -nE 's|^ref: refs/heads/(\S+)\s+HEAD|\1|p'
```

Or Powershell equivalent:

```powershell
"$(git ls-remote --symref 'https://gitlab.com/bowmanjd/dotfiles1.git' HEAD)" -replace '.*?^ref: refs/heads/(\S+).+','$1'
```

## Get local origin/HEAD reference if available

If the repo was downloaded with `git clone`, then `origin/HEAD` is set automatically. In such cases, the following should work quickly, without needing to query the remote:

```sh
git symbolic-ref refs/remotes/origin/HEAD | cut -d '/' -f4
```

In Powershell:

```powershell
(git symbolic-ref refs/remotes/origin/HEAD) -split '/' | select -Last 1
```

Please note the above is unreliable, as it is easily possible to work locally without `origin/HEAD` being set.

Again, thanks to [u/Cyberbeni for the tip on Reddit](https://www.reddit.com/r/github/comments/l7rn3j/get_github_default_branch_from_the_command_line/).

## Get locally-set Git preference

Of course, if you just want to know the current user's preferred default branch, the following will yield the results, or blank if none has been set up:

```sh
git config init.defaultBranch
```

One can set this value to, for instance, `main` with something like

```sh
git config --global init.defaultBranch main
```

Happy scripting!