git: Enable git stash in git panel (#32821)

Related discussion #31484

Release Notes:

- Added a menu entry on the git panel to git stash and git pop stash. 

Preview: 


![Screenshot-2025-06-17_08:26:36](https://github.com/user-attachments/assets/d3699ba4-511f-4c7b-a7cc-00a295d01f64)

---------

Co-authored-by: Cole Miller <cole@zed.dev>
This commit is contained in:
Alvaro Parker 2025-07-25 19:15:54 -04:00 committed by GitHub
parent 4d00d07df1
commit 07252c3309
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 290 additions and 2 deletions

View file

@ -55,6 +55,10 @@ actions!(
StageAll,
/// Unstages all changes in the repository.
UnstageAll,
/// Stashes all changes in the repository, including untracked files.
StashAll,
/// Pops the most recent stash.
StashPop,
/// Restores all tracked files to their last committed state.
RestoreTrackedFiles,
/// Moves all untracked files to trash.

View file

@ -395,6 +395,14 @@ pub trait GitRepository: Send + Sync {
env: Arc<HashMap<String, String>>,
) -> BoxFuture<'_, Result<()>>;
fn stash_paths(
&self,
paths: Vec<RepoPath>,
env: Arc<HashMap<String, String>>,
) -> BoxFuture<Result<()>>;
fn stash_pop(&self, env: Arc<HashMap<String, String>>) -> BoxFuture<Result<()>>;
fn push(
&self,
branch_name: String,
@ -1189,6 +1197,55 @@ impl GitRepository for RealGitRepository {
.boxed()
}
fn stash_paths(
&self,
paths: Vec<RepoPath>,
env: Arc<HashMap<String, String>>,
) -> BoxFuture<Result<()>> {
let working_directory = self.working_directory();
self.executor
.spawn(async move {
let mut cmd = new_smol_command("git");
cmd.current_dir(&working_directory?)
.envs(env.iter())
.args(["stash", "push", "--quiet"])
.arg("--include-untracked");
cmd.args(paths.iter().map(|p| p.as_ref()));
let output = cmd.output().await?;
anyhow::ensure!(
output.status.success(),
"Failed to stash:\n{}",
String::from_utf8_lossy(&output.stderr)
);
Ok(())
})
.boxed()
}
fn stash_pop(&self, env: Arc<HashMap<String, String>>) -> BoxFuture<Result<()>> {
let working_directory = self.working_directory();
self.executor
.spawn(async move {
let mut cmd = new_smol_command("git");
cmd.current_dir(&working_directory?)
.envs(env.iter())
.args(["stash", "pop"]);
let output = cmd.output().await?;
anyhow::ensure!(
output.status.success(),
"Failed to stash pop:\n{}",
String::from_utf8_lossy(&output.stderr)
);
Ok(())
})
.boxed()
}
fn commit(
&self,
message: SharedString,