Setiap proyek yang hidup lebih dari sehari akhirnya menghadapi pertanyaan yang sama: apa yang berubah, kapan berubah, dan bagaimana kembali bila perubahan itu salah. Nama folder seperti proyek-final.zip dan proyek-final-beneran.zip adalah jawaban improvisasi yang kita semua pernah coba — dan version control adalah jawaban yang benar. Git, buatan Linus Torvalds untuk pengembangan kernel Linux, kini menjadi standar de facto; dan berbeda dari tiga chapter sebelumnya yang membahas toolchain tak terpasang, git versi 2.47.3 tersedia penuh di mesin latihan ini. Artinya, seluruh siklus lokal yang kita bahas — identitas, commit, diff, branch, merge, .gitignore — dijalankan sungguhan, bukan dibayangkan.
Konfigurasi Identitas Sebelum Commit Pertama #
Git mencatat penulis pada setiap commit, sehingga langkah pertama di mesin baru adalah memperkenalkan diri. Identitas disimpan bertingkat: --system untuk seluruh mesin, --global untuk satu user di ~/.gitconfig, dan tanpa flag untuk satu repositori saja — yang terakhir selalu menang atas yang di atasnya:
git --version
git config --global user.name "Budi Santoso"
git config --global user.email "[email protected]"
git config --global --listOutput yang Dihasilkan:
git version 2.47.3
user.name=Budi Santoso
[email protected]Bedah baris-barisnya:
git --version: memastikan Git terpasang dan mencetak versinya — kebiasaan yang sama sebelum memakai tool apa pun.- Dua perintah
git config --global: menulis nama dan email ke~/.gitconfig. Nama bebas, tetapi email sebaiknya satu yang tetap — pada hosting seperti GitHub dan GitLab, email inilah yang mencocokkan commit dengan akun kita. git config --global --list: membaca kembali seluruh pengaturan global sebagai konfirmasi bahwa penulisan berhasil.
Repositori Pertama: init, status, add, commit #
Sebuah folder biasa berubah menjadi repositori begitu Git menemukan direktori .git di dalamnya — dan direktori itulah satu-satunya yang dibuat oleh git init. Opsi -b main sekalian menamai cabang awal main, sesuai kebiasaan modern (tanpa opsi ini, Git memakai nama lama master sambil menampilkan saran untuk mengaturnya):
git config --global user.name "Budi Santoso"
git config --global user.email "[email protected]"
mkdir -p proyek-catatan && cd proyek-catatan
git init -b main
printf 'Daftar belanja:\n- beras\n' > catatan.txt
git status
git add catatan.txt
git status --short
GIT_AUTHOR_DATE="2026-01-10T08:00:00+07:00" GIT_COMMITTER_DATE="2026-01-10T08:00:00+07:00" git commit -m "commit pertama: daftar belanja"
git log --onelineOutput yang Dihasilkan:
Initialized empty Git repository in /home/budi/proyek-catatan/.git/
On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
catatan.txt
nothing added to commit but untracked files present (use "git add" to track)
A catatan.txt
[main (root-commit) dc972f1] commit pertama: daftar belanja
1 file changed, 2 insertions(+)
create mode 100644 catatan.txt
dc972f1 commit pertama: daftar belanjaMari kita bedah tiap tahapnya:
git init -b main: membuat direktori.gittersembunyi — seluruh sejarah proyek, konfigurasi lokal, dan cabang hidup di dalamnya. Menghapus folder ini berarti menghapus sejarah.git status(bentuk panjang): melaporkan tiga hal — cabang aktifmain, belum ada commit, dancatatan.txtberstatus untracked: file ada di disk, belum dikenal Git.git add catatan.txt: memindahkan file ke staging area — ruang antara disk dan sejarah.git status --shortkini mencetakA catatan.txt; hurufAberarti added, dan dua spasi menandai kolom status.git commit -m "...": membekukan isi staging area menjadi satu commit bernomor hash — baris[main (root-commit) dc972f1]menunjukkan cabang, tanda commit pertama, dan hash pendeknya.git log --oneline: mencetak sejarah ringkas — satu baris per commit, diurutkan dari yang terbaru. Di terminal interaktif, Git menambahi baris ini dekorasi seperti(HEAD -> main); dekorasi itu otomatis dimatikan ketika output diarahkan ke file atau pipe.
Satu kekeliruan klasik layak dicatat sejak awal: seluruh perintah di atas hanya berlaku di dalam repositori. Menjalankannya di folder biasa berakhir dengan keluhan yang justru informatif:
git log --oneline 2>&1Output yang Dihasilkan:
fatal: not a git repository (or any of the parent directories): .gitPesan fatal: not a git repository berarti Git menyusuri folder kerja dan seluruh induknya namun tidak menemukan .git — cek lokasi Anda dengan pwd, lalu cd ke folder proyek yang benar.
diff: Membaca Perubahan Sebelum Membekukannya #
Alur kerja harian Git berputar pada satu pertanyaan: apa yang berubah sejak commit terakhir? Perintah git diff menjawabnya untuk file yang sudah dilacak, dan commit kedua kita lahir tepat dari situ:
git config --global user.name "Budi Santoso"
git config --global user.email "[email protected]"
mkdir -p proyek-catatan && cd proyek-catatan
git init -q -b main
printf 'Daftar belanja:\n- beras\n' > catatan.txt
git add catatan.txt
GIT_AUTHOR_DATE="2026-01-10T08:00:00+07:00" GIT_COMMITTER_DATE="2026-01-10T08:00:00+07:00" git commit -q -m "commit pertama: daftar belanja"
echo '- gula' >> catatan.txt
git diff
git add catatan.txt
GIT_AUTHOR_DATE="2026-01-11T09:00:00+07:00" GIT_COMMITTER_DATE="2026-01-11T09:00:00+07:00" git commit -q -m "tambah gula ke daftar"
git log --onelineOutput yang Dihasilkan:
diff --git a/catatan.txt b/catatan.txt
index fb81981..d044bdc 100644
--- a/catatan.txt
+++ b/catatan.txt
@@ -1,2 +1,3 @@
Daftar belanja:
- beras
+- gula
26c9390 tambah gula ke daftar
dc972f1 commit pertama: daftar belanjaBedah format git diff — format yang sama dipakai diff dan patch sejak era Unix awal:
- Baris
diff --git a/catatan.txt b/catatan.txt: header yang menyebut file yang dibandingkan;a/adalah versi commit,b/versi di disk. - Baris
index fb81981..d044bdc 100644: hash pendek kedua versi file — cara Git menyebut “dari isi sekian menjadi isi sekian”. - Baris
@@ -1,2 +1,3 @@: hunk — potongan perubahan. Dari sisi kiri, versi lama memiliki 2 baris mulai baris 1; sisi kanan, versi baru 3 baris. - Baris berawalan
+dan-: isi perubahannya. Baris tanpa awalan adalah konteks,-dihapus,+ditambahkan — dalam contoh ini hanya satu baris- gulayang baru.
Setelah perubahan ditinjau, git add menaikkannya ke staging area dan commit kedua membekukannya; git log --oneline kini mencetak dua baris. Variasi yang sering dipakai: git diff --staged membandingkan staging area dengan commit terakhir (sudah di-add, belum di-commit), dan git diff <hash> membandingkan kondisi kini dengan commit mana pun.
Branch dan Merge: Bekerja Paralel tanpa Saling Menimpa #
Cabang (branch) adalah inti kelincahan Git: penunjuk yang bisa digerakkan ke commit mana pun, dibuat dalam sekejap karena tak lebih dari file kecil berisi hash. Alur kerjanya: pekerjaan berisiko dikerjakan di cabang khusus, lalu digabungkan kembali setelah yakin:
git config --global user.name "Budi Santoso"
git config --global user.email "[email protected]"
mkdir -p proyek-catatan && cd proyek-catatan
git init -q -b main
printf 'Daftar belanja:\n- beras\n' > catatan.txt
git add catatan.txt
GIT_AUTHOR_DATE="2026-01-10T08:00:00+07:00" GIT_COMMITTER_DATE="2026-01-10T08:00:00+07:00" git commit -q -m "commit pertama: daftar belanja"
git switch -c fitur-minuman
echo '- teh' >> catatan.txt
git add catatan.txt
GIT_AUTHOR_DATE="2026-01-11T09:00:00+07:00" GIT_COMMITTER_DATE="2026-01-11T09:00:00+07:00" git commit -q -m "tambah teh ke daftar"
git switch main
GIT_AUTHOR_DATE="2026-01-12T10:00:00+07:00" GIT_COMMITTER_DATE="2026-01-12T10:00:00+07:00" git merge --no-ff fitur-minuman -m "gabungkan fitur minuman"
git log --oneline --graph
git branchOutput yang Dihasilkan:
Merge made by the 'ort' strategy.
catatan.txt | 1 +
1 file changed, 1 insertion(+)
* a1bb4af gabungkan fitur minuman
|\
| * 2c0e916 tambah teh ke daftar
|/
* dc972f1 commit pertama: daftar belanja
fitur-minuman
* mainBedah alurnya:
git switch -c fitur-minuman: membuat cabang baru sekaligus berpindah ke sana —HEAD, penunjuk posisi kita, kini menunjukfitur-minuman. Commit berikutnya mengalir ke cabang ini, bukan kemain.- Satu commit di cabang baru: menambahkan
- tehke catatan —maintidak tersentuh sama sekali, persis tujuan isolasi. git switch main: kembali ke cabang utama; isi file di disk ikut kembali ke kondisimain.git merge --no-ff: menggabungkanfitur-minumankemain. Tanpa--no-ff, bila kondisinya sederhana Git memakai fast-forward — hanya menggeser penunjuk tanpa commit baru; flag ini memaksa commit gabungan, sehingga jejak “pernah ada cabang” terlihat di sejarah.git log --oneline --graph: menggambar sejarah dengan karakter ASCII. Commit gabungana1bb4afberada di atas dengan dua induk, cabang fitur (2c0e916) berpisah lalu menyatu kembali didc972f1— grafik kecil yang menceritakan seluruh cerita.git branch: mencetak cabang yang ada; tanda*menandai posisi kita kini berada.
.gitignore: Menyisihkan yang Tak Perlu Dilacak #
Sejarah repositori sebaiknya hanya berisi file yang memang dikelola. File sementara, hasil build, dan rahasia lokal disisihkan lewat satu file bernama .gitignore — daftar pola yang dibaca Git sebelum mempertimbangkan sebuah file:
git config --global user.name "Budi Santoso"
git config --global user.email "[email protected]"
mkdir -p proyek-catatan && cd proyek-catatan
git init -q -b main
printf 'Daftar belanja:\n- beras\n' > catatan.txt
cat > .gitignore << 'AKHIR'
*.log
.env
target/
AKHIR
echo 'pesan debug lama' > debug.log
git add .gitignore catatan.txt
git status --short
git check-ignore -v debug.logOutput yang Dihasilkan:
A .gitignore
A catatan.txt
.gitignore:1:*.log debug.logBedah tiga polanya dan dua perintah penutupnya:
*.log: semua file berakhiran.log— file log yang tumbuh sendiri ini pantang masuk sejarah..env: file konfigurasi rahasia yang lazim dipakai tool modern untuk menyimpan password dan API key — mencampakkannya ke.gitignoreadalah langkah pertama; sejarah Git tidak mudah dilunturkan.target/: direktori hasil build —cargomilik Rust dan Maven sama-sama memakai nama ini, sehingga pola ini melindungi proyek dari kedua toolchain sekaligus.git status --short: hanya menampilkanA .gitignoredanA catatan.txt;debug.logmemang ada di disk, tetapi Git diam saja — inilah bukti pola bekerja.git check-ignore -v debug.log: memverifikasi keputusan Git dengan menyebut aturan mana yang cocok — file.gitignorebaris ke-1, pola*.log. Pola lengkapnya terdokumentasi di gitignore(5) .
Remote, clone, dan SSH Key untuk Hosting #
Seluruh siklus di atas berjalan murni lokal — sejarah lengkap ada di .git tanpa perlu jaringan. Kolaborasi masuk lewat remote: repositori lain yang diberi nama, lazimnya origin, yang berada di hosting seperti GitHub atau GitLab. Pola untuk proyek baru: buat repositori kosong di hosting, lalu hubungkan dan kirim:
git remote add origin git@hosting-contoh:budi/proyek-catatan.git
git push -u origin mainPerintah pertama mencatat alamat remote di .git/config; perintah kedua mengirim seluruh sejarah main ke sana, dan -u mengikat cabang lokal dengan cabang remote sehingga git push dan git pull berikutnya bekerja tanpa argumen. Sebaliknya, git clone <alamat> menyalin repositori yang sudah ada — lengkap dengan sejarahnya — ke folder baru; inilah cara bergabung ke proyek yang sedang berjalan. Kedua arah itu menyentuh jaringan, sehingga contoh konkretnya tidak bisa dijalankan di mesin latihan ini.
Bagian git@hosting-contoh: pada alamat di atas adalah bentuk SSH — protokol yang sama dengan login server di Chapter SSH Server
. Berbeda dengan HTTPS yang meminta autentikasi tiap kali, SSH memakai pasangan kunci yang dibuat sekali:
ssh-keygen -t ed25519 -C "[email protected]"Perintah ini membuat kunci privat ~/.ssh/id_ed25519 yang tak boleh dibagikan, dan kunci publik ~/.ssh/id_ed25519.pub yang justru harus ditempel ke pengaturan akun hosting kita — tipe ed25519 adalah pilihan modern yang lebih pendek dan lebih cepat daripada RSA. Setelah itu, git push dan git pull terautentikasi lewat kriptografi tanpa mengetik apa pun, dengan mekanisme kunci publik yang sama dengan login server tanpa password. Untuk pendalaman, buku resmi Pro Git
terbaca gratis dari awal sampai bab lanjutan, dan gittutorial
adalah ringkasan lima menit yang layak dibookmark.
Dari identitas hingga merge, seluruh ritual Git kini milik kita. Namun satu mesin dengan banyak proyek menimbulkan soal baru: bagaimana menjaga dependensi dan konfigurasi tiap proyek agar tidak saling mencemari? Jawabannya adalah isolasi lingkungan — pembahasan Chapter Environment Isolation .