status: Show ahead/behind info for local branches

When viewing `repo status`, it is difficult to distinguish between branches that have active unpushed changes and stale branches that are fully synced. Previously, developers had to run commands like `repo forall -c "git status"` to see their ahead/behind counts.

This change updates Project.PrintWorkTreeStatus to automatically calculate and display the number of commits a branch is ahead and/or behind its upstream tracking branch. We use `git rev-list --left-right --count` to fetch this information natively and efficiently.

If the branch is completely synced with upstream, no extra text is shown.

Added tests for ahead-only, behind-only, diverged, no-tracking, and fully-synced branch states.

Bug: 319412954
Change-Id: I23879b2d472c7a7e11d01b565428a84b1b4f09c1
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/602423
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Brian Gan <brgan@google.com>
Commit-Queue: Brian Gan <brgan@google.com>
This commit is contained in:
Brian Gan
2026-06-29 20:15:53 +00:00
committed by gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 91986011b0
commit e7cac4bca6
4 changed files with 272 additions and 3 deletions
+24 -3
View File
@@ -996,11 +996,32 @@ class Project:
out.nl()
return "DIRTY"
branch = self.CurrentBranch
if branch is None:
branch_name = self.CurrentBranch
if branch_name is None:
out.nobranch("(*** NO BRANCH ***)")
else:
out.branch("branch %s", branch)
branch_obj = self.GetBranch(branch_name)
ahead_behind = ""
try:
local_merge = branch_obj.LocalMerge
if local_merge:
left_right = self.work_git.rev_list(
"--left-right",
"--count",
f"{local_merge}...{R_HEADS}{branch_name}",
)
left, right = left_right[0].split()
behind = int(left)
ahead = int(right)
if ahead and behind:
ahead_behind = f" [ahead {ahead}, behind {behind}]"
elif ahead:
ahead_behind = f" [ahead {ahead}]"
elif behind:
ahead_behind = f" [behind {behind}]"
except GitError:
pass
out.branch("branch %s%s", branch_name, ahead_behind)
out.nl()
if rb: