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
[Bug]: Forgejo merges ignore the repository's delete-branch-after-merge setting #14296
I searched existing issues and did not find a duplicate.
I included enough detail to investigate the problem.
Area
apps/server
Steps to reproduce
Enable the default deletion of pull request branches after merge in a Forgejo repository's settings.
Merge a pull request through T3 Code's Pull Requests interface.
Check whether the source branch remains in Forgejo.
Expected behavior
T3 Code respects the target repository's default_delete_branch_after_merge setting when merging.
When enabled, request branch deletion through Forgejo's merge endpoint; when disabled, retain the branch.
Forgejo should enforce its own branch protection and deletion permissions.
Actual behavior
The source branch is retained.
Code inspection on upstream 27bdf1aa1 confirms that ForgejoPullRequestProvider.runAction sends only { Do: input.mergeMethod ?? "merge" } to POST /repos/{owner}/{repo}/pulls/{number}/merge.
It never supplies delete_branch_after_merge, and the ForgejoRepository decoder does not include default_delete_branch_after_merge.
Suggested fix
Read the target repository's current setting before submitting the merge and include delete_branch_after_merge in the merge request.
Keep branches when the optional setting is absent, and do not proceed with a merge if reading the repository settings fails.
Cover enabled, disabled, missing, and failed settings reads with focused regression tests.
Verification
Reported behavior verified against the current merge implementation; no live repository was merged or modified during investigation.
Confirmed. This is a bug in T3's Forgejo/Gitea provider, and there is no existing issue for it.
Forgejo does not apply the repository setting inside the merge call. MergePullRequestForm.DeleteBranchAfterMerge is a plain bool, so an omitted delete_branch_after_merge is false, and POST /repos/{owner}/{repo}/pulls/{index}/merge deletes the head branch only when that flag is true. The web UI is what honors the setting: the merge form is initialized from defaultDeleteBranchAfterMerge on the pull-request unit. Gitea’s merge API behaves the same way, and this provider serves both (fj and tea).
ForgejoPullRequestProvider.runAction sends only { Do: input.mergeMethod ?? "merge" } for a merge, and ForgejoRepository never decodes default_delete_branch_after_merge. A merge from T3 therefore always leaves the source branch, even when the repository default is on. GitHub is different: it applies delete_branch_on_merge on the server, so the GitHub provider does not need to send a flag.
Reading the target repository and passing delete_branch_after_merge is the right fix. getRepo already calls GET /repos/{owner}/{repo}; treat a missing field as false. Two constraints for the implementation:
If the flag is true and deletion fails, Forgejo still completes the merge and then returns an error (403 when the head branch is protected, is the default branch, or the merger cannot write to the head repo, which includes many forks). write() treats that as a failed action, so the UI can report a failed merge after the pull request has already landed. The web UI only offers the checkbox when the head branch is deletable. Sending the repository default unconditionally will hit that path.
Refusing to merge when that settings read fails avoids silently ignoring an enabled setting. That failure should stay distinct from a merge rejection, so a transient GET does not look like the host refused the merge.
Triage on main at b5a226e49c, Linux VM: neither fj nor tea is installed, and the standard Forgejo CLI and tea credential files are absent. The live reproduction is blocked before enabling the repository setting or merging a PR; no repository was merged or modified. Source inspection still shows the merge request containing only Do, but that is not runtime reproduction. No duplicate found in 949 open issues. Verification needs a writable Forgejo test repository and an authenticated environment; please also provide the Forgejo version used for the reported behavior.
The bug is reproducible straightforward and shows up on every instance when merging a PR - the branch is left behind even though "delete branch after merge" is ticked in the repo settings.
Reproduced on Linux with current main 3b95e7831b, Forgejo 14.0.5, and tea 0.16.0. In a disposable local repository, I enabled default_delete_branch_after_merge, then merged a PR through T3’s web Pull Requests detail panel. T3 showed “Merged” and Forgejo returned merged: true; the source branch still existed. No additional reporter information is needed.
Fix opened in #23471, labeled bugfix. Verified with the real T3 web client and Forgejo 14.0.5: enabled deletes the source branch; disabled retains it; a protected source branch remains while T3 correctly reports the completed merge. Runtime evidence. The focused 108 tests and changed-file checks pass. The PR is unmerged.
Activity
juliusmarminge commentedon Sep 29, 2026
Triage
Confirmed. This is a bug in T3's Forgejo/Gitea provider, and there is no existing issue for it.
Forgejo does not apply the repository setting inside the merge call.
MergePullRequestForm.DeleteBranchAfterMergeis a plain bool, so an omitteddelete_branch_after_mergeis false, andPOST /repos/{owner}/{repo}/pulls/{index}/mergedeletes the head branch only when that flag is true. The web UI is what honors the setting: the merge form is initialized fromdefaultDeleteBranchAfterMergeon the pull-request unit. Gitea’s merge API behaves the same way, and this provider serves both (fjandtea).ForgejoPullRequestProvider.runActionsends only{ Do: input.mergeMethod ?? "merge" }for a merge, andForgejoRepositorynever decodesdefault_delete_branch_after_merge. A merge from T3 therefore always leaves the source branch, even when the repository default is on. GitHub is different: it appliesdelete_branch_on_mergeon the server, so the GitHub provider does not need to send a flag.Reading the target repository and passing
delete_branch_after_mergeis the right fix.getRepoalready callsGET /repos/{owner}/{repo}; treat a missing field as false. Two constraints for the implementation:write()treats that as a failed action, so the UI can report a failed merge after the pull request has already landed. The web UI only offers the checkbox when the head branch is deletable. Sending the repository default unconditionally will hit that path.GETdoes not look like the host refused the merge.fix(server): Forgejo merges respect the repository's delete-branch se…
juliusmarminge commentedon Oct 22, 2026
Triage on main at b5a226e49c, Linux VM: neither
fjnorteais installed, and the standard Forgejo CLI and tea credential files are absent. The live reproduction is blocked before enabling the repository setting or merging a PR; no repository was merged or modified. Source inspection still shows the merge request containing onlyDo, but that is not runtime reproduction. No duplicate found in 949 open issues. Verification needs a writable Forgejo test repository and an authenticated environment; please also provide the Forgejo version used for the reported behavior.pat-s commentedon Oct 22, 2026
Hard-to-read comment.
The bug is reproducible straightforward and shows up on every instance when merging a PR - the branch is left behind even though "delete branch after merge" is ticked in the repo settings.
juliusmarminge commentedon Oct 22, 2026
Reproduced on Linux with current main 3b95e7831b, Forgejo 14.0.5, and tea 0.16.0. In a disposable local repository, I enabled
default_delete_branch_after_merge, then merged a PR through T3’s web Pull Requests detail panel. T3 showed “Merged” and Forgejo returnedmerged: true; the source branch still existed. No additional reporter information is needed.juliusmarminge commentedon Oct 22, 2026
Fix opened in #23471, labeled
bugfix. Verified with the real T3 web client and Forgejo 14.0.5: enabled deletes the source branch; disabled retains it; a protected source branch remains while T3 correctly reports the completed merge. Runtime evidence. The focused 108 tests and changed-file checks pass. The PR is unmerged.