feat: add git stash management

Add a Stashes dialog with create, apply, pop, and drop actions
Include untracked files automatically when stashing
Show file counts for current changes and stash entries
This commit is contained in:
Bohdan Triapitsyn
2026-05-05 23:39:20 +03:00
parent c80c2b62a8
commit 93267927ff
19 changed files with 754 additions and 109 deletions
@@ -54,6 +54,7 @@ import { getSessionWorktreeRepairActions, getMutationBlockingReasons } from '@/s
import { IntegrateCommitsSection } from './git/IntegrateCommitsSection';
import { GitHeader } from './git/GitHeader';
import { StashesDialog } from './git/StashesDialog';
import { ChangesSection } from './git/ChangesSection';
import { CommitSection } from './git/CommitSection';
import { GitEmptyState } from './git/GitEmptyState';
@@ -429,6 +430,7 @@ export const GitView: React.FC = () => {
const [isGitmojiPickerOpen, setIsGitmojiPickerOpen] = React.useState(false);
const actionPanelScrollRef = React.useRef<HTMLElement | null>(null);
const [syncAction, setSyncAction] = React.useState<SyncAction>(null);
const [isStashesDialogOpen, setIsStashesDialogOpen] = React.useState(false);
const [commitAction, setCommitAction] = React.useState<CommitAction>(null);
const [logMaxCountLocal, setLogMaxCountLocal] = React.useState<number>(25);
const [isSettingIdentity, setIsSettingIdentity] = React.useState(false);
@@ -2069,6 +2071,7 @@ export const GitView: React.FC = () => {
isApplyingIdentity={isSettingIdentity}
isWorktreeMode={!!worktreeMetadata}
onOpenHistory={() => setIsHistoryDialogOpen(true)}
onOpenStashes={() => setIsStashesDialogOpen(true)}
/>
{/* In-progress operation banner */}
@@ -2274,6 +2277,18 @@ export const GitView: React.FC = () => {
</DialogContent>
</Dialog>
<StashesDialog
open={isStashesDialogOpen}
onOpenChange={setIsStashesDialogOpen}
directory={currentDirectory}
hasUncommittedChanges={(status?.files?.length ?? 0) > 0}
uncommittedFileCount={status?.files?.length ?? 0}
onChanged={async () => {
await refreshStatusAndBranches(false);
await refreshLog();
}}
/>
<Dialog open={isGitmojiPickerOpen} onOpenChange={setIsGitmojiPickerOpen}>
<DialogContent className="max-w-md p-0 overflow-hidden">
<DialogHeader className="px-4 pt-4">