Reflog telah menyelamatkan kita dua kali, tetapi keduanya dari kesalahan yang kita lakukan sendiri di mesin sendiri. Jaring penyelamat itu punya tiga lubang: reflog tidak pernah meninggalkan mesin ini, entri lamanya dibersihkan git gc, dan semuanya lenyap bila folder .git itu sendiri hilang. Bagian penutup proyek ini menambal ketiganya dengan dua jalur cadangan resmi Git — mirror yang hidup di direktori tetap dan bundle yang bisa dibawa ke mana saja — lalu menguji keduanya dengan pemulihan total. Teori lengkap keduanya dibahas di Backup Repository ; di sini kita menjalankannya sampai tuntas pada buku-resep.

Mirror: Salinan Refs yang Utuh #

Dari dalam buku-resep, buat mirror sebagai folder tetangga:

bash
git clone --mirror . ../buku-resep-backup.git

Output yang Dihasilkan:

text
Cloning into bare repository '../buku-resep-backup.git'...
done.

Kata kunci --mirror mengubah sifat salinan total: refspec yang dipasang adalah +refs/*:refs/*, sehingga seluruh namespace refs disalin apa adanya — tidak dipindah ke refs/remotes seperti clone biasa — dan hasilnya berbentuk bare tanpa working tree. Sumber clone-nya adalah . (directory ini), yang Git simpan sebagai jalur absolut.

Verifikasi pertama: tanyakan daftar refs pada mirror lewat ls-remote, lalu bandingkan dengan show-ref di sumber:

bash
git ls-remote ../buku-resep-backup.git
git show-ref

Output yang Dihasilkan (perintah git ls-remote ../buku-resep-backup.git):

text
467361217975d92baec94fe475f95e26009223c7	HEAD
467361217975d92baec94fe475f95e26009223c7	refs/heads/main

Output yang Dihasilkan (perintah git show-ref):

text
467361217975d92baec94fe475f95e26009223c7 refs/heads/main

Hash pada baris refs/heads/main sama persis di kedua sisi — mirror berdiri sejajar dengan sumber. Baris HEAD hanya muncul di ls-remote karena perintah itu juga melaporkan penunjuk default yang akan diambil clone berikutnya. Perbedaan tampilan pemisah (tab pada ls-remote, spasi pada show-ref) murni soal format keluaran — isinya tetap satu benda yang sama.

Memutakhirkan Mirror #

Mirror yang dibuat sekali akan menua — sumbernya terus hidup. Simulasikan pekerjaan baru: catat prosedur backup yang barusan kita rancang ke dalam README.md:

bash
printf '# Buku Resep Warung\n\nKumpulan resep andalan warung — latihan pemulihan riwayat untuk\nCourse Git Proyek 05.\n\n## Isi\n\n- `sample.txt` — seluruh resep dalam satu berkas\n\n## Daftar Resep\n\n- Sup Jagung\n- Gudeg\n- Rendang\n- Bakso Rendang (fusi)\n\n## Cadangan\n\n- Mirror `../buku-resep-backup.git` — mutakhirkan dengan `git remote update`\n- Bundle `buku-resep.bundle` — buat ulang setiap pekan\n' > README.md
git add README.md
git commit -m "Catat prosedur backup pada README"

Output yang Dihasilkan (perintah git commit):

text
[main 57a74dc] Catat prosedur backup pada README
 1 file changed, 5 insertions(+)

Riwayat final hari ini — sembilan commit, dua di antaranya pernah “hilang” dan kembali:

bash
git log --oneline

Output yang Dihasilkan:

text
57a74dc Catat prosedur backup pada README
4673612 Sebutkan resep fusi pada README
6bba564 Lengkapi langkah resep fusi
239f8fc Coba resep fusi bakso rendang
563d368 Lengkapi README dengan daftar resep
84e2ae5 Tambah catatan penyajian
1c4a93c Tambah resep rendang
691f4f6 Tambah resep gudeg
12594d0 Rintis buku resep dengan resep sup

Mirror masih tertinggal satu commit. Mirror tidak punya working tree, jadi pembaruannya tidak memakai git pull — melainkan git remote update yang dijalankan dari dalam mirror:

bash
cd ../buku-resep-backup.git
git remote update

Output yang Dihasilkan:

text
From /home/z/my-project/tutorial-extracted/work/sandbox/proyek-git/proyek-05/buku-resep/.
   4673612..57a74dc  main       -> main

Dua baris itu adalah laporan fetch: sumber buku-resep (jalur pada keluaran menyesuaikan lokasi direktori) memindahkan main dari 4673612 ke 57a74dc di sisi mirror. Verifikasi ulang kedua sisi:

bash
git show-ref
cd ../buku-resep
git show-ref

Output yang Dihasilkan (perintah git show-ref di dalam buku-resep-backup.git):

text
57a74dca575e7830b1421da7260d3f6e691b378b refs/heads/main

Output yang Dihasilkan (perintah git show-ref di dalam buku-resep):

text
57a74dca575e7830b1421da7260d3f6e691b378b refs/heads/main

Baris demi baris identik — mirror kembali sejajar dengan sumber, dan prosedur ini bisa diulang kapan saja.

Bundle: Cadangan dalam Satu Berkas #

Jalur kedua menjawab kebutuhan yang tidak bisa dipenuhi mirror: cadangan berbentuk berkas tunggal yang bisa dikirim lewat USB, dilampirkan ke email, atau disimpan di arsip. Bungkus seluruh riwayat:

bash
git bundle create buku-resep.bundle --all

Perintah itu berhasil tanpa mengucap satu kata — git bundle create melaporkan dirinya lewat keluaran senyap. Bukti pertama ada di ukuran berkasnya:

bash
ls -lh buku-resep.bundle

Output yang Dihasilkan:

text
-rw-rw-r-- 1 z z 3.3K Dec 14  2026 buku-resep.bundle

Ukuran dan tanggal pada keluaran kita akan menyesuaikan isi repository dan waktu pembuatan. Bukti kedua: minta Git memeriksa isi bundlenya sendiri:

bash
git bundle verify buku-resep.bundle

Output yang Dihasilkan:

text
buku-resep.bundle is okay
The bundle contains these 2 refs:
57a74dca575e7830b1421da7260d3f6e691b378b refs/heads/main
57a74dca575e7830b1421da7260d3f6e691b378b HEAD
The bundle records a complete history.
The bundle uses this hash algorithm: sha1

Tiga baris tengah adalah isi perjanjian: bundle membawa refs main dan HEAD yang sama dengan sumber, dan records a complete history menegaskan bahwa --all membungkus seluruh rantai commit — bukan potongan. Rujukan sintaks lengkapnya ada di dokumentasi git bundle .

Uji Pemulihan Total #

Cadangan yang belum pernah dipakai untuk pulih hanyalah doa. Uji paling keras yang bisa dilakukan terhadap buku-resep.bundle: jadikan ia satu-satunya sumber kehidupan baru:

bash
git clone buku-resep.bundle dari-bundle

Output yang Dihasilkan:

text
Cloning into 'dari-bundle'...

Clone dari bundle berjalan seperti clone biasa — origin pada hasilnya menunjuk ke berkas bundle itu sendiri. Baca riwayat kehidupan barunya:

bash
git -C dari-bundle log --oneline

Output yang Dihasilkan:

text
57a74dc Catat prosedur backup pada README
4673612 Sebutkan resep fusi pada README
6bba564 Lengkapi langkah resep fusi
239f8fc Coba resep fusi bakso rendang
563d368 Lengkapi README dengan daftar resep
84e2ae5 Tambah catatan penyajian
1c4a93c Tambah resep rendang
691f4f6 Tambah resep gudeg
12594d0 Rintis buku resep dengan resep sup

Sembilan commit, baris demi baris identik dengan git log --oneline di sumber. Seandainya disk buku-resep hilang beserta reflog-nya, berkas 3.3K ini cukup untuk memulihkan seluruh pekerjaan. Selesai uji, folder dari-bundle/ boleh dihapus — ia hanya alat uji. Hubungan ketiganya terangkum begini:

Diagram itu dibaca sebagai tiga aliran cadangan: mirror ditarik terus-menerus lewat remote update, bundle dibuat ulang setiap kali disimpan, dan setiap bundle bisa di-clone menjadi repository hidup kapan diperlukan.

Jadwal Backup Harian, Mingguan, Bulanan #

Kedua jalur ini paling kuat saat dijadwalkan — ritual rutin mengalahkan niat baik. Pola yang dipakai tim kecil:

RitmeAlatPerintah intiMelindungi dari
Harianremote (hosting atau pusat bare)git push di akhir hari kerjadisk lokal rusak, laptop hilang
Mingguanbundlegit bundle create cadangan-$(date +%F).bundle --allkegagalan hosting, kebutuhan arsip offline
Bulananmirrorgit clone --mirror baru, atau git remote update pada mirror lamakerusakan menyeluruh, migrasi mesin

Baris harian adalah git push biasa yang sudah dilatih di Proyek 03 — remote adalah cadangan termurah karena sudah menyatu dengan alur kerja. Bundle mingguan memberi titik pemulihan yang tidak bergantung pada koneksi atau layanan pihak ketiga, dan pemberian nama bertanggal menjadikannya arsip berlapis. Mirror bulanan mengunci keadaan utuh untuk jangka panjang. Otomatisasi lewat cron dan pola bundle inkremental dibahas di Backup Repository .

Ringkasan Proyek #

Hari buruk yang direkayasa ini menutup dengan catatan pencapaian:

PencapaianBukti pada sesi
Membaca reflog sebagai peta pergerakanlima entri commit terbaca dan diurai, HEAD@{n} dites dengan git rev-parse
Memulihkan commit tertelan resetlog kembali dari tiga ke lima commit setelah reset diarahkan ke hash dari HEAD@{1}
Memulihkan branch terhapus paksaeksperimen/fusi bangkit dari reflog HEAD dengan tujuh commit utuh, lalu digabungkan ke main
Membangun backup dua jalurmirror refs identik dengan sumber, dan bundle di-clone menjadi riwayat sembilan commit yang identik

Konsep yang barusan dilatih tangan ini memiliki kedalaman teorinya masing-masing: anatomi reflog di git reflog , dua jalur pemulihan commit di Memulihkan Commit , dan prosedur lengkap saat insiden sungguhan datang di Prosedur Recovery Aman .

Kita kini bisa memulihkan apa pun yang Git catat — dan semuanya dicatat. Kompetensi terakhir yang belum dimiliki tim ini bukan menyelamatkan diri setelah kesalahan, melainkan mencegah kesalahan terulang secara otomatis: pemeriksaan yang berjalan sendiri setiap kali commit dibuat. Mesin penjaga itu bernama hooks, dan proyek berikutnya membangunnya: Proyek 06: Otomasi Git Hooks .