From 92540201ae18e60605c2aa685db22cd168f63bb8 Mon Sep 17 00:00:00 2001
From: Don Syme <dsyme@github.com>
Date: Wed, 10 Sep 2025 18:14:13 +0100
Subject: [PATCH] fix multi commit PRs

---
 .../test-claude-create-pull-request.lock.yml  | 138 ++++++++-----
 .../test-claude-create-pull-request.md        |  58 +++++-
 .../test-claude-push-to-branch.lock.yml       | 192 +++++++++++-------
 .../workflows/test-claude-push-to-branch.md   |  99 +++++----
 .../test-codex-create-pull-request.lock.yml   | 136 ++++++++-----
 .../test-codex-create-pull-request.md         |  60 +++++-
 .../test-codex-push-to-branch.lock.yml        | 164 +++++++++++----
 .../workflows/test-codex-push-to-branch.md    |  63 ++++++
 .../test-safe-outputs-custom-engine.lock.yml  | 133 ++++++------
 pkg/workflow/js/create_pull_request.cjs       |  58 ++----
 pkg/workflow/js/create_pull_request.test.cjs  |  60 ------
 pkg/workflow/js/push_to_branch.cjs            |  87 +++++---
 pkg/workflow/js/push_to_branch.test.cjs       |   3 +-
 13 files changed, 791 insertions(+), 460 deletions(-)

diff --git a/.github/workflows/test-claude-create-pull-request.lock.yml b/.github/workflows/test-claude-create-pull-request.lock.yml
index 7f415dceee9..dcdab7f6d6e 100644
--- a/.github/workflows/test-claude-create-pull-request.lock.yml
+++ b/.github/workflows/test-claude-create-pull-request.lock.yml
@@ -2,7 +2,7 @@
 # To update this file, edit the corresponding .md file and run:
 #   gh aw compile
 
-name: "Test Claude Create Pull Request"
+name: "Test Project"
 on:
   workflow_dispatch: null
 
@@ -11,10 +11,10 @@ permissions: {}
 concurrency:
   group: "gh-aw-${{ github.workflow }}"
 
-run-name: "Test Claude Create Pull Request"
+run-name: "Test Project"
 
 jobs:
-  test-claude-create-pull-request:
+  test-project:
     runs-on: ubuntu-latest
     permissions: read-all
     outputs:
@@ -190,13 +190,63 @@ jobs:
         run: |
           mkdir -p /tmp/aw-prompts
           cat > $GITHUB_AW_PROMPT << 'EOF'
-          Add a file "TEST.md" with content "Hello from Claude"
+          This test workflow specifically tests multi-commit functionality in create-pull-request.
           
-          Add a log file "foo.log" containing the current time. This is just a log file and isn't meant to go in the pull request.
+          **IMPORTANT: Create multiple separate commits for this test case**
           
-          Create a pull request with title "A Pull Request from Claude" and body "World"
+          1. **First commit**: Create a file "README-test.md" with content:
+             ```markdown
+             # Test Project
+             
+             This is a test project created by Claude to test multi-commit pull requests.
+             
+             Created at: {{ current timestamp }}
+             ```
           
-          Add a haiku about GitHub Actions and AI to the PR body.
+          2. **Second commit**: Create a Python script "test-script.py" with:
+             ```python
+             #!/usr/bin/env python3
+             def hello():
+                 print("Hello from Claude multi-commit test!")
+                 
+             if __name__ == "__main__":
+                 hello()
+             ```
+          
+          3. **Third commit**: Create a configuration file "config.json" with:
+             ```json
+             {
+                 "test": true,
+                 "engine": "claude",
+                 "purpose": "multi-commit-test",
+                 "timestamp": "{{ current timestamp }}"
+             }
+             ```
+          
+          4. **Fourth commit**: Create a log file "test.log" containing the current time. This is just a log file.
+          
+          Create a pull request with title "Multi-commit test from Claude" and body:
+          ```markdown
+          # Multi-Commit Test Pull Request
+          
+          This PR was created by Claude to test the multi-commit functionality in agentic workflows.
+          
+          ## Changes Made
+          
+          This PR contains exactly 4 commits:
+          1. Added README-test.md with project description
+          2. Added test-script.py with Python hello function  
+          3. Added config.json with test configuration
+          4. Added test.log with timestamp
+          
+          Each change was made in a separate commit to test that `git am` properly applies all commits from the patch file, not just the first one.
+          
+          ## Haiku about Multi-Commits
+          
+          Git commits in line,  
+          Each change tells its own story—  
+          Patch applies them all.
+          ```
           
           
           ---
@@ -253,7 +303,7 @@ jobs:
               engine_name: "Claude Code",
               model: "",
               version: "",
-              workflow_name: "Test Claude Create Pull Request",
+              workflow_name: "Test Project",
               experimental: false,
               supports_tools_whitelist: true,
               supports_http_transport: true,
@@ -366,13 +416,13 @@ jobs:
         run: |
           # Copy the detailed execution file from Agentic Action if available
           if [ -n "${{ steps.agentic_execution.outputs.execution_file }}" ] && [ -f "${{ steps.agentic_execution.outputs.execution_file }}" ]; then
-            cp ${{ steps.agentic_execution.outputs.execution_file }} /tmp/test-claude-create-pull-request.log
+            cp ${{ steps.agentic_execution.outputs.execution_file }} /tmp/test-project.log
           else
-            echo "No execution file output found from Agentic Action" >> /tmp/test-claude-create-pull-request.log
+            echo "No execution file output found from Agentic Action" >> /tmp/test-project.log
           fi
           
           # Ensure log file exists
-          touch /tmp/test-claude-create-pull-request.log
+          touch /tmp/test-project.log
       - name: Collect agent output
         id: collect_output
         uses: actions/github-script@v7
@@ -1117,7 +1167,7 @@ jobs:
         if: always()
         uses: actions/github-script@v7
         env:
-          AGENT_LOG_FILE: /tmp/test-claude-create-pull-request.log
+          AGENT_LOG_FILE: /tmp/test-project.log
         with:
           script: |
             function main() {
@@ -1434,8 +1484,8 @@ jobs:
         if: always()
         uses: actions/upload-artifact@v4
         with:
-          name: test-claude-create-pull-request.log
-          path: /tmp/test-claude-create-pull-request.log
+          name: test-project.log
+          path: /tmp/test-project.log
           if-no-files-found: warn
       - name: Generate git patch
         if: always()
@@ -1541,7 +1591,7 @@ jobs:
             echo '## Git Patch' >> $GITHUB_STEP_SUMMARY
             echo '' >> $GITHUB_STEP_SUMMARY
             echo '```diff' >> $GITHUB_STEP_SUMMARY
-            head -50 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY
+            head -500 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY
             echo '...' >> $GITHUB_STEP_SUMMARY
             echo '```' >> $GITHUB_STEP_SUMMARY
             echo '' >> $GITHUB_STEP_SUMMARY
@@ -1555,7 +1605,7 @@ jobs:
           if-no-files-found: ignore
 
   create_pull_request:
-    needs: test-claude-create-pull-request
+    needs: test-project
     runs-on: ubuntu-latest
     permissions:
       contents: write
@@ -1586,8 +1636,8 @@ jobs:
         id: create_pull_request
         uses: actions/github-script@v7
         env:
-          GITHUB_AW_AGENT_OUTPUT: ${{ needs.test-claude-create-pull-request.outputs.output }}
-          GITHUB_AW_WORKFLOW_ID: "test-claude-create-pull-request"
+          GITHUB_AW_AGENT_OUTPUT: ${{ needs.test-project.outputs.output }}
+          GITHUB_AW_WORKFLOW_ID: "test-project"
           GITHUB_AW_BASE_BRANCH: ${{ github.ref_name }}
           GITHUB_AW_PR_TITLE_PREFIX: "[claude-test] "
           GITHUB_AW_PR_LABELS: "claude,automation,bot"
@@ -1756,7 +1806,14 @@ jobs:
               }
               console.log("Generated branch name:", branchName);
               console.log("Base branch:", baseBranch);
-              // Create a new branch using git CLI
+              // Create a new branch using git CLI, ensuring it's based on the correct base branch
+              // First, fetch latest changes and checkout the base branch
+              console.log(
+                "Fetching latest changes and checking out base branch:",
+                baseBranch
+              );
+              execSync("git fetch origin", { stdio: "inherit" });
+              execSync(`git checkout ${baseBranch}`, { stdio: "inherit" });
               // Handle branch creation/checkout
               const branchFromJsonl = pullRequestItem.branch
                 ? pullRequestItem.branch.trim()
@@ -1764,15 +1821,15 @@ jobs:
               if (branchFromJsonl) {
                 console.log("Checking if branch from JSONL exists:", branchFromJsonl);
                 console.log(
-                  "Branch does not exist locally, creating new branch:",
+                  "Branch does not exist locally, creating new branch from base:",
                   branchFromJsonl
                 );
                 execSync(`git checkout -b ${branchFromJsonl}`, { stdio: "inherit" });
-                console.log("Using existing/created branch:", branchFromJsonl);
+                console.log("Created new branch from base:", branchFromJsonl);
               } else {
-                // Create and checkout new branch with generated name
+                // Create and checkout new branch with generated name from base branch
                 execSync(`git checkout -b ${branchName}`, { stdio: "inherit" });
-                console.log("Created and checked out new branch:", branchName);
+                console.log("Created and checked out new branch from base:", branchName);
               }
               // Apply the patch using git CLI (skip if empty)
               if (!isEmpty) {
@@ -1780,30 +1837,18 @@ jobs:
                 // Patches are created with git format-patch, so use git am to apply them
                 execSync("git am /tmp/aw.patch", { stdio: "inherit" });
                 console.log("Patch applied successfully");
+                // Push the applied commits to the branch
+                execSync(`git push origin ${branchName}`, { stdio: "inherit" });
+                console.log("Changes pushed to branch");
               } else {
                 console.log("Skipping patch application (empty patch)");
-              }
-              // Commit and push the changes
-              execSync("git add .", { stdio: "inherit" });
-              // Check if there are changes to commit
-              let hasChanges = false;
-              let gitError = null;
-              try {
-                execSync("git diff --cached --exit-code", { stdio: "ignore" });
-                // No changes - exit code 0
-                hasChanges = false;
-              } catch (error) {
-                // Exit code != 0 means there are changes to commit, which is what we want
-                hasChanges = true;
-              }
-              if (!hasChanges) {
-                // No changes to commit - apply if-no-changes configuration
+                // For empty patches, handle if-no-changes configuration
                 const message =
-                  "No changes to commit - noop operation completed successfully";
+                  "No changes to apply - noop operation completed successfully";
                 switch (ifNoChanges) {
                   case "error":
                     throw new Error(
-                      "No changes to commit - failing as configured by if-no-changes: error"
+                      "No changes to apply - failing as configured by if-no-changes: error"
                     );
                   case "ignore":
                     // Silent success - no console output
@@ -1814,17 +1859,6 @@ jobs:
                     return;
                 }
               }
-              if (hasChanges) {
-                execSync(`git commit -m "Add agent output: ${title}"`, {
-                  stdio: "inherit",
-                });
-                execSync(`git push origin ${branchName}`, { stdio: "inherit" });
-                console.log("Changes committed and pushed");
-              } else {
-                // This should not happen due to the early return above, but keeping for safety
-                console.log("No changes to commit");
-                return;
-              }
               // Create the pull request
               const { data: pullRequest } = await github.rest.pulls.create({
                 owner: context.repo.owner,
diff --git a/.github/workflows/test-claude-create-pull-request.md b/.github/workflows/test-claude-create-pull-request.md
index 5bba64bdbaa..ba037109bf0 100644
--- a/.github/workflows/test-claude-create-pull-request.md
+++ b/.github/workflows/test-claude-create-pull-request.md
@@ -11,10 +11,60 @@ safe-outputs:
     labels: [claude, automation, bot]
 ---
 
-Add a file "TEST.md" with content "Hello from Claude"
+This test workflow specifically tests multi-commit functionality in create-pull-request.
 
-Add a log file "foo.log" containing the current time. This is just a log file and isn't meant to go in the pull request.
+**IMPORTANT: Create multiple separate commits for this test case**
 
-Create a pull request with title "A Pull Request from Claude" and body "World"
+1. **First commit**: Create a file "README-test.md" with content:
+   ```markdown
+   # Test Project
+   
+   This is a test project created by Claude to test multi-commit pull requests.
+   
+   Created at: {{ current timestamp }}
+   ```
 
-Add a haiku about GitHub Actions and AI to the PR body.
\ No newline at end of file
+2. **Second commit**: Create a Python script "test-script.py" with:
+   ```python
+   #!/usr/bin/env python3
+   def hello():
+       print("Hello from Claude multi-commit test!")
+       
+   if __name__ == "__main__":
+       hello()
+   ```
+
+3. **Third commit**: Create a configuration file "config.json" with:
+   ```json
+   {
+       "test": true,
+       "engine": "claude",
+       "purpose": "multi-commit-test",
+       "timestamp": "{{ current timestamp }}"
+   }
+   ```
+
+4. **Fourth commit**: Create a log file "test.log" containing the current time. This is just a log file.
+
+Create a pull request with title "Multi-commit test from Claude" and body:
+```markdown
+# Multi-Commit Test Pull Request
+
+This PR was created by Claude to test the multi-commit functionality in agentic workflows.
+
+## Changes Made
+
+This PR contains exactly 4 commits:
+1. Added README-test.md with project description
+2. Added test-script.py with Python hello function  
+3. Added config.json with test configuration
+4. Added test.log with timestamp
+
+Each change was made in a separate commit to test that `git am` properly applies all commits from the patch file, not just the first one.
+
+## Haiku about Multi-Commits
+
+Git commits in line,  
+Each change tells its own story—  
+Patch applies them all.
+```
\ No newline at end of file
diff --git a/.github/workflows/test-claude-push-to-branch.lock.yml b/.github/workflows/test-claude-push-to-branch.lock.yml
index a8510ef91f5..20de129dc2b 100644
--- a/.github/workflows/test-claude-push-to-branch.lock.yml
+++ b/.github/workflows/test-claude-push-to-branch.lock.yml
@@ -2,7 +2,7 @@
 # To update this file, edit the corresponding .md file and run:
 #   gh aw compile
 
-name: "Test Claude Push To Branch"
+name: "Claude Push-to-Branch Multi-Commit Test"
 on:
   issues:
     types: [opened, edited, reopened]
@@ -18,7 +18,7 @@ permissions: {}
 concurrency:
   group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number }}"
 
-run-name: "Test Claude Push To Branch"
+run-name: "Claude Push-to-Branch Multi-Commit Test"
 
 jobs:
   task:
@@ -95,7 +95,7 @@ jobs:
             }
             await main();
 
-  test-claude-push-to-branch:
+  claude-push-to-branch-multi-commit-test:
     needs: task
     if: >
       contains(github.event.issue.body, '/test-claude-push-to-branch') || contains(github.event.comment.body, '/test-claude-push-to-branch') ||
@@ -275,43 +275,68 @@ jobs:
         run: |
           mkdir -p /tmp/aw-prompts
           cat > $GITHUB_AW_PROMPT << 'EOF'
-          Create a new file called "claude-test-file.md" with the following content:
+          This test workflow specifically tests multi-commit functionality in push-to-branch.
           
-          ```markdown
-          # Test Claude Push To Branch
+          **IMPORTANT: Create multiple separate commits for this test case**
           
-          This file was created by the Claude agentic workflow to test the push-to-branch functionality.
+          1. **First commit**: Create a file called "README-claude-test.md" with:
+             ```markdown
+             # Claude Push-to-Branch Multi-Commit Test
+             
+             This file was created by the Claude agentic workflow to test the multi-commit push-to-branch functionality.
+             
+             Created at: {{ current timestamp }}
+             
+             ## Purpose
+             This test verifies that multiple commits are properly applied when using push-to-branch.
+             ```
           
-          Created at: {{ current timestamp }}
+          2. **Second commit**: Create a Python script called "claude-script.py" with:
+             ```python
+             #!/usr/bin/env python3
+             """
+             Multi-commit test script created by Claude agentic workflow
+             """
+             
+             import datetime
+             
+             def main():
+                 print("Hello from Claude agentic workflow!")
+                 print(f"Current time: {datetime.datetime.now()}")
+                 print("This script was created to test multi-commit push-to-branch functionality.")
+                 print("This is commit #2 in the multi-commit test.")
+             
+             if __name__ == "__main__":
+                 main()
+             ```
           
-          ## Test Content
+          3. **Third commit**: Create a configuration file "claude-config.json" with:
+             ```json
+             {
+                 "test_type": "multi-commit-push-to-branch",
+                 "engine": "claude",
+                 "branch": "claude-test-branch",
+                 "commit_number": 3,
+                 "timestamp": "{{ current timestamp }}"
+             }
+             ```
           
-          This is a test file created by Claude to demonstrate:
-          - File creation
-          - Branch pushing
-          - Automated commit generation
+          4. **Fourth commit**: Create a simple test file "claude-test-results.txt" with:
+             ```
+             Claude Multi-Commit Push-to-Branch Test Results
+             ===============================================
+             
+             Test Type: Multi-commit functionality
+             Engine: Claude
+             Branch: claude-test-branch
+             Commits Expected: 4
+             
+             This file represents the final commit in the multi-commit test sequence.
+             If you can see all 4 files (README, Python script, JSON config, and this file),
+             then the multi-commit functionality is working correctly.
+             ```
           
-          The workflow should push this file to the specified branch.
-          ```
-          
-          Also create a simple Python script called "claude-script.py" with:
-          
-          ```python
-          #!/usr/bin/env python3
-          """
-          Test script created by Claude agentic workflow
-          """
-          
-          import datetime
-          
-          def main():
-              print("Hello from Claude agentic workflow!")
-              print(f"Current time: {datetime.datetime.now()}")
-              print("This script was created to test push-to-branch functionality.")
-          
-          if __name__ == "__main__":
-              main()
-          ```
+          The workflow should push all these files to the claude-test-branch in separate commits, testing that `git am` properly applies multiple commits from the patch file.
           
           Create a commit message: "Add test files created by Claude agentic workflow"
           
@@ -371,7 +396,7 @@ jobs:
               engine_name: "Claude Code",
               model: "",
               version: "",
-              workflow_name: "Test Claude Push To Branch",
+              workflow_name: "Claude Push-to-Branch Multi-Commit Test",
               experimental: false,
               supports_tools_whitelist: true,
               supports_http_transport: true,
@@ -484,13 +509,13 @@ jobs:
         run: |
           # Copy the detailed execution file from Agentic Action if available
           if [ -n "${{ steps.agentic_execution.outputs.execution_file }}" ] && [ -f "${{ steps.agentic_execution.outputs.execution_file }}" ]; then
-            cp ${{ steps.agentic_execution.outputs.execution_file }} /tmp/test-claude-push-to-branch.log
+            cp ${{ steps.agentic_execution.outputs.execution_file }} /tmp/claude-push-to-branch-multi-commit-test.log
           else
-            echo "No execution file output found from Agentic Action" >> /tmp/test-claude-push-to-branch.log
+            echo "No execution file output found from Agentic Action" >> /tmp/claude-push-to-branch-multi-commit-test.log
           fi
           
           # Ensure log file exists
-          touch /tmp/test-claude-push-to-branch.log
+          touch /tmp/claude-push-to-branch-multi-commit-test.log
       - name: Collect agent output
         id: collect_output
         uses: actions/github-script@v7
@@ -1235,7 +1260,7 @@ jobs:
         if: always()
         uses: actions/github-script@v7
         env:
-          AGENT_LOG_FILE: /tmp/test-claude-push-to-branch.log
+          AGENT_LOG_FILE: /tmp/claude-push-to-branch-multi-commit-test.log
         with:
           script: |
             function main() {
@@ -1552,8 +1577,8 @@ jobs:
         if: always()
         uses: actions/upload-artifact@v4
         with:
-          name: test-claude-push-to-branch.log
-          path: /tmp/test-claude-push-to-branch.log
+          name: claude-push-to-branch-multi-commit-test.log
+          path: /tmp/claude-push-to-branch-multi-commit-test.log
           if-no-files-found: warn
       - name: Generate git patch
         if: always()
@@ -1660,7 +1685,7 @@ jobs:
             echo '## Git Patch' >> $GITHUB_STEP_SUMMARY
             echo '' >> $GITHUB_STEP_SUMMARY
             echo '```diff' >> $GITHUB_STEP_SUMMARY
-            head -50 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY
+            head -500 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY
             echo '...' >> $GITHUB_STEP_SUMMARY
             echo '```' >> $GITHUB_STEP_SUMMARY
             echo '' >> $GITHUB_STEP_SUMMARY
@@ -1674,7 +1699,7 @@ jobs:
           if-no-files-found: ignore
 
   push_to_branch:
-    needs: test-claude-push-to-branch
+    needs: claude-push-to-branch-multi-commit-test
     if: >
       contains(github.event.issue.body, '/test-claude-push-to-branch') || contains(github.event.comment.body, '/test-claude-push-to-branch') ||
       contains(github.event.pull_request.body, '/test-claude-push-to-branch')
@@ -1707,7 +1732,7 @@ jobs:
         id: push_to_branch
         uses: actions/github-script@v7
         env:
-          GITHUB_AW_AGENT_OUTPUT: ${{ needs.test-claude-push-to-branch.outputs.output }}
+          GITHUB_AW_AGENT_OUTPUT: ${{ needs.claude-push-to-branch-multi-commit-test.outputs.output }}
           GITHUB_AW_PUSH_BRANCH: "claude-test-branch"
           GITHUB_AW_PUSH_TARGET: "*"
           GITHUB_AW_PUSH_IF_NO_CHANGES: "warn"
@@ -1837,12 +1862,48 @@ jobs:
               try {
                 // Try to checkout existing branch first
                 execSync("git fetch origin", { stdio: "inherit" });
-                execSync(`git checkout ${branchName}`, { stdio: "inherit" });
-                console.log("Checked out existing branch:", branchName);
+                // Check if branch exists on origin
+                try {
+                  execSync(`git rev-parse --verify origin/${branchName}`, {
+                    stdio: "pipe",
+                  });
+                  // Branch exists on origin, check it out
+                  execSync(`git checkout -B ${branchName} origin/${branchName}`, {
+                    stdio: "inherit",
+                  });
+                  console.log("Checked out existing branch from origin:", branchName);
+                } catch (originError) {
+                  // Branch doesn't exist on origin, check if it exists locally
+                  try {
+                    execSync(`git rev-parse --verify ${branchName}`, { stdio: "pipe" });
+                    // Branch exists locally, check it out
+                    execSync(`git checkout ${branchName}`, { stdio: "inherit" });
+                    console.log("Checked out existing local branch:", branchName);
+                  } catch (localError) {
+                    // Branch doesn't exist locally or on origin, create it from default branch
+                    console.log(
+                      "Branch does not exist, creating new branch from default branch:",
+                      branchName
+                    );
+                    // Get the default branch name
+                    const defaultBranch = execSync(
+                      "git remote show origin | grep 'HEAD branch' | cut -d' ' -f5",
+                      { encoding: "utf8" }
+                    ).trim();
+                    console.log("Default branch:", defaultBranch);
+                    // Ensure we have the latest default branch
+                    execSync(`git checkout ${defaultBranch}`, { stdio: "inherit" });
+                    execSync(`git pull origin ${defaultBranch}`, { stdio: "inherit" });
+                    // Create new branch from default branch
+                    execSync(`git checkout -b ${branchName}`, { stdio: "inherit" });
+                    console.log("Created new branch from default branch:", branchName);
+                  }
+                }
               } catch (error) {
-                // Branch doesn't exist, create it
-                console.log("Branch does not exist, creating new branch:", branchName);
-                execSync(`git checkout -b ${branchName}`, { stdio: "inherit" });
+                core.setFailed(
+                  `Failed to switch to branch ${branchName}: ${error instanceof Error ? error.message : String(error)}`
+                );
+                return;
               }
               // Apply the patch using git CLI (skip if empty)
               if (!isEmpty) {
@@ -1851,6 +1912,9 @@ jobs:
                   // Patches are created with git format-patch, so use git am to apply them
                   execSync("git am /tmp/aw.patch", { stdio: "inherit" });
                   console.log("Patch applied successfully");
+                  // Push the applied commits to the branch
+                  execSync(`git push origin ${branchName}`, { stdio: "inherit" });
+                  console.log("Changes committed and pushed to branch:", branchName);
                 } catch (error) {
                   core.error(
                     `Failed to apply patch: ${error instanceof Error ? error.message : String(error)}`
@@ -1860,20 +1924,13 @@ jobs:
                 }
               } else {
                 console.log("Skipping patch application (empty patch)");
-              }
-              // Commit and push the changes
-              execSync("git add .", { stdio: "inherit" });
-              // Check if there are changes to commit
-              let hasChanges = false;
-              try {
-                execSync("git diff --cached --exit-code", { stdio: "ignore" });
-                // No changes to commit - apply if-no-changes configuration
+                // Handle if-no-changes configuration for empty patches
                 const message =
-                  "No changes to commit - noop operation completed successfully";
+                  "No changes to apply - noop operation completed successfully";
                 switch (ifNoChanges) {
                   case "error":
                     core.setFailed(
-                      "No changes to commit - failing as configured by if-no-changes: error"
+                      "No changes to apply - failing as configured by if-no-changes: error"
                     );
                     return;
                   case "ignore":
@@ -1884,23 +1941,10 @@ jobs:
                     console.log(message);
                     break;
                 }
-                hasChanges = false;
-              } catch (error) {
-                // Exit code != 0 means there are changes to commit, which is what we want
-                hasChanges = true;
-              }
-              let commitSha;
-              if (hasChanges) {
-                const commitMessage = pushItem.message || "Apply agent changes";
-                execSync(`git commit -m "${commitMessage}"`, { stdio: "inherit" });
-                execSync(`git push origin ${branchName}`, { stdio: "inherit" });
-                console.log("Changes committed and pushed to branch:", branchName);
-                commitSha = execSync("git rev-parse HEAD", { encoding: "utf8" }).trim();
-              } else {
-                // For noop operations, get the current HEAD commit
-                commitSha = execSync("git rev-parse HEAD", { encoding: "utf8" }).trim();
               }
               // Get commit SHA and push URL
+              const commitSha = execSync("git rev-parse HEAD", { encoding: "utf8" }).trim();
+              // Get commit SHA and push URL
               const pushUrl = context.payload.repository
                 ? `${context.payload.repository.html_url}/tree/${branchName}`
                 : `https://github.com/${context.repo.owner}/${context.repo.repo}/tree/${branchName}`;
diff --git a/.github/workflows/test-claude-push-to-branch.md b/.github/workflows/test-claude-push-to-branch.md
index 0b4efea732c..8eeeb97b98e 100644
--- a/.github/workflows/test-claude-push-to-branch.md
+++ b/.github/workflows/test-claude-push-to-branch.md
@@ -12,43 +12,68 @@ safe-outputs:
     target: "*"
 ---
 
-Create a new file called "claude-test-file.md" with the following content:
-
-```markdown
-# Test Claude Push To Branch
-
-This file was created by the Claude agentic workflow to test the push-to-branch functionality.
-
-Created at: {{ current timestamp }}
-
-## Test Content
-
-This is a test file created by Claude to demonstrate:
-- File creation
-- Branch pushing
-- Automated commit generation
-
-The workflow should push this file to the specified branch.
-```
-
-Also create a simple Python script called "claude-script.py" with:
-
-```python
-#!/usr/bin/env python3
-"""
-Test script created by Claude agentic workflow
-"""
-
-import datetime
-
-def main():
-    print("Hello from Claude agentic workflow!")
-    print(f"Current time: {datetime.datetime.now()}")
-    print("This script was created to test push-to-branch functionality.")
-
-if __name__ == "__main__":
-    main()
-```
+This test workflow specifically tests multi-commit functionality in push-to-branch.
+
+**IMPORTANT: Create multiple separate commits for this test case**
+
+1. **First commit**: Create a file called "README-claude-test.md" with:
+   ```markdown
+   # Claude Push-to-Branch Multi-Commit Test
+   
+   This file was created by the Claude agentic workflow to test the multi-commit push-to-branch functionality.
+   
+   Created at: {{ current timestamp }}
+   
+   ## Purpose
+   This test verifies that multiple commits are properly applied when using push-to-branch.
+   ```
+
+2. **Second commit**: Create a Python script called "claude-script.py" with:
+   ```python
+   #!/usr/bin/env python3
+   """
+   Multi-commit test script created by Claude agentic workflow
+   """
+   
+   import datetime
+   
+   def main():
+       print("Hello from Claude agentic workflow!")
+       print(f"Current time: {datetime.datetime.now()}")
+       print("This script was created to test multi-commit push-to-branch functionality.")
+       print("This is commit #2 in the multi-commit test.")
+   
+   if __name__ == "__main__":
+       main()
+   ```
+
+3. **Third commit**: Create a configuration file "claude-config.json" with:
+   ```json
+   {
+       "test_type": "multi-commit-push-to-branch",
+       "engine": "claude",
+       "branch": "claude-test-branch",
+       "commit_number": 3,
+       "timestamp": "{{ current timestamp }}"
+   }
+   ```
+
+4. **Fourth commit**: Create a simple test file "claude-test-results.txt" with:
+   ```
+   Claude Multi-Commit Push-to-Branch Test Results
+   ===============================================
+   
+   Test Type: Multi-commit functionality
+   Engine: Claude
+   Branch: claude-test-branch
+   Commits Expected: 4
+   
+   This file represents the final commit in the multi-commit test sequence.
+   If you can see all 4 files (README, Python script, JSON config, and this file),
+   then the multi-commit functionality is working correctly.
+   ```
+
+The workflow should push all these files to the claude-test-branch in separate commits, testing that `git am` properly applies multiple commits from the patch file.
 
 Create a commit message: "Add test files created by Claude agentic workflow"
 
diff --git a/.github/workflows/test-codex-create-pull-request.lock.yml b/.github/workflows/test-codex-create-pull-request.lock.yml
index cdfb0bc1d50..caab1ec0fa2 100644
--- a/.github/workflows/test-codex-create-pull-request.lock.yml
+++ b/.github/workflows/test-codex-create-pull-request.lock.yml
@@ -2,7 +2,7 @@
 # To update this file, edit the corresponding .md file and run:
 #   gh aw compile
 
-name: "Test Codex Create Pull Request"
+name: "Test Project"
 on:
   workflow_dispatch: null
 
@@ -11,10 +11,10 @@ permissions: {}
 concurrency:
   group: "gh-aw-${{ github.workflow }}"
 
-run-name: "Test Codex Create Pull Request"
+run-name: "Test Project"
 
 jobs:
-  test-codex-create-pull-request:
+  test-project:
     runs-on: ubuntu-latest
     permissions: read-all
     outputs:
@@ -84,13 +84,65 @@ jobs:
         run: |
           mkdir -p /tmp/aw-prompts
           cat > $GITHUB_AW_PROMPT << 'EOF'
-          Add a file "TEST.md" with content "Hello from Codex"
+          This test workflow specifically tests multi-commit functionality in create-pull-request.
           
-          Add a log file "foo.log" containing the current time. This is just a log file and isn't meant to go in the pull request.
+          **IMPORTANT: Create multiple separate commits for this test case**
           
-          Create a pull request with title "A Pull Request from Codex" and body "World"
+          1. **First commit**: Create a file "README-test.md" with content:
+             ```markdown
+             # Test Project
+             
+             This is a test project created by Codex to test multi-commit pull requests.
+             
+             Created at: {{ current timestamp }}
+             ```
           
-          Add a haiku about GitHub Actions and AI to the PR body.
+          2. **Second commit**: Create a JavaScript script "test-script.js" with:
+             ```javascript
+             #!/usr/bin/env node
+             function hello() {
+                 console.log("Hello from Codex multi-commit test!");
+             }
+             
+             if (require.main === module) {
+                 hello();
+             }
+             ```
+          
+          3. **Third commit**: Create a configuration file "config.json" with:
+             ```json
+             {
+                 "test": true,
+                 "engine": "codex",
+                 "purpose": "multi-commit-test",
+                 "timestamp": "{{ current timestamp }}"
+             }
+             ```
+          
+          4. **Fourth commit**: Create a log file "test.log" containing the current time. This is just a log file.
+          
+          Create a pull request with title "Multi-commit test from Codex" and body:
+          ```markdown
+          # Multi-Commit Test Pull Request
+          
+          This PR was created by Codex to test the multi-commit functionality in agentic workflows.
+          
+          ## Changes Made
+          
+          This PR contains exactly 4 commits:
+          1. Added README-test.md with project description
+          2. Added test-script.js with JavaScript hello function
+          3. Added config.json with test configuration
+          4. Added test.log with timestamp
+          
+          Each change was made in a separate commit to test that `git am` properly applies all commits from the patch file, not just the first one.
+          
+          ## Haiku about Multi-Commits
+          
+          Git commits aligned,  
+          Each change builds upon the last—  
+          Patch preserves them all.
+          ```
           
           
           ---
@@ -147,7 +199,7 @@ jobs:
               engine_name: "Codex",
               model: "",
               version: "",
-              workflow_name: "Test Codex Create Pull Request",
+              workflow_name: "Test Project",
               experimental: true,
               supports_tools_whitelist: true,
               supports_http_transport: false,
@@ -186,7 +238,7 @@ jobs:
           # Run codex with log capture - pipefail ensures codex exit code is preserved
           codex exec \
             -c model=o4-mini \
-            --full-auto "$INSTRUCTION" 2>&1 | tee /tmp/test-codex-create-pull-request.log
+            --full-auto "$INSTRUCTION" 2>&1 | tee /tmp/test-project.log
         env:
           GITHUB_AW_PROMPT: /tmp/aw-prompts/prompt.txt
           GITHUB_AW_SAFE_OUTPUTS: ${{ env.GITHUB_AW_SAFE_OUTPUTS }}
@@ -926,7 +978,7 @@ jobs:
         if: always()
         uses: actions/github-script@v7
         env:
-          AGENT_LOG_FILE: /tmp/test-codex-create-pull-request.log
+          AGENT_LOG_FILE: /tmp/test-project.log
         with:
           script: |
             function main() {
@@ -1183,8 +1235,8 @@ jobs:
         if: always()
         uses: actions/upload-artifact@v4
         with:
-          name: test-codex-create-pull-request.log
-          path: /tmp/test-codex-create-pull-request.log
+          name: test-project.log
+          path: /tmp/test-project.log
           if-no-files-found: warn
       - name: Generate git patch
         if: always()
@@ -1290,7 +1342,7 @@ jobs:
             echo '## Git Patch' >> $GITHUB_STEP_SUMMARY
             echo '' >> $GITHUB_STEP_SUMMARY
             echo '```diff' >> $GITHUB_STEP_SUMMARY
-            head -50 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY
+            head -500 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY
             echo '...' >> $GITHUB_STEP_SUMMARY
             echo '```' >> $GITHUB_STEP_SUMMARY
             echo '' >> $GITHUB_STEP_SUMMARY
@@ -1304,7 +1356,7 @@ jobs:
           if-no-files-found: ignore
 
   create_pull_request:
-    needs: test-codex-create-pull-request
+    needs: test-project
     runs-on: ubuntu-latest
     permissions:
       contents: write
@@ -1335,8 +1387,8 @@ jobs:
         id: create_pull_request
         uses: actions/github-script@v7
         env:
-          GITHUB_AW_AGENT_OUTPUT: ${{ needs.test-codex-create-pull-request.outputs.output }}
-          GITHUB_AW_WORKFLOW_ID: "test-codex-create-pull-request"
+          GITHUB_AW_AGENT_OUTPUT: ${{ needs.test-project.outputs.output }}
+          GITHUB_AW_WORKFLOW_ID: "test-project"
           GITHUB_AW_BASE_BRANCH: ${{ github.ref_name }}
           GITHUB_AW_PR_TITLE_PREFIX: "[codex-test] "
           GITHUB_AW_PR_LABELS: "codex,automation,bot"
@@ -1505,7 +1557,14 @@ jobs:
               }
               console.log("Generated branch name:", branchName);
               console.log("Base branch:", baseBranch);
-              // Create a new branch using git CLI
+              // Create a new branch using git CLI, ensuring it's based on the correct base branch
+              // First, fetch latest changes and checkout the base branch
+              console.log(
+                "Fetching latest changes and checking out base branch:",
+                baseBranch
+              );
+              execSync("git fetch origin", { stdio: "inherit" });
+              execSync(`git checkout ${baseBranch}`, { stdio: "inherit" });
               // Handle branch creation/checkout
               const branchFromJsonl = pullRequestItem.branch
                 ? pullRequestItem.branch.trim()
@@ -1513,15 +1572,15 @@ jobs:
               if (branchFromJsonl) {
                 console.log("Checking if branch from JSONL exists:", branchFromJsonl);
                 console.log(
-                  "Branch does not exist locally, creating new branch:",
+                  "Branch does not exist locally, creating new branch from base:",
                   branchFromJsonl
                 );
                 execSync(`git checkout -b ${branchFromJsonl}`, { stdio: "inherit" });
-                console.log("Using existing/created branch:", branchFromJsonl);
+                console.log("Created new branch from base:", branchFromJsonl);
               } else {
-                // Create and checkout new branch with generated name
+                // Create and checkout new branch with generated name from base branch
                 execSync(`git checkout -b ${branchName}`, { stdio: "inherit" });
-                console.log("Created and checked out new branch:", branchName);
+                console.log("Created and checked out new branch from base:", branchName);
               }
               // Apply the patch using git CLI (skip if empty)
               if (!isEmpty) {
@@ -1529,30 +1588,18 @@ jobs:
                 // Patches are created with git format-patch, so use git am to apply them
                 execSync("git am /tmp/aw.patch", { stdio: "inherit" });
                 console.log("Patch applied successfully");
+                // Push the applied commits to the branch
+                execSync(`git push origin ${branchName}`, { stdio: "inherit" });
+                console.log("Changes pushed to branch");
               } else {
                 console.log("Skipping patch application (empty patch)");
-              }
-              // Commit and push the changes
-              execSync("git add .", { stdio: "inherit" });
-              // Check if there are changes to commit
-              let hasChanges = false;
-              let gitError = null;
-              try {
-                execSync("git diff --cached --exit-code", { stdio: "ignore" });
-                // No changes - exit code 0
-                hasChanges = false;
-              } catch (error) {
-                // Exit code != 0 means there are changes to commit, which is what we want
-                hasChanges = true;
-              }
-              if (!hasChanges) {
-                // No changes to commit - apply if-no-changes configuration
+                // For empty patches, handle if-no-changes configuration
                 const message =
-                  "No changes to commit - noop operation completed successfully";
+                  "No changes to apply - noop operation completed successfully";
                 switch (ifNoChanges) {
                   case "error":
                     throw new Error(
-                      "No changes to commit - failing as configured by if-no-changes: error"
+                      "No changes to apply - failing as configured by if-no-changes: error"
                     );
                   case "ignore":
                     // Silent success - no console output
@@ -1563,17 +1610,6 @@ jobs:
                     return;
                 }
               }
-              if (hasChanges) {
-                execSync(`git commit -m "Add agent output: ${title}"`, {
-                  stdio: "inherit",
-                });
-                execSync(`git push origin ${branchName}`, { stdio: "inherit" });
-                console.log("Changes committed and pushed");
-              } else {
-                // This should not happen due to the early return above, but keeping for safety
-                console.log("No changes to commit");
-                return;
-              }
               // Create the pull request
               const { data: pullRequest } = await github.rest.pulls.create({
                 owner: context.repo.owner,
diff --git a/.github/workflows/test-codex-create-pull-request.md b/.github/workflows/test-codex-create-pull-request.md
index b46e9419833..61fe75966d4 100644
--- a/.github/workflows/test-codex-create-pull-request.md
+++ b/.github/workflows/test-codex-create-pull-request.md
@@ -11,10 +11,62 @@ safe-outputs:
     labels: [codex, automation, bot]
 ---
 
-Add a file "TEST.md" with content "Hello from Codex"
+This test workflow specifically tests multi-commit functionality in create-pull-request.
 
-Add a log file "foo.log" containing the current time. This is just a log file and isn't meant to go in the pull request.
+**IMPORTANT: Create multiple separate commits for this test case**
 
-Create a pull request with title "A Pull Request from Codex" and body "World"
+1. **First commit**: Create a file "README-test.md" with content:
+   ```markdown
+   # Test Project
+   
+   This is a test project created by Codex to test multi-commit pull requests.
+   
+   Created at: {{ current timestamp }}
+   ```
 
-Add a haiku about GitHub Actions and AI to the PR body.
\ No newline at end of file
+2. **Second commit**: Create a JavaScript script "test-script.js" with:
+   ```javascript
+   #!/usr/bin/env node
+   function hello() {
+       console.log("Hello from Codex multi-commit test!");
+   }
+   
+   if (require.main === module) {
+       hello();
+   }
+   ```
+
+3. **Third commit**: Create a configuration file "config.json" with:
+   ```json
+   {
+       "test": true,
+       "engine": "codex",
+       "purpose": "multi-commit-test",
+       "timestamp": "{{ current timestamp }}"
+   }
+   ```
+
+4. **Fourth commit**: Create a log file "test.log" containing the current time. This is just a log file.
+
+Create a pull request with title "Multi-commit test from Codex" and body:
+```markdown
+# Multi-Commit Test Pull Request
+
+This PR was created by Codex to test the multi-commit functionality in agentic workflows.
+
+## Changes Made
+
+This PR contains exactly 4 commits:
+1. Added README-test.md with project description
+2. Added test-script.js with JavaScript hello function
+3. Added config.json with test configuration
+4. Added test.log with timestamp
+
+Each change was made in a separate commit to test that `git am` properly applies all commits from the patch file, not just the first one.
+
+## Haiku about Multi-Commits
+
+Git commits aligned,  
+Each change builds upon the last—  
+Patch preserves them all.
+```
\ No newline at end of file
diff --git a/.github/workflows/test-codex-push-to-branch.lock.yml b/.github/workflows/test-codex-push-to-branch.lock.yml
index 18883a8990c..ff94f04559b 100644
--- a/.github/workflows/test-codex-push-to-branch.lock.yml
+++ b/.github/workflows/test-codex-push-to-branch.lock.yml
@@ -2,7 +2,7 @@
 # To update this file, edit the corresponding .md file and run:
 #   gh aw compile
 
-name: "Test Codex Push To Branch"
+name: "Codex Push-to-Branch Multi-Commit Test"
 on:
   issues:
     types: [opened, edited, reopened]
@@ -18,7 +18,7 @@ permissions: {}
 concurrency:
   group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number }}"
 
-run-name: "Test Codex Push To Branch"
+run-name: "Codex Push-to-Branch Multi-Commit Test"
 
 jobs:
   task:
@@ -95,7 +95,7 @@ jobs:
             }
             await main();
 
-  test-codex-push-to-branch:
+  codex-push-to-branch-multi-commit-test:
     needs: task
     if: >
       contains(github.event.issue.body, '/test-codex-push-to-branch') || contains(github.event.comment.body, '/test-codex-push-to-branch') ||
@@ -169,6 +169,69 @@ jobs:
         run: |
           mkdir -p /tmp/aw-prompts
           cat > $GITHUB_AW_PROMPT << 'EOF'
+          This test workflow specifically tests multi-commit functionality in push-to-branch.
+          
+          **IMPORTANT: Create multiple separate commits for this test case**
+          
+          1. **First commit**: Create a file called "README-codex-test.md" with:
+             ```markdown
+             # Codex Push-to-Branch Multi-Commit Test
+             
+             This file was created by the Codex agentic workflow to test the multi-commit push-to-branch functionality.
+             
+             Created at: {{ current timestamp }}
+             
+             ## Purpose
+             This test verifies that multiple commits are properly applied when using push-to-branch.
+             ```
+          
+          2. **Second commit**: Create a JavaScript script called "codex-script.js" with:
+             ```javascript
+             #!/usr/bin/env node
+             /**
+              * Multi-commit test script created by Codex agentic workflow
+              */
+             
+             function main() {
+                 console.log("Hello from Codex agentic workflow!");
+                 console.log(`Current time: ${new Date().toISOString()}`);
+                 console.log("This script was created to test multi-commit push-to-branch functionality.");
+                 console.log("This is commit #2 in the multi-commit test.");
+             }
+             
+             if (require.main === module) {
+                 main();
+             }
+             ```
+          
+          3. **Third commit**: Create a configuration file "codex-config.json" with:
+             ```json
+             {
+                 "test_type": "multi-commit-push-to-branch",
+                 "engine": "codex",
+                 "branch": "codex-test-branch", 
+                 "commit_number": 3,
+                 "timestamp": "{{ current timestamp }}"
+             }
+             ```
+          
+          4. **Fourth commit**: Create a simple test file "codex-test-results.txt" with:
+             ```
+             Codex Multi-Commit Push-to-Branch Test Results
+             ==============================================
+             
+             Test Type: Multi-commit functionality
+             Engine: Codex
+             Branch: codex-test-branch
+             Commits Expected: 4
+             
+             This file represents the final commit in the multi-commit test sequence.
+             If you can see all 4 files (README, JavaScript script, JSON config, and this file),
+             then the multi-commit functionality is working correctly.
+             ```
+          
+          The workflow should push all these files to the codex-test-branch in separate commits, testing that `git am` properly applies multiple commits from the patch file.
+          
           Create a new file called "codex-test-file.md" with the following content:
           
           ```markdown
@@ -267,7 +330,7 @@ jobs:
               engine_name: "Codex",
               model: "",
               version: "",
-              workflow_name: "Test Codex Push To Branch",
+              workflow_name: "Codex Push-to-Branch Multi-Commit Test",
               experimental: true,
               supports_tools_whitelist: true,
               supports_http_transport: false,
@@ -306,7 +369,7 @@ jobs:
           # Run codex with log capture - pipefail ensures codex exit code is preserved
           codex exec \
             -c model=o4-mini \
-            --full-auto "$INSTRUCTION" 2>&1 | tee /tmp/test-codex-push-to-branch.log
+            --full-auto "$INSTRUCTION" 2>&1 | tee /tmp/codex-push-to-branch-multi-commit-test.log
         env:
           GITHUB_AW_PROMPT: /tmp/aw-prompts/prompt.txt
           GITHUB_AW_SAFE_OUTPUTS: ${{ env.GITHUB_AW_SAFE_OUTPUTS }}
@@ -1046,7 +1109,7 @@ jobs:
         if: always()
         uses: actions/github-script@v7
         env:
-          AGENT_LOG_FILE: /tmp/test-codex-push-to-branch.log
+          AGENT_LOG_FILE: /tmp/codex-push-to-branch-multi-commit-test.log
         with:
           script: |
             function main() {
@@ -1303,8 +1366,8 @@ jobs:
         if: always()
         uses: actions/upload-artifact@v4
         with:
-          name: test-codex-push-to-branch.log
-          path: /tmp/test-codex-push-to-branch.log
+          name: codex-push-to-branch-multi-commit-test.log
+          path: /tmp/codex-push-to-branch-multi-commit-test.log
           if-no-files-found: warn
       - name: Generate git patch
         if: always()
@@ -1411,7 +1474,7 @@ jobs:
             echo '## Git Patch' >> $GITHUB_STEP_SUMMARY
             echo '' >> $GITHUB_STEP_SUMMARY
             echo '```diff' >> $GITHUB_STEP_SUMMARY
-            head -50 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY
+            head -500 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY
             echo '...' >> $GITHUB_STEP_SUMMARY
             echo '```' >> $GITHUB_STEP_SUMMARY
             echo '' >> $GITHUB_STEP_SUMMARY
@@ -1425,7 +1488,7 @@ jobs:
           if-no-files-found: ignore
 
   push_to_branch:
-    needs: test-codex-push-to-branch
+    needs: codex-push-to-branch-multi-commit-test
     if: >
       contains(github.event.issue.body, '/test-codex-push-to-branch') || contains(github.event.comment.body, '/test-codex-push-to-branch') ||
       contains(github.event.pull_request.body, '/test-codex-push-to-branch')
@@ -1458,7 +1521,7 @@ jobs:
         id: push_to_branch
         uses: actions/github-script@v7
         env:
-          GITHUB_AW_AGENT_OUTPUT: ${{ needs.test-codex-push-to-branch.outputs.output }}
+          GITHUB_AW_AGENT_OUTPUT: ${{ needs.codex-push-to-branch-multi-commit-test.outputs.output }}
           GITHUB_AW_PUSH_BRANCH: "codex-test-branch"
           GITHUB_AW_PUSH_TARGET: "*"
           GITHUB_AW_PUSH_IF_NO_CHANGES: "warn"
@@ -1588,12 +1651,48 @@ jobs:
               try {
                 // Try to checkout existing branch first
                 execSync("git fetch origin", { stdio: "inherit" });
-                execSync(`git checkout ${branchName}`, { stdio: "inherit" });
-                console.log("Checked out existing branch:", branchName);
+                // Check if branch exists on origin
+                try {
+                  execSync(`git rev-parse --verify origin/${branchName}`, {
+                    stdio: "pipe",
+                  });
+                  // Branch exists on origin, check it out
+                  execSync(`git checkout -B ${branchName} origin/${branchName}`, {
+                    stdio: "inherit",
+                  });
+                  console.log("Checked out existing branch from origin:", branchName);
+                } catch (originError) {
+                  // Branch doesn't exist on origin, check if it exists locally
+                  try {
+                    execSync(`git rev-parse --verify ${branchName}`, { stdio: "pipe" });
+                    // Branch exists locally, check it out
+                    execSync(`git checkout ${branchName}`, { stdio: "inherit" });
+                    console.log("Checked out existing local branch:", branchName);
+                  } catch (localError) {
+                    // Branch doesn't exist locally or on origin, create it from default branch
+                    console.log(
+                      "Branch does not exist, creating new branch from default branch:",
+                      branchName
+                    );
+                    // Get the default branch name
+                    const defaultBranch = execSync(
+                      "git remote show origin | grep 'HEAD branch' | cut -d' ' -f5",
+                      { encoding: "utf8" }
+                    ).trim();
+                    console.log("Default branch:", defaultBranch);
+                    // Ensure we have the latest default branch
+                    execSync(`git checkout ${defaultBranch}`, { stdio: "inherit" });
+                    execSync(`git pull origin ${defaultBranch}`, { stdio: "inherit" });
+                    // Create new branch from default branch
+                    execSync(`git checkout -b ${branchName}`, { stdio: "inherit" });
+                    console.log("Created new branch from default branch:", branchName);
+                  }
+                }
               } catch (error) {
-                // Branch doesn't exist, create it
-                console.log("Branch does not exist, creating new branch:", branchName);
-                execSync(`git checkout -b ${branchName}`, { stdio: "inherit" });
+                core.setFailed(
+                  `Failed to switch to branch ${branchName}: ${error instanceof Error ? error.message : String(error)}`
+                );
+                return;
               }
               // Apply the patch using git CLI (skip if empty)
               if (!isEmpty) {
@@ -1602,6 +1701,9 @@ jobs:
                   // Patches are created with git format-patch, so use git am to apply them
                   execSync("git am /tmp/aw.patch", { stdio: "inherit" });
                   console.log("Patch applied successfully");
+                  // Push the applied commits to the branch
+                  execSync(`git push origin ${branchName}`, { stdio: "inherit" });
+                  console.log("Changes committed and pushed to branch:", branchName);
                 } catch (error) {
                   core.error(
                     `Failed to apply patch: ${error instanceof Error ? error.message : String(error)}`
@@ -1611,20 +1713,13 @@ jobs:
                 }
               } else {
                 console.log("Skipping patch application (empty patch)");
-              }
-              // Commit and push the changes
-              execSync("git add .", { stdio: "inherit" });
-              // Check if there are changes to commit
-              let hasChanges = false;
-              try {
-                execSync("git diff --cached --exit-code", { stdio: "ignore" });
-                // No changes to commit - apply if-no-changes configuration
+                // Handle if-no-changes configuration for empty patches
                 const message =
-                  "No changes to commit - noop operation completed successfully";
+                  "No changes to apply - noop operation completed successfully";
                 switch (ifNoChanges) {
                   case "error":
                     core.setFailed(
-                      "No changes to commit - failing as configured by if-no-changes: error"
+                      "No changes to apply - failing as configured by if-no-changes: error"
                     );
                     return;
                   case "ignore":
@@ -1635,23 +1730,10 @@ jobs:
                     console.log(message);
                     break;
                 }
-                hasChanges = false;
-              } catch (error) {
-                // Exit code != 0 means there are changes to commit, which is what we want
-                hasChanges = true;
-              }
-              let commitSha;
-              if (hasChanges) {
-                const commitMessage = pushItem.message || "Apply agent changes";
-                execSync(`git commit -m "${commitMessage}"`, { stdio: "inherit" });
-                execSync(`git push origin ${branchName}`, { stdio: "inherit" });
-                console.log("Changes committed and pushed to branch:", branchName);
-                commitSha = execSync("git rev-parse HEAD", { encoding: "utf8" }).trim();
-              } else {
-                // For noop operations, get the current HEAD commit
-                commitSha = execSync("git rev-parse HEAD", { encoding: "utf8" }).trim();
               }
               // Get commit SHA and push URL
+              const commitSha = execSync("git rev-parse HEAD", { encoding: "utf8" }).trim();
+              // Get commit SHA and push URL
               const pushUrl = context.payload.repository
                 ? `${context.payload.repository.html_url}/tree/${branchName}`
                 : `https://github.com/${context.repo.owner}/${context.repo.repo}/tree/${branchName}`;
diff --git a/.github/workflows/test-codex-push-to-branch.md b/.github/workflows/test-codex-push-to-branch.md
index f18d9bfe164..c2b1cf1035f 100644
--- a/.github/workflows/test-codex-push-to-branch.md
+++ b/.github/workflows/test-codex-push-to-branch.md
@@ -12,6 +12,69 @@ safe-outputs:
     target: "*"
 ---
 
+This test workflow specifically tests multi-commit functionality in push-to-branch.
+
+**IMPORTANT: Create multiple separate commits for this test case**
+
+1. **First commit**: Create a file called "README-codex-test.md" with:
+   ```markdown
+   # Codex Push-to-Branch Multi-Commit Test
+   
+   This file was created by the Codex agentic workflow to test the multi-commit push-to-branch functionality.
+   
+   Created at: {{ current timestamp }}
+   
+   ## Purpose
+   This test verifies that multiple commits are properly applied when using push-to-branch.
+   ```
+
+2. **Second commit**: Create a JavaScript script called "codex-script.js" with:
+   ```javascript
+   #!/usr/bin/env node
+   /**
+    * Multi-commit test script created by Codex agentic workflow
+    */
+   
+   function main() {
+       console.log("Hello from Codex agentic workflow!");
+       console.log(`Current time: ${new Date().toISOString()}`);
+       console.log("This script was created to test multi-commit push-to-branch functionality.");
+       console.log("This is commit #2 in the multi-commit test.");
+   }
+   
+   if (require.main === module) {
+       main();
+   }
+   ```
+
+3. **Third commit**: Create a configuration file "codex-config.json" with:
+   ```json
+   {
+       "test_type": "multi-commit-push-to-branch",
+       "engine": "codex",
+       "branch": "codex-test-branch", 
+       "commit_number": 3,
+       "timestamp": "{{ current timestamp }}"
+   }
+   ```
+
+4. **Fourth commit**: Create a simple test file "codex-test-results.txt" with:
+   ```
+   Codex Multi-Commit Push-to-Branch Test Results
+   ==============================================
+   
+   Test Type: Multi-commit functionality
+   Engine: Codex
+   Branch: codex-test-branch
+   Commits Expected: 4
+   
+   This file represents the final commit in the multi-commit test sequence.
+   If you can see all 4 files (README, JavaScript script, JSON config, and this file),
+   then the multi-commit functionality is working correctly.
+   ```
+
+The workflow should push all these files to the codex-test-branch in separate commits, testing that `git am` properly applies multiple commits from the patch file.
+
 Create a new file called "codex-test-file.md" with the following content:
 
 ```markdown
diff --git a/.github/workflows/test-safe-outputs-custom-engine.lock.yml b/.github/workflows/test-safe-outputs-custom-engine.lock.yml
index 4f01406b60d..8c62f046139 100644
--- a/.github/workflows/test-safe-outputs-custom-engine.lock.yml
+++ b/.github/workflows/test-safe-outputs-custom-engine.lock.yml
@@ -1270,7 +1270,7 @@ jobs:
             echo '## Git Patch' >> $GITHUB_STEP_SUMMARY
             echo '' >> $GITHUB_STEP_SUMMARY
             echo '```diff' >> $GITHUB_STEP_SUMMARY
-            head -50 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY
+            head -500 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY
             echo '...' >> $GITHUB_STEP_SUMMARY
             echo '```' >> $GITHUB_STEP_SUMMARY
             echo '' >> $GITHUB_STEP_SUMMARY
@@ -2644,7 +2644,14 @@ jobs:
               }
               console.log("Generated branch name:", branchName);
               console.log("Base branch:", baseBranch);
-              // Create a new branch using git CLI
+              // Create a new branch using git CLI, ensuring it's based on the correct base branch
+              // First, fetch latest changes and checkout the base branch
+              console.log(
+                "Fetching latest changes and checking out base branch:",
+                baseBranch
+              );
+              execSync("git fetch origin", { stdio: "inherit" });
+              execSync(`git checkout ${baseBranch}`, { stdio: "inherit" });
               // Handle branch creation/checkout
               const branchFromJsonl = pullRequestItem.branch
                 ? pullRequestItem.branch.trim()
@@ -2652,15 +2659,15 @@ jobs:
               if (branchFromJsonl) {
                 console.log("Checking if branch from JSONL exists:", branchFromJsonl);
                 console.log(
-                  "Branch does not exist locally, creating new branch:",
+                  "Branch does not exist locally, creating new branch from base:",
                   branchFromJsonl
                 );
                 execSync(`git checkout -b ${branchFromJsonl}`, { stdio: "inherit" });
-                console.log("Using existing/created branch:", branchFromJsonl);
+                console.log("Created new branch from base:", branchFromJsonl);
               } else {
-                // Create and checkout new branch with generated name
+                // Create and checkout new branch with generated name from base branch
                 execSync(`git checkout -b ${branchName}`, { stdio: "inherit" });
-                console.log("Created and checked out new branch:", branchName);
+                console.log("Created and checked out new branch from base:", branchName);
               }
               // Apply the patch using git CLI (skip if empty)
               if (!isEmpty) {
@@ -2668,30 +2675,18 @@ jobs:
                 // Patches are created with git format-patch, so use git am to apply them
                 execSync("git am /tmp/aw.patch", { stdio: "inherit" });
                 console.log("Patch applied successfully");
+                // Push the applied commits to the branch
+                execSync(`git push origin ${branchName}`, { stdio: "inherit" });
+                console.log("Changes pushed to branch");
               } else {
                 console.log("Skipping patch application (empty patch)");
-              }
-              // Commit and push the changes
-              execSync("git add .", { stdio: "inherit" });
-              // Check if there are changes to commit
-              let hasChanges = false;
-              let gitError = null;
-              try {
-                execSync("git diff --cached --exit-code", { stdio: "ignore" });
-                // No changes - exit code 0
-                hasChanges = false;
-              } catch (error) {
-                // Exit code != 0 means there are changes to commit, which is what we want
-                hasChanges = true;
-              }
-              if (!hasChanges) {
-                // No changes to commit - apply if-no-changes configuration
+                // For empty patches, handle if-no-changes configuration
                 const message =
-                  "No changes to commit - noop operation completed successfully";
+                  "No changes to apply - noop operation completed successfully";
                 switch (ifNoChanges) {
                   case "error":
                     throw new Error(
-                      "No changes to commit - failing as configured by if-no-changes: error"
+                      "No changes to apply - failing as configured by if-no-changes: error"
                     );
                   case "ignore":
                     // Silent success - no console output
@@ -2702,17 +2697,6 @@ jobs:
                     return;
                 }
               }
-              if (hasChanges) {
-                execSync(`git commit -m "Add agent output: ${title}"`, {
-                  stdio: "inherit",
-                });
-                execSync(`git push origin ${branchName}`, { stdio: "inherit" });
-                console.log("Changes committed and pushed");
-              } else {
-                // This should not happen due to the early return above, but keeping for safety
-                console.log("No changes to commit");
-                return;
-              }
               // Create the pull request
               const { data: pullRequest } = await github.rest.pulls.create({
                 owner: context.repo.owner,
@@ -3325,12 +3309,48 @@ jobs:
               try {
                 // Try to checkout existing branch first
                 execSync("git fetch origin", { stdio: "inherit" });
-                execSync(`git checkout ${branchName}`, { stdio: "inherit" });
-                console.log("Checked out existing branch:", branchName);
+                // Check if branch exists on origin
+                try {
+                  execSync(`git rev-parse --verify origin/${branchName}`, {
+                    stdio: "pipe",
+                  });
+                  // Branch exists on origin, check it out
+                  execSync(`git checkout -B ${branchName} origin/${branchName}`, {
+                    stdio: "inherit",
+                  });
+                  console.log("Checked out existing branch from origin:", branchName);
+                } catch (originError) {
+                  // Branch doesn't exist on origin, check if it exists locally
+                  try {
+                    execSync(`git rev-parse --verify ${branchName}`, { stdio: "pipe" });
+                    // Branch exists locally, check it out
+                    execSync(`git checkout ${branchName}`, { stdio: "inherit" });
+                    console.log("Checked out existing local branch:", branchName);
+                  } catch (localError) {
+                    // Branch doesn't exist locally or on origin, create it from default branch
+                    console.log(
+                      "Branch does not exist, creating new branch from default branch:",
+                      branchName
+                    );
+                    // Get the default branch name
+                    const defaultBranch = execSync(
+                      "git remote show origin | grep 'HEAD branch' | cut -d' ' -f5",
+                      { encoding: "utf8" }
+                    ).trim();
+                    console.log("Default branch:", defaultBranch);
+                    // Ensure we have the latest default branch
+                    execSync(`git checkout ${defaultBranch}`, { stdio: "inherit" });
+                    execSync(`git pull origin ${defaultBranch}`, { stdio: "inherit" });
+                    // Create new branch from default branch
+                    execSync(`git checkout -b ${branchName}`, { stdio: "inherit" });
+                    console.log("Created new branch from default branch:", branchName);
+                  }
+                }
               } catch (error) {
-                // Branch doesn't exist, create it
-                console.log("Branch does not exist, creating new branch:", branchName);
-                execSync(`git checkout -b ${branchName}`, { stdio: "inherit" });
+                core.setFailed(
+                  `Failed to switch to branch ${branchName}: ${error instanceof Error ? error.message : String(error)}`
+                );
+                return;
               }
               // Apply the patch using git CLI (skip if empty)
               if (!isEmpty) {
@@ -3339,6 +3359,9 @@ jobs:
                   // Patches are created with git format-patch, so use git am to apply them
                   execSync("git am /tmp/aw.patch", { stdio: "inherit" });
                   console.log("Patch applied successfully");
+                  // Push the applied commits to the branch
+                  execSync(`git push origin ${branchName}`, { stdio: "inherit" });
+                  console.log("Changes committed and pushed to branch:", branchName);
                 } catch (error) {
                   core.error(
                     `Failed to apply patch: ${error instanceof Error ? error.message : String(error)}`
@@ -3348,20 +3371,13 @@ jobs:
                 }
               } else {
                 console.log("Skipping patch application (empty patch)");
-              }
-              // Commit and push the changes
-              execSync("git add .", { stdio: "inherit" });
-              // Check if there are changes to commit
-              let hasChanges = false;
-              try {
-                execSync("git diff --cached --exit-code", { stdio: "ignore" });
-                // No changes to commit - apply if-no-changes configuration
+                // Handle if-no-changes configuration for empty patches
                 const message =
-                  "No changes to commit - noop operation completed successfully";
+                  "No changes to apply - noop operation completed successfully";
                 switch (ifNoChanges) {
                   case "error":
                     core.setFailed(
-                      "No changes to commit - failing as configured by if-no-changes: error"
+                      "No changes to apply - failing as configured by if-no-changes: error"
                     );
                     return;
                   case "ignore":
@@ -3372,23 +3388,10 @@ jobs:
                     console.log(message);
                     break;
                 }
-                hasChanges = false;
-              } catch (error) {
-                // Exit code != 0 means there are changes to commit, which is what we want
-                hasChanges = true;
-              }
-              let commitSha;
-              if (hasChanges) {
-                const commitMessage = pushItem.message || "Apply agent changes";
-                execSync(`git commit -m "${commitMessage}"`, { stdio: "inherit" });
-                execSync(`git push origin ${branchName}`, { stdio: "inherit" });
-                console.log("Changes committed and pushed to branch:", branchName);
-                commitSha = execSync("git rev-parse HEAD", { encoding: "utf8" }).trim();
-              } else {
-                // For noop operations, get the current HEAD commit
-                commitSha = execSync("git rev-parse HEAD", { encoding: "utf8" }).trim();
               }
               // Get commit SHA and push URL
+              const commitSha = execSync("git rev-parse HEAD", { encoding: "utf8" }).trim();
+              // Get commit SHA and push URL
               const pushUrl = context.payload.repository
                 ? `${context.payload.repository.html_url}/tree/${branchName}`
                 : `https://github.com/${context.repo.owner}/${context.repo.repo}/tree/${branchName}`;
diff --git a/pkg/workflow/js/create_pull_request.cjs b/pkg/workflow/js/create_pull_request.cjs
index 3361793c546..d1fc84df678 100644
--- a/pkg/workflow/js/create_pull_request.cjs
+++ b/pkg/workflow/js/create_pull_request.cjs
@@ -186,7 +186,15 @@ async function main() {
   console.log("Generated branch name:", branchName);
   console.log("Base branch:", baseBranch);
 
-  // Create a new branch using git CLI
+  // Create a new branch using git CLI, ensuring it's based on the correct base branch
+
+  // First, fetch latest changes and checkout the base branch
+  console.log(
+    "Fetching latest changes and checking out base branch:",
+    baseBranch
+  );
+  execSync("git fetch origin", { stdio: "inherit" });
+  execSync(`git checkout ${baseBranch}`, { stdio: "inherit" });
 
   // Handle branch creation/checkout
   const branchFromJsonl = pullRequestItem.branch
@@ -196,15 +204,15 @@ async function main() {
     console.log("Checking if branch from JSONL exists:", branchFromJsonl);
 
     console.log(
-      "Branch does not exist locally, creating new branch:",
+      "Branch does not exist locally, creating new branch from base:",
       branchFromJsonl
     );
     execSync(`git checkout -b ${branchFromJsonl}`, { stdio: "inherit" });
-    console.log("Using existing/created branch:", branchFromJsonl);
+    console.log("Created new branch from base:", branchFromJsonl);
   } else {
-    // Create and checkout new branch with generated name
+    // Create and checkout new branch with generated name from base branch
     execSync(`git checkout -b ${branchName}`, { stdio: "inherit" });
-    console.log("Created and checked out new branch:", branchName);
+    console.log("Created and checked out new branch from base:", branchName);
   }
 
   // Apply the patch using git CLI (skip if empty)
@@ -213,35 +221,21 @@ async function main() {
     // Patches are created with git format-patch, so use git am to apply them
     execSync("git am /tmp/aw.patch", { stdio: "inherit" });
     console.log("Patch applied successfully");
+
+    // Push the applied commits to the branch
+    execSync(`git push origin ${branchName}`, { stdio: "inherit" });
+    console.log("Changes pushed to branch");
   } else {
     console.log("Skipping patch application (empty patch)");
-  }
-
-  // Commit and push the changes
-  execSync("git add .", { stdio: "inherit" });
-
-  // Check if there are changes to commit
-  let hasChanges = false;
-  let gitError = null;
-
-  try {
-    execSync("git diff --cached --exit-code", { stdio: "ignore" });
-    // No changes - exit code 0
-    hasChanges = false;
-  } catch (error) {
-    // Exit code != 0 means there are changes to commit, which is what we want
-    hasChanges = true;
-  }
 
-  if (!hasChanges) {
-    // No changes to commit - apply if-no-changes configuration
+    // For empty patches, handle if-no-changes configuration
     const message =
-      "No changes to commit - noop operation completed successfully";
+      "No changes to apply - noop operation completed successfully";
 
     switch (ifNoChanges) {
       case "error":
         throw new Error(
-          "No changes to commit - failing as configured by if-no-changes: error"
+          "No changes to apply - failing as configured by if-no-changes: error"
         );
       case "ignore":
         // Silent success - no console output
@@ -253,18 +247,6 @@ async function main() {
     }
   }
 
-  if (hasChanges) {
-    execSync(`git commit -m "Add agent output: ${title}"`, {
-      stdio: "inherit",
-    });
-    execSync(`git push origin ${branchName}`, { stdio: "inherit" });
-    console.log("Changes committed and pushed");
-  } else {
-    // This should not happen due to the early return above, but keeping for safety
-    console.log("No changes to commit");
-    return;
-  }
-
   // Create the pull request
   const { data: pullRequest } = await github.rest.pulls.create({
     owner: context.repo.owner,
diff --git a/pkg/workflow/js/create_pull_request.test.cjs b/pkg/workflow/js/create_pull_request.test.cjs
index ede13dd8c23..5701c61b4df 100644
--- a/pkg/workflow/js/create_pull_request.test.cjs
+++ b/pkg/workflow/js/create_pull_request.test.cjs
@@ -189,17 +189,6 @@ describe("create_pull_request.cjs", () => {
       "git am /tmp/aw.patch",
       { stdio: "inherit" }
     );
-    expect(mockDependencies.execSync).toHaveBeenCalledWith("git add .", {
-      stdio: "inherit",
-    });
-    expect(mockDependencies.execSync).toHaveBeenCalledWith(
-      "git diff --cached --exit-code",
-      { stdio: "ignore" }
-    );
-    expect(mockDependencies.execSync).toHaveBeenCalledWith(
-      'git commit -m "Add agent output: New Feature"',
-      { stdio: "inherit" }
-    );
     expect(mockDependencies.execSync).toHaveBeenCalledWith(
       "git push origin test-workflow/1234567890abcdef",
       { stdio: "inherit" }
@@ -564,55 +553,6 @@ describe("create_pull_request.cjs", () => {
       expect(mockDependencies.github.rest.pulls.create).not.toHaveBeenCalled();
     });
 
-    it("should handle no changes to commit with warn behavior", async () => {
-      // Mock valid patch content but no changes after git add
-      mockDependencies.fs.readFileSync.mockReturnValue(
-        "diff --git a/file.txt b/file.txt\n+content"
-      );
-      mockDependencies.execSync.mockImplementation(command => {
-        if (command === "git diff --cached --exit-code") {
-          // Return with exit code 0 (no changes)
-          return "";
-        }
-        if (command.includes("git commit")) {
-          throw new Error("Should not reach commit");
-        }
-      });
-      mockDependencies.process.env.GITHUB_AW_PR_IF_NO_CHANGES = "warn";
-
-      const mainFunction = createMainFunction(mockDependencies);
-
-      await mainFunction();
-
-      expect(mockDependencies.console.log).toHaveBeenCalledWith(
-        "No changes to commit - noop operation completed successfully"
-      );
-      expect(mockDependencies.github.rest.pulls.create).not.toHaveBeenCalled();
-    });
-
-    it("should handle no changes to commit with error behavior", async () => {
-      // Mock valid patch content but no changes after git add
-      mockDependencies.fs.readFileSync.mockReturnValue(
-        "diff --git a/file.txt b/file.txt\n+content"
-      );
-      mockDependencies.execSync.mockImplementation(command => {
-        if (command === "git diff --cached --exit-code") {
-          // Return with exit code 0 (no changes) - don't throw an error
-          return "";
-        }
-        // For other git commands, return normally
-        return "";
-      });
-      mockDependencies.process.env.GITHUB_AW_PR_IF_NO_CHANGES = "error";
-
-      const mainFunction = createMainFunction(mockDependencies);
-
-      await expect(mainFunction()).rejects.toThrow(
-        "No changes to commit - failing as configured by if-no-changes: error"
-      );
-      expect(mockDependencies.github.rest.pulls.create).not.toHaveBeenCalled();
-    });
-
     it("should default to warn when if-no-changes is not specified", async () => {
       mockDependencies.fs.readFileSync.mockReturnValue("");
       // Don't set GITHUB_AW_PR_IF_NO_CHANGES env var
diff --git a/pkg/workflow/js/push_to_branch.cjs b/pkg/workflow/js/push_to_branch.cjs
index 7a8ea63d1ee..241b815ec8f 100644
--- a/pkg/workflow/js/push_to_branch.cjs
+++ b/pkg/workflow/js/push_to_branch.cjs
@@ -140,12 +140,52 @@ async function main() {
   try {
     // Try to checkout existing branch first
     execSync("git fetch origin", { stdio: "inherit" });
-    execSync(`git checkout ${branchName}`, { stdio: "inherit" });
-    console.log("Checked out existing branch:", branchName);
+
+    // Check if branch exists on origin
+    try {
+      execSync(`git rev-parse --verify origin/${branchName}`, {
+        stdio: "pipe",
+      });
+      // Branch exists on origin, check it out
+      execSync(`git checkout -B ${branchName} origin/${branchName}`, {
+        stdio: "inherit",
+      });
+      console.log("Checked out existing branch from origin:", branchName);
+    } catch (originError) {
+      // Branch doesn't exist on origin, check if it exists locally
+      try {
+        execSync(`git rev-parse --verify ${branchName}`, { stdio: "pipe" });
+        // Branch exists locally, check it out
+        execSync(`git checkout ${branchName}`, { stdio: "inherit" });
+        console.log("Checked out existing local branch:", branchName);
+      } catch (localError) {
+        // Branch doesn't exist locally or on origin, create it from default branch
+        console.log(
+          "Branch does not exist, creating new branch from default branch:",
+          branchName
+        );
+
+        // Get the default branch name
+        const defaultBranch = execSync(
+          "git remote show origin | grep 'HEAD branch' | cut -d' ' -f5",
+          { encoding: "utf8" }
+        ).trim();
+        console.log("Default branch:", defaultBranch);
+
+        // Ensure we have the latest default branch
+        execSync(`git checkout ${defaultBranch}`, { stdio: "inherit" });
+        execSync(`git pull origin ${defaultBranch}`, { stdio: "inherit" });
+
+        // Create new branch from default branch
+        execSync(`git checkout -b ${branchName}`, { stdio: "inherit" });
+        console.log("Created new branch from default branch:", branchName);
+      }
+    }
   } catch (error) {
-    // Branch doesn't exist, create it
-    console.log("Branch does not exist, creating new branch:", branchName);
-    execSync(`git checkout -b ${branchName}`, { stdio: "inherit" });
+    core.setFailed(
+      `Failed to switch to branch ${branchName}: ${error instanceof Error ? error.message : String(error)}`
+    );
+    return;
   }
 
   // Apply the patch using git CLI (skip if empty)
@@ -155,6 +195,10 @@ async function main() {
       // Patches are created with git format-patch, so use git am to apply them
       execSync("git am /tmp/aw.patch", { stdio: "inherit" });
       console.log("Patch applied successfully");
+
+      // Push the applied commits to the branch
+      execSync(`git push origin ${branchName}`, { stdio: "inherit" });
+      console.log("Changes committed and pushed to branch:", branchName);
     } catch (error) {
       core.error(
         `Failed to apply patch: ${error instanceof Error ? error.message : String(error)}`
@@ -164,24 +208,15 @@ async function main() {
     }
   } else {
     console.log("Skipping patch application (empty patch)");
-  }
-
-  // Commit and push the changes
-  execSync("git add .", { stdio: "inherit" });
-
-  // Check if there are changes to commit
-  let hasChanges = false;
-  try {
-    execSync("git diff --cached --exit-code", { stdio: "ignore" });
 
-    // No changes to commit - apply if-no-changes configuration
+    // Handle if-no-changes configuration for empty patches
     const message =
-      "No changes to commit - noop operation completed successfully";
+      "No changes to apply - noop operation completed successfully";
 
     switch (ifNoChanges) {
       case "error":
         core.setFailed(
-          "No changes to commit - failing as configured by if-no-changes: error"
+          "No changes to apply - failing as configured by if-no-changes: error"
         );
         return;
       case "ignore":
@@ -192,24 +227,10 @@ async function main() {
         console.log(message);
         break;
     }
-
-    hasChanges = false;
-  } catch (error) {
-    // Exit code != 0 means there are changes to commit, which is what we want
-    hasChanges = true;
   }
 
-  let commitSha;
-  if (hasChanges) {
-    const commitMessage = pushItem.message || "Apply agent changes";
-    execSync(`git commit -m "${commitMessage}"`, { stdio: "inherit" });
-    execSync(`git push origin ${branchName}`, { stdio: "inherit" });
-    console.log("Changes committed and pushed to branch:", branchName);
-    commitSha = execSync("git rev-parse HEAD", { encoding: "utf8" }).trim();
-  } else {
-    // For noop operations, get the current HEAD commit
-    commitSha = execSync("git rev-parse HEAD", { encoding: "utf8" }).trim();
-  }
+  // Get commit SHA and push URL
+  const commitSha = execSync("git rev-parse HEAD", { encoding: "utf8" }).trim();
 
   // Get commit SHA and push URL
   const pushUrl = context.payload.repository
diff --git a/pkg/workflow/js/push_to_branch.test.cjs b/pkg/workflow/js/push_to_branch.test.cjs
index 6ec274e4c98..4c194395da8 100644
--- a/pkg/workflow/js/push_to_branch.test.cjs
+++ b/pkg/workflow/js/push_to_branch.test.cjs
@@ -85,7 +85,6 @@ describe("push_to_branch.cjs", () => {
       expect(scriptContent).toContain("fs.existsSync");
       expect(scriptContent).toContain("fs.readFileSync");
       expect(scriptContent).toContain("git am");
-      expect(scriptContent).toContain("git commit");
       expect(scriptContent).toContain("git push");
     });
 
@@ -106,7 +105,7 @@ describe("push_to_branch.cjs", () => {
       expect(scriptContent).toContain("noop operation");
       expect(scriptContent).toContain("Patch file is empty");
       expect(scriptContent).toContain(
-        "No changes to commit - noop operation completed successfully"
+        "No changes to apply - noop operation completed successfully"
       );
     });
 
