Sejarah Komit dan Analisis Perbezaan
Menelusuri sejarah komit, mengekstrak fail yang berubah dan meringkaskan perbezaan.
Sejarah Komit dan Analisis Perbezaan ialah pelajaran Ejen AI percuma di CoddyKit. Ini ialah pelajaran 4 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Ejen AI, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Ejen AI merangkumi sejumlah 4 pelajaran.
Mengapa Menganalisis Sejarah Komit?
Sejarah komit merupakan sumber yang sangat bernilai untuk ejen: sejarah ini mendedahkan perkara yang berubah, masa perubahan berlaku dan pihak yang melakukannya. Ejen menggunakan sejarah komit untuk menjana log perubahan, ringkasan semakan kod, laporan aktiviti pembangun, mengesan risiko (perubahan besar yang hampir dengan keluaran) dan memahami evolusi pangkalan kod.
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()}')Menapis Komit mengikut Julat Masa
Gunakan parameter since dan until untuk mendapatkan komit dalam julat tarikh tertentu. Kedua-duanya menerima objek Python datetime. Ini ialah alat utama untuk menjana laporan aktiviti 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 Pemadaman
Setiap objek komit mempunyai sifat stats dengan kiraan perubahan additions, deletions dan total merentas semua fail yang diubah. Ini memberikan gambaran pantas tentang saiz sesuatu 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')Menyenaraikan Fail yang Diubah dalam Komit
commit.files ialah senarai objek File bagi setiap fail yang diubah dalam komit. Sifat: filename, status (ditambah/diubah suai/dialih keluar/dinamakan semula), additions, deletions, patch (teks perbezaan).
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)}')Menghuraikan Teks Perbezaan (Tampalan)
file.patch mengandungi perbezaan bersatu. Baris yang bermula dengan + ialah penambahan, baris yang bermula dengan - ialah pemadaman dan baris konteks tidak mempunyai awalan. Huraikannya untuk mengekstrak baris yang ditambahkan bagi tujuan analisis — contohnya, untuk mencari rahsia baharu, komen TODO atau anti-corak.
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)
Mengagregatkan Aktiviti mengikut Pengarang
Kumpulkan komit mengikut pengarang untuk menghasilkan laporan aktiviti pembangun. Kira jumlah komit, baris yang ditambah atau dipadam dan fail yang diubah bagi setiap pengarang dalam suatu tempoh masa. Ini berguna untuk retrospektif pasukan 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')Menjana Log Perubahan daripada Komit
Ejen log perubahan membaca komit antara dua tag atau tarikh, mengumpulkannya mengikut jenis (feat/fix/chore menggunakan format komit konvensional) dan menjana log perubahan berformat. Gunakan LLM untuk meningkatkan mutu penerangan bagi 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')Mengenal Pasti Komit Berisiko Tinggi
Komit berisiko tinggi ialah komit yang bersaiz besar, menyentuh fail kritikal (pengesahan, pembayaran, keselamatan) atau dibuat sangat hampir dengan sesuatu keluaran. Ejen boleh menandakan komit ini untuk penelitian tambahan sebelum digabungkan ke main.
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 perbezaan antara dua rujukan (cawangan, tag atau SHA komit). Ini mengembalikan objek Comparison dengan statistik gabungan, senarai komit dan senarai fail yang diubah antara kedua-dua 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 Dikuasakan LLM
Bekalkan sekumpulan mesej komit dan nama fail kepada LLM untuk menjana ringkasan yang mudah dibaca manusia tentang perkara yang berubah dalam suatu tempoh masa. Ini ialah teras bot ringkasan kejuruteraan 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].textMengesan Fail Sensitif dalam Komit
Ejen analisis komit yang berfokuskan keselamatan mengimbas komit yang secara tidak sengaja menyertakan fail sensitif: kunci peribadi, fail .env, konfigurasi dengan kelayakan atau longgokan pangkalan data. Periksa commit.files untuk mencari nama fail yang sepadan dengan corak sensitif yang 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}')Semakan Pantas: commit.files berbanding pr.get_files()
Uji pemahaman anda tentang akses kepada perbezaan komit.
Imbas Kembali Analisis Sejarah Komit
Ejen anda kini boleh menganalisis sejarah komit secara menyeluruh:
- repo.get_commits(since, until, author, sha) — menapis komit mengikut masa, pengarang atau cawangan
- commit.stats — penambahan/pemadaman/jumlah merentas semua fail yang diubah
- commit.files — butiran setiap fail termasuk tampalan (perbezaan bersatu)
- Huraikan
file.patchuntuk mengimbas baris yang ditambahkan bagi mencari rahsia, komen TODO atau anti-corak - Kumpulkan komit mengikut pengarang untuk laporan aktiviti
- repo.compare(base, head) — perbezaan antara dua rujukan (cawangan, tag, SHA)
- Gunakan LLM untuk menjana ringkasan yang mudah dibaca manusia daripada senarai mesej komit
- Tandakan komit berisiko tinggi: perubahan besar + fail kritikal + hampir dengan keluaran
Pelajari Ejen AI dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 60
- Pelajaran
- 239
Soalan Lazim
Adakah pelajaran “Sejarah Komit dan Analisis Perbezaan” percuma?
Ya — teks penuh “Sejarah Komit dan Analisis Perbezaan” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Ejen AI, tingkat taraf kepada CoddyKit PRO. Kursus Ejen AI merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Sejarah Komit dan Analisis Perbezaan”?
Menelusuri sejarah komit, mengekstrak fail yang berubah dan meringkaskan perbezaan. Anda berlatih Ejen AI menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan Ejen AI?
Tiada pengalaman terdahulu diperlukan. Pembelajaran Ejen AI di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 4 daripada 4.
Berapa lamakah pelajaran “Sejarah Komit dan Analisis Perbezaan” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran Ejen AI ini?
Ya. Setiap pelajaran Ejen AI menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- Gambaran Keseluruhan GitHub REST API
- Menyenaraikan dan Mengurus Isu
- Komen Semakan PR Automatik
- Sejarah Komit dan Analisis Perbezaan