Subtree Split atau Snapshot Rsync: Memilih Mekanisme Publish
Satu folder atau banyak path tersebar? Bentuk include set menentukan kapan subtree split aman dan kapan rsync snapshot lebih masuk akal.
Skrip split-publish saya jalan mulus selama bagian publik yang diekspos cuma satu folder. Masalah muncul waktu set publik berubah jadi lima path yang tercecer: folder tema kustom, dua folder plugin, mu-plugins, lalu manifest composer, semua harus terekspos barengan. Insting pertama saya salah besar: memaksa git subtree split biar bisa menutup banyak prefix sekaligus. Perintah git subtree split -P <prefix> -b <branch> memang mengekstrak history sintetis yang hanya berisi commit yang menyentuh prefix itu, memindahkan isinya ke root, lalu mencetak satu commit id yang bisa langsung dipush sebagai repo terpisah [1]. Tapi dia hanya menerima satu prefix. Dipaksa multi path, jalannya bukan diperbaiki, tapi berhenti total. Di situ saya sadar pertanyaannya salah: bukan alat mana yang paling jago, tapi bentuk include set saya seperti apa.
Bentuk include set menentukan mekanismenya
Aturannya sederhana dan bisa dites cepat. Kalau bagian publiknya satu folder, git subtree split menang: history khusus folder itu utuh dari awal sampai akhir, dan dokumen resminya mencatat sifat yang jarang diketahui, yaitu split berulang atas history yang sama dengan pengaturan yang sama menghasilkan commit id yang identik [1]. Bayarannya, branch publik di host kedua adalah history yang di-rewrite, jadi tiap publikasi ulang berarti force-push, dan branch itu harus diperlakukan baca-saja. GitHub sendiri, lewat git filter-repo --subdirectory-filter, mengingatkan bahwa repo hasil split tidak membawa branch dan tag asli repo sumber [2]. Pola ini sehat selama saya sadar yang saya terbitkan adalah hasil rekonstruksi, bukan repo yang sama.
Begitu publiknya lima path yang tinggal di tiga sudut berbeda, saya berhenti memaksakan satu prefix dan pindah ke rsync allowlist plus snapshot commit. Tiap publikasi jadi commit biasa di atas snapshot sebelumnya, lengkap dengan hash commit repo penuh tempat snapshot itu dibangun, lalu push biasa. Tidak pernah force. Branch publik jadi stabil dan bisa diaudit: siapa pun bisa menelusuri commit publik ke commit sumbernya. Ada pintu ketiga untuk kebutuhan rewrite paling berat, git filter-repo, yang sekarang direkomendasikan proyek git pengganti git filter-branch, dengan syarat paling berat juga: git minimal 2.36.0 dan python3 minimal 3.6 [4]. Sementara panduan GitHub untuk tutorial split subfolder menargetkan git minimal 2.22 [2], dua angka yang perlu dibaca sebagai syarat dua konteks berbeda, bukan kontradiksi.
Pintu ketiga dan jebakan first-match-wins
Bagian yang paling sering nggak diperkirakan orang justru di sisi rsync. Aturan include/exclude-nya first-match-wins: aturan pertama yang cocok itulah yang berlaku, jadi include yang mau menimpa sebuah exclude harus ditulis sebelum exclude itu [3]. Folder yang di-exclude bahkan tidak dipindai sama sekali oleh pengirim, yang sekaligus jadi penghematan traversal di tree besar [3].
| Mekanisme | Bentuk include set | History | Tipe push |
|---|---|---|---|
git subtree split | Satu folder | Sintetis, utuh | Force-push |
| rsync + snapshot commit | Banyak path tersebar | Rantai snapshot | Plain push |
git filter-repo | Rewrite kompleks | Ditulis ulang | Force-push |
Pola konkretnya bisa dilihat dari template allowlist saya: parent dulu, baru anak, lalu pola + ganda untuk menarik seluruh isi folder yang diizinkan. Skrip ekspornya membawa dua jaring pengaman: rsync dijalankan dengan --exclude '*' sebagai penutup sehingga apa pun di luar allowlist jatuh ke penolakan default, dan sebelum commit ada pemeriksaan yang membatalkan push bila ada wp-config*.php, .env, atau berkas .pem lolos sampai folder view. Sedangkan flag --delete menghapus berkas di tujuan yang tak lagi ada di daftar sumber [3]. Ini yang membuat semantik first-match-wins jadi penting dua kali: dia menentukan apa yang tersalin dan apa yang boleh dihapus. Salah posisi satu baris, dua hal bisa terjadi sekaligus, berkas internal ikut terbit atau sisa berkas usang diam-diam tertahan di repo publik karena dilindungi aturan yang salah tempat.
Menariknya bukan pada banyaknya pilihan, tapi urutan keputusannya. Bentuk include set adalah fakta yang bisa saya periksa lima detik sebelum menulis skrip, sementara preferensi alat cuma selera yang berubah-ubah. Satu folder: git subtree split, history utuh, terima konsekuensi force-push. Banyak path tercecer: rsync allowlist plus rantai snapshot, branch publik stabil dan tidak pernah menuntut paksaan. Rewrite paling berat: git filter-repo, pintu paling kuat dengan syarat paling tinggi. Tiga alat, satu pertanyaan di depan: bentuk include set Anda seperti apa?
Sumber