Di jj, Working Copy Kamu Sudah Commit

Model mental pertama yang perlu dibongkar waktu pindah dari git ke Jujutsu, yaitu bahwa tidak ada ruang tunggu sebelum commit.

· 4 menit baca

Sore 25 September, hari pertama saya pakai Jujutsu (jj) di repo internal core kami. Working copy saya penuh campuran: tool MCP baru, perubahan deploy staging, docs agen, dan beberapa file sesi yang tidak ada hubungannya dengan apa pun. Refleks sepuluh tahun pakai git langsung jalan: stash dulu, bikin branch, git add -p pelan-pelan, jangan sampai ada yang ketinggalan.

Lalu saya sadar tidak ada yang perlu di-stash. Semua perubahan itu sudah tersimpan di sebuah commit. Saya cuma belum tahu karena belum pernah melihatnya dari sudut itu.

Artikel ini soal satu ide saja. Kalau ide ini sudah nyangkut, sisanya di jj terasa masuk akal. Kalau belum, semua perintah jj akan terasa seperti git yang dipasang terbalik.

Satu change dengan change ID tetap berganti revisi setiap file diedit; jj new menyegelnya dan membuka change baru

Git punya ruang tunggu, jj tidak

Di git, sebuah perubahan melewati tiga tempat. File yang kamu ubah hidup di working copy. git add memindahkannya ke staging area. git commit menyegelnya jadi commit. Dua tempat pertama itu ruang tunggu: isinya belum resmi, belum punya nama, dan gampang hilang kalau kamu salah checkout.

jj menghapus ruang tunggu itu. Working copy kamu adalah sebuah commit, dengan nama @. Setiap kali kamu menjalankan perintah jj apa pun, isi disk di-snapshot ke commit itu. Tidak ada add, tidak ada “lupa commit”, karena kamu memang selalu sedang berada di dalam commit.

Jadi pertanyaannya bergeser. Di git kamu bertanya “sudah saya commit belum?”. Di jj pertanyaannya “commit yang sekarang sudah selesai belum?”. Kalau sudah, segel dan mulai yang baru:

jj describe -m "feat(api): tool MCP untuk lead invoice"
jj new

jj describe memberi nama ke commit yang sedang kamu kerjakan. jj new menyegelnya dan membuka commit kosong di atasnya. Edit berikutnya masuk ke commit baru itu. Catatan kecil buat yang kerja bareng agen: selalu pakai -m. jj describe tanpa -m membuka editor, dan agen akan duduk diam menunggu editor itu selamanya. Saya sudah melihatnya sendiri.

Change dan revision

Ini bagian yang butuh waktu paling lama buat saya. jj membedakan dua hal yang di git dilebur jadi satu.

Change adalah unit kerja yang bisa terus berubah. Ia punya change ID yang stabil, misalnya qpvuntsm. Revision adalah snapshot tetap dari change itu pada satu titik waktu, dan itulah yang jadi commit git dengan SHA-nya. Setiap kali kamu mengedit sebuah change, ID-nya tetap, revisinya baru.

gitjj
Tempat kerjaworking copy + stagingcommit @
Menyimpangit add + git commitotomatis tiap perintah
Mulai kerja barugit commit, lalu lanjutjj new
Nama yang stabiltidak ada, SHA berubah saat amendchange ID
Amendgit commit --amendtidak perlu apa-apa

Konsekuensi praktisnya: rujuk pekerjaan pakai change ID, bukan hash. Saya belajar ini dengan cara yang tidak enak. Saya menyalin hash sebuah commit, lalu me-rebase, lalu mencoba squash --into ke hash yang barusan saya salin. Kontennya tidak pindah ke tempat yang saya kira, karena hash itu sudah menunjuk ke revisi lama. Change ID tidak punya masalah itu.

Hash itu foto. Change ID itu orangnya.

Pisahkan belakangan

Kalau tidak ada staging, bagaimana memisahkan pekerjaan yang campur? Jawabannya: tidak perlu dipisah di depan. Kerjakan dulu, pecah belakangan.

jj split -m "feat(api): tool MCP lead invoice" apps/api/app/Mcp apps/api/tests

Perintah itu mengambil file yang kamu sebut, menaruhnya di satu commit, dan sisanya di commit lain. Sore itu saya ulangi split per kelompok file sampai tumpukan campuran tadi jadi delapan change terpisah, masing-masing kemudian jadi satu MR. Tanpa stash, tanpa pindah branch, tanpa add -p satu hunk demi satu hunk.

Di git, disiplin memisahkan pekerjaan harus terjadi sebelum commit. Di jj boleh terjadi sesudahnya, kapan saja sampai kamu push.

Jadi penjelajah waktu

Karena commit bisa berubah, kamu bisa kembali ke commit lama dan memperbaikinya langsung:

jj log
jj edit qpvuntsm

jj log menampilkan graph dengan change ID di tiap baris. jj edit memindahkan working copy ke change itu. Sekarang file di disk adalah isi change tersebut, dan setiap edit langsung masuk ke sana. Semua commit di atasnya ikut di-rebase otomatis. Selesai memperbaiki, jj edit lagi ke change paling atas dan lanjut kerja.

Di git, ini pekerjaan rebase -i dengan edit, lalu commit --amend, lalu rebase --continue, sambil berharap tidak ada konflik di tengah. Di jj, rasanya seperti membuka laci yang salah isi, membetulkannya, lalu menutupnya lagi.

Kenapa ini layak dibiasakan

Butuh beberapa jam pemakaian sungguhan sampai model ini klik. Buat saya klik-nya terjadi waktu sadar ada empat hal dari git yang tidak saya butuhkan lagi. Tidak ada kerja yang hilang karena semuanya sudah di dalam commit. Tidak ada stash karena “menyimpan sementara” cukup dengan jj new. Amend gratis karena commit memang selalu terbuka. Dan menulis ulang history tidak menakutkan, karena jj mencatat setiap operasi dan hampir semuanya bisa dibatalkan. Bagian terakhir itu punya artikelnya sendiri nanti di seri ini.

Satu hal yang perlu diingat: di jj kamu tidak pernah berada di luar commit, jadi pertanyaannya bukan “sudah commit belum”, tapi “commit ini sudah selesai belum”.

Berikutnya: kamus pindahan dari git ke jj, padanan perintah yang tiap hari kamu ketik.


Bahan dasar: panduan Mental Model di lazyjj.dev oleh Ernesto Jiménez.

Tulisan terkait

Daftar isi
  1. Git punya ruang tunggu, jj tidak
  2. Change dan revision
  3. Pisahkan belakangan
  4. Jadi penjelajah waktu
  5. Kenapa ini layak dibiasakan
Berikutnya: Kamus Pindahan: Perintah Git yang Kamu Cari di jj →