* Check if the local can fast-forward to origin/ . * Returns true if local is behind or equal to origin (safe to use origin). * Returns false if local is ahead or diverged (preserve local state). * * @param branch - The branch name to compare locally and on origin (e.g. "
(
workspacePath: string,
branch: string,
initLogger: InitLogger,
abortSignal?: AbortSignal
)
| 3022 | * @param branch - The branch name to compare locally and on origin (e.g. "main") |
| 3023 | */ |
| 3024 | private async canFastForwardToOrigin( |
| 3025 | workspacePath: string, |
| 3026 | branch: string, |
| 3027 | initLogger: InitLogger, |
| 3028 | abortSignal?: AbortSignal |
| 3029 | ): Promise<boolean> { |
| 3030 | try { |
| 3031 | // Check if local <branch> is an ancestor of origin/<branch> |
| 3032 | // Exit code 0 = local is ancestor (can fast-forward), non-zero = cannot |
| 3033 | const checkCmd = `git merge-base --is-ancestor ${shescape.quote(branch)} origin/${shescape.quote(branch)}`; |
| 3034 | const checkStream = await this.exec(checkCmd, { |
| 3035 | cwd: workspacePath, |
| 3036 | timeout: 30, |
| 3037 | abortSignal, |
| 3038 | }); |
| 3039 | |
| 3040 | const exitCode = await checkStream.exitCode; |
| 3041 | if (exitCode === 0) { |
| 3042 | return true; // Local is behind or equal to origin |
| 3043 | } |
| 3044 | |
| 3045 | // Local is ahead or diverged - preserve local state |
| 3046 | initLogger.logStderr( |
| 3047 | `Note: Local ${branch} is ahead of or diverged from origin/${branch}, using local state` |
| 3048 | ); |
| 3049 | return false; |
| 3050 | } catch { |
| 3051 | // Error checking - assume we should preserve local state |
| 3052 | return false; |
| 3053 | } |
| 3054 | } |
| 3055 | |
| 3056 | /** |
| 3057 | * Fast-forward merge to latest origin/<trunkBranch> after checkout. |
no test coverage detected