fix(coding-agent): handle force-pushed git extensions in pi update

Simplified to use @{upstream} instead of branch detection.
Moved changelog entry to [Unreleased].

Closes #961
This commit is contained in:
Mario Zechner 2026-01-26 22:02:17 +01:00
parent bfb21e31f8
commit 0134a2a73d
2 changed files with 6 additions and 48 deletions

View file

@ -2,6 +2,10 @@
## [Unreleased]
### Fixed
- Git extension updates now handle force-pushed remotes gracefully instead of failing ([#961](https://github.com/badlogic/pi-mono/pull/961) by [@aliou](https://github.com/aliou))
## [0.50.0] - 2026-01-26
### New Features
@ -66,7 +70,6 @@ There are multiple SDK breaking changes since v0.49.3. For the quickest migratio
### Fixed
- Git extension updates now handle force-pushed remotes gracefully instead of failing ([#961](https://github.com/badlogic/pi-mono/pull/961) by [@aliou](https://github.com/aliou))
- Extension `setWorkingMessage()` calls in `agent_start` handlers now work correctly; previously the message was silently ignored because the loading animation didn't exist yet ([#935](https://github.com/badlogic/pi-mono/issues/935))
- Fixed package auto-discovery to respect loader rules, config overrides, and force-exclude patterns
- Fixed /reload restoring the correct editor after reload ([#949](https://github.com/badlogic/pi-mono/pull/949) by [@Perlence](https://github.com/Perlence))

View file

@ -939,9 +939,8 @@ export class DefaultPackageManager implements PackageManager {
// Fetch latest from remote (handles force-push by getting new history)
await this.runCommand("git", ["fetch", "--prune", "origin"], { cwd: targetDir });
// Detect default branch and reset to it
const defaultBranch = this.getGitDefaultBranch(targetDir);
await this.runCommand("git", ["reset", "--hard", `origin/${defaultBranch}`], { cwd: targetDir });
// Reset to upstream tracking branch (handles force-push gracefully)
await this.runCommand("git", ["reset", "--hard", "@{upstream}"], { cwd: targetDir });
// Clean untracked files (extensions should be pristine)
await this.runCommand("git", ["clean", "-fdx"], { cwd: targetDir });
@ -952,50 +951,6 @@ export class DefaultPackageManager implements PackageManager {
}
}
/**
* Detect the default branch of a git repository.
* Tries multiple methods with fallbacks.
*/
private getGitDefaultBranch(repoDir: string): string {
// Try symbolic-ref first (fast and reliable)
const symbolicRef = spawnSync("git", ["symbolic-ref", "-q", "refs/remotes/origin/HEAD"], {
cwd: repoDir,
encoding: "utf-8",
});
if (symbolicRef.status === 0 && symbolicRef.stdout) {
// Returns something like "refs/remotes/origin/main"
const match = symbolicRef.stdout.trim().match(/refs\/remotes\/origin\/(.+)/);
if (match) {
return match[1];
}
}
// Try common branch names
for (const branch of ["main", "master"]) {
const showRef = spawnSync("git", ["show-ref", "--verify", `refs/remotes/origin/${branch}`], {
cwd: repoDir,
encoding: "utf-8",
});
if (showRef.status === 0) {
return branch;
}
}
// Last resort: use current branch
const revParse = spawnSync("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
cwd: repoDir,
encoding: "utf-8",
});
if (revParse.status === 0 && revParse.stdout) {
const branch = revParse.stdout.trim();
if (branch && branch !== "HEAD") {
return branch;
}
}
return "main";
}
private async removeGit(source: GitSource, scope: SourceScope): Promise<void> {
const targetDir = this.getGitInstallPath(source, scope);
if (!existsSync(targetDir)) return;