Handbook AI Engineering
Bagian I - Bab 4

Version Control dengan Git dan GitHub

Memahami tiga zona Git, siklus kerja harian, cara membaca dan menyelesaikan merge conflict, serta konfigurasi .gitignore yang tepat.

Apa yang Akan Kamu Pahami Setelah Bab Ini

Bab ini menjelaskan Git dari sudut pandang yang berbeda dari kebanyakan tutorial: bukan daftar perintah yang harus dihafal, tapi sistem yang perlu dipahami cara kerjanya. Ketika kamu mengerti apa yang sebenarnya terjadi di balik setiap perintah, kamu bisa mendiagnosis masalah sendiri, termasuk merge conflict yang sering membuat panik.

4.1 Apa yang Sebenarnya Dilakukan Git

Git adalah sistem yang mencatat perubahan pada file dari waktu ke waktu. Kata kunci di sini adalah perubahan, bukan salinan file secara keseluruhan setiap kali ada perubahan, melainkan hanya bagian yang berubah beserta catatannya.

Setiap kali kamu membuat commit, Git menyimpan sebuah snapshot dari kondisi proyekmu saat itu, lengkap dengan metadata: siapa yang membuat perubahan, kapan, dan pesan yang mendeskripsikan apa yang berubah. Kumpulan snapshot inilah yang membentuk riwayat proyek, dan kamu bisa kembali ke snapshot manapun kapanpun dibutuhkan.

GitHub adalah layanan hosting berbasis web untuk repositori Git. Ia bukan bagian dari Git itu sendiri, Git bisa digunakan sepenuhnya secara lokal tanpa GitHub. Tapi GitHub menambahkan kemampuan kolaborasi: menyimpan salinan repositori di server yang bisa diakses oleh siapapun yang diberi izin.

4.2 Tiga Zona Git yang Perlu Dipahami

Kebingungan paling umum tentang Git berasal dari tidak memahami bahwa Git memiliki tiga zona berbeda tempat file bisa berada. Memahami ketiga zona ini adalah kunci untuk mengerti apa yang dilakukan setiap perintah.

Tiga zona Git: Working Directory, Staging Area, Repository, lalu Remote di GitHub

Tiga zona ini menjelaskan mengapa siklus Git selalu terdiri dari tiga langkah dan bukan satu: git add memindahkan perubahan dari Working Directory ke Staging Area, git commit memindahkan dari Staging Area ke Repository, dan git push mengirim Repository lokal ke Remote di GitHub.

Kenapa Staging Area Diperlukan

Staging Area memberi kontrol. Kamu mungkin sudah mengubah tiga file, tapi hanya ingin meng-commit dua di antaranya karena yang ketiga belum selesai. Staging Area memungkinkan seleksi itu.

4.3 Siklus Kerja Dasar

Berikut adalah perintah-perintah yang akan kamu gunakan setiap hari, dengan penjelasan apa yang sebenarnya terjadi di setiap langkahnya.

Setup, Konfigurasi Identitas Git (Sekali Seumur Hidup per Komputer)

git config --global user.name "Nama Kamu"
git config --global user.email "email@kamu.com"

Identitas ini melekat pada setiap commit yang kamu buat. GitHub menggunakannya untuk menampilkan siapa yang membuat perubahan. Lakukan ini sekali di awal, tidak perlu diulang.

Inisialisasi, Memulai Repositori Baru (Sekali per Proyek Baru)

git init
git remote add origin https://github.com/username/repo.git

git init membuat repositori Git baru di direktori saat ini, ini membuat folder tersembunyi .git/ yang menyimpan semua riwayat. git remote add origin menghubungkan repositori lokal ke repositori di GitHub.

Alternatif: buat repositori di GitHub terlebih dahulu, lalu gunakan git clone URL untuk menyalinnya ke lokal. Pendekatan ini lebih mudah untuk pemula.

Siklus Harian, Add, Commit, Push (Setiap Kali Menyelesaikan Satu Unit Kerja)

# Lihat status perubahan saat ini
git status

# Tambahkan semua perubahan ke staging
git add .

# Atau tambahkan file tertentu saja
git add main.py rag.py

# Buat commit dengan pesan yang deskriptif
git commit -m "tambah endpoint RAG ke FastAPI"

# Kirim ke GitHub
git push origin main

Tentang git status: selalu jalankan git status sebelum git add. Ia menunjukkan file mana yang berubah, file mana yang sudah di-staging, dan file mana yang tidak dilacak Git. Ini mencegah kamu tidak sengaja meng-add file yang tidak seharusnya.

Tentang pesan commit: pesan commit yang baik menjelaskan apa yang berubah dan mengapa, bukan bagaimana. "update file" adalah pesan yang buruk. "tambah validasi Pydantic di endpoint /chat" adalah pesan yang baik.

Tentang git add .: titik di belakang berarti "semua file yang berubah di direktori ini". Pastikan .gitignore sudah dikonfigurasi dengan benar sebelum menggunakan ini, agar file sensitif tidak ikut ter-staging.

Sinkronisasi, Mengambil Perubahan dari Remote (Sebelum Mulai Bekerja saat Berkolaborasi)

# Ambil dan gabungkan perubahan dari remote
git pull origin main

Jalankan ini setiap kali mulai sesi kerja saat berkolaborasi dengan orang lain. git pull memastikan kode lokalmu sinkron dengan versi terbaru di GitHub sebelum kamu mulai membuat perubahan baru. Ini mengurangi kemungkinan terjadinya konflik.

Inspeksi, Melihat Riwayat dan Perubahan (Kapanpun Dibutuhkan)

# Lihat riwayat commit
git log --oneline

# Lihat perubahan yang belum di-staging
git diff

# Lihat perubahan yang sudah di-staging
git diff --staged

git log --oneline menampilkan riwayat commit dalam format ringkas: hash commit di kiri dan pesan commit di kanan. Hash ini bisa digunakan untuk kembali ke versi tertentu jika dibutuhkan. git diff menunjukkan persis baris mana yang berubah, berguna sebelum membuat commit untuk memastikan perubahan sudah sesuai.

4.4 Memahami dan Menyelesaikan Merge Conflict

Merge conflict terjadi ketika dua perubahan yang berbeda dibuat pada baris yang sama di file yang sama, dan Git tidak bisa memutuskan sendiri mana yang harus dipertahankan. Ini bukan tanda bahwa sesuatu rusak, ini adalah Git yang meminta keputusan dari manusia.

Skenario paling umum: kamu dan rekan tim mengedit file yang sama secara bersamaan. Rekan tim push perubahannya lebih dulu. Ketika kamu mencoba push, Git mendeteksi konflik dan meminta kamu menyelesaikannya secara manual sebelum bisa melanjutkan.

Skenario merge conflict dan penyelesaiannya

Membaca Tanda Konflik

Ketika konflik terjadi, Git menyisipkan tanda-tanda khusus langsung ke dalam file yang berkonflik. Kamu harus membaca dan mengedit tanda ini secara manual.

import os
from langchain_google_genai import ChatGoogleGenerativeAI

llm = ChatGoogleGenerativeAI(
    model="gemini-1.5-flash",
<<<<<<< HEAD
    temperature=0.1,  # perubahan kamu: untuk RAG
=======
    temperature=0.9,  # perubahan rekan: untuk creative writing
>>>>>>> origin/main
)
Lokal / Milikmu

<<<<<<< HEAD

Awal bagian konflik. "HEAD" berarti ini adalah versi milikmu, perubahan yang ada di repositori lokalmu saat ini.

Pemisah

=======

Pemisah. Semua yang di atas adalah milikmu, semua yang di bawah adalah milik remote (rekan tim atau versi sebelumnya di GitHub).

Remote / GitHub

>>>>>>> origin/main

Akhir bagian konflik. Menunjukkan dari branch mana perubahan yang berkonflik berasal.

Setelah diedit, pilih satu versi atau gabungkan keduanya, lalu hapus semua tanda konflik:

import os
from langchain_google_genai import ChatGoogleGenerativeAI

llm = ChatGoogleGenerativeAI(
    model="gemini-1.5-flash",
    temperature=0.1,  # dipilih versi milik kita untuk konteks RAG
)

Langkah Menyelesaikan Konflik

1. Edit file yang berkonflik. Buka file di editor. Cari semua tanda konflik (<<<<<<<, =======, dan >>>>>>>), putuskan konten mana yang dipertahankan, lalu hapus semua tanda konflik. Pastikan tidak ada tanda konflik yang tersisa.

2. Verifikasi tidak ada konflik yang tersisa.

git status

Pastikan tidak ada file dengan label "both modified" yang tersisa. Jika masih ada, berarti masih ada konflik lain yang belum diselesaikan.

3. Staging dan commit hasil resolusi.

git add .
git commit -m "resolve conflict: gunakan temperature 0.1 untuk RAG"

Pesan commit untuk resolusi konflik sebaiknya menjelaskan keputusan yang diambil, bukan hanya "fix conflict". Ini penting untuk riwayat proyek.

4. Push hasil resolusi ke remote.

git push origin main

Setelah ini, repositori lokal dan remote kembali sinkron dengan versi yang sudah diselesaikan konfliknya.

4.5 File .gitignore

File .gitignore memberitahu Git file dan direktori mana yang harus diabaikan sepenuhnya, tidak dilacak, tidak di-staging, tidak ikut ter-commit. Ini adalah mekanisme yang melindungi file sensitif seperti .env dari terunggah ke GitHub.

Penting Dipahami

.gitignore hanya bekerja pada file yang belum pernah dilacak Git sebelumnya. Jika sebuah file sudah ter-commit sebelumnya lalu kamu tambahkan ke .gitignore, Git tetap akan melacaknya. Untuk menghentikan pelacakan file yang sudah terlanjur di-commit, diperlukan langkah tambahan.

Template Lengkap .gitignore

Berikut adalah contoh template .gitignore yang umum digunakan untuk proyek Python. Kamu bisa menyesuaikannya sesuai kebutuhan proyekmu.

# === WAJIB: Kredensial & konfigurasi sensitif ===
.env
.env.local
.env.*.local

# === WAJIB: Virtual environment ===
venv/
.venv/
env/

# === Cache Python ===
__pycache__/
*.py[cod]
*.pyo
.pytest_cache/

# === Build & distribusi ===
dist/
build/
*.egg-info/

# === File sistem ===
.DS_Store          # macOS
Thumbs.db          # Windows
desktop.ini

# === IDE & editor ===
.vscode/
.idea/
*.swp              # Vim swap files

# === Data & model lokal ===
data/raw/          # data mentah yang tidak perlu di-share
*.csv              # hapus baris ini jika CSV perlu di-track
models/            # model file yang besar

# === Log ===
*.log
logs/

Sintaks Pola .gitignore

Pola Arti
.envAbaikan file bernama persis .env di direktori manapun dalam proyek
venv/Tanda / di akhir berarti abaikan direktori bernama venv, bukan file
*.logTanda * adalah wildcard, mengabaikan semua file dengan ekstensi .log
*.py[cod]Tanda kurung siku mencocokkan satu karakter dari daftar: .pyc, .pyo, .pyd
# komentarBaris yang dimulai dengan # adalah komentar, tidak diproses oleh Git
!important.logTanda ! di awal adalah negasi, pengecualian dari aturan di atasnya

Menghentikan Pelacakan File yang Sudah Terlanjur Ter-commit

Jika kamu menambahkan file sensitif seperti .env ke .gitignore setelah file itu sudah ter-commit, Git tetap akan melacaknya. Untuk menghentikan pelacakan file yang sudah terlanjur di-commit, gunakan perintah git rm --cached. Berikut contoh langkah-langkahnya:

# Hentikan pelacakan file .env tanpa menghapusnya dari disk
git rm --cached .env

# Hentikan pelacakan seluruh direktori venv/
git rm --cached -r venv/

# Setelah itu, tambahkan ke .gitignore lalu commit
git add .gitignore
git commit -m "hapus .env dan venv dari pelacakan Git"
git push origin main

Kesalahan Umum

Jangan menunggu proyek selesai baru mulai commit.

Commit yang jarang dan besar membuat riwayat tidak bermakna dan membuat diagnosis masalah hampir mustahil. Jika laptop rusak atau kode tiba-tiba error, kamu tidak bisa kembali ke versi yang berjalan karena tidak ada snapshot di antara "kosong" dan "selesai". Commit setiap kali satu unit kerja kecil selesai, satu fitur, satu perbaikan, satu refactor.

Jangan panik saat melihat merge conflict.

Merge conflict bukan tanda bahwa sesuatu rusak secara permanen. Git hanya tidak bisa memutuskan sendiri, ia menunggu keputusanmu. Baca tanda konflik dengan tenang, putuskan konten mana yang benar, hapus semua tanda konflik, lalu selesaikan dengan git add → commit → push. Tidak ada yang hilang selama proses ini.

.gitignore Hanya Bekerja pada File yang Belum Pernah Dilacak Git

Menambahkan nama file ke .gitignore setelah file itu sudah ter-commit tidak akan menghentikan Git dari melacaknya. Gunakan git rm --cached nama-file untuk menghentikan pelacakan file yang sudah terlanjur masuk ke riwayat.

Jalankan git pull Sebelum Mulai Bekerja saat Berkolaborasi

Sebagian besar merge conflict bisa dihindari dengan kebiasaan sederhana ini: selalu sinkronkan kode lokal dengan versi terbaru di remote sebelum membuat perubahan baru. Semakin jarang kamu sinkron, semakin besar kemungkinan terjadinya konflik yang kompleks.

Gunakan git status Sesering Mungkin

git status adalah perintah yang paling aman di Git, ia tidak mengubah apapun, hanya melaporkan kondisi saat ini. Jalankan sebelum git add untuk memastikan file yang benar yang akan di-staging, dan setelah resolusi konflik untuk memastikan tidak ada konflik yang tersisa.

Ringkasan Bab 4

Checklist Pemahaman
  • Saya memahami perbedaan antara Git (sistem version control) dan GitHub (layanan hosting repositori), dan hubungan antara keduanya.
  • Saya bisa menjelaskan tiga zona Git: Working Directory, Staging Area, dan Repository, dan apa yang dilakukan setiap perintah terhadap ketiga zona tersebut.
  • Saya bisa menjalankan siklus kerja dasar Git secara mandiri: git status, git add, git commit, git push.
  • Saya menulis pesan commit yang deskriptif menjelaskan apa yang berubah dan mengapa, bukan hanya "update" atau "fix".
  • Saya bisa membaca tanda konflik Git dan menyelesaikan merge conflict secara manual.
  • Saya sudah membuat file .gitignore di proyek saya yang mengecualikan .env dan venv/ minimal.
  • Saya memahami bahwa .gitignore hanya bekerja pada file yang belum pernah dilacak, dan tahu cara menghentikan pelacakan file yang sudah terlanjur di-commit menggunakan git rm --cached.
  • Saya memiliki kebiasaan commit yang sering dan bermakna setiap satu unit kerja kecil selesai, bukan menunggu proyek selesai.