Skip to content

Create a branch that is missing in the fork - #2

Merged
Paebbels merged 2 commits into
devfrom
claude/create-missing-branches
Sep 10, 2026
Merged

Create a branch that is missing in the fork#2
Paebbels merged 2 commits into
devfrom
claude/create-missing-branches

Conversation

@pytooling-claude

@pytooling-claude pytooling-claude Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Rebased onto dev after #1 was merged; the base was retargeted automatically.

New Features

  • A branch listed in an <organisation>.repos file that the fork doesn't have is created, from the upstream
    repository's branch head, and the next run synchronizes it like any other branch.

    gh repo sync updates a branch; it can't create one. So a branch added upstream after the fork was made — or every
    branch but one, when the fork was made with Copy the default branch only — could never be synchronized: the entry
    in the configuration file simply failed on every run, for ever.

      📂 OSVVM/AXI4 ⇒ PLC2/OSVVM-AXI4
        🌱 dev — created from OSVVM/AXI4@a1b2c3d
    
  • create-missing-branches enables it. It is false by default (second commit, on your call): the branch head
    is read from <upstream>, so a stale or copy-pasted upstream would create the branch from the wrong repository, and
    each repository should enable it once its configuration file has been checked. While disabled, a missing branch is a
    counted error naming the parameter — which is already an improvement, because it says why the branch can't be
    synchronized. created is a new output parameter and a new line in the summary.

Changes

  • The mechanism is one API call, not fetch/push. You suggested fetch/pull/push; I checked whether the shorter path
    works first, and it does — GitHub keeps a fork and its upstream in one object network, so the upstream's commit
    is addressable through the fork and POST /repos/<fork>/git/refs accepts it directly.

    Verified read-only against real repositories before writing the code: ghdl/ghdl's rust branch is
    fa173d3bed630ee51f8c62426a12dd4748142a59, Paebbels/ghdl has no rust ref (GET .../git/ref/heads/rust
    404), and yet GET /repos/Paebbels/ghdl/commits/fa173d3… returns that commit. The object is already there; only the
    ref is missing.

    That avoids cloning a repository per fork on the runner. A shallow fetch wouldn't help either — GitHub rejects a
    push from a shallow clone ("shallow update not allowed"), so the fetch/push route would pull GHDL's full history
    onto the runner to upload objects GitHub already has. If you'd rather have the git route regardless, it's a
    self-contained replacement of one function.

  • <upstream> becomes functional. Until now it was reported; it is now the repository the new branch's head is
    read from.

    This is why the parameter defaults to false. PLC2/Synchronize and VHDL/Synchronize name OSVVM/osvvm as the
    upstream on every line of their OSVVM.repos — 14 and 13 forks. GitHub resolves repository names
    case-insensitively, so OSVVM/osvvm is a real repository, and a missing branch in any of those 27 forks would
    otherwise be created from the wrong one. Enable the parameter per repository, after its file has been corrected.

  • The fork's branch is checked before synchronizing, one gh api read per branch, rather than after a failed sync.
    It costs ~50 reads per day for a namespace the size of Paebbels, and in exchange the missing-branch case doesn't
    depend on parsing gh's error text, and a doomed gh repo sync isn't run at all. Dry-run mode is unchanged and
    still reads nothing.

Bug Fixes

  • The case above is the bug: a configured branch missing from the fork was a permanent, self-repeating error, with no
    path to a green run other than editing the configuration file or clicking through the GitHub UI.

Documentation

  • README.md gains a Missing Branches section — what gh repo sync can't do, what the action does instead, why
    <upstream> matters now, and the escape hatch. The parameter tables, the sample log and the summary block are
    updated.

Unit Tests

  • check-outputs verifies created too, and both verification jobs assert it.
  • The workflow can't reach this path: dry-run deliberately touches no repository, and a real run would need a fork
    and a token. Four cases in the local harness cover it instead, against a stub gh that answers git/ref/heads
    with 404 for a configured set of refs:
    • a branch missing in the fork → created, created=1, the POST carries ref=refs/heads/dev and the upstream SHA,
      and gh repo sync is not called for it,
    • missing in the fork and upstream → one counted error, no POST,
    • the default, create-missing-branches: false → counted error naming the parameter, and the upstream isn't even
      read,
    • a POST that fails → the message is quoted, annotated with %0A escaping, and the fork appears in
      Not synchronized:.
  • All 14 cases in the harness pass (10 from Add the 'SynchronizeForks' composite action #1, 4 new).

Related Issues and Pull-Requests

🤖 Generated with Claude Code

@pytooling-claude pytooling-claude Bot mentioned this pull request Sep 10, 2026
@pytooling-claude pytooling-claude Bot added CI: GitHub Actions Continuous Integration issues related to GitHub Actions (Windows, Linux and MacOS) Documentation Improvements or additions to documentation Enhancement New feature or request labels Sep 10, 2026
Base automatically changed from claude/synchronize-forks-action to dev September 10, 2026 21:08
claude-code and others added 2 commits September 10, 2026 21:13
'gh repo sync' updates a branch, it can't create one, so a branch listed in an '<organisation>.repos' file that
the fork doesn't have yet can never be synchronized. Before synchronizing, the action now checks whether the
fork has the branch, and creates it from the upstream repository's branch head when it doesn't.

The upstream's commit is addressable through the fork, because GitHub keeps a fork and its upstream in one object
network, so creating the branch is a single API call - no clone, fetch or push. This makes the '<upstream>' field
functional: it names the repository the new branch's head is read from.

A branch that exists in neither repository, a failed creation, and a missing branch while
'create-missing-branches' is disabled are counted errors. 'created' is a new output parameter.

Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RnpaXYDwfNwnJrQew78j3f
The branch head is read from '<upstream>', so a stale or copy-pasted upstream in a configuration file would create
the branch from the wrong repository. Off by default; a repository enables it once its file was checked. While
disabled, a missing branch stays a counted error naming the parameter.

Co-Authored-By: Patrick Lehmann <Paebbels@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RnpaXYDwfNwnJrQew78j3f
@pytooling-claude
pytooling-claude Bot force-pushed the claude/create-missing-branches branch from 5fae190 to b1aaa86 Compare September 10, 2026 21:13
@Paebbels
Paebbels merged commit 439ec14 into dev Sep 10, 2026
3 checks passed
@Paebbels
Paebbels deleted the claude/create-missing-branches branch September 10, 2026 21:15
@pytooling-claude pytooling-claude Bot mentioned this pull request Sep 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI: GitHub Actions Continuous Integration issues related to GitHub Actions (Windows, Linux and MacOS) Documentation Improvements or additions to documentation Enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants