0

I work on a bunch of different repos - many of them use master, and many of them use main.

I also have various shell aliases set up for git commands, e.g. gcm for git checkout master.

The problem is that I cannot use these aliases on repos where master doesn't exist. It's obviously not a big deal, because I just need to type out the command manually in that case, but it's slightly annoying.

I am wondering if there's a way I can "alias" branches in git, so when I say git push origin master it can just automatically replace that with main.

SwissCodeMen
  • 4,222
  • 8
  • 24
  • 34
max pleaner
  • 26,189
  • 9
  • 66
  • 118
  • Could you check `git config init.defaultBranch`? It could default to master if empty. – Cole Tierney Aug 04 '22 at 22:49
  • 1
    You can set per-repository aliases, stored in `.git/config`. A little more work to add the correct alias to each repository, but the alias definitions themselves are much simpler. – chepner Aug 04 '22 at 23:00
  • Thank you @chepner this is probably what I would prefer to do – max pleaner Aug 05 '22 at 00:03

3 Answers3

2

You could use git show-ref -q to check if the branch exists:

alias gcm='git show-ref -q --heads main && git checkout main || git checkout master'

You could write a shell function to return the default branch name:

default_branch_name() {
    git show-ref -q --heads main && echo main || echo master
}

alias gcm="git checkout $(default_branch_name)"

That probably simplifies writing additional aliases.


The above assumes only two possible names for the primary branch. You could of course check for more:

default_branch_name() {
    for name in master trunk main; do
        git show-ref -q --heads $name && break
    done

    echo $name
}
Romain Valeri
  • 19,645
  • 3
  • 36
  • 61
larsks
  • 277,717
  • 41
  • 399
  • 399
2

In a repository that has main, but not master, the simplest is to create a branch alias master that points to main:

git symbolic-ref refs/heads/master refs/heads/main

This gives the following list of branches (for example):

$ git branch -a
* main
  master -> main
  side

Now everytime your commands reference master they apply to main. Even when you push master, the actual target is main:

$ git push origin master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 241 bytes | 241.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To ../gitupstream
   f57e131..15c1aad  master -> main
j6t
  • 9,150
  • 1
  • 15
  • 35
  • This seems like the best solution, but I can't get it to work. Even after manually creating `master` on a repo which previously just had `main`, this `symbolic-ref` command doesn't cause the result you show (the `master -> main` mapping). – max pleaner Aug 05 '22 at 18:00
  • What do you mean with "manually create `master`"? There must not be a branch `master`, neither in the local repository nor in the remote. After the `symbolic-ref` command in the local repository, there is just a, let's call it "symbolic link", named `master` that acts like it were the branch `main`. – j6t Aug 06 '22 at 07:06
0

I personally like j6t's answer, but note that when you run git clone, the default branch in the origin repository, after mapping to remote-tracking name, becomes the origin/HEAD symbolic-reference name. So you could use git rev-parse --symbolic-full-name refs/remotes/origin/HEAD to discover whether this is refs/remotes/origin/master, refs/remotes/origin/main, or some other value.

Using that result, you can then choose whether to use the name main or master or some other value.

For repositories where the origin's default branch is, e.g., develop, this means you might resolve to develop. If that's what you want, that's good.

You can combine these ideas: after git clone (perhaps instead of git clone), run a script that reads:

#! /bin/sh
rhead=$(git rev-parse --symbolic-full-name origin/HEAD) || {
    echo "can't figure out default, not creating symbolic name"
    exit 1
}
rhead=${rhead#refs/remotes/origin/}
case "$rhead" in
master) ;; # do nothing
*)
    git symbolic-ref refs/heads/master "refs/heads/$rhead"
    echo "master -> $rhead"
    ;;
esac
exit 0

(note: the above is entirely untested).

torek
  • 448,244
  • 59
  • 642
  • 775
  • This is useful for scripting in repos in bulk, but personally I am just working with a few repos (maybe up to a dozen) so this kind of automation is probably unnecessary. I can see it being helpful for other use cases though. Thanks for putting in the work to write the script. – max pleaner Aug 05 '22 at 17:57