Skip to content

Commit 4d1947a

Browse files
authored
🤖 fix: reduce git lock conflicts in background polling (#915)
## Problem Background git polling runs `git fetch` every 3-60 seconds. Even when there's nothing new to fetch, `git fetch` acquires `maintenance.lock`, which can conflict with: - Manual git commands in terminal - Agent git operations during streaming ## Solution Check if fetch is needed before acquiring any locks: 1. `git ls-remote` → get remote SHA (network only, **no lock**) 2. `git cat-file -e` → is SHA already local? (**no lock**) 3. If local → skip fetch (**no lock needed**) 4. If not local → fetch to get new commits (lock, but only when genuinely needed) ## Why this works ``` # Before: always locks git fetch → maintenance.lock (even if nothing to fetch) # After: only locks when needed ls-remote + cat-file → no lock (common case: SHA already local) git fetch → lock (rare: new remote commits) ``` In practice, IDEs fetch periodically and agent `git pull` operations keep refs current, so the "already local" path triggers most of the time. --- _Generated with `mux`_
1 parent 4d61f89 commit 4d1947a

File tree

1 file changed

+33
-4
lines changed

1 file changed

+33
-4
lines changed

src/common/utils/git/gitStatus.ts

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,17 @@ export function parseGitStatusScriptOutput(output: string): ParsedGitStatusOutpu
8282
}
8383

8484
/**
85-
* Optimized git fetch script with no prompts.
85+
* Smart git fetch script that minimizes lock contention.
8686
*
87-
* Environment variables disable all interactive prompts (keychain, SSH, credentials).
88-
* Git flags optimize for speed - only fetch refs, not objects.
87+
* Uses ls-remote to check if remote has new commits before fetching.
88+
* This avoids locks in the common case where remote SHA is already local
89+
* (e.g., IDE or user already fetched).
90+
*
91+
* Flow:
92+
* 1. ls-remote to get remote SHA (no lock, network only)
93+
* 2. cat-file to check if SHA exists locally (no lock)
94+
* 3. If local: skip fetch (no lock needed)
95+
* 4. If not local: fetch to get new commits (lock, but rare)
8996
*/
9097
export const GIT_FETCH_SCRIPT = `
9198
# Disable ALL prompts
@@ -94,7 +101,29 @@ export GIT_ASKPASS=echo
94101
export SSH_ASKPASS=echo
95102
export GIT_SSH_COMMAND="\${GIT_SSH_COMMAND:-ssh} -o BatchMode=yes -o StrictHostKeyChecking=accept-new"
96103
97-
# Fast fetch with optimization flags
104+
# Get primary branch name
105+
PRIMARY_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')
106+
if [ -z "$PRIMARY_BRANCH" ]; then
107+
PRIMARY_BRANCH=$(git remote show origin 2>/dev/null | grep 'HEAD branch' | cut -d' ' -f5)
108+
fi
109+
if [ -z "$PRIMARY_BRANCH" ]; then
110+
PRIMARY_BRANCH="main"
111+
fi
112+
113+
# Check remote SHA via ls-remote (no lock, network only)
114+
REMOTE_SHA=$(git ls-remote origin "refs/heads/$PRIMARY_BRANCH" 2>/dev/null | cut -f1)
115+
if [ -z "$REMOTE_SHA" ]; then
116+
echo "SKIP: Could not get remote SHA"
117+
exit 0
118+
fi
119+
120+
# Check if SHA exists locally (no lock)
121+
if git cat-file -e "$REMOTE_SHA" 2>/dev/null; then
122+
echo "SKIP: Remote SHA already local"
123+
exit 0
124+
fi
125+
126+
# Remote has new commits we don't have - fetch them
98127
git -c protocol.version=2 \\
99128
-c fetch.negotiationAlgorithm=skipping \\
100129
fetch origin \\

0 commit comments

Comments
 (0)