修复:推送窗口的提交列表识别不到在其它分支已远程推送的提交记录

This commit is contained in:
xintaofei
2026-03-29 21:39:16 +08:00
parent bff17f09ff
commit 19890b3cb5

View File

@@ -3794,16 +3794,11 @@ async fn get_unpushed_hashes(
.trim() .trim()
.is_empty(); .is_empty();
// When remote_override is specified, always compare against that remote // Determine the comparison target for unpushed commits.
let rev_list_output = if let Some(target_remote) = remote_override { // We compare against <remote>/<branch> specifically rather than all remote
let remote_arg = format!("--remotes={}", target_remote); // branches, so that commits shared with other remote branches still appear.
crate::process::tokio_command("git") let rev_list_output = if has_upstream && remote_override.is_none() {
.args(["rev-list", &limit_arg, "HEAD", "--not", &remote_arg]) // Fast path: branch has an upstream tracking ref, use it directly
.current_dir(path)
.output()
.await
.map_err(AppCommandError::io)?
} else if has_upstream {
let upstream = String::from_utf8_lossy(&upstream_output.stdout) let upstream = String::from_utf8_lossy(&upstream_output.stdout)
.trim() .trim()
.to_string(); .to_string();
@@ -3815,8 +3810,8 @@ async fn get_unpushed_hashes(
.await .await
.map_err(AppCommandError::io)? .map_err(AppCommandError::io)?
} else { } else {
// No upstream (e.g. newly created branch): fall back to comparing // Either remote_override is specified or no upstream exists.
// against all remote branches to find commits not yet pushed. // Resolve the current branch and the target remote.
let branch_output = crate::process::tokio_command("git") let branch_output = crate::process::tokio_command("git")
.args(["rev-parse", "--abbrev-ref", "HEAD"]) .args(["rev-parse", "--abbrev-ref", "HEAD"])
.current_dir(path) .current_dir(path)
@@ -3833,19 +3828,67 @@ async fn get_unpushed_hashes(
return Ok((None, has_upstream)); return Ok((None, has_upstream));
} }
let remote = if let Some(r) = remote_override {
r.to_string()
} else {
let remote_key = format!("branch.{}.remote", branch); let remote_key = format!("branch.{}.remote", branch);
let remote_output = crate::process::tokio_command("git") let remote_output = crate::process::tokio_command("git")
.args(["config", "--get", &remote_key]) .args(["config", "--get", &remote_key])
.current_dir(path) .current_dir(path)
.output() .output()
.await; .await;
let remote = remote_output remote_output
.ok() .ok()
.filter(|output| output.status.success()) .filter(|output| output.status.success())
.map(|output| String::from_utf8_lossy(&output.stdout).trim().to_string()) .map(|output| String::from_utf8_lossy(&output.stdout).trim().to_string())
.filter(|value| !value.is_empty()) .filter(|value| !value.is_empty())
.unwrap_or_else(|| "origin".to_string()); .unwrap_or_else(|| "origin".to_string())
};
// Try comparing against <remote>/<branch> directly
let remote_branch_ref = format!("refs/remotes/{}/{}", remote, branch);
let verify_output = crate::process::tokio_command("git")
.args(["rev-parse", "--verify", "--quiet", &remote_branch_ref])
.current_dir(path)
.output()
.await;
let remote_branch_exists = verify_output
.is_ok_and(|o| o.status.success());
if remote_branch_exists {
let range = format!("{}/{}..HEAD", remote, branch);
crate::process::tokio_command("git")
.args(["rev-list", &limit_arg, &range])
.current_dir(path)
.output()
.await
.map_err(AppCommandError::io)?
} else {
// Branch doesn't exist on remote yet (new branch).
// Try merge-base with the remote's default branch to show
// the meaningful divergence point.
let remote_head = format!("{}/HEAD", remote);
let mb_output = crate::process::tokio_command("git")
.args(["merge-base", "HEAD", &remote_head])
.current_dir(path)
.output()
.await;
let merge_base = mb_output
.ok()
.filter(|o| o.status.success())
.map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string())
.filter(|s| !s.is_empty());
if let Some(base) = merge_base {
let range = format!("{}..HEAD", base);
crate::process::tokio_command("git")
.args(["rev-list", &limit_arg, &range])
.current_dir(path)
.output()
.await
.map_err(AppCommandError::io)?
} else {
// Last resort: compare against all branches on the remote
let remote_arg = format!("--remotes={}", remote); let remote_arg = format!("--remotes={}", remote);
crate::process::tokio_command("git") crate::process::tokio_command("git")
.args(["rev-list", &limit_arg, "HEAD", "--not", &remote_arg]) .args(["rev-list", &limit_arg, "HEAD", "--not", &remote_arg])
@@ -3853,6 +3896,8 @@ async fn get_unpushed_hashes(
.output() .output()
.await .await
.map_err(AppCommandError::io)? .map_err(AppCommandError::io)?
}
}
}; };
if !rev_list_output.status.success() { if !rev_list_output.status.success() {