Model shared di chapter sebelumnya bekerja karena semua orang dipercaya membawa kunci yang sama. Begitu kontributor datang dari luar — proyek terbuka, repository kantor lain, atau maintainer yang membatasi akses — asumsi itu runtuh: tidak semua orang boleh mendorong ke repository asal. Model fork menjawabnya dengan memberi setiap kontributor salinan repository pribadi untuk didorong bebas, sementara repository asal hanya menerima perubahan lewat review. Chapter ini membangun model itu utuh dengan Git murni: tiga repository di sandbox, dua remote dalam satu clone, dan propagasi perubahan dari repository asal ke salinan pribadi.
Dua Remote dalam Satu Clone #
Pada model fork ada tiga pihak yang perlu dibedakan dengan cermat. Repository asal milik maintainer disebut upstream — sumber kebenaran tempat semua perubahan pada akhirnya bergabung. Salinan pribadi kontributor di platform hosting disebut fork. Clone di meja kontributor lalu memegang dua alamat sekaligus: origin yang menunjuk fork miliknya, dan upstream yang menunjuk repository asal.
Perbedaan arah kerjanya menjadi identitas masing-masing remote:
| Remote | Menunjuk ke | Dipakai untuk |
|---|---|---|
origin | fork pribadi (fork-budi.git) | mendorong pekerjaan sendiri |
upstream | repository asal (upstream-toko.git) | menarik pembaruan maintainer |
Pekerjaan mengalir satu arah dari meja kontributor: commit didorong ke origin, lalu diajukan ke upstream lewat pull request
. Pembaruan mengalir satu arah sebaliknya: dari upstream ditarik ke clone, lalu diteruskan ke fork. Perintah git push tetap satu — yang berubah hanyalah tujuannya.
Membangun Tiga Repository di Sandbox #
Panggungnya: Siti memainkan maintainer pemilik repository asal, Budi menjadi kontributor. Siti menyiapkan repository kerja berisi dua commit lalu mempublikasikannya sebagai bare repository:
mkdir proyek-siti && cd proyek-siti
git init -b main
printf 'beranda\n' > situs.md
git add situs.md
git commit -m "Buat kerangka toko"
printf 'kopi\ngula\n' > produk.md
git add produk.md
git commit -m "Tambah daftar produk"
git init --bare ../upstream-toko.git
git remote add origin ../upstream-toko.git
git push -u origin mainOutput yang Dihasilkan (perintah terakhir):
To ../upstream-toko.git
* [new branch] main -> main
branch 'main' set up to track 'origin/main'.Di platform nyata, tindakan Budi selanjutnya adalah menekan tombol Fork di halaman repository Siti: server menyalin seluruh riwayat ke ruang akun Budi — github.com/budi/upstream-toko — lengkap dengan branch dan tag, tanpa issues dan pengaturan. Sandbox meniru penyalinan sisi server itu dengan satu perintah: git clone --bare dari upstream ke sebuah bare repository baru milik Budi:
cd ..
git clone --bare upstream-toko.git fork-budi.gitOutput yang Dihasilkan:
Cloning into bare repository 'fork-budi.git'...
done.git clone fork-budi.git toko-budi
cd toko-budi
git config user.name "Budi Santoso"
git config user.email "[email protected]"Output yang Dihasilkan (perintah pertama):
Cloning into 'toko-budi'...
done.Tiga repository kini berdiri: upstream-toko.git milik Siti, fork-budi.git salinan Budi, dan toko-budi clone kerja Budi. Clone terakhir itu otomatis menamai sumbernya origin — kebiasaan Git yang sudah kita kenal sejak Konsep Remote
. Yang belum ada adalah jendela ke repository asal. Budi mendaftarkannya dengan nama konvensi upstream:
git remote add upstream ../upstream-toko.git
git remote -vOutput yang Dihasilkan (perintah terakhir):
origin ../fork-budi.git (fetch)
origin ../fork-budi.git (push)
upstream ../upstream-toko.git (fetch)
upstream ../upstream-toko.git (push)Empat baris alamat, dua arah tiap remote — persis bentuk git remote -v dari Menambahkan Remote
, hanya kini buku alamatnya berisi dua entri. Penarikan pertama membuktikan keduanya hidup:
git fetch upstreamOutput yang Dihasilkan:
From ../upstream-toko
* [new branch] main -> upstream/mainSatu baris [new branch] mencatat lahirnya remote-tracking branch upstream/main — penunjuk bayangan ke ujung main versi repository asal, saudara dari origin/main yang dijelaskan di Remote-Tracking Branch
. Perbedaan keduanya: origin/main melacak fork Budi, upstream/main melacak repo Siti.
Propagasi Perubahan Upstream ke Fork #
Alur lengkapnya terlihat begitu kedua pihak bergerak. Budi mengerjakan daftar harga di fork-nya — commit biasa, lalu dorong ke origin:
printf 'kopi 20000\ngula 7000\n' > harga.md
git add harga.md
git commit -m "Tambah daftar harga"Output yang Dihasilkan (perintah terakhir):
[main 3d0c368] Tambah daftar harga
1 file changed, 2 insertions(+)
create mode 100644 harga.mdgit push origin mainOutput yang Dihasilkan:
To ../fork-budi.git
ffc1433..3d0c368 main -> mainSementara itu Siti maju terus: halaman kontak masuk ke repository asal.
cd ../proyek-siti
printf 'kontak\n' > kontak.md
git add kontak.md
git commit -m "Tambah halaman kontak"
git push origin mainOutput yang Dihasilkan (perintah terakhir):
To ../upstream-toko.git
ffc1433..b5841d0 main -> mainDi meja Budi, main lokal dan origin/main sama-sama berhenti di ffc1433 — perubahan Siti belum terlihat, dan memang tidak akan pernah terlihat lewat origin, karena fork tidak menerima dorongan dari Siti. Jendela yang benar adalah upstream:
cd ../toko-budi
git fetch upstreamOutput yang Dihasilkan:
From ../upstream-toko
ffc1433..b5841d0 main -> upstream/mainRentang ffc1433..b5841d0 hanya menggerakkan penunjuk upstream/main — pekerjaan Budi di main lokal tidak tersentuh, perilaku fetch yang sudah dibedah di git fetch
. Pekerjaan Siti baru benar-benar tiba di meja Budi saat digabungkan:
git merge upstream/mainOutput yang Dihasilkan:
Merge made by the 'ort' strategy.
kontak.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 kontak.mdGit membuka editor dengan pesan siap pakai Merge remote-tracking branch 'upstream/main' — simpan tanpa perubahan, seperti kebiasaan di Sinkronisasi Remote
. Merge ini bukan fast-forward: main Budi membawa commit harga sendiri, jadi Git melahirkan commit merge berinduk dua. Topologinya terbaca dari graf:
git log --oneline --graph -5Output yang Dihasilkan:
* e99141f Merge remote-tracking branch 'upstream/main'
|\
| * b5841d0 Tambah halaman kontak
* | 3d0c368 Tambah daftar harga
|/
* ffc1433 Tambah daftar produk
* 0ea16fb Buat kerangka tokoHash di mesin pembaca akan berbeda, tetapi bentuknya sama: dua jalur bertemu di commit merge — jalur Budi (harga) di kiri, jalur Siti (kontak) dari upstream/main di kanan, keduanya berakar pada ffc1433. Langkah pamungkas propagasi: mengirim hasil sinkronisasi ini ke fork, tempat pull request kelak dibuat:
git push origin mainOutput yang Dihasilkan:
To ../fork-budi.git
3d0c368..e99141f main -> mainRantai lengkapnya: kontak lahir di upstream → ditarik lewat fetch upstream → digabungkan di meja Budi → didorong ke origin. Perubahan upstream kini sampai ke fork tanpa satu pun akses tulis ke repository asal.
Kapan Fork, Kapan Branch Bersama #
| Situasi | Pilihan | Alasan |
|---|---|---|
| Tim internal satu perusahaan | shared repository | akses tulis bisa diberikan ke semua anggota |
| Proyek terbuka dengan kontributor luar | fork | maintainer menjaga pintu lewat review |
| Kontribusi sekali waktu ke proyek orang | fork | tanpa perlu meminta akses |
| Eksperimen panjang di luar proyek utama | fork | fork menjadi taman sandbox pribadi |
| Perubahan kecil oleh tim kecil terpercaya | branch bersama | langkah paling ringkas |
Model fork dan model shared tidak saling meniadakan: banyak proyek besar memakai keduanya — core team mendorong langsung lewat branch bersama, kontributor luar lewat fork. Register perintah remote yang dipakai sepanjang chapter ini terdokumentasi di dokumentasi git remote .
Fork menyelesaikan masalah akses, tetapi belum menyentuh prosesnya: bagaimana pekerjaan di fork sampai ke upstream tetap urutan manual — buka halaman web, ajukan, diskusikan. Urutan itulah yang dibakukan platform lewat pull request, pokok bahasan chapter berikutnya.