Cronologia dei commit e analisi dei diff
Scorrimento della cronologia dei commit, estrazione dei file modificati e riepilogo dei diff
Cronologia dei commit e analisi dei diff è una lezione AI Agents gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Agents, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Agents include 4 lezioni in totale.
Perché analizzare la cronologia dei commit
La cronologia dei commit è una vera miniera d'oro per gli agenti: rivela che cosa è cambiato, quando e ad opera di chi. Gli agenti utilizzano la cronologia dei commit per generare changelog, riepiloghi delle revisioni del codice, report sull'attività degli sviluppatori, rilevare i rischi (modifiche consistenti a ridosso dei rilasci) e comprendere l'evoluzione di una codebase.
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()}')Filtrare i commit per intervallo di tempo
Utilizzi i parametri since e until per ottenere i commit in un intervallo di date specifico. Entrambi accettano oggetti Python datetime. Questo è lo strumento principale per generare report settimanali o mensili sull'attività.
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
)Statistiche dei commit: aggiunte e rimozioni
Ogni oggetto commit ha una proprietà stats con i conteggi delle modifiche additions, deletions e total relativi a tutti i file modificati. In questo modo è possibile farsi rapidamente un'idea delle dimensioni di una modifica.
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')Elencare i file modificati in un commit
commit.files è un elenco di oggetti File, uno per ogni file modificato nel commit. Proprietà: filename, status (added/modified/removed/renamed), additions, deletions, patch (il testo del diff).
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)}')Analizzare il testo del diff (patch)
file.patch contiene un diff unificato. Le righe che iniziano con + sono aggiunte, quelle con - sono rimozioni e le righe di contesto non hanno prefisso. Lo analizzi per estrarre le righe aggiunte, ad esempio per trovare nuovi segreti, commenti TODO o anti-pattern.
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)
Aggregare l'attività per autore
Raggruppi i commit per autore per produrre report sull'attività degli sviluppatori. Conteggi i commit, le righe aggiunte e rimosse e i file modificati da ciascun autore in un determinato intervallo di tempo. Questo è utile per le retrospettive del team e per decidere a chi assegnare le 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')Generare un changelog dai commit
Un agente per la generazione del changelog legge i commit compresi tra due tag o date, li raggruppa per tipo (feat/fix/chore secondo il formato dei conventional commit) e genera un changelog formattato. Utilizzi un LLM per migliorare la qualità della descrizione di ogni commit.
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')Individuare i commit ad alto rischio
I commit ad alto rischio sono quelli di grandi dimensioni, che modificano file critici (autenticazione, pagamenti, sicurezza) o che vengono creati molto a ridosso di un rilascio. Un agente può segnalarli per sottoporli a un controllo più approfondito prima dell'unione in 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}')Confrontare due commit
Utilizzi repo.compare(base, head) per ottenere il diff tra due riferimenti (branch, tag o SHA di commit). Restituisce un oggetto Comparison con le statistiche complessive, l'elenco dei commit e l'elenco dei file modificati tra i due punti.
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')Riepilogo dei commit generato da un LLM
Fornisca a un LLM un insieme di messaggi di commit e nomi di file per generare un riepilogo comprensibile da una persona delle modifiche apportate in un determinato periodo. Questo costituisce il nucleo di un bot per il riepilogo settimanale dell'attività di sviluppo.
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].textRilevare i file sensibili nei commit
Un agente di analisi dei commit incentrato sulla sicurezza cerca i commit che includono accidentalmente file sensibili: chiavi private, file .env, configurazioni con credenziali o dump di database. Controlli in commit.files i nomi dei file che corrispondono a pattern sensibili noti.
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}')Verifica rapida: commit.files e pr.get_files()
Verifichi la Sua comprensione dell'accesso ai diff dei commit.
Riepilogo dell'analisi della cronologia dei commit
Ora il Suo agente è in grado di analizzare in modo completo la cronologia dei commit:
- repo.get_commits(since, until, author, sha) — filtra i commit per data, autore o branch
- commit.stats — aggiunte/rimozioni/totale per tutti i file modificati
- commit.files — dettagli per file, incluso il patch (diff unificato)
- Analizzi
file.patchper cercare segreti, TODO o anti-pattern nelle righe aggiunte - Raggruppi i commit per autore per generare report sull'attività
- repo.compare(base, head) — diff tra due riferimenti (branch, tag, SHA)
- Utilizzi gli LLM per generare riepiloghi comprensibili da una persona a partire dagli elenchi dei messaggi di commit
- Segnali i commit ad alto rischio: modifiche consistenti, file critici e prossimità ai rilasci
Domande Frequenti
La lezione «Cronologia dei commit e analisi dei diff» è gratuita?
Sì — il testo completo di «Cronologia dei commit e analisi dei diff» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Agents, passa a CoddyKit PRO. Il corso AI Agents include 4 lezioni in totale.
Cosa imparerò in «Cronologia dei commit e analisi dei diff»?
Scorrimento della cronologia dei commit, estrazione dei file modificati e riepilogo dei diff Eserciti AI Agents con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare AI Agents?
Non è richiesta alcuna esperienza precedente. AI Agents su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Cronologia dei commit e analisi dei diff»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione AI Agents?
Sì. Ogni lezione AI Agents include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Panoramica della GitHub REST API
- Elenco e gestione delle issue
- Commenti automatizzati nelle PR
- Cronologia dei commit e analisi dei diff