Riwayat Commit dan Analisis Perbedaan
Telusuri riwayat commit, ekstrak file yang berubah, dan rangkum perbedaannya.
Riwayat Commit dan Analisis Perbedaan adalah pelajaran AI Agents gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Agents, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Agents mencakup 4 pelajaran total.
Mengapa Menganalisis Riwayat Komit?
Riwayat komit adalah sumber informasi yang sangat berharga bagi agen: riwayat ini mengungkapkan apa yang berubah, kapan perubahan terjadi, dan siapa yang melakukannya. Agen menggunakan riwayat komit untuk membuat catatan perubahan, ringkasan peninjauan kode, laporan aktivitas pengembang, mendeteksi risiko (perubahan besar yang dilakukan mendekati rilis), dan memahami evolusi suatu basis kode.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
# Get recent commits on the default branch
commits = repo.get_commits()
print(f'Total commits: {commits.totalCount}')
# Preview the last 5
for commit in commits[:5]:
print(f'{commit.sha[:8]} | {commit.commit.author.name}')
print(f' {commit.commit.message.split(chr(10))[0][:60]}')
print(f' {commit.commit.author.date.date()}')Memfilter Komit Berdasarkan Rentang Waktu
Gunakan parameter since dan until untuk mendapatkan komit dalam rentang tanggal tertentu. Keduanya menerima objek Python datetime. Ini adalah alat utama untuk membuat laporan aktivitas mingguan atau bulanan.
import datetime
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
# Last 7 days of commits
now = datetime.datetime.utcnow()
last_week = now - datetime.timedelta(days=7)
recent_commits = repo.get_commits(
since=last_week,
until=now
)
print(f'Commits in last 7 days: {recent_commits.totalCount}')
# By specific author
author_commits = repo.get_commits(
since=last_week,
author='alice' # GitHub username
)
print(f'Alice\'s commits last week: {author_commits.totalCount}')
# On a specific branch
branch_commits = repo.get_commits(
sha='feature/new-api',
since=last_week
)Statistik Komit: Penambahan dan Penghapusan
Setiap objek komit memiliki properti stats dengan jumlah perubahan additions, deletions, dan total di seluruh berkas yang diubah. Informasi ini memberikan gambaran cepat tentang ukuran suatu perubahan.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
commit = repo.get_commit('abc12345sha')
# Overall stats
print(f'SHA: {commit.sha[:8]}')
print(f'Message: {commit.commit.message[:80]}')
print(f'Author: {commit.commit.author.name}')
print(f'Date: {commit.commit.author.date}')
print(f'Additions: +{commit.stats.additions}')
print(f'Deletions: -{commit.stats.deletions}')
print(f'Total changes: {commit.stats.total}')
# Large commit warning
if commit.stats.total > 500:
print('WARNING: Large commit — careful code review needed')Mencantumkan Berkas yang Diubah dalam Komit
commit.files adalah daftar objek File untuk setiap berkas yang diubah dalam komit. Properti: filename, status (ditambahkan/diubah/dihapus/diubah namanya), additions, deletions, patch (teks perbedaan).
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
commit = repo.get_commit('abc12345sha')
print(f'Files changed: {len(commit.files)}')
for f in commit.files:
print(f' [{f.status.upper():<8}] {f.filename}')
print(f' +{f.additions} -{f.deletions}')
if f.previous_filename: # for renamed files
print(f' Renamed from: {f.previous_filename}')
# Find changed Python files
python_changes = [
f for f in commit.files
if f.filename.endswith('.py')
]
print(f'\nPython files changed: {len(python_changes)}')Mengurai Teks Perbedaan
file.patch berisi perbedaan terpadu. Baris yang diawali + adalah penambahan, baris yang diawali - adalah penghapusan, sedangkan baris konteks tidak memiliki awalan. Urai teks tersebut untuk mengekstrak baris yang ditambahkan untuk dianalisis — misalnya, untuk menemukan rahasia baru, komentar TODO, atau anti-pola.
def extract_added_lines(patch):
if not patch:
return []
added = []
for line in patch.split('\n'):
if line.startswith('+') and not line.startswith('+++'):
added.append(line[1:]) # strip the '+' prefix
return added
def scan_for_secrets(added_lines):
import re
PATTERNS = [
(r'api[_-]?key\s*=\s*["\'][^"\']{20,}', 'potential API key'),
(r'password\s*=\s*["\'][^"\']{6,}', 'potential hardcoded password'),
(r'sk-[a-zA-Z0-9]{20,}', 'potential OpenAI key'),
(r'ghp_[a-zA-Z0-9]{36}', 'potential GitHub token'),
]
findings = []
for i, line in enumerate(added_lines, 1):
for pattern, label in PATTERNS:
if re.search(pattern, line, re.IGNORECASE):
findings.append({'line': i, 'type': label, 'preview': line[:80]})
return findings
# --- demo ---
patch = (
'@@ -1,2 +1,3 @@\n'
' def connect():\n'
'+ api_key = "sk-abcdefghijklmnopqrstuvwx"\n'
'+ password = "hunter2222"\n'
)
added = extract_added_lines(patch)
print('Added lines:', added)
for finding in scan_for_secrets(added):
print(finding)
Mengagregasikan Aktivitas Berdasarkan Penulis
Kelompokkan komit berdasarkan penulis untuk membuat laporan aktivitas pengembang. Hitung jumlah komit, baris yang ditambahkan atau dihapus, serta berkas yang diubah oleh setiap penulis dalam suatu rentang waktu. Hal ini berguna untuk retrospektif tim dan keputusan penugasan PR.
import datetime
from collections import defaultdict
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
last_month = datetime.datetime.utcnow() - datetime.timedelta(days=30)
author_stats = defaultdict(lambda: {'commits': 0, 'additions': 0, 'deletions': 0, 'files': set()})
for commit in repo.get_commits(since=last_month):
author = commit.commit.author.name
author_stats[author]['commits'] += 1
author_stats[author]['additions'] += commit.stats.additions
author_stats[author]['deletions'] += commit.stats.deletions
for f in commit.files:
author_stats[author]['files'].add(f.filename)
print('Author Activity (last 30 days):')
for author, stats in sorted(author_stats.items(), key=lambda x: -x[1]['commits']):
print(f'{author}: {stats["commits"]} commits, +{stats["additions"]} -{stats["deletions"]}, {len(stats["files"])} files')Membuat Catatan Perubahan dari Komit
Agen catatan perubahan membaca komit di antara dua tag atau tanggal, mengelompokkannya berdasarkan jenis (feat/fix/chore menggunakan format komit konvensional), lalu membuat catatan perubahan yang telah diformat. Gunakan LLM untuk meningkatkan kualitas deskripsi setiap komit.
import re
import datetime
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
def get_commits_since_tag(repo, tag_name):
try:
ref = repo.get_git_ref(f'tags/{tag_name}')
tag_sha = ref.object.sha
tag_commit = repo.get_commit(tag_sha)
since = tag_commit.commit.author.date
return list(repo.get_commits(since=since))[:-1] # exclude the tag commit
except Exception:
return []
def parse_conventional_commit(message):
match = re.match(r'^(feat|fix|chore|docs|test|refactor|perf|style)(\(.+?\))?: (.+)', message)
if match:
return match.group(1), match.group(3)
return 'other', message.split('\n')[0][:60]
commits = get_commits_since_tag(repo, 'v1.2.0')
by_type = {'feat': [], 'fix': [], 'other': []}
for c in commits:
msg = c.commit.message
ctype, desc = parse_conventional_commit(msg)
by_type.get(ctype, by_type['other']).append(desc)
print(f'Parsed {len(commits)} commits')Mengidentifikasi Komit Berisiko Tinggi
Komit berisiko tinggi adalah komit yang berukuran besar, menyentuh berkas penting (autentikasi, pembayaran, keamanan), atau dibuat sangat dekat dengan waktu rilis. Agen dapat menandainya untuk pemeriksaan tambahan sebelum digabungkan ke cabang utama.
import datetime
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
CRITICAL_PATHS = [
'src/auth', 'src/payment', 'src/security',
'config/', '.env', 'Dockerfile', 'requirements.txt'
]
def is_high_risk(commit):
reasons = []
# Large change
if commit.stats.total > 300:
reasons.append(f'Large change: {commit.stats.total} lines')
# Touches critical files
for f in commit.files:
for path in CRITICAL_PATHS:
if f.filename.startswith(path):
reasons.append(f'Touches critical: {f.filename}')
break
return reasons
now = datetime.datetime.utcnow()
for commit in repo.get_commits(since=now - datetime.timedelta(days=1)):
risks = is_high_risk(commit)
if risks:
print(f'HIGH RISK: {commit.sha[:8]} - {commit.commit.message[:50]}')
for r in risks:
print(f' - {r}')Membandingkan Dua Komit
Gunakan repo.compare(base, head) untuk mendapatkan perbedaan antara dua referensi (cabang, tag, atau SHA komit). Fungsi ini mengembalikan objek Comparison dengan statistik gabungan, daftar komit, dan daftar berkas yang diubah di antara kedua titik tersebut.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
# Compare two branches
comparison = repo.compare('main', 'feature/new-api')
print(f'Commits ahead: {comparison.ahead_by}')
print(f'Commits behind: {comparison.behind_by}')
print(f'Status: {comparison.status}') # ahead/behind/identical/diverged
print(f'Total commits in diff: {len(comparison.commits)}')
print(f'Files changed: {len(comparison.files)}')
# Summary of what changed
for f in comparison.files:
print(f' {f.status}: {f.filename} +{f.additions} -{f.deletions}')
# Compare two tags
tag_comparison = repo.compare('v1.0.0', 'v1.1.0')
print(f'Changes between v1.0.0 and v1.1.0: {len(tag_comparison.commits)} commits')Ringkasan Komit dengan Bantuan LLM
Berikan sekumpulan pesan komit dan nama berkas kepada LLM untuk membuat ringkasan yang mudah dipahami manusia tentang perubahan dalam suatu periode. Inilah inti bot ringkasan teknik mingguan.
import anthropic
import os
client = anthropic.Anthropic(api_key=os.environ['ANTHROPIC_API_KEY'])
def summarize_commits(commits, time_period='last week'):
commit_data = []
for commit in commits[:30]: # limit to avoid context overflow
commit_data.append(
f'- {commit.commit.message.split(chr(10))[0][:80]} '
f'(+{commit.stats.additions}/-{commit.stats.deletions})'
)
commit_list = '\n'.join(commit_data)
prompt = (
f'Summarize what happened in this codebase {time_period} '
f'based on these commit messages. Be concise (3-5 bullet points). '
f'Focus on user-facing changes and significant technical work.\n\n'
f'Commits:\n{commit_list}'
)
response = client.messages.create(
model='claude-opus-4-5',
max_tokens=400,
messages=[{'role': 'user', 'content': prompt}]
)
return response.content[0].textMendeteksi Berkas Sensitif dalam Komit
Agen analisis komit yang berfokus pada keamanan memindai komit yang secara tidak sengaja menyertakan berkas sensitif: kunci pribadi, berkas .env, konfigurasi dengan kredensial, atau salinan basis data. Periksa commit.files untuk mencari nama berkas yang cocok dengan pola sensitif yang telah diketahui.
import re
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
SENSITIVE_PATTERNS = [
r'\.env$', r'\.pem$', r'\.key$', r'id_rsa', r'credentials\.json',
r'secret', r'password', r'\.p12$', r'keystore', r'\btoken\b'
]
def is_sensitive_filename(filename):
for pattern in SENSITIVE_PATTERNS:
if re.search(pattern, filename, re.IGNORECASE):
return pattern
return None
import datetime
last_day = datetime.datetime.utcnow() - datetime.timedelta(days=1)
for commit in repo.get_commits(since=last_day):
for f in commit.files:
matched = is_sensitive_filename(f.filename)
if matched and f.status in ('added', 'modified'):
print(f'ALERT: Sensitive file in commit {commit.sha[:8]}')
print(f' File: {f.filename} (matched: {matched})')
print(f' Author: {commit.commit.author.name}')
print(f' Link: {commit.html_url}')Pemeriksaan Singkat: commit.files vs pr.get_files()
Uji pemahaman Anda tentang akses ke perbedaan komit.
Ringkasan Analisis Riwayat Komit
Agen Anda sekarang dapat menganalisis riwayat komit secara menyeluruh:
- repo.get_commits(since, until, author, sha) — memfilter komit berdasarkan waktu, penulis, atau cabang
- commit.stats — penambahan/penghapusan/total di seluruh berkas yang diubah
- commit.files — detail setiap berkas, termasuk patch (perbedaan terpadu)
- Urai
file.patchuntuk memindai baris yang ditambahkan dari rahasia, TODO, atau anti-pola - Kelompokkan komit berdasarkan penulis untuk laporan aktivitas
- repo.compare(base, head) — perbedaan antara dua referensi (cabang, tag, SHA)
- Gunakan LLM untuk membuat ringkasan yang mudah dipahami manusia dari daftar pesan komit
- Tandai komit berisiko tinggi: perubahan besar + berkas penting + waktu yang dekat dengan rilis
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Riwayat Commit dan Analisis Perbedaan” gratis?
Ya — teks lengkap “Riwayat Commit dan Analisis Perbedaan” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Agents, upgrade ke CoddyKit PRO. Kursus AI Agents mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Riwayat Commit dan Analisis Perbedaan”?
Telusuri riwayat commit, ekstrak file yang berubah, dan rangkum perbedaannya. Kamu berlatih AI Agents dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai AI Agents?
Tidak diperlukan pengalaman sebelumnya. AI Agents di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.
Berapa lama pelajaran “Riwayat Commit dan Analisis Perbedaan” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Agents ini?
Ya. Setiap pelajaran AI Agents menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Ikhtisar GitHub REST API
- Mencantumkan dan Mengelola Isu
- Komentar Tinjauan PR Otomatis
- Riwayat Commit dan Analisis Perbedaan