| 1208 | } |
| 1209 | |
| 1210 | async push(credentialsId?: string | null, force = false) { |
| 1211 | console.log(`[git] Push remote=origin force=${force ? 'true' : 'false'}`); |
| 1212 | |
| 1213 | const response = await git.push({ |
| 1214 | ...this._baseOpts, |
| 1215 | ...gitCallbacks(credentialsId), |
| 1216 | remote: 'origin', |
| 1217 | force, |
| 1218 | }); |
| 1219 | |
| 1220 | if (response.error) { |
| 1221 | console.log('[git] Push rejected', response); |
| 1222 | throw new Error( |
| 1223 | `Push rejected with errors: ${response.error}.\n\nGo to View > Toggle DevTools > Console for more information.`, |
| 1224 | ); |
| 1225 | } |
| 1226 | |
| 1227 | if ('errors' in response && response.errors && Array.isArray(response.errors)) { |
| 1228 | console.log('[git] Push failed with errors', response.errors); |
| 1229 | const errorsString = JSON.stringify(response.errors); |
| 1230 | throw new Error( |
| 1231 | `Push rejected with errors: ${errorsString}.\n\nGo to View > Toggle DevTools > Console for more information.`, |
| 1232 | ); |
| 1233 | } |
| 1234 | |
| 1235 | // NOTE: Response can be ok and have errors so we check this in the end to make sure we throw an error if there are any. |
| 1236 | if (response.ok) { |
| 1237 | console.log('[git] Push successful'); |
| 1238 | // Set up upstream tracking for the current branch. When linking to an empty repo, |
| 1239 | // init() never configures tracking, so a later native git pull via CLI fails with "no tracking information". |
| 1240 | // The push just created origin/<branch>, so this is the point where tracking becomes valid. |
| 1241 | // We only write when tracking is missing - so steady-state pushes do no config writes, an existing |
| 1242 | // user-set upstream is never clobbered, and already-linked repos self-heal on their next push. |
| 1243 | try { |
| 1244 | const branch = await this.getCurrentBranch(); |
| 1245 | const trackingRemote = await this.getBranchTrackingRemote(branch); |
| 1246 | if (!trackingRemote) { |
| 1247 | await git.setConfig({ ...this._baseOpts, path: `branch.${branch}.remote`, value: 'origin' }); |
| 1248 | await git.setConfig({ ...this._baseOpts, path: `branch.${branch}.merge`, value: `refs/heads/${branch}` }); |
| 1249 | } |
| 1250 | } catch (err) { |
| 1251 | console.log('[git] Failed to set upstream tracking after push', err); |
| 1252 | } |
| 1253 | |
| 1254 | return; |
| 1255 | } |
| 1256 | |
| 1257 | throw new Error('Push failed with unknown error. Please try again.'); |
| 1258 | } |
| 1259 | |
| 1260 | async hasUncommittedChanges() { |
| 1261 | const changes = await this.status(); |