Free lesson · LLMOps Engineering

AI ప్రాజెక్ట్‌ల కోసం trunk-based development అమలు చేయండి

మీరు GKE పై AI/ML ప్రాజెక్ట్‌ల కోసం ఆప్టిమైజ్ చేసిన Git branching strategyని సెటప్ చేస్తారు. main ఎల్లప్పుడూ deployable గా ఉండేలా trunk-based workflowను కాన్ఫిగర్ చేయండి. ఈ naming conventionsతో short-lived feature branchesను సృష్టించండి: feature/add-prompt-template, fix/embedding-pipeline, config/model-parameters. branch lifecycleను అమలు చేయండి: mainనుండి create చేయండి, commitsను push చేయండి, PR తెరవండి, తిరిగి mainలోకి squash merge చేయండి, branchను తొలగించండి. డిఫాల్ట్‌గా rebaseను ఉపయోగించేలా gitను కాన్ఫిగర్ చేయండి (git config pull.rebase true). ఒక prompt template మార్పుతో workflowను end-to-end గా ప్రదర్శించండి.

Course: DevOps Foundations for GenAI Engineers · Chapter 1 · Git Workflows for AI Teams

Free to read — no subscription required.

పరిచయం

ఒక వారం పాటు డ్రిఫ్ట్ అయ్యే feature branches నుండి మీరు prompts, training JSONL, మరియు model configs ను షిప్ చేసినప్పుడు — ఒకే ఫైల్‌కు training rows జోడించిన లేదా వేర్వేరు branches లో అదే prompt version ను బంప్ చేసిన ఇద్దరు ఇంజనీర్‌లను Git సమన్వయం చేయలేదని merge సమయంలో మీరు గ్రహిస్తారు. ఈ conflict surface ను merge చేయడం అసాధ్యం: ప్రతి JSONL లైన్ అర్థపరంగా స్వతంత్రమైనది, మరియు prompt registry entries అనేవి point-in-time వాస్తవాలు — three-way-merge చేయాల్సిన టెక్స్ట్ కాదు. branches ను 48 గంటలకు మించి పాతబడనిచ్చే జట్లు దీన్ని పోగొట్టుకున్న sprint రోజుల రూపంలో, మరియు తప్పుగా జరిగిన merges తర్వాత eval scores లో నిశ్శబ్ద regressions రూపంలో చెల్లిస్తాయి.

ఈ పాఠం ముగిసే సమయానికి మీరు ఒక AI codebase పై trunk-based క్రమశిక్షణను అమలు చేయగలుగుతారు: branches ను ఉద్దేశం ప్రకారం పేరు పెట్టడం (feat, data, fix, infra, deps), push సమయంలో ఒక Git hook తో పేర్లను మరియు వయస్సులను validate చేయడం, మరియు prompt మరియు data మార్పులు atomic గా మరియు bisectable గా ఉండేలా branch type ప్రకారం merge strategy ను configure చేయడం.

ముఖ్య పరిభాష

  • Trunk — ఎల్లప్పుడూ deployable గా ఉండే ఏకైక భాగస్వామ్య branch (సాధారణంగా main); ప్రతి commit schema, evaluation, మరియు infrastructure validation ను ట్రిగ్గర్ చేస్తుంది, కాబట్టి trunk అనేది prompts, models, మరియు configs కు source of truth.
  • Short-lived feature branch — trunk కు తిరిగి merge అయ్యే ముందు గరిష్ఠంగా 48 గంటలు మాత్రమే జీవించే branch; ఈ సమయ పరిమితే prompt మరియు JSONL drift ను యాంత్రికంగా పరిష్కరించగలిగేంత చిన్నదిగా ఉంచుతుంది.
  • Squash merge — ఒక feature branch పైని ప్రతి commit ను trunk పై ఒకే atomic commit గా కూల్చివేస్తుంది, తద్వారా git bisect అనేది WIP saves బదులుగా "add summarization prompt v3" లాంటి అర్థవంతమైన units పై దిగుతుంది.
  • Branch protection rule — remote (GitHub/GitLab) పైని server-side policy, ఇది branch pattern ప్రకారం required checks మరియు merge strategy పై merges ను gate చేస్తుంది, కాబట్టి ఒక local hook ను bypass చేసినప్పటికీ policy నిలబడుతుంది.
  • Prompt registry — trunk పైని ఒక tracked JSON ఫైల్ (ఉదా. prompt_registry.json), ఇది prompt IDs ను version numbers మరియు file paths కు మ్యాప్ చేస్తుంది; "ఒక branch కు ఒక version bump" అనే నియమం regressions ను సులభంగా ఆపాదించదగినవిగా చేస్తుంది.

భావనలు

integration ను నిరంతరంగా చేయడం మరియు prompt/data మార్పులను atomic గా చేయడం లక్ష్యం. అక్కడికి చేరుకోవడానికి మూడు ఆలోచనలు కలుస్తాయి: ఉద్దేశాన్ని encode చేసే ఒక branch taxonomy, drift ను పరిమితం చేసే 48-గంటల జీవితకాలం, మరియు auditability ను కాపాడే per-category merge strategy. ఈ ఆలోచనలను ఆచరణలో పెట్టే branch validator మరియు pre-push hook code లో చూపబడ్డాయి (Code Walkthrough చూడండి).

AI codebases కు short-lived branches ఎందుకు ముఖ్యం

AI repositories long-lived branches ను విరిచే మూడు artifact classes ను కలిగి ఉంటాయి. Prompt మరియు config ఫైల్‌లు భాగస్వామ్య blocks — ఇక్కడ సమాంతర edits ఢీకొంటాయి. JSONL training ఫైల్‌లు append ద్వారా పెరుగుతాయి, మరియు వేర్వేరు rows ను append చేసే రెండు branches — Git flag చేసినా సరిగ్గా పరిష్కరించలేని overlapping diffs ను ఉత్పత్తి చేస్తాయి — reproducibility కు లైన్ క్రమం ముఖ్యం. Dependency graphs దట్టంగా ఉంటాయి: serving config అనేది preprocessing పై ఆధారపడి ఉంటుంది, అది feature-store schema పై ఆధారపడి ఉంటుంది, కాబట్టి ఈ మూడింటిలో ఏది ఒంటరిగా పరిణామం చెందినా ఒక బాధాకరమైన rebase ను హామీ ఇస్తుంది.

branch జీవితాన్ని 48 గంటలకు పరిమితం చేయడం conflict window ను కుదిస్తుంది. Work-in-progress అనేది పార్క్ చేసిన branches పై కాకుండా trunk పైని feature flags వెనుక ఉంటుంది. Renovate మరియు Dependabot PRs శుభ్రంగా దిగుతాయి — ఎందుకంటే అవి apply అయ్యే ముందు లోతైన rebase అవసరమయ్యేంత పాతబడిన human branch ఏదీ ఉండదు.

Branch taxonomy ఉద్దేశాన్ని encode చేస్తుంది

ఒక naming convention అనేది branch పేర్లను hooks మరియు CI కు routable metadata గా మారుస్తుంది. ప్రతి branch type ఒక వేర్వేరు validation lane ను ట్రిగ్గర్ చేస్తుంది: feat/prompt-* eval suites ను నడుపుతుంది, data/* schema మరియు row-count checks ను నడుపుతుంది, fix/* పూర్తి regression ను నడుపుతుంది, infra/* IaC plan/apply ను నడుపుతుంది, deps/* build + dependency audit ను నడుపుతుంది.

Loading diagram...

మూడు short-lived branches ఒకే sprint cycle లోపు trunk కు తిరిగి merge అవుతాయి. ఏ branch కూడా ఒక పని దినానికి మించి మరొకదానితో సహ-అస్తిత్వంలో ఉండదు — ఇదే JSONL మరియు prompt ఫైల్‌లలో బాధాకరమైన merge conflicts కు కారణమయ్యే drift ను నివారిస్తుంది.

Squash merge vs merge commit

Squash merge అనేది feat, data, fix, మరియు infra branches కు default — ఎందుకంటే trunk అనేది "wip" → "fix typo" → "actually fix it" గా కాకుండా atomic, bisectable మార్పుల శ్రేణిగా చదవాలి — "add summarization prompt v3". deps/* కింది branches స్పష్టమైన మినహాయింపు: Renovate మరియు Dependabot downstream audit tooling parse చేసే structured changelog metadata (package name, version range, changelog URL) ను commit messages లో పొందుపరుస్తాయి, కాబట్టి ఆ branches ఒక నిజమైన merge commit తో merge అవుతాయి. మొదటి నాలుగు prefixes కు squash అవసరమయ్యేలా మరియు merge commits కేవలం deps/* కు మాత్రమే అనుమతించబడేలా branch protection ను configure చేయండి.

ఒక branch కు ఒక prompt bump

ప్రతి feature branch prompt_registry.json లో సరిగ్గా ఒక prompt version ను పెంచుతుంది మరియు దాని eval results ను పక్కనే షిప్ చేస్తుంది. branches చిన్నవి మరియు scope బిగుతుగా ఉన్నందున, registry conflicts వేర్వేరు keys పై concurrent increments కు తగ్గిపోతాయి — ఒక అరరోజు దర్యాప్తు కాదు, 30-సెకన్ల reconcile. deploy తర్వాత ఒక eval metric పడిపోయినప్పుడు, trunk పైని git log --oneline సరిగ్గా ఒక prompt మార్పును సూచిస్తుంది.

Code Walkthrough

కింది రెండు snippets — Concepts విభాగం నుండి branch taxonomy, 48-గంటల జీవితకాలం, మరియు local enforcement layer ను ఆచరణలో పెడతాయి. మొదటిది regex patterns మరియు age check తో validator ను నిర్వచిస్తుంది; రెండవది దాన్ని ఒక pre-push hook లోకి wire చేస్తుంది — తద్వారా పాతబడిన లేదా off-pattern branch remote కు చేరకముందే policy fire అవుతుంది.

Code snippetpython
1import re 2import subprocess 3from datetime import datetime, timezone 4from dataclasses import dataclass 5from typing import Optional 6 7BRANCH_PATTERNS = { 8 "feature": re.compile(r"^feat/(prompt|model|pipeline|serve)-[\w-]{3,50}$"), 9 "data": re.compile(r"^data/(training|eval|validation)-[\w-]{3,50}$"), 10 "fix": re.compile(r"^fix/[\w-]{3,50}$"), 11 "infra": re.compile(r"^infra/(gke|helm|terraform)-[\w-]{3,50}$"), 12 "deps": re.compile(r"^deps/(renovate|dependabot)-[\w-]{3,50}$"), 13} 14MAX_BRANCH_AGE_HOURS = 48 15 16@dataclass 17class BranchMetadata: 18 category: str 19 is_valid: bool 20 age_hours: Optional[float] = None 21 is_stale: bool = False 22 23def validate_branch_name(branch: str) -> BranchMetadata: 24 for category, pattern in BRANCH_PATTERNS.items(): 25 if pattern.match(branch): 26 return BranchMetadata(category=category, is_valid=True) 27 return BranchMetadata(category="unknown", is_valid=False) 28 29def get_branch_age_hours(branch: str) -> Optional[float]: 30 result = subprocess.run( 31 ["git", "log", "-1", "--format=%cI", branch], 32 capture_output=True, text=True, 33 ) 34 if result.returncode != 0: 35 return None 36 created = datetime.fromisoformat(result.stdout.strip()) 37 return (datetime.now(timezone.utc) - created).total_seconds() / 3600 38 39def enforce_branch_policy(branch: str) -> BranchMetadata: 40 metadata = validate_branch_name(branch) 41 if not metadata.is_valid: 42 return metadata 43 metadata.age_hours = get_branch_age_hours(branch) 44 if metadata.age_hours is not None and metadata.age_hours > MAX_BRANCH_AGE_HOURS: 45 metadata.is_stale = True 46 return metadata

BRANCH_PATTERNS అనేది Concepts విభాగం నుండి taxonomy ను encode చేస్తుంది: subcategory tokens (prompt, training, gke, మొదలైనవి) ఇంజనీర్‌లను branch పేరులో ఉద్దేశాన్ని ప్రకటించమని బలవంతం చేస్తాయి. MAX_BRANCH_AGE_HOURS = 48 అనేది policy knob — దాన్ని పెంచడం short-lived క్రమశిక్షణను సడలిస్తుంది. enforce_branch_policy రెండు checks ను కలుపుతుంది; get_branch_age_hours అనేది branch tip యొక్క committer date (ISO 8601) ను చదివి గంటలను float గా తిరిగి ఇస్తుంది — branch లేకపోతే exception raise చేయకుండా None ను తిరిగి ఇస్తుంది.

Code snippetpython
1import sys 2import subprocess 3from branch_validator import enforce_branch_policy 4 5def get_current_branch() -> str: 6 result = subprocess.run( 7 ["git", "rev-parse", "--abbrev-ref", "HEAD"], 8 capture_output=True, text=True, 9 ) 10 return result.stdout.strip() 11 12def main() -> int: 13 branch = get_current_branch() 14 if branch == "main": 15 return 0 16 metadata = enforce_branch_policy(branch) 17 if not metadata.is_valid: 18 print(f"ERROR: '{branch}' does not match any allowed pattern.") 19 print("Allowed: feat/(prompt|model|pipeline|serve)-..., data/(training|eval|validation)-...,") 20 print(" fix/..., infra/(gke|helm|terraform)-..., deps/(renovate|dependabot)-...") 21 return 1 22 if metadata.is_stale: 23 print(f"WARNING: '{branch}' is {metadata.age_hours:.1f}h old; merge or delete.") 24 return 1 25 print(f"Branch policy OK: [{metadata.category}] {branch}") 26 return 0 27 28if __name__ == "__main__": 29 sys.exit(main())

ఈ hook git rev-parse --abbrev-ref HEAD తో ప్రస్తుత branch ను పరిష్కరిస్తుంది, trunk కు CI merge commits ప్రభావితం కాకుండా ఉండేలా main పై short-circuit చేస్తుంది, మరియు invalid names లేదా stale branches — ఏదైనా కోసం exit code 1 ను తిరిగి ఇస్తుంది. దాన్ని .git/hooks/pre-push గా (లేదా pre-push stage కింద pre-commit framework ద్వారా) ఇన్‌స్టాల్ చేయండి, మరియు feat/*, data/*, fix/*, infra/* కు squash merges అవసరమయ్యేలా మరియు merge commits కేవలం deps/* కు మాత్రమే అనుమతించే server-side branch protection rules తో దాన్ని జోడించండి.

(1) wip-stuff ను push చేయడం allowed-patterns help text తో తిరస్కరించబడినప్పుడు, (2) 50-గంటల పాత feat/prompt-foo ను push చేయడం గంటల్లో వయస్సుతో తిరస్కరించబడినప్పుడు, (3) valid, తాజా feat/prompt-foo ను push చేయడం OK లైన్‌ను print చేసినప్పుడు, మరియు (4) trunk పైని prompt_registry.json ప్రతి merge అయిన branch కు సరిగ్గా ఒక version bump ను చూపించినప్పుడు — ఇది పని చేస్తోందని మీకు తెలుస్తుంది.

Do's and Don'ts

Do's

  1. ✓feat/data/fix/infra branches ను squash-merge చేయండి — WIP commits ను trunk పై ఒకే bisectable మార్పుగా కూల్చివేస్తుంది, తద్వారా eval regressions ఒకే prompt లేదా data delta ను సూచిస్తాయి.
  2. ✓merge commits ను కేవలం deps/* branches కు మాత్రమే అనుమతించండి — Renovate మరియు Dependabot audit tooling parse చేసే structured changelog metadata ను commit messages లో పొందుపరుస్తాయి; squashing దాన్ని ధ్వంసం చేస్తుంది.
  3. ✓ఒక branch కు సరిగ్గా ఒక prompt version ను bump చేయండి — prompt_registry.json conflicts ను తేలికగా ఉంచుతుంది మరియు trunk పైని git log --oneline ను ఒక ఖచ్చితమైన change history గా చేస్తుంది.

Don'ts

  1. ✗ఏ branch ను కూడా 48 గంటలకు మించి జీవించనివ్వకండి — JSONL appends మరియు prompt edits — Git ఆటోమేటిక్‌గా పరిష్కరించలేని drift ను పోగుచేస్తాయి; rebase మరియు merge చేయండి, లేదా branch ను తొలగించండి.
  2. ✗భాగస్వామ్య branches ను force-push చేయకండి — teammates కింద history ను తిరిగి రాయడం వారి rebases ను విరిచి, trunk-based development ఆధారపడే audit trail ను ధ్వంసం చేస్తుంది.
  3. ✗భాగస్వామ్య branches పై --no-verify తో pre-push hook ను bypass చేయకండి — ఈ hook అనేది local enforcement layer; దాన్ని దాటవేస్తే stale లేదా off-pattern names remote కు చేరతాయి, server-side branch protection ను ఏకైక రక్షణగా మిగుల్చుతాయి.

3 hands-on labs come with this lesson — real code, in a cloud IDE. Create a free account to run them. No card.

Free account · no card · straight to the labs

Or get the full path — from

Listen to this lesson

Audio overviews of this lesson's labs and its chapter, from GenBodha Bytes.

More free lessons in DevOps Foundations for GenAI Engineers

All free lessons in LLMOps Engineering →