()
| 560 | * Priority: tracking branch > origin/main > origin/staging > origin/master |
| 561 | */ |
| 562 | export async function findRemoteBase(): Promise<string | null> { |
| 563 | // First try: get the tracking branch for the current branch |
| 564 | const { stdout: trackingBranch, code: trackingCode } = await execFileNoThrow( |
| 565 | gitExe(), |
| 566 | ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'], |
| 567 | { preserveOutputOnError: false }, |
| 568 | ) |
| 569 | |
| 570 | if (trackingCode === 0 && trackingBranch.trim()) { |
| 571 | return trackingBranch.trim() |
| 572 | } |
| 573 | |
| 574 | // Second try: check for common default branch names on origin |
| 575 | const { stdout: remoteRefs, code: remoteCode } = await execFileNoThrow( |
| 576 | gitExe(), |
| 577 | ['remote', 'show', 'origin', '--', 'HEAD'], |
| 578 | { preserveOutputOnError: false }, |
| 579 | ) |
| 580 | |
| 581 | if (remoteCode === 0) { |
| 582 | // Parse the default branch from remote show output |
| 583 | const match = remoteRefs.match(/HEAD branch: (\S+)/) |
| 584 | if (match && match[1]) { |
| 585 | return `origin/${match[1]}` |
| 586 | } |
| 587 | } |
| 588 | |
| 589 | // Third try: check which common branches exist |
| 590 | const candidates = ['origin/main', 'origin/staging', 'origin/master'] |
| 591 | for (const candidate of candidates) { |
| 592 | const { code } = await execFileNoThrow( |
| 593 | gitExe(), |
| 594 | ['rev-parse', '--verify', candidate], |
| 595 | { preserveOutputOnError: false }, |
| 596 | ) |
| 597 | if (code === 0) { |
| 598 | return candidate |
| 599 | } |
| 600 | } |
| 601 | |
| 602 | return null |
| 603 | } |
| 604 | |
| 605 | /** |
| 606 | * Check if we're in a shallow clone by looking for <gitDir>/shallow. |
no test coverage detected