feat: add local branch checks to PR picker and integrate refresh

Enable optimistic local-branch checks for PR heads to disable non-existent branches
Show IntegrateCommitsSection only when upstream tracking is origin-based or applicable
This commit is contained in:
Bohdan Triapitsyn
2026-01-29 01:11:45 +02:00
parent a78ad90d78
commit 9064e8e73f
3 changed files with 192 additions and 31 deletions
+11 -1
View File
@@ -260,6 +260,7 @@ export const GitView: React.FC = () => {
);
const [hasUserAdjustedSelection, setHasUserAdjustedSelection] = React.useState(false);
const [revertingPaths, setRevertingPaths] = React.useState<Set<string>>(new Set());
const [integrateRefreshKey, setIntegrateRefreshKey] = React.useState(0);
const [isGeneratingMessage, setIsGeneratingMessage] = React.useState(false);
const [generatedHighlights, setGeneratedHighlights] = React.useState<string[]>(
initialSnapshot?.generatedHighlights ?? []
@@ -267,6 +268,13 @@ export const GitView: React.FC = () => {
const repoRootForIntegrate = worktreeMetadata?.projectDirectory || null;
const sourceBranchForIntegrate = status?.current || null;
const shouldShowIntegrateCommits = React.useMemo(() => {
// For PR worktrees from forks we set upstream to a non-origin remote (e.g. pr-<owner>-<repo>).
// Re-integrate commits is intended for local scratch branches -> base branch, not fork PR branches.
const tracking = status?.tracking;
if (!tracking) return true;
return tracking.startsWith('origin/');
}, [status?.tracking]);
const defaultTargetBranch = React.useMemo(() => {
const fromMeta = worktreeMetadata?.createdFromBranch;
if (typeof fromMeta === 'string' && fromMeta.trim().length > 0) {
@@ -602,6 +610,7 @@ export const GitView: React.FC = () => {
}
await refreshLog();
setIntegrateRefreshKey((v) => v + 1);
} catch (err) {
const message = err instanceof Error ? err.message : 'Failed to create commit';
toast.error(message);
@@ -1048,13 +1057,14 @@ export const GitView: React.FC = () => {
)}
</div>
{worktreeMetadata && repoRootForIntegrate && sourceBranchForIntegrate ? (
{worktreeMetadata && repoRootForIntegrate && sourceBranchForIntegrate && shouldShowIntegrateCommits ? (
<IntegrateCommitsSection
repoRoot={repoRootForIntegrate}
sourceBranch={sourceBranchForIntegrate}
worktreeMetadata={worktreeMetadata}
localBranches={localBranches}
defaultTargetBranch={defaultTargetBranch}
refreshKey={integrateRefreshKey}
onRefresh={() => {
if (!currentDirectory) return;
fetchStatus(currentDirectory, git);
@@ -51,6 +51,7 @@ export const IntegrateCommitsSection: React.FC<{
worktreeMetadata: WorktreeMetadata;
localBranches: string[];
defaultTargetBranch: string;
refreshKey?: number;
onRefresh?: () => void;
}> = ({
repoRoot,
@@ -58,6 +59,7 @@ export const IntegrateCommitsSection: React.FC<{
worktreeMetadata,
localBranches,
defaultTargetBranch,
refreshKey,
onRefresh,
}) => {
const currentSessionId = useSessionStore((s) => s.currentSessionId);
@@ -156,7 +158,7 @@ export const IntegrateCommitsSection: React.FC<{
return () => {
cancelled = true;
};
}, [isEligible, repoRoot, sourceBranch, targetBranch]);
}, [isEligible, repoRoot, sourceBranch, targetBranch, refreshKey]);
const persistTarget = React.useCallback(
(branch: string) => {