@@ -23,22 +23,46 @@ PREFERRED_BRANCH="${preferredBranch}"
2323if [ -n "$PREFERRED_BRANCH" ]; then
2424 if git rev-parse --verify "refs/remotes/origin/$PREFERRED_BRANCH" >/dev/null 2>&1; then
2525 PRIMARY_BRANCH="$PREFERRED_BRANCH"
26+ elif [ "$PREFERRED_BRANCH" = "main" ] && git rev-parse --verify "refs/remotes/origin/master" >/dev/null 2>&1; then
27+ PRIMARY_BRANCH="master"
28+ elif [ "$PREFERRED_BRANCH" = "master" ] && git rev-parse --verify "refs/remotes/origin/main" >/dev/null 2>&1; then
29+ PRIMARY_BRANCH="main"
2630 fi
2731fi
2832
2933# Fall back to auto-detection
3034if [ -z "$PRIMARY_BRANCH" ]; then
31- # Method 1: symbolic-ref (fastest)
32- PRIMARY_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')
35+ # symbolic-ref can be stale (e.g., when cloned from a bundle)
36+ SYMREF_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')
37+
38+ # Trust symbolic-ref only if it looks like a default branch name
39+ case "$SYMREF_BRANCH" in
40+ main|master|develop|trunk|default|release)
41+ if git rev-parse --verify "refs/remotes/origin/$SYMREF_BRANCH" >/dev/null 2>&1; then
42+ PRIMARY_BRANCH="$SYMREF_BRANCH"
43+ fi
44+ ;;
45+ esac
46+
47+ # Prefer origin/main or origin/master if present (handles stale origin/HEAD)
48+ if [ -z "$PRIMARY_BRANCH" ]; then
49+ if git rev-parse --verify "refs/remotes/origin/main" >/dev/null 2>&1; then
50+ PRIMARY_BRANCH="main"
51+ elif git rev-parse --verify "refs/remotes/origin/master" >/dev/null 2>&1; then
52+ PRIMARY_BRANCH="master"
53+ fi
54+ fi
3355
34- # Method 2: remote show origin (fallback )
56+ # Fallback: ask origin (may require network )
3557 if [ -z "$PRIMARY_BRANCH" ]; then
3658 PRIMARY_BRANCH=$(git remote show origin 2>/dev/null | grep 'HEAD branch' | cut -d' ' -f5)
3759 fi
3860
39- # Method 3: check for main or master
40- if [ -z "$PRIMARY_BRANCH" ]; then
41- PRIMARY_BRANCH=$(git branch -r 2>/dev/null | grep -E 'origin/(main|master)$' | head -1 | sed 's@^.*origin/@@')
61+ # Last resort: use symbolic-ref if it points to an existing remote-tracking ref
62+ if [ -z "$PRIMARY_BRANCH" ] && [ -n "$SYMREF_BRANCH" ]; then
63+ if git rev-parse --verify "refs/remotes/origin/$SYMREF_BRANCH" >/dev/null 2>&1; then
64+ PRIMARY_BRANCH="$SYMREF_BRANCH"
65+ fi
4266 fi
4367fi
4468
@@ -48,8 +72,10 @@ if [ -z "$PRIMARY_BRANCH" ]; then
4872 exit 1
4973fi
5074
75+ BASE_REF="origin/$PRIMARY_BRANCH"
76+
5177# Get show-branch output for ahead/behind counts
52- SHOW_BRANCH=$(git show-branch --sha1-name HEAD "origin/$PRIMARY_BRANCH " 2>/dev/null)
78+ SHOW_BRANCH=$(git show-branch --sha1-name HEAD "$BASE_REF " 2>/dev/null)
5379
5480if [ $? -ne 0 ]; then
5581 echo "ERROR: git show-branch failed"
@@ -62,7 +88,7 @@ DIRTY_COUNT=$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ')
6288# Compute line deltas (additions/deletions) vs merge-base with origin's primary branch.
6389#
6490# We emit *only* totals to keep output tiny (avoid output truncation in large repos).
65- MERGE_BASE=$(git merge-base HEAD "origin/$PRIMARY_BRANCH " 2>/dev/null || echo "")
91+ MERGE_BASE=$(git merge-base HEAD "$BASE_REF " 2>/dev/null || echo "")
6692
6793# Outgoing: local changes vs merge-base (working tree vs base, includes uncommitted changes)
6894OUTGOING_STATS="0 0"
76102# Incoming: remote primary branch changes vs merge-base
77103INCOMING_STATS="0 0"
78104if [ -n "$MERGE_BASE" ]; then
79- INCOMING_STATS=$(git diff --numstat "$MERGE_BASE" "origin/$PRIMARY_BRANCH " 2>/dev/null | awk '{ if ($1 == "-" || $2 == "-") next; add += $1; del += $2 } END { printf "%d %d", add+0, del+0 }')
105+ INCOMING_STATS=$(git diff --numstat "$MERGE_BASE" "$BASE_REF " 2>/dev/null | awk '{ if ($1 == "-" || $2 == "-") next; add += $1; del += $2 } END { printf "%d %d", add+0, del+0 }')
80106 if [ -z "$INCOMING_STATS" ]; then
81107 INCOMING_STATS="0 0"
82108 fi
@@ -153,10 +179,10 @@ export function parseGitStatusScriptOutput(output: string): ParsedGitStatusOutpu
153179 * (e.g., IDE or user already fetched).
154180 *
155181 * Flow:
156- * 1. ls-remote to get remote SHA (no lock, network only)
157- * 2. cat-file to check if SHA exists locally (no lock)
158- * 3. If local: skip fetch (no lock needed)
159- * 4. If not local : fetch to get new commits (lock, but rare)
182+ * 1. ls-remote --symref origin HEAD to get default branch + SHA (no lock, network only)
183+ * 2. rev-parse to check local remote-tracking SHA (no lock)
184+ * 3. If local already matches : skip fetch (no lock needed)
185+ * 4. If not: fetch updates (lock, but rare)
160186 */
161187export const GIT_FETCH_SCRIPT = `
162188# Disable ALL prompts
@@ -165,19 +191,13 @@ export GIT_ASKPASS=echo
165191export SSH_ASKPASS=echo
166192export GIT_SSH_COMMAND="\${GIT_SSH_COMMAND:-ssh} -o BatchMode=yes -o StrictHostKeyChecking=accept-new"
167193
168- # Get primary branch name
169- PRIMARY_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')
170- if [ -z "$PRIMARY_BRANCH" ]; then
171- PRIMARY_BRANCH=$(git remote show origin 2>/dev/null | grep 'HEAD branch' | cut -d' ' -f5)
172- fi
173- if [ -z "$PRIMARY_BRANCH" ]; then
174- PRIMARY_BRANCH="main"
175- fi
194+ # Determine remote default branch + SHA via ls-remote (no lock, network only)
195+ REMOTE_INFO=$(git ls-remote --symref origin HEAD 2>/dev/null || echo "")
196+ PRIMARY_BRANCH=$(printf '%s\n' "$REMOTE_INFO" | awk '$1=="ref:" && $3=="HEAD" {sub("^refs/heads/","",$2); print $2; exit}')
197+ REMOTE_SHA=$(printf '%s\n' "$REMOTE_INFO" | awk '$2=="HEAD" && $1!="ref:" {print $1; exit}')
176198
177- # Check remote SHA via ls-remote (no lock, network only)
178- REMOTE_SHA=$(git ls-remote origin "refs/heads/$PRIMARY_BRANCH" 2>/dev/null | cut -f1)
179- if [ -z "$REMOTE_SHA" ]; then
180- echo "SKIP: Could not get remote SHA"
199+ if [ -z "$PRIMARY_BRANCH" ] || [ -z "$REMOTE_SHA" ]; then
200+ echo "SKIP: Could not get remote HEAD"
181201 exit 0
182202fi
183203
0 commit comments