5.4 KiB
Firmware fork → DT Gitea migration + clean RRG-tracking model
Status: Planned, not started · Date: 2026-07-05 · Related: 2026-07-03-firmware-upstream-rebase-plan.md
Goal
Host pm3py and its Proxmark3 firmware fork on the DT Gitea, customize the firmware,
and pull RRG (RfidResearchGroup/proxmark3) updates without ever touching the RRG
version — via the standard rebase-fork model.
The model
One firmware repo, <dt-org>/proxmark3, with a strict branch split:
| Branch | Role |
|---|---|
master |
pristine RRG mirror — only ever fast-forwarded from upstream, never our commits |
pm3py |
our customizations (atomic single-file commits) on top of master; the submodule pins this |
Remotes: origin = <dt-org>/proxmark3 (SSH), upstream = RRG (already configured).
pm3py itself moves to <dt-org>/pm3py; its .gitmodules points at the pm3py branch.
Why rebase-fork (not merge / subtree / quilt): our ~33 patches already are a hand-managed
atomic-commit patch queue; rebase is the native git form. It keeps git diff master..pm3py
a clean picture of exactly our changes, and resolves the recurring iso15693.c conflict
(24/33 commits touch it) once per update instead of on every merge.
The three real gotchas (all handled)
- Gitlink must be published or fresh clones dangle. The firmware
pm3pytip must be pushed before pm3py's gitlink references it (Phase 6 before 7). - The uncommitted EML host-poll change is in no ref — it would be silently lost on any
checkout/reclone. Backed up (
scratchpad/eml-hostpoll.patch) and committed onpm3pyin Phase 5. - Our history is intermixed with upstream merges —
merge-base(main, upstream/master)is only 11 commits below HEAD, so 48 of our 59 commits sit below it in the upstream DAG. A naiverebase --onto master $MB pm3pywould carry only the top 11 and drop 48. So the migration does not rebase — it mirrors everything verbatim and defers the clean split to the first upstream pull (see Ongoing).
Migration runbook (no rewrite, no data loss)
Split by who: [A] = I do it locally (offline); [U] = you run it (Gitea web / pushes,
since my sandbox can't reach :20022).
- Phase 0 [A] — safety net: back up the EML diff (done); tag every must-preserve head
bak/<name>;git bundle create --allfor both repos. - Phase 1 [U] — create EMPTY DT repos
<dt-org>/proxmark3and<dt-org>/pm3py(no README/license — a first commit blocks a mirror push). - Phase 2 [A] — materialize local heads:
git branch pm3py main(verbatim), and local branches for the 6 feature branches. No rebase. - Phase 3 [U] — mirror-push firmware:
git fetch upstream masterthengit push --mirror ssh://git@git.dngr.us:20022/<dt-org>/proxmark3.git(safe: target empty). - Phase 4 [U] — seed
master:git push <dt> refs/remotes/upstream/master:refs/heads/master. - Phase 5 [A] — commit EML on
pm3py, repoint config, bump gitlink: commit the EML host-poll; rename firmwareorigin→mikefaith-backup, add DTorigin; set.gitmodulesurl=DT SSH +branch=pm3py,submodule sync;git add .gitmodules firmware+ commit. - Phase 6 [U] — publish the firmware tip (CRITICAL):
git push origin pm3py. - Phase 7 [U] — mirror-push pm3py + repoint origin to
<dt-org>/pm3py. - Phase 8 [U] — VERIFY a fresh
git clone --recurse-submodulesof<dt-org>/pm3py: submodule resolves (no "reference is not a tree"),make PLATFORM=PM3GENERIC+pytestpass, then a hardware smoke test. - Phase 9 [U] — retire old repos (ARCHIVE read-only, never delete) only after Phase 8.
Rollback at any point: nothing is rewritten/deleted, so git remote rename mikefaith-backup origin restores the pre-migration state; the old repos and the Phase-0 bundles are the
backstop until Phase 8 passes.
Ongoing: pull RRG updates without impacting RRG
git -C firmware fetch upstream master
git -C firmware push origin refs/remotes/upstream/master:refs/heads/master # ff-only, pristine
# rebase our patches onto the new base in an isolated worktree, build+test, then:
git -C firmware push origin rebase-wip:pm3py --force-with-lease # only our branch, leased
cd <pm3py> && git add firmware && git commit -m "chore(firmware): rebase onto RRG <tip>, bump gitlink"
master is append-only (never rewritten); only pm3py is force-pushed, always with a lease.
The first pull also does the deferred clean split: enumerate our commits
(git log --author=michael --author=dangerous-tac0s upstream/master..pm3py), skip
already-upstreamed ones (hf-mfu-esetblk PR #3404), and rebuild pm3py as an explicit
patch series onto fresh master — validate git diff <rebuilt> pm3py shows only deltas
upstream lacks. Later pulls are the simple linear rebase --onto case. See the 2026-07-03
plan for the per-file conflict detail (iso15693.c hot spot).
Inputs needed from you
- The DT org name on git.dngr.us (substitutes
<dt-org>). - Fork default branch: recommend
master(matches RRG). - Confirm your SSH key has write in the
<dt-org>namespace.
Provenance
Multi-agent workflow (strategy eval + state audit + topology design → synthesized runbook). The adversarial data-loss verify pass was cut short by a rate limit; the mirror-to-empty-repo safety, publish-before-reference ordering, and EML backup were re-checked by hand.