Summary
In the agent job, the built-in Checkout PR branch step (checkout_pr_branch.cjs) re-fetches the PR head branch with git fetch origin <head-ref> --depth=2. Running a --depth fetch against an already-complete clone writes .git/shallow and grafts history, silently undoing an explicit checkout: fetch-depth: 0.
create_pull_request then generates its patch in mode=full via git merge-base -- origin/<default-branch> <pinned-sha>. Across the graft there is no reachable common ancestor, so git exits 1 and the tool fails, deterministically, on every retry:
Fetching branch: <head-ref> from origin (depth: 2 for 1 PR commit(s))
/usr/bin/git fetch origin <head-ref> --depth=2
...
[generate_git_patch] Starting patch generation: mode=full, branch=docs/1737, defaultBranch=<default>
[generate_git_patch] Strategy 1 (full): Computing merge-base with <default>
[debug] Executing git command: git merge-base -- origin/<default> <sha>
[error] Git command failed: git merge-base -- origin/<default> <sha>
[error] Exit status: 1
[generate_git_patch] Strategy 1: Branch 'docs/1737' does not exist locally - ERR_SYSTEM: Git command failed with status 1
Version
gh-aw v0.84.3, engine copilot (CLI 1.0.77), awf 0.27.43.
Reproduction
git init up && cd up
for i in 1 2 3 4 5; do echo $i > f$i; git add .; git commit -m "c$i"; done
git branch -M develop && git checkout -b feature
for i in 6 7; do echo $i > f$i; git add .; git commit -m "c$i"; done
cd .. && git clone --no-single-branch up clone && cd clone
git fetch origin '+refs/heads/*:refs/remotes/origin/*' # complete clone, as fetch-depth: 0 gives
git merge-base origin/develop origin/feature # OK
git fetch origin feature --depth=2 # what checkout_pr_branch.cjs does
git checkout feature && git checkout -b docs/1 && echo x > d && git add . && git commit -m docs
ls .git/shallow # now exists
git merge-base origin/develop HEAD; echo "exit=$?" # exit=1 <-- ERR_SYSTEM
rm .git/shallow
git merge-base origin/develop HEAD # OK again, no network needed
Why this is hard to recover from
Three things compound:
- The workflow asked for
fetch-depth: 0 and the Checkout repository step honoured it. A later built-in step then re-shallows the repo, so the config is quietly overridden.
- The generated prompt still tells the agent
[full history, all branches available as remote-tracking refs], which is no longer true at agent time.
- The agent cannot fix it. gh-aw removes git credentials before the agent runs and its own context block lists "Deepening a shallow clone (
git fetch --unshallow)" as unsupported in private repos. So the agent burns turns retrying, then gives up via report_incomplete.
The error text also misleads: details says "No commits were found to create a pull request. Make sure you have committed your changes using git add and git commit before calling create_pull_request." The commit did exist and was valid; only the merge-base failed. That sends the agent down a "clean the tree and retry" path that cannot succeed.
Suggested fixes
Any one of these would do:
- Skip the
--depth=2 fetch when the repo is not already shallow (test -f .git/shallow), or when checkout.fetch-depth is 0. The needed objects are already present in that case.
- If the shallow fetch is kept, drop the graft afterwards. When the clone was complete beforehand,
rm .git/shallow is sufficient and needs no network.
- Fall back in
generate_git_patch when merge-base fails, for example diff against the PR base ref or the branch's own first commit, rather than returning ERR_SYSTEM.
- Distinguish "no commits" from "merge-base unreachable" in the error
details, and mention .git/shallow when it is present. It would have saved the agent several turns.
Separately: mode=full computes the merge-base against the repository default branch even when create_pull_request is called with an explicit base (here a non-default branch, permitted via allowed-base-branches). Diffing against the requested base seems more correct, and would shrink the patch on long-lived branches.
Workaround
pre-agent-steps runs after the PR checkout and before credential cleanup, so this restores things without network access:
pre-agent-steps:
- name: Drop the shallow graft left by the PR-branch checkout
env:
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
run: |
if [ ! -f .git/shallow ]; then
echo "Repository is not shallow, nothing to do."
exit 0
fi
rm .git/shallow
git merge-base HEAD "origin/${DEFAULT_BRANCH}" > /dev/null
Summary
In the
agentjob, the built-in Checkout PR branch step (checkout_pr_branch.cjs) re-fetches the PR head branch withgit fetch origin <head-ref> --depth=2. Running a--depthfetch against an already-complete clone writes.git/shallowand grafts history, silently undoing an explicitcheckout: fetch-depth: 0.create_pull_requestthen generates its patch inmode=fullviagit merge-base -- origin/<default-branch> <pinned-sha>. Across the graft there is no reachable common ancestor, so git exits 1 and the tool fails, deterministically, on every retry:Version
gh-aw
v0.84.3, enginecopilot(CLI 1.0.77),awf0.27.43.Reproduction
Why this is hard to recover from
Three things compound:
fetch-depth: 0and theCheckout repositorystep honoured it. A later built-in step then re-shallows the repo, so the config is quietly overridden.[full history, all branches available as remote-tracking refs], which is no longer true at agent time.git fetch --unshallow)" as unsupported in private repos. So the agent burns turns retrying, then gives up viareport_incomplete.The error text also misleads:
detailssays "No commits were found to create a pull request. Make sure you have committed your changes using git add and git commit before calling create_pull_request." The commit did exist and was valid; only the merge-base failed. That sends the agent down a "clean the tree and retry" path that cannot succeed.Suggested fixes
Any one of these would do:
--depth=2fetch when the repo is not already shallow (test -f .git/shallow), or whencheckout.fetch-depthis 0. The needed objects are already present in that case.rm .git/shallowis sufficient and needs no network.generate_git_patchwhenmerge-basefails, for example diff against the PR base ref or the branch's own first commit, rather than returningERR_SYSTEM.details, and mention.git/shallowwhen it is present. It would have saved the agent several turns.Separately:
mode=fullcomputes the merge-base against the repository default branch even whencreate_pull_requestis called with an explicitbase(here a non-default branch, permitted viaallowed-base-branches). Diffing against the requested base seems more correct, and would shrink the patch on long-lived branches.Workaround
pre-agent-stepsruns after the PR checkout and before credential cleanup, so this restores things without network access: