From dd4b65996bffd58e0df141333c773ef496ee9e1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Michon?= Date: Tue, 10 Mar 2026 17:00:24 +0100 Subject: [PATCH 1/2] feat(apps/create): detect Git main branch name --- CHANGELOG.md | 1 + apps/create.go | 8 +++++--- utils/git.go | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e15b62e..c50f56b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * fix(error): correctly parse in case of `RequestFailedError` * feat(run): add a `bash` alias for us out there often forgetting the `run` in front * feat(sshkeys): add support for ed25519 keys +* feat(apps/create): detect Git main branch name ## 1.43.3 diff --git a/apps/create.go b/apps/create.go index cc69f352..14c08f0c 100644 --- a/apps/create.go +++ b/apps/create.go @@ -39,10 +39,12 @@ func Create(ctx context.Context, appName, remote, buildpack, projectID string, h } fmt.Printf("App '%s' has been created\n", app.Name) - if _, ok := utils.DetectGit(); ok && utils.AddGitRemote(ctx, app.GitURL, remote) == nil { - fmt.Printf("Git repository detected: remote %s added\n→ 'git push %s master' to deploy your app\n", remote, remote) + mainBranch := utils.MainBranchName(ctx) + _, ok := utils.DetectGit() + if ok && utils.AddGitRemote(ctx, app.GitURL, remote) == nil { + fmt.Printf("Git repository detected: remote %s added\n→ 'git push %s %s' to deploy your app\n", remote, remote, mainBranch) } else { - fmt.Printf("To deploy your application, run these commands in your GIT repository:\n→ git remote add %s %s\n→ git push %s master\n", remote, app.GitURL, remote) + fmt.Printf("To deploy your application, run these commands in your Git repository:\n→ git remote add %s %s\n→ git push %s %s\n", remote, app.GitURL, remote, mainBranch) } return nil } diff --git a/utils/git.go b/utils/git.go index 03a4f52b..1cd7c6b2 100644 --- a/utils/git.go +++ b/utils/git.go @@ -10,6 +10,7 @@ import ( "github.com/go-git/go-git/v5" gitconfig "github.com/go-git/go-git/v5/config" + "github.com/go-git/go-git/v5/plumbing" "github.com/Scalingo/go-scalingo/v10/debug" "github.com/Scalingo/go-utils/errors/v3" @@ -98,3 +99,35 @@ func AddGitRemote(ctx context.Context, url string, name string) error { return nil } + +// MainBranchName returns the repository main branch name, preferring origin/HEAD, +// then common local branch names. In case of errors, return `main`. +func MainBranchName(ctx context.Context) string { + repo, err := git.PlainOpen(".") + if err != nil { + return "main" + } + + // Try to resolve `origin/HEAD` + remoteOrigin, err := repo.Remote("origin") + if err == nil { + references, _ := remoteOrigin.ListContext(ctx, &git.ListOptions{}) + // Search through the list of references in that remote for a symbolic reference named HEAD; + // Its target should be the default branch name. + for _, reference := range references { + if reference.Name() == "HEAD" && reference.Type() == plumbing.SymbolicReference { + return reference.Target().Short() + } + } + } + + // Try the usual main branch names + for _, name := range []string{"main", "master"} { + _, err := repo.Reference(plumbing.NewBranchReferenceName(name), true) + if err == nil { + return name + } + } + + return "main" +} From fa1612a93fb2d13be4da5903f2daf4e9e7f2f2d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Michon?= Date: Wed, 11 Mar 2026 10:01:38 +0100 Subject: [PATCH 2/2] feat(git): resolve `origin` locally --- utils/git.go | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/utils/git.go b/utils/git.go index 1cd7c6b2..2d34dc7a 100644 --- a/utils/git.go +++ b/utils/git.go @@ -108,6 +108,23 @@ func MainBranchName(ctx context.Context) string { return "main" } + // Try to resolve the locally cached `origin/HEAD` + localOriginHEAD, err := repo.Reference(plumbing.ReferenceName("refs/remotes/origin/HEAD"), false) + if err == nil && localOriginHEAD.Type() == plumbing.SymbolicReference { + target := strings.TrimPrefix(localOriginHEAD.Target().Short(), "origin/") + if target != "" { + return target + } + } + + // Try the usual main branch names + for _, name := range []string{"main", "master"} { + _, err := repo.Reference(plumbing.NewBranchReferenceName(name), true) + if err == nil { + return name + } + } + // Try to resolve `origin/HEAD` remoteOrigin, err := repo.Remote("origin") if err == nil { @@ -121,13 +138,5 @@ func MainBranchName(ctx context.Context) string { } } - // Try the usual main branch names - for _, name := range []string{"main", "master"} { - _, err := repo.Reference(plumbing.NewBranchReferenceName(name), true) - if err == nil { - return name - } - } - return "main" }