Commit-historian ja diffien analyysi
Commit-historian läpikäynti, muuttuneiden tiedostojen poiminta ja diffien tiivistäminen
Commit-historian ja diffien analyysi on ilmainen Tekoälyagentit-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Tekoälyagentit-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Tekoälyagentit-kurssilla on yhteensä 4 oppituntia.
Miksi commit-historiaa analysoidaan
Commit-historia on agenteille aarreaitta: siitä käy ilmi, mitä muuttui, milloin ja kenen toimesta. Agentit käyttävät commit-historiaa muutoslokien luomiseen, koodikatselmointien yhteenvetoihin, kehittäjien aktiivisuusraportteihin, riskien tunnistamiseen (suuret muutokset lähellä julkaisuja) ja koodikannan kehityksen ymmärtämiseen.
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()}')Commitien suodattaminen aikavälin perusteella
Käytä since- ja until-parametreja hakeaksesi commitit tietyltä päivämääräväliksi. Molemmat vastaanottavat Pythonin datetime-objekteja. Tämä on ensisijainen työkalu viikoittaisten tai kuukausittaisten aktiivisuusraporttien luomiseen.
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
)Commit-tilastot: lisäykset ja poistot
Jokaisella commit-objektilla on stats-ominaisuus, joka sisältää kaikkien muuttuneiden tiedostojen yhteenlasketut additions-, deletions- ja total-muutosmäärät. Näin muutoksen koosta saa nopeasti käsityksen.
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')Commitissa muuttuneiden tiedostojen luetteleminen
commit.files on luettelo File-objekteista, yhden jokaista commitissa muuttunutta tiedostoa kohti. Ominaisuudet ovat filename, status (added/modified/removed/renamed), additions, deletions ja patch (diff-teksti).
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)}')Diff- eli patch-tekstin jäsentäminen
file.patch sisältää unified diff -esityksen. Merkillä + alkavat rivit ovat lisäyksiä, merkillä - alkavat poistettavia rivejä, eikä kontekstiriveillä ole etuliitettä. Jäsennä teksti lisättyjen rivien poimimiseksi analyysia varten — esimerkiksi uusien salaisuuksien, TODO-kommenttien tai tietoturvan vastaisten käytäntöjen löytämiseksi.
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)
Aktiviteetin koostaminen tekijän mukaan
Ryhmittele commitit tekijän mukaan kehittäjien aktiivisuusraportteja varten. Laske kunkin tekijän commitit, lisätyt ja poistetut rivit sekä käsiteltyjen tiedostojen määrä tietyltä aikaväliltä. Tämä on hyödyllistä tiimien retrospektiiveissä ja PR-katselmointien jakamista koskevissa päätöksissä.
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')Muutoslokin luominen commitien perusteella
Muutoslokiagentti lukee commitit kahden tagin tai päivämäärän väliltä, ryhmittelee ne tyypin mukaan (feat/fix/chore conventional commit -muotoa käyttäen) ja luo muotoillun muutoslokin. Käytä LLM:ää kunkin commitin kuvauksen laadun parantamiseen.
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')Suuren riskin commitien tunnistaminen
Suuren riskin commitit ovat suuria, kriittisiin tiedostoihin (todennus, maksaminen, tietoturva) vaikuttavia tai hyvin lähellä julkaisua tehtyjä committeja. Agentti voi merkitä ne tarkempaa tarkastelua varten ennen yhdistämistä main-haaraan.
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}')Kahden commitin vertaaminen
Käytä repo.compare(base, head)-kutsua saadaksesi kahden ref-viitteen (haaran, tagin tai commit SHA:n) välisen diffin. Tämä palauttaa Comparison-objektin, joka sisältää yhdistetyt tilastot, commit-luettelon ja näiden kahden kohdan välillä muuttuneiden tiedostojen luettelon.
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')LLM:n tuottama commit-yhteenveto
Syötä LLM:lle joukko commit-viestejä ja tiedostonimiä, jotta se voi luoda ihmisen luettavissa olevan yhteenvedon tietyn ajanjakson muutoksista. Tämä on viikoittaisen kehitystyön koontibotin ydin.
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].textArkaluonteisten tiedostojen tunnistaminen commitien joukosta
Tietoturvaan keskittyvä commit-analyysiagentti etsii committeja, joihin on vahingossa sisällytetty arkaluonteisia tiedostoja: yksityisiä avaimia, .env-tiedostoja, tunnistetietoja sisältäviä määrityksiä tai tietokantavedoksia. Tarkista commit.files tiedostonimien osalta, jotka vastaavat tunnettuja arkaluonteisten tiedostojen malleja.
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}')Pikatarkistus: commit.files ja pr.get_files()
Testaa ymmärrystäsi commit-diffien käsittelystä.
Commit-historian analyysin yhteenveto
Agenttisi osaa nyt analysoida commit-historiaa kattavasti:
- repo.get_commits(since, until, author, sha) — suodata committeja ajan, tekijän tai haaran perusteella
- commit.stats — kaikkien muuttuneiden tiedostojen lisäykset, poistot ja kokonaismäärä
- commit.files — tiedostokohtaiset tiedot, mukaan lukien patch (unified diff)
- Jäsennä
file.patchja etsi lisätyiltä riveiltä salaisuuksia, TODO-kommentteja tai tietoturvan vastaisia käytäntöjä - Ryhmittele commitit tekijän mukaan aktiivisuusraportteja varten
- repo.compare(base, head) — kahden ref-viitteen (haaran, tagin tai SHA:n) välinen diff
- Luo LLM:ien avulla ihmisen luettavissa olevia yhteenvetoja commit-viestiluetteloista
- Merkitse suuren riskin commitit: suuret muutokset + kriittiset tiedostot + läheinen ajankohta julkaisuun
Opi Tekoälyagentit tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 60
- Oppitunnit
- 239
Usein kysytyt kysymykset
Onko oppitunti ”Commit-historian ja diffien analyysi” ilmainen?
Kyllä – oppitunnin ”Commit-historian ja diffien analyysi” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Tekoälyagentit-kurssin, päivitä CoddyKit PROhon. Tekoälyagentit-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Commit-historian ja diffien analyysi”?
Commit-historian läpikäynti, muuttuneiden tiedostojen poiminta ja diffien tiivistäminen Harjoittelet Tekoälyagentit-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Tekoälyagentit-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Tekoälyagentit-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.
Kuinka kauan ”Commit-historian ja diffien analyysi”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Tekoälyagentit-oppitunnilla?
Kyllä. Jokainen Tekoälyagentit-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- GitHub REST API:n yleiskatsaus
- Issuejen luettelointi ja hallinta
- Automaattiset PR-katselmointikommentit
- Commit-historian ja diffien analyysi