MainBranchName returns the repository main branch name, preferring origin/HEAD, then common local branch names. In case of errors, return `main`.
(ctx context.Context)
| 103 | // MainBranchName returns the repository main branch name, preferring origin/HEAD, |
| 104 | // then common local branch names. In case of errors, return `main`. |
| 105 | func MainBranchName(ctx context.Context) string { |
| 106 | repo, err := git.PlainOpen(".") |
| 107 | if err != nil { |
| 108 | return "main" |
| 109 | } |
| 110 | |
| 111 | // Try to resolve the locally cached `origin/HEAD` |
| 112 | localOriginHEAD, err := repo.Reference(plumbing.ReferenceName("refs/remotes/origin/HEAD"), false) |
| 113 | if err == nil && localOriginHEAD.Type() == plumbing.SymbolicReference { |
| 114 | target := strings.TrimPrefix(localOriginHEAD.Target().Short(), "origin/") |
| 115 | if target != "" { |
| 116 | return target |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | // Try the usual main branch names |
| 121 | for _, name := range []string{"main", "master"} { |
| 122 | _, err := repo.Reference(plumbing.NewBranchReferenceName(name), true) |
| 123 | if err == nil { |
| 124 | return name |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | // Try to resolve `origin/HEAD` |
| 129 | remoteOrigin, err := repo.Remote("origin") |
| 130 | if err == nil { |
| 131 | references, _ := remoteOrigin.ListContext(ctx, &git.ListOptions{}) |
| 132 | // Search through the list of references in that remote for a symbolic reference named HEAD; |
| 133 | // Its target should be the default branch name. |
| 134 | for _, reference := range references { |
| 135 | if reference.Name() == "HEAD" && reference.Type() == plumbing.SymbolicReference { |
| 136 | return reference.Target().Short() |
| 137 | } |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | return "main" |
| 142 | } |