From 133932ed74dec9ce49f0603adc4308c4255b3931 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 17 Apr 2025 09:13:02 -0700 Subject: [PATCH] Add support for remote branches to the branch picker (#28978) Release Notes: - Added support for remote branches to the branch picker --------- Co-authored-by: Cole Miller --- crates/git/src/repository.rs | 41 +++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/crates/git/src/repository.rs b/crates/git/src/repository.rs index 7a21866487..793d977e7d 100644 --- a/crates/git/src/repository.rs +++ b/crates/git/src/repository.rs @@ -772,7 +772,13 @@ impl GitRepository for RealGitRepository { "%(contents:subject)", ] .join("%00"); - let args = vec!["for-each-ref", "refs/heads/**/*", "--format", &fields]; + let args = vec![ + "for-each-ref", + "refs/heads/**/*", + "refs/remotes/**/*", + "--format", + &fields, + ]; let working_directory = working_directory?; let output = new_smol_command(&git_binary_path) .current_dir(&working_directory) @@ -823,8 +829,21 @@ impl GitRepository for RealGitRepository { self.executor .spawn(async move { let repo = repo.lock(); - let revision = repo.find_branch(&name, BranchType::Local)?; - let revision = revision.get(); + let branch = if let Ok(branch) = repo.find_branch(&name, BranchType::Local) { + branch + } else if let Ok(revision) = repo.find_branch(&name, BranchType::Remote) { + let (_, branch_name) = + name.split_once("/").context("Unexpected branch format")?; + let revision = revision.get(); + let branch_commit = revision.peel_to_commit()?; + let mut branch = repo.branch(&branch_name, &branch_commit, false)?; + branch.set_upstream(Some(&name))?; + branch + } else { + return Err(anyhow!("Branch not found")); + }; + + let revision = branch.get(); let as_tree = revision.peel_to_tree()?; repo.checkout_tree(as_tree.as_object(), None)?; repo.set_head( @@ -1637,13 +1656,15 @@ fn parse_branch_input(input: &str) -> Result> { let is_current_branch = fields.next().context("no HEAD")? == "*"; let head_sha: SharedString = fields.next().context("no objectname")?.to_string().into(); let parent_sha: SharedString = fields.next().context("no parent")?.to_string().into(); - let ref_name: SharedString = fields - .next() - .context("no refname")? - .strip_prefix("refs/heads/") - .context("unexpected format for refname")? - .to_string() - .into(); + let raw_ref_name = fields.next().context("no refname")?; + let ref_name: SharedString = + if let Some(ref_name) = raw_ref_name.strip_prefix("refs/heads/") { + ref_name.to_string().into() + } else if let Some(ref_name) = raw_ref_name.strip_prefix("refs/remotes/") { + ref_name.to_string().into() + } else { + return Err(anyhow!("unexpected format for refname")); + }; let upstream_name = fields.next().context("no upstream")?.to_string(); let upstream_tracking = parse_upstream_track(fields.next().context("no upstream:track")?)?; let commiterdate = fields.next().context("no committerdate")?.parse::()?;