Transfer git repo changes between air-gapped machines using QR codes and a webcam.
Sender displays git bundle data as cycling QR codes on screen. Receiver reads them via webcam, reconstructs the bundle, and applies it.
- Python 3.6+
- Git on PATH (
git --versionshould work from terminal/command prompt) - Webcam (for the receiving machine)
- Install Git for Windows — make sure "Git from the command line" is selected during install
- Use
pyorpython(notpython3) in commands below - If camera doesn't open, try
--camera 1or close other apps using the camera
cd qr-git-sync
pip install -r requirements.txtpython qr_git_sync.py statuspython qr_git_sync.py send --repo /path/to/repo- Displays a carousel of QR codes. Point the other machine's camera at the screen.
- Uses
qr-sync-*tags for incremental transfer (only new commits since last sync). --fullto ignore tags and send the entire repo.--chunk-size 400for unreliable cameras (smaller QR = easier to read).
python qr_git_sync.py receive --repo /path/to/repo- Opens webcam and watches for QR codes.
- Shows progress bar overlay on the camera feed.
- Automatically applies the bundle when all chunks are received.
git bundle createpackages commits into a single binary- Bundle is compressed (zlib) and base64-encoded
- Payload is split into ~600-byte chunks, each becomes a QR code
- Sender cycles through QR codes in a loop
- Receiver collects chunks via webcam (order doesn't matter, duplicates ignored)
- On completion: verify SHA256, decompress, apply bundle
- Both machines get a
qr-sync-<timestamp>tag for incremental sync next time
| Key | Send mode | Receive mode |
|---|---|---|
SPACE |
Pause/resume | — |
+ / = |
Faster cycling | — |
- |
Slower cycling | — |
n / → |
Next QR | — |
p / ← |
Previous QR | — |
q / ESC |
Quit | Quit |
Sync is one-direction per session. For two-way:
- Machine A sends → Machine B receives
- B resolves any merge conflicts
- Machine B sends → Machine A receives
The machine that receives first acts as the merge authority.
- ~600 bytes per QR code at default settings
- A 100KB bundle = ~170 QR codes ≈ 85 seconds per pass
- A 1MB bundle = ~1,700 QR codes ≈ 15 minutes per pass
- For large transfers, consider sneakernet (USB drive)