You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Cross-repo safe-output PRs fail: patch generated as "create new file" when target file already exists #17969
This issue was AI-generated based on investigation of two failing workflow runs.
Problem
When a workflow's target-repo differs from the source repo (cross-repo safe-output PR), git am fails with exit code 128 because the patch is generated as create mode 100644 (new file) even though the file already exists in the target repo.
Reproduction
This is reproducible in a cross-repo workflow that:
runs in a source repo workspace
reads a file from a different target repo via GitHub MCP
writes/edits that file locally
emits a patch via generate_git_patch.sh
applies the patch in the target repo via safe-outputs
In this configuration, the patch is generated as create mode 100644, but the file already exists in the target repo, so git am fails with exit code 128.
Root Cause
The agent runs in the source repo workspace
It reads a file from the target repo via GitHub MCP, writes it locally, and edits it
generate_git_patch.sh diffs against the source repo's HEAD — since the file doesn't exist in the source repo, the diff is create mode 100644 (a full new-file patch)
The safe_outputs job checks out the target repo (where the file already exists) and runs git am, which correctly rejects creating a file that already exists
Workflow config
safe-outputs:
create-pull-request:
target-repo: 'microsoft/vscode-docs'allowed-repos: ['microsoft/vscode-docs']base-branch: main
Suggested Fix
Either (or both):
Patch generation: When target-repo differs from the source repo, diff against the target repo's tree instead of the source repo's HEAD. This would produce a proper "modify existing file" patch.
Patch application: Use git am --3way (or fall back to git apply --3way) when applying cross-repo patches, which can resolve the create-vs-modify mismatch using the target repo's index.
Reopening — the fix in #18175 (git am --3way) does not resolve this. We confirmed v0.50.1 is deployed and running (the Setup Scripts step loads setup@fad43e3c91a4e1d43e458f68e96574127934e7d1, and the logs show git am --3way being invoked), but the patch still fails.
Why --3way doesn't help here: The patch is create mode 100644 with blob 0000000..abc1234. There's no base blob to do a 3-way merge against — the patch says "this file is brand new" but the file already exists in the target repo. git am --3way falls back to regular apply in this case, which still fails.
Logs from v0.50.1 run:
[command]/usr/bin/git am --3way /tmp/gh-aw/aw-insiders-relnotes-vscode-295080.patch
Patch failed at 0001 Add Insiders release note for microsoft/vscode#295080
##[error]Failed to apply patch: The process '/usr/bin/git' failed with exit code 128
The patch header:
create mode 100644 release-notes/v1_110.md
The core issue remains:generate_git_patch.sh diffs against the source repo's HEAD. When target-repo differs, files that exist in the target repo but not the source repo produce create mode patches. The fix needs to be in patch generation (diff against target repo tree) or in application (detect create mode for existing files and convert to a modify patch before applying).
To clarify why --3way can't help: the root cause is that generate_git_patch.sh diffs against the source repo's git tree (vscode-engineering), not the target repo's tree (vscode-docs). Since the file doesn't exist in the source repo, the diff produces create mode 100644 with base blob 0000000 (null tree). When git am --3way tries to find a common ancestor for a null blob, there's nothing to merge against.
This is a patch generation issue in generate_git_patch.sh, not something fixable via prompting. The script runs automatically after the agent finishes — workflow authors and agents have no control over how the patch is produced. When the workflow config specifies a target-repo different from the source repo, generate_git_patch.sh should diff the agent's workspace against the target repo's tree (e.g. by fetching the target repo's HEAD as the base) so that existing files produce modify diffs instead of create diffs.
Approach: After format-patch generation, when workflow repo ≠ target repo, rewrite "new file" hunks to modify diffs against origin/<base> in the target checkout (fixes the #18175--3way gap).
Local tests:vitest run git_patch_utils.test.cjs — 19/19 pass (includes git am --3way integration test)
Status (2026-10-07; Contributor proposal): On July 11, a contributor shared a fork PR proposing to rewrite cross-repo new-file patches against the target tree and opened tracking issue #44977 after the maintainer requested a separate issue. The next step is to review that proposal and its target-checkout tests upstream; the fork and tracking issue do not establish a merged fix.
Activity
dsyme commentedon Feb 24, 2026
Fixed in #18175 (we hope, testing is hard for theis area)
Yoyokrazy commentedon Feb 24, 2026
Reopening — the fix in #18175 (
git am --3way) does not resolve this. We confirmed v0.50.1 is deployed and running (the Setup Scripts step loadssetup@fad43e3c91a4e1d43e458f68e96574127934e7d1, and the logs showgit am --3waybeing invoked), but the patch still fails.Why
--3waydoesn't help here: The patch iscreate mode 100644with blob0000000..abc1234. There's no base blob to do a 3-way merge against — the patch says "this file is brand new" but the file already exists in the target repo.git am --3wayfalls back to regular apply in this case, which still fails.Logs from v0.50.1 run:
The patch header:
The core issue remains:
generate_git_patch.shdiffs against the source repo's HEAD. Whentarget-repodiffers, files that exist in the target repo but not the source repo producecreate modepatches. The fix needs to be in patch generation (diff against target repo tree) or in application (detectcreate modefor existing files and convert to a modify patch before applying).Yoyokrazy commentedon Feb 24, 2026
To clarify why
--3waycan't help: the root cause is thatgenerate_git_patch.shdiffs against the source repo's git tree (vscode-engineering), not the target repo's tree (vscode-docs). Since the file doesn't exist in the source repo, the diff producescreate mode 100644with base blob0000000(null tree). Whengit am --3waytries to find a common ancestor for a null blob, there's nothing to merge against.This is a patch generation issue in
generate_git_patch.sh, not something fixable via prompting. The script runs automatically after the agent finishes — workflow authors and agents have no control over how the patch is produced. When the workflow config specifies atarget-repodifferent from the source repo,generate_git_patch.shshould diff the agent's workspace against the target repo's tree (e.g. by fetching the target repo's HEAD as the base) so that existing files produce modify diffs instead of create diffs.Tarekchehahde commentedon Jul 11, 2026
Fork PR: Tarekchehahde#10
Upstream compare: main...Tarekchehahde:gh-aw:fix/17969-cross-repo-patch-modify
Approach: After format-patch generation, when workflow repo ≠ target repo, rewrite "new file" hunks to modify diffs against
origin/<base>in the target checkout (fixes the #18175--3waygap).Local tests:
vitest run git_patch_utils.test.cjs— 19/19 pass (includesgit am --3wayintegration test)pelikhan commentedon Jul 11, 2026
@Tarekchehahde open new issues, inline patch description in body - thanks
Tarekchehahde commentedon Jul 11, 2026
@pelikhan Thanks for the feedback.
js-typecheckCI (addedtargetTreeCwdtogenerateGitPatchJSDoc)pelikhan commentedon Jul 11, 2026
@Tarekchehahde i will certainly miss comments but not new issues. Keep it coming.
fix(copilot): rewrite cross-repo create patches as modify diffs
pelikhan commentedon Oct 7, 2026
Status (2026-10-07; Contributor proposal): On July 11, a contributor shared a fork PR proposing to rewrite cross-repo new-file patches against the target tree and opened tracking issue #44977 after the maintainer requested a separate issue. The next step is to review that proposal and its target-checkout tests upstream; the fork and tracking issue do not establish a merged fix.