AI Agents · บทเรียน

ประวัติการคอมมิตและการวิเคราะห์ส่วนต่าง

ไล่ดูประวัติการคอมมิต ดึงไฟล์ที่เปลี่ยนแปลง และสรุปส่วนต่าง

บทเรียน 4 จาก 413 ขั้นตอน

ประวัติการคอมมิตและการวิเคราะห์ส่วนต่าง เป็นบทเรียน AI Agents ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Agents และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใดจึงต้องวิเคราะห์ประวัติการคอมมิต

ประวัติการคอมมิตเป็นแหล่งข้อมูลล้ำค่าสำหรับเอเจนต์ เพราะเผยให้เห็นว่าอะไรเปลี่ยนแปลง เมื่อใด และโดยใคร เอเจนต์ใช้ประวัติการคอมมิตเพื่อสร้างบันทึกการเปลี่ยนแปลง สรุปการรีวิวโค้ด จัดทำรายงานกิจกรรมของผู้พัฒนา ตรวจจับความเสี่ยง เช่น การเปลี่ยนแปลงขนาดใหญ่ที่เกิดขึ้นใกล้ช่วงออกรีลีส และทำความเข้าใจวิวัฒนาการของฐานโค้ด

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()}')

กรองการคอมมิตตามช่วงเวลา

ใช้พารามิเตอร์ since และ until เพื่อรับการคอมมิตในช่วงวันที่ที่ระบุ ทั้งสองพารามิเตอร์รับอ็อบเจ็กต์ datetime ของ Python นี่คือเครื่องมือหลักสำหรับสร้างรายงานกิจกรรมรายสัปดาห์หรือรายเดือน

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
)

สถิติการคอมมิต: การเพิ่มและการลบ

อ็อบเจ็กต์การคอมมิตแต่ละรายการมีพร็อพเพอร์ตี stats ซึ่งระบุจำนวนการเปลี่ยนแปลง additions, deletions และ total รวมจากไฟล์ทั้งหมดที่เปลี่ยนแปลง ข้อมูลนี้ช่วยให้ประเมินขนาดของการเปลี่ยนแปลงได้อย่างรวดเร็ว

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')

แสดงรายการไฟล์ที่เปลี่ยนแปลงในการคอมมิต

commit.files คือรายการอ็อบเจ็กต์ File สำหรับไฟล์แต่ละไฟล์ที่เปลี่ยนแปลงในการคอมมิต พร็อพเพอร์ตีได้แก่ filename, status (เพิ่ม/แก้ไข/ลบ/เปลี่ยนชื่อ), additions, deletions และ patch (ข้อความส่วนต่าง)

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)}')

การแยกวิเคราะห์ข้อความส่วนต่าง (แพตช์)

file.patch มีส่วนต่างแบบรวม บรรทัดที่ขึ้นต้นด้วย + คือการเพิ่ม บรรทัดที่ขึ้นต้นด้วย - คือการลบ และบรรทัดบริบทจะไม่มีคำนำหน้า แยกวิเคราะห์ส่วนนี้เพื่อดึงบรรทัดที่เพิ่มออกมาวิเคราะห์ เช่น ค้นหาข้อมูลลับใหม่ ความคิดเห็น TODO หรือรูปแบบการเขียนโค้ดที่ไม่ปลอดภัย

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)

รวมกิจกรรมตามผู้เขียน

จัดกลุ่มการคอมมิตตามผู้เขียนเพื่อสร้างรายงานกิจกรรมของผู้พัฒนา นับจำนวนการคอมมิต บรรทัดที่เพิ่มหรือลบ และไฟล์ที่ผู้เขียนแต่ละคนแก้ไขภายในช่วงเวลาที่กำหนด ข้อมูลนี้มีประโยชน์สำหรับการทบทวนผลงานของทีมและการตัดสินใจมอบหมาย 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')

สร้างบันทึกการเปลี่ยนแปลงจากการคอมมิต

เอเจนต์สำหรับสร้างบันทึกการเปลี่ยนแปลงจะอ่านการคอมมิตระหว่างแท็กหรือวันที่สองจุด จัดกลุ่มตามประเภท (feat/fix/chore ตามรูปแบบ conventional commit) แล้วสร้างบันทึกการเปลี่ยนแปลงที่จัดรูปแบบแล้ว ใช้ LLM เพื่อปรับปรุงคุณภาพคำอธิบายของการคอมมิตแต่ละรายการ

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')

ระบุการคอมมิตที่มีความเสี่ยงสูง

การคอมมิตที่มีความเสี่ยงสูงคือการคอมมิตที่มีขนาดใหญ่ แก้ไขไฟล์สำคัญ เช่น ไฟล์การยืนยันตัวตน การชำระเงิน หรือความปลอดภัย หรือเกิดขึ้นใกล้ช่วงออกรีลีสมาก เอเจนต์สามารถทำเครื่องหมายรายการเหล่านี้เพื่อให้ตรวจสอบเพิ่มเติมก่อนผสานเข้ากับสาขาหลัก

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}')

เปรียบเทียบการคอมมิตสองรายการ

ใช้ repo.compare(base, head) เพื่อรับส่วนต่างระหว่างข้อมูลอ้างอิงสองรายการ เช่น สาขา แท็ก หรือค่า SHA ของการคอมมิต ฟังก์ชันนี้จะส่งคืนอ็อบเจ็กต์ Comparison ซึ่งมีสถิติรวม รายการการคอมมิต และรายการไฟล์ที่เปลี่ยนแปลงระหว่างจุดทั้งสอง

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

ส่งชุดข้อความการคอมมิตและชื่อไฟล์ให้ LLM เพื่อสร้างสรุปที่มนุษย์อ่านเข้าใจได้ว่าเกิดการเปลี่ยนแปลงอะไรขึ้นในช่วงเวลาหนึ่ง นี่คือแกนหลักของบอตสรุปงานวิศวกรรมรายสัปดาห์

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].text

ตรวจจับไฟล์ที่มีข้อมูลอ่อนไหวในการคอมมิต

เอเจนต์วิเคราะห์การคอมมิตที่เน้นความปลอดภัยจะสแกนหาการคอมมิตที่เผลอรวมไฟล์ที่มีข้อมูลอ่อนไหว เช่น คีย์ส่วนตัว ไฟล์ .env ไฟล์การกำหนดค่าที่มีข้อมูลรับรอง หรือไฟล์สำรองฐานข้อมูล ตรวจสอบ commit.files เพื่อค้นหาชื่อไฟล์ที่ตรงกับรูปแบบข้อมูลอ่อนไหวที่รู้จัก

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}')

ตรวจสอบอย่างรวดเร็ว: commit.files เทียบกับ pr.get_files()

ทดสอบความเข้าใจเกี่ยวกับการเข้าถึงส่วนต่างของการคอมมิต

สรุปการวิเคราะห์ประวัติการคอมมิต

ตอนนี้เอเจนต์ของคุณสามารถวิเคราะห์ประวัติการคอมมิตได้อย่างครอบคลุมแล้ว:

  • repo.get_commits(since, until, author, sha) — กรองการคอมมิตตามเวลา ผู้เขียน หรือสาขา
  • commit.stats — จำนวนการเพิ่ม/ลบ/ทั้งหมดจากไฟล์ที่เปลี่ยนแปลงทั้งหมด
  • commit.files — รายละเอียดระดับไฟล์ รวมถึงแพตช์ (ส่วนต่างแบบรวม)
  • แยกวิเคราะห์ file.patch เพื่อสแกนบรรทัดที่เพิ่มหาข้อมูลลับ TODO หรือรูปแบบการเขียนโค้ดที่ไม่ปลอดภัย
  • จัดกลุ่มการคอมมิตตามผู้เขียนเพื่อสร้างรายงานกิจกรรม
  • repo.compare(base, head) — ส่วนต่างระหว่างข้อมูลอ้างอิงสองรายการ เช่น สาขา แท็ก หรือค่า SHA
  • ใช้ LLM เพื่อสร้างสรุปที่มนุษย์อ่านเข้าใจได้จากรายการข้อความการคอมมิต
  • ทำเครื่องหมายการคอมมิตที่มีความเสี่ยงสูง ได้แก่ การเปลี่ยนแปลงขนาดใหญ่ ไฟล์สำคัญ และช่วงเวลาที่ใกล้รีลีส
เริ่มต้นได้ฟรี

เรียนรู้ AI Agents ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
60
บทเรียน
239

คำถามที่พบบ่อย

บทเรียน “ประวัติการคอมมิตและการวิเคราะห์ส่วนต่าง” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ประวัติการคอมมิตและการวิเคราะห์ส่วนต่าง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Agents ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ประวัติการคอมมิตและการวิเคราะห์ส่วนต่าง”

ไล่ดูประวัติการคอมมิต ดึงไฟล์ที่เปลี่ยนแปลง และสรุปส่วนต่าง คุณปฏิบัติ AI Agents ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Agents หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Agents บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “ประวัติการคอมมิตและการวิเคราะห์ส่วนต่าง” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน AI Agents นี้ได้ไหม

ได้ บทเรียน AI Agents ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ภาพรวม GitHub REST API
  2. การแสดงรายการและจัดการประเด็น
  3. ความคิดเห็นตรวจสอบ PR อัตโนมัติ
  4. ประวัติการคอมมิตและการวิเคราะห์ส่วนต่าง
← กลับไปที่ AI Agents