Controlul Versiunilor Git: Referința Tehnică Completă pentru Dezvoltatori
Git este un sistem de control al versiunilor distribuit (DVCS) care înregistrează instantanee ale arborelui de fișiere al unui proiect în timp, permițând oricărui număr de colaboratori să lucreze în paralel fără a suprascrie modificările celorlalți. Fiecare dezvoltator deține o copie completă a depozitului — inclusiv întregul istoric al commit-urilor — pe mașina sa locală, eliminând orice punct unic de defecțiune și permițând fluxuri de lucru complet offline.
Creat de Linus Torvalds în aprilie 2005 pentru a înlocui BitKeeper în dezvoltarea nucleului Linux, Git a fost conceput de la zero în jurul a trei cerințe non-negociabile: viteză, integritatea datelor și suport pentru fluxuri de lucru neliniare și distribuite. Aceste obiective de proiectare definesc în continuare ceea ce face Git categoric diferit de predecesorii săi și de ce rămâne VCS-ul dominant la mai mult de două decenii după creare.
Cum diferă Git de controlul centralizat al versiunilor
Înțelegerea arhitecturii Git necesită o comparație directă cu sistemele centralizate precum Subversion (SVN) sau CVS, unde un singur server autoritar deține depozitul canonic, iar dezvoltatorii extrag copii de lucru superficiale.
| Dimensiune | Git (Distribuit) | SVN (Centralizat) |
|---|---|---|
| — | — | — |
| Model de depozit | Clonă completă pe fiecare nod | Copie de lucru superficială, serverul deține istoricul |
| Capacitate offline | Commit, branch, diff, log complet | Doar citire; commit-urile necesită server |
| Costul ramificării | Aproape zero (manipulare de pointeri) | Copiere costisitoare de directoare |
| Punct unic de defecțiune | Niciunul — orice clonă poate restaura | Întreruperea serverului oprește toate commit-urile |
| Strategie de fuzionare | Fuzionare în trei căi + rebase | Doar fuzionare în trei căi |
| Integritatea istoricului | Hashing de conținut SHA-1/SHA-256 | Numere de revizuire secvențiale |
| Dependența de rețea | Doar pentru push/pull/fetch | Aproape fiecare operațiune |
| Checkout parțial | Nu este suportat nativ | Suportat (checkout selectiv) |
| Curba de învățare | Curbă inițială mai abruptă | Mai ușoară pentru veteranii SVN |
| Adoptare (2024) | ~95% dintre echipele profesionale | Medii enterprise moștenite |
Modelul distribuit înseamnă că, chiar dacă o platformă de găzduire precum GitHub experimentează o întrerupere, clona locală a fiecărui dezvoltator este o copie de rezervă completă și autoritară a întregului istoric al proiectului.
Arhitectura de bază: Ce stochează de fapt Git
Git nu stochează diff-uri. Stochează instantanee. Fiecare commit indică un obiect tree care reprezintă starea completă a fiecărui fișier urmărit în acel moment. Dacă un fișier nu s-a modificat între două commit-uri, Git stochează un pointer către blob-ul anterior în loc să îl duplice — astfel Git obține atât completitudine, cât și eficiență de stocare.
Cele patru tipuri fundamentale de obiecte din depozitul de obiecte Git (.git/objects/) sunt:
- Blob — conținut brut al fișierului, adresat prin hash SHA
- Tree — o listă de directoare care mapează numele fișierelor la hash-uri de blob sau subtree
- Commit — un pointer către un tree, zero sau mai multe commit-uri părinte, metadate despre autor și un mesaj
- Tag — un pointer adnotat către un commit specific, utilizat pentru marcatori de versiune
Fiecare obiect este imuabil și adresat prin conținut. Modificarea unui singur byte în orice fișier produce un hash SHA complet diferit, care se propagă în sus prin obiectele tree și commit. De aceea istoricul Git este criptografic rezistent la manipulare — nu poți modifica silențios un commit trecut fără a schimba hash-ul fiecărui commit ulterior.
Zona de staging (numită și index, stocată la .git/index) este un fișier binar care conține propunerea pentru următorul commit. Acest model cu trei zone — directorul de lucru, indexul, depozitul — este caracteristica arhitecturală cea mai înțeleasă greșit din Git și sursa majorității confuziei pentru începători.
Instalarea și configurarea Git
Înainte de a rula orice comenzi, verificați instalarea și configurați identitatea. Git încorporează informațiile despre autor în fiecare obiect commit, iar identitatea configurată greșit este una dintre cele mai frecvente cauze ale istoricelor de commit dezordonate pe depozitele partajate.
# Verify installation
git --version
# Set global identity (stored in ~/.gitconfig)
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
# Set default branch name to 'main' (modern convention)
git config --global init.defaultBranch main
# Set preferred editor for commit messages
git config --global core.editor "vim"
# Enable colored output
git config --global color.ui auto
# Verify configuration
git config --listConfigurarea este stratificată: --system (toți utilizatorii, /etc/gitconfig), --global (utilizatorul curent, ~/.gitconfig) și --local (depozitul, .git/config). Domeniile mai specifice le suprascriu pe cele mai largi.
Comenzi esențiale Git: Referință completă
Inițializare și clonare
git init creează un depozit nou scriind un director .git/ în folderul curent. Nu creează niciun commit — depozitul pornește gol.
git init
git init my-project # Initialize into a new subdirectory
git init --bare repo.git # Bare repository (no working tree, used for servers)Un depozit bare conține doar depozitul de obiecte și referințele — fără director de lucru. Acesta este formatul corect pentru un depozit remote la care mai mulți dezvoltatori fac push. Dacă găzduiți Git pe un server VPS Hosting, inițializați întotdeauna depozitele partajate ca bare.
git clone creează o copie locală completă a unui depozit remote, inclusiv toate branch-urile, tag-urile și istoricul.
git clone https://github.com/user/repo.git
git clone git@github.com:user/repo.git # SSH transport (preferred for auth)
git clone --depth 1 https://github.com/user/repo.git # Shallow clone (latest commit only)
git clone --branch develop https://github.com/user/repo.git # Clone specific branchClonele superficiale (--depth) sunt utile pentru pipeline-urile CI/CD unde aveți nevoie doar de starea cea mai recentă, nu de istoricul complet. Reduc dramatic timpul de clonare pe depozitele mari, dar împiedică unele operațiuni dependente de istoric, precum git bisect.
Inspectarea stării
git status este cea mai frecvent rulată comandă în orice flux de lucru. Afișează starea cu trei zone a depozitului dvs.
git status
git status -s # Short format: two-column status codes
git status -sb # Short format with branch infogit diff compară conținutul între zone sau commit-uri.
git diff # Working directory vs. index (unstaged changes)
git diff --staged # Index vs. last commit (what will be committed)
git diff HEAD # Working directory vs. last commit (all changes)
git diff main..feature # Compare tips of two branches
git diff abc123..def456 # Compare two specific commits
git diff --stat # Show changed files and line counts onlygit log traversează graful de commit-uri. Opțiunile sale de filtrare sunt printre cele mai puternice și mai puțin utilizate caracteristici ale Git.
git log
git log --oneline --graph --decorate --all # Visual branch graph
git log -p # Show patch (diff) for each commit
git log --author="Jane" # Filter by author
git log --since="2 weeks ago" # Filter by date
git log --grep="fix:" # Filter by commit message pattern
git log -- path/to/file # History of a specific file
git log --follow -- path/to/file # Follow renamesCombinația --graph --oneline --decorate --all este atât de universal utilă încât majoritatea inginerilor îi creează un alias:
git config --global alias.lg "log --oneline --graph --decorate --all"Staging și commit
git add filename.py # Stage a specific file
git add src/ # Stage an entire directory
git add . # Stage all changes in current directory
git add -p # Interactive patch staging (stage hunks, not whole files)
git add -u # Stage modifications and deletions, but not new filesStaging-ul interactiv (git add -p) este una dintre cele mai puternice și mai puțin utilizate caracteristici ale Git. Vă permite să revizuiți și să adăugați selectiv în staging fragmente individuale dintr-un fișier, permițând commit-uri precise și atomice chiar și atunci când directorul dvs. de lucru conține mai multe modificări necorelate.
git commit -m "feat: add OAuth2 token refresh logic"
git commit --amend # Modify the most recent commit (message or content)
git commit --amend --no-edit # Amend content without changing the message
git commit -v # Open editor showing full diff of staged changesRegulă critică: Nu modificați niciodată commit-urile care au fost deja trimise la un remote partajat. Modificarea rescrie hash-ul commit-ului, forțând colaboratorii să facă rebase sau să reseteze branch-urile locale.
Push și pull
git push origin main
git push origin feature/auth # Push a specific branch
git push -u origin feature/auth # Push and set upstream tracking
git push --force-with-lease # Safer force push (fails if remote has new commits)
git push origin --delete old-branch # Delete a remote branch
git push --tags # Push all local tagsPreferați --force-with-lease față de --force când trebuie să rescrieți istoricul remote. Verifică că nimeni altcineva nu a făcut push de la ultimul dvs. fetch, prevenind pierderea accidentală de date.
git pull origin main
git pull --rebase origin main # Fetch and rebase instead of merge
git pull --ff-only # Only fast-forward; abort if a merge commit would be createdgit fetch descarcă modificările remote fără a atinge directorul dvs. de lucru sau branch-ul curent. Aceasta este modalitatea sigură de a inspecta modificările din upstream înainte de a le integra.
git fetch origin
git fetch --all # Fetch from all remotes
git fetch --prune # Remove remote-tracking branches that no longer exist upstreamRamificare și fuzionare: Fluxul de lucru de bază
Modelul de ramificare al Git este caracteristica sa arhitecturală cea mai semnificativă. Un branch este pur și simplu un pointer cu nume (un fișier de 41 de octeți în .git/refs/heads/) către un hash de commit. Crearea unui branch este instantanee indiferent de dimensiunea depozitului.
Gestionarea branch-urilor
git branch # List local branches
git branch -a # List all branches (local and remote-tracking)
git branch -v # List branches with last commit info
git branch feature/user-auth # Create a new branch
git branch -d feature/user-auth # Delete merged branch
git branch -D feature/user-auth # Force delete (even if unmerged)
git branch -m old-name new-name # Rename a branchComutarea branch-urilor
Git modern (2.23+) separă responsabilitățile git checkout în două comenzi dedicate:
git switch main # Switch to existing branch
git switch -c feature/payments # Create and switch in one step
git restore filename.py # Discard working directory changes to a file
git restore --staged filename.py # Unstage a file (remove from index)git checkout funcționează în continuare pentru toate acestea, dar git switch și git restore au semantici mai clare și mai puțin ambigue și ar trebui preferate în fluxurile de lucru moderne.
Strategii de fuzionare
git merge feature/user-auth # Standard merge (creates merge commit if needed)
git merge --no-ff feature/user-auth # Always create merge commit (preserves branch topology)
git merge --squash feature/user-auth # Squash all branch commits into one staged change
git merge --abort # Abort an in-progress conflicted mergeFuzionarea fast-forward apare când branch-ul țintă nu a divergit față de sursă — Git mută pur și simplu pointerul înainte. Nu se creează niciun commit de fuzionare. --no-ff forțează un commit de fuzionare chiar și în acest caz, ceea ce păstrează istoricul vizual al branch-urilor de funcționalitate în git log --graph.
Fuzionarea squash comprimă toate commit-urile dintr-un branch de funcționalitate într-o singură modificare în staging, pe care o commit-ați manual. Aceasta produce un istoric liniar curat pe main, dar elimină istoricul granular al commit-urilor din branch-ul de funcționalitate.
Rebase
git rebase redă commit-urile dintr-un branch pe deasupra altuia, rescriindu-le hash-urile pentru a crea un istoric liniar.
git rebase main # Rebase current branch onto main
git rebase -i HEAD~5 # Interactive rebase: edit last 5 commits
git rebase --onto main server client # Transplant client branch onto main, excluding server
git rebase --abort # Abort a rebase in progress
git rebase --continue # Continue after resolving a conflictRebase-ul interactiv (-i) este instrumentul profesionistului pentru igiena commit-urilor. Vă permite să reordonați, să comprimați, să editați, să eliminați sau să împărțiți commit-urile înainte de a le partaja. Caz de utilizare frecvent: curățarea unui branch de funcționalitate dezordonat înainte de a deschide un pull request.
| Strategie | Istoric | Caz de utilizare | Risc |
|---|---|---|---|
| — | — | — | — |
| Merge (implicit) | Neliniar, păstrează branch-urile | Branch-uri de funcționalitate cu durată lungă | `git log` zgomotos |
| Merge `–no-ff` | Neliniar, commit-uri de fuzionare explicite | Topologie de branch impusă | La fel ca mai sus |
| Merge `–squash` | Liniar, un commit per funcționalitate | Branch principal curat | Pierde istoricul granular |
| Rebase | Liniar, fără commit-uri de fuzionare | Branch-uri personale, curățare pre-PR | Rescrie hash-urile; periculos pe branch-urile partajate |
| Cherry-pick | Selectiv, liniar | Backportarea corecțiilor | Commit-uri duplicate între branch-uri |
Regula de aur a rebase-ului: Nu faceți niciodată rebase pe commit-uri care există pe un branch public, partajat. Rebase-ul rescrie hash-urile commit-urilor. Dacă un coleg și-a bazat munca pe acele commit-uri, istoricul său va diverge și va trebui să facă o reconciliere dificilă.
Rezolvarea conflictelor de fuzionare
Conflictele apar când două branch-uri modifică aceeași regiune a aceluiași fișier. Git marchează conflictul în fișier cu marcatori de conflict standard:
<<<<<<< HEAD
const timeout = 30000;
=======
const timeout = 60000;
>>>>>>> feature/increase-timeoutFluxul de lucru pentru rezolvare:
# After a conflicted merge or rebase
git status # Identify conflicted files (marked as "both modified")
# Edit each conflicted file, remove markers, keep correct content
git add resolved-file.js # Mark as resolved
git commit # Complete the merge (message is pre-populated)Pentru conflicte complexe, un instrument de fuzionare în trei căi oferă o vizualizare mai clară:
git mergetool # Launch configured merge tool (vimdiff, meld, etc.)
git config --global merge.tool vimdiffAnularea modificărilor: Matricea de decizie
Alegerea comenzii greșite de anulare este una dintre cele mai frecvente modalități prin care dezvoltatorii pierd lucrul sau corup istoricul partajat. Alegerea corectă depinde de două variabile: unde se află modificarea și dacă a fost trimisă prin push.
| Scenariu | Comandă | Rescrie istoricul | Sigur pe branch-ul partajat |
|---|---|---|---|
| — | — | — | — |
| Scoaterea unui fișier din staging | `git restore –staged file` | Nu | Da |
| Eliminarea modificărilor din directorul de lucru | `git restore file` | Nu | Da |
| Anularea ultimului commit, păstrând modificările în staging | `git reset –soft HEAD~1` | Da | Nu |
| Anularea ultimului commit, păstrând modificările în afara staging-ului | `git reset HEAD~1` | Da | Nu |
| Anularea ultimului commit, eliminând toate modificările | `git reset –hard HEAD~1` | Da | Nu |
| Anularea în siguranță a unui commit trimis prin push | `git revert <hash>` | Nu | Da |
| Eliminarea unui fișier din întregul istoric | `git filter-repo` | Da | Nu |
git reset --soft HEAD~1 # Undo commit, keep changes in index
git reset HEAD~1 # Undo commit, keep changes in working dir
git reset --hard HEAD~1 # Undo commit, discard all changes permanently
git revert abc1234 # Create new commit that inverts abc1234
git revert HEAD~3..HEAD # Revert last 3 commits (creates 3 revert commits)
git revert -n HEAD~3..HEAD # Stage the reversals without committing (batch revert)git reset --hard este ireversibil prin comenzile normale Git. Dacă îl rulați accidental, singura cale de recuperare este git reflog, care înregistrează fiecare poziție la care a indicat HEAD timp de aproximativ 90 de zile.
git reflog # Show HEAD movement history with hashes
git checkout -b recovery abc1234 # Recover by creating a branch at the lost commitComenzi avansate pentru fluxuri de lucru în producție
git stash
git stash salvează starea curentă a directorului de lucru și a indexului pe o stivă, oferindu-vă un arbore de lucru curat pentru a schimba contextul.
git stash # Stash tracked changes
git stash -u # Include untracked files
git stash push -m "WIP: auth refactor" # Stash with a descriptive name
git stash list # List all stash entries
git stash pop # Apply most recent stash and remove it from stack
git stash apply stash@{2} # Apply specific stash without removing it
git stash drop stash@{2} # Delete a specific stash entry
git stash branch feature/wip # Create a new branch from a stashgit cherry-pick
git cherry-pick abc1234 # Apply a single commit to current branch
git cherry-pick abc1234 def5678 # Apply multiple commits
git cherry-pick abc1234 --no-commit # Apply changes without committing
git cherry-pick main~3..main # Apply a range of commitsCherry-pick este mecanismul standard pentru backportarea corecțiilor de erori pe branch-urile de mentenanță. Dacă remediați o vulnerabilitate critică de securitate pe main, faceți cherry-pick al acelui commit pe v2.1-stable și v2.0-stable fără a fuziona funcționalități necorelate.
git bisect
git bisect efectuează o căutare binară prin istoricul commit-urilor pentru a găsi exact commit-ul care a introdus un bug. Este unul dintre cele mai puternice și mai puțin cunoscute instrumente de depanare din Git.
git bisect start
git bisect bad # Mark current commit as broken
git bisect good v2.3.0 # Mark a known-good commit or tag
# Git checks out the midpoint commit automatically
# Test your code, then:
git bisect good # If this commit is fine
git bisect bad # If this commit is broken
# Repeat until Git identifies the first bad commit
git bisect reset # Return to original HEAD when donePe un depozit cu 1.000 de commit-uri între punctele bun și rău, git bisect găsește vinovatul în cel mult 10 pași.
git tag
Tag-urile marchează commit-uri specifice ca semnificative — de obicei versiunile de lansare.
git tag v1.4.2 # Lightweight tag (just a pointer)
git tag -a v1.4.2 -m "Release 1.4.2" # Annotated tag (recommended; stores metadata)
git tag -a v1.4.2 abc1234 # Tag a specific past commit
git push origin v1.4.2 # Push a specific tag
git push origin --tags # Push all tags
git tag -d v1.4.2 # Delete local tag
git push origin --delete v1.4.2 # Delete remote tagFolosiți întotdeauna tag-uri adnotate pentru lansări. Acestea stochează numele, adresa de email, data și un mesaj al celui care a creat tag-ul și pot fi semnate cu GPG. Tag-urile ușoare sunt potrivite doar pentru marcaje locale temporare.
git worktree
git worktree permite ca mai multe directoare de lucru să fie extrase simultan din același depozit — fiecare pe un branch diferit. Aceasta elimină necesitatea de a face stash sau commit la lucrul în curs când trebuie să treceți la un hotfix.
git worktree add ../hotfix-branch hotfix/critical-auth-bug
git worktree list
git worktree remove ../hotfix-branchAcest lucru este deosebit de valoros pe un Server Dedicat care rulează un pipeline CI/CD unde mai multe sarcini de build au nevoie de acces simultan la branch-uri diferite ale aceluiași depozit fără a se interfera reciproc.
Fluxuri de lucru Git pentru echipe
Strategia corectă de ramificare depinde de cadența de lansare și de dimensiunea echipei. Există trei modele dominante:
Fluxul de lucru cu branch-uri de funcționalitate
Fiecare funcționalitate sau corecție trăiește pe propriul branch. Dezvoltatorii deschid pull request-uri pentru a fuziona în main. Simplu, eficient pentru majoritatea echipelor.
Gitflow
Definește branch-uri cu durată lungă main și develop, plus branch-uri cu durată scurtă feature/, release/ și hotfix/ cu reguli stricte de fuzionare. Potrivit pentru software cu lansări versionate explicite (biblioteci, aplicații împachetate).
Dezvoltarea bazată pe trunk
Dezvoltatorii commit-ează direct pe main (sau folosesc branch-uri cu durată foarte scurtă fuzionate în decurs de o zi). Se bazează puternic pe flag-uri de funcționalitate pentru a ascunde lucrul incomplet. Preferată de echipele cu viteză mare care practică deployment-ul continuu.
| Flux de lucru | Cadența de lansare | Dimensiunea echipei | Complexitatea CI/CD |
|---|---|---|---|
| — | — | — | — |
| Branch de funcționalitate | Flexibil | Orice | Scăzută |
| Gitflow | Lansări programate | Medie–Mare | Medie |
| Bazat pe trunk | Deployment continuu | Orice | Ridicată |
Găzduirea depozitelor Git: Auto-găzduit vs. platforme gestionate
Pentru echipele care necesită suveranitate a datelor, conformitate sau infrastructură privată, auto-găzduirea unui server Git este o alegere viabilă și adesea necesară. Opțiunile includ Gitea (ușor, bazat pe Go), GitLab CE (platformă DevOps completă) și Forgejo (fork Gitea cu guvernanță comunitară).
O instanță Gitea auto-găzduită minimă rulează confortabil pe un plan VPS Hosting cu 2 vCPU și 2 GB RAM. Pentru echipe mai mari sau GitLab CE cu runnere CI, 4–8 GB RAM este minimul practic.
Când vă auto-găzduiți, securizați serverul Git cu:
- Autentificare prin cheie SSH (dezactivați complet autentificarea prin parolă)
- HTTPS cu un certificat valid — Certificatele SSL sunt esențiale pentru protejarea credențialelor în tranzit
- Reguli de firewall care limitează expunerea portului Git (22 sau port SSH personalizat, 443 pentru HTTPS)
- Copii de rezervă automate regulate ale directoarelor de depozit bare
.git - Secrete webhook pentru integrările CI/CD
Pentru echipele care utilizează pipeline-uri de deployment bazate pe Git și care gestionează și infrastructura web, asocierea unui server Git auto-găzduit cu un VPS cu cPanel vă oferă hook-uri de deployment integrate alături de instrumente familiare de gestionare a găzduirii.
Hook-uri Git: Automatizarea porților de calitate
Hook-urile Git sunt scripturi care se execută automat la puncte specifice din ciclul de viață Git. Acestea se află în .git/hooks/ și nu sunt commit-ate în depozit în mod implicit (utilizați un instrument precum pre-commit sau husky pentru a le partaja).
Hook-uri cheie pentru fluxurile de lucru în producție:
| Hook | Declanșator | Utilizare frecventă |
|---|---|---|
| — | — | — |
| `pre-commit` | Înainte de crearea commit-ului | Rularea linterelor, formatatoarelor, testelor |
| `commit-msg` | După scrierea mesajului de commit | Impunerea formatului de commit convențional |
| `pre-push` | Înainte de push la remote | Rularea suitei complete de teste |
| `post-receive` | După ce remote-ul primește un push | Declanșarea deployment-ului, trimiterea notificărilor |
| `pre-rebase` | Înainte de începerea rebase-ului | Prevenirea rebase-ului pe branch-urile partajate |
# Example pre-commit hook: reject commits with debug print statements
#!/bin/bash
if git diff --cached | grep -E '^+.*(console.log|debugger|print("DEBUG)'; then
echo "ERROR: Debug statement detected. Remove before committing."
exit 1
fiHook-ul post-receive pe un depozit server bare este baza deployment-ului simplu bazat pe Git: faceți push la server, hook-ul extrage noul HEAD în rădăcina web, rulează pașii de build și repornește serviciile — fără nicio platformă CI externă necesară.
.gitignore: Menținerea depozitelor curate
Fișierul .gitignore îi spune Git ce fișiere și tipare să lase neurmărite. Ar trebui să fie commit-at în depozit și menținut cu atenție.
# Dependencies
node_modules/
vendor/
# Build artifacts
dist/
build/
*.o
*.pyc
__pycache__/
# Environment and secrets — NEVER commit these
.env
.env.local
*.pem
*.key
config/secrets.yml
# IDE files
.idea/
.vscode/
*.swp
# OS files
.DS_Store
Thumbs.dbCapcană critică: Dacă un fișier era deja urmărit înainte de a fi adăugat la .gitignore, Git va continua să îl urmărească. Trebuie să îl dezurmăriți explicit:
git rm --cached path/to/sensitive-file
git commit -m "chore: stop tracking secrets file"Nu commit-ați niciodată credențiale, chei API sau chei private într-un depozit — chiar și unul privat. Utilizați variabile de mediu, manageri de secrete (HashiCorp Vault, AWS Secrets Manager) sau fișiere .env care sunt incluse în .gitignore.
Optimizarea performanței pentru depozite mari
Git standard se degradează pe depozitele cu milioane de fișiere sau gigaocteți de active binare. Strategii de atenuare:
- Git LFS (Large File Storage): Înlocuiește fișierele binare mari cu fișiere pointer în depozit și stochează conținutul real pe un server LFS separat. Esențial pentru depozitele care conțin media, ponderi de modele ML sau binare compilate.
- Clonare parțială:
git clone --filter=blob:nonedescarcă commit-urile și tree-urile, dar preia blob-urile la cerere. Reduce dramatic dimensiunea clonei inițiale pentru monorepo-urile mari. - Checkout selectiv:
git sparse-checkout set path/to/subdirextrage doar un subset al arborelui de lucru. Util în monorepo-uri unde un dezvoltator lucrează doar într-un director de serviciu. - Fișierul commit-graph:
git commit-graph write --reachablepre-calculează graful de commit-uri, accelerând operațiuni precumgit log --graphși interogările de accesibilitate pe istorice mari. git maintenance start: Programează sarcini de mentenanță în fundal (împachetarea obiectelor libere, actualizări ale commit-graph, prefetch fetch) pentru a menține operațiunile depozitului rapide în timp.
Lista de verificare a punctelor cheie tehnice
Înainte de a considera configurarea Git gata pentru producție, verificați fiecare dintre următoarele:
- Identitate configurată:
user.nameșiuser.emailsetate corect la domeniul de configurare corespunzător - Chei SSH utilizate: Autentificarea prin parolă la remote-uri înlocuită cu perechi de chei SSH sau HTTPS bazat pe token
.gitignorecommit-at: Secretele, artefactele de build și fișierele OS excluse înainte de primul commit- Branch-ul implicit numit
main:init.defaultBranchsetat global pentru a evita denumirea moștenitămaster - Mesajele de commit urmează o convenție: Conventional Commits (
feat:,fix:,chore:) sau formatul agreat de echipă impus prin hook-ulcommit-msg git revertpentru istoricul public:git reset --hardutilizat doar pe commit-uri locale, netrimise prin push--force-with-leaseîn loc de--force: Previne suprascrierea accidentală a push-urilor colegilor- Tag-uri adnotate pentru lansări:
git tag -acu un mesaj, nu tag-uri ușoare - Hook-uri partajate prin
pre-commitsauhusky: Porțile de calitate impuse în mod consistent în întreaga echipă - Git LFS configurat dacă depozitul conține active binare peste 1 MB
- Depozit bare pe server: Remote-urile auto-găzduite inițializate cu
git init --bare git fetch --pruneregulat: Referințele de urmărire remote menținute sincronizate cu starea reală a remote-ului
Întrebări frecvente
Care este diferența dintre git fetch și git pull?
git fetch descarcă commit-urile, branch-urile și tag-urile de la remote în referințele locale de urmărire remote (de ex., origin/main) fără a atinge directorul de lucru sau branch-ul curent. git pull este git fetch urmat imediat de git merge (sau git rebase dacă este configurat). Utilizați git fetch când doriți să inspectați modificările din upstream înainte de a le integra.
Când ar trebui să folosesc git rebase în loc de git merge?
Utilizați rebase pentru a lineariza branch-ul local de funcționalitate înainte de a deschide un pull request, menținând istoricul proiectului lizibil. Nu faceți niciodată rebase pe un branch pe care alți dezvoltatori l-au clonat deja sau pe care și-au bazat munca — rescrierea hash-urilor de commit publicate îi forțează pe toți ceilalți să reconcilieze manual istoricele divergente.
Cum elimin permanent un fișier sensibil care a fost commit-at accidental?
Utilizați git filter-repo (înlocuitorul modern pentru git filter-branch): git filter-repo --path secrets.env --invert-paths. Aceasta rescrie întregul istoric al depozitului, eliminând fișierul din fiecare commit. După rescriere, faceți force-push pe toate branch-urile și tag-urile, apoi rotați imediat credențialele expuse — presupuneți că sunt compromise indiferent de cât de repede acționați.
Ce este starea HEAD detașat și cum mă recuperez din ea?
HEAD detașat înseamnă că pointerul HEAD referențiază direct un hash de commit specific în loc de un nume de branch. Orice commit-uri pe care le faceți nu vor aparține niciunui branch și vor deveni inaccesibile după ce comutați. Pentru recuperare: git switch -c new-branch-name pentru a atașa commit-urile la un branch nou, sau git switch main pentru a le elimina.
Cum gestionează Git fișierele binare diferit față de fișierele text?
Git stochează fișierele binare ca blob-uri opace — nu poate calcula diff-uri semnificative la nivel de linie sau efectua fuzionări automate pe ele. Conflictele în fișierele binare trebuie rezolvate alegând complet o versiune. Pentru depozitele cu active binare semnificative, configurați Git LFS pentru a stoca binarele extern și a menține depozitul în sine compact și rapid.
