fix: branch_rename force-updates target ref instead of delete+recreate #335

Merged
jmiller merged 1 commits from fix/promote-rc-force-update into main 2026-07-04 23:26:40 +00:00
2 changed files with 39 additions and 16 deletions
+3
View File
@@ -12,6 +12,9 @@ BRIEF: Release changelog
# Changelog
## [Unreleased]
### Fixed
- branch_rename.php: force-update the target branch ref in place instead of delete+recreate, so `moko repo:rename-branch` works when the target (e.g. `rc`) is a protected branch that cannot be deleted — previously the delete silently failed and the recreate returned HTTP 409
## [09.42.00] --- 2026-07-04
## [09.42.00] --- 2026-07-04
+36 -16
View File
@@ -64,26 +64,46 @@ class BranchRenameCli extends CliFramework
return 1;
}
// Step 2: Delete target branch if it already exists
// Step 2: Point the target branch at the source commit.
// If the target already exists (e.g. a protected `rc` branch that cannot be
// deleted), force-update its ref in place instead of delete+recreate: deleting a
// protected branch fails, which then makes the recreate return HTTP 409.
$sourceSha = '';
if (isset($check['body']['commit']['id']) && is_string($check['body']['commit']['id'])) {
$sourceSha = $check['body']['commit']['id'];
}
$targetCheck = $this->apiRequest('GET', "{$apiBase}/branches/{$to}", $headers);
if ($targetCheck['code'] === 200) {
echo "Target branch '{$to}' already exists — deleting\n";
echo "Target branch '{$to}' already exists - force-updating to {$from}
";
if (!$this->dryRun) {
$this->apiRequest('DELETE', "{$apiBase}/branches/{$to}", $headers);
if ($sourceSha === '') {
$this->log('ERROR', "Cannot resolve HEAD commit of source '{$from}'");
return 1;
}
$ref = $this->apiRequest('PATCH', "{$apiBase}/git/refs/heads/{$to}", $headers, [
'sha' => $sourceSha,
'force' => true,
]);
if ($ref['code'] < 200 || $ref['code'] >= 300) {
$this->log('ERROR', "Failed to force-update '{$to}': HTTP {$ref['code']} (needs force-push perm)");
$this->log('ERROR', json_encode($ref['body']));
return 1;
}
}
}
// Step 3: Create new branch from source
echo "Creating branch: {$to} (from {$from})\n";
if (!$this->dryRun) {
$create = $this->apiRequest('POST', "{$apiBase}/branches", $headers, [
'new_branch_name' => $to,
'old_branch_name' => $from,
]);
if ($create['code'] < 200 || $create['code'] >= 300) {
$this->log('ERROR', "Failed to create branch '{$to}': HTTP {$create['code']}");
$this->log('ERROR', json_encode($create['body']));
return 1;
} else {
echo "Creating branch: {$to} (from {$from})
";
if (!$this->dryRun) {
$create = $this->apiRequest('POST', "{$apiBase}/branches", $headers, [
'new_branch_name' => $to,
'old_branch_name' => $from,
]);
if ($create['code'] < 200 || $create['code'] >= 300) {
$this->log('ERROR', "Failed to create branch '{$to}': HTTP {$create['code']}");
$this->log('ERROR', json_encode($create['body']));
return 1;
}
}
}