204 lines
4.6 KiB
Markdown
204 lines
4.6 KiB
Markdown
<!-- File: 06-gestione-conflitti-merge.md -->
|
||
|
||
# Gestione dei conflitti di merge
|
||
|
||
I **conflitti di merge** in Git capitano quando due branch hanno modificato **le stesse righe** dello stesso file in modo diverso.
|
||
|
||
Esempio tipico:
|
||
- Branch `development` viene aggiornato da un collega
|
||
- Tu lavori su `feature/nuovo-report` partendo da una versione vecchia di `development`
|
||
- Quando fai il merge di `development` o il merge della feature, Git non sa quale versione tenere → conflitto
|
||
|
||
---
|
||
|
||
## Quando si verificano i conflitti
|
||
|
||
Situazioni classiche:
|
||
|
||
1. Stai facendo un merge:
|
||
|
||
```bash
|
||
git checkout development
|
||
git merge feature/nuovo-report
|
||
```
|
||
|
||
Oppure:
|
||
|
||
```bash
|
||
git pull # (equivalente a fetch + merge)
|
||
```
|
||
|
||
2. Git mostra qualcosa del genere:
|
||
|
||
```text
|
||
Auto-merging src/report.py
|
||
CONFLICT (content): Merge conflict in src/report.py
|
||
Automatic merge failed; fix conflicts and then commit the result.
|
||
```
|
||
|
||
---
|
||
|
||
## Come appaiono i conflitti nel file
|
||
|
||
Aprendo il file in conflitto (es. `src/report.py`) troverai blocchi tipo:
|
||
|
||
```text
|
||
<<<<<<< HEAD
|
||
def calcola_totale(dati):
|
||
# versione su development
|
||
totale = sum(dati)
|
||
return totale
|
||
=======
|
||
def calcola_totale(dati):
|
||
# versione sulla tua feature branch
|
||
totale = sum(dati) + 10 # aggiunta bonus
|
||
return totale
|
||
>>>>>>> feature/nuovo-report
|
||
```
|
||
|
||
* `<<<<<<< HEAD` → la versione **della branch su cui sei** (es. `development`)
|
||
* `=======` → separatore
|
||
* `>>>>>>> feature/nuovo-report` → la versione **dell’altra branch** (es. `feature/nuovo-report`)
|
||
|
||
Devi **modificare a mano** questo blocco, scegliendo cosa tenere (o unendo le due versioni) e poi rimuovere i marker `<<<<<<<`, `=======`, `>>>>>>>`.
|
||
|
||
Esempio di risultato finale dopo la risoluzione:
|
||
|
||
```python
|
||
def calcola_totale(dati):
|
||
# unisco le logiche: somma + bonus solo in alcuni casi
|
||
totale = sum(dati)
|
||
if len(dati) > 10:
|
||
totale += 10 # bonus
|
||
return totale
|
||
```
|
||
|
||
---
|
||
|
||
## Passi base per risolvere un conflitto
|
||
|
||
1. **Vedi quali file sono in conflitto**
|
||
|
||
```bash
|
||
git status
|
||
```
|
||
|
||
Esempio:
|
||
|
||
```text
|
||
Unmerged paths:
|
||
both modified: src/report.py
|
||
```
|
||
|
||
2. **Apri i file in conflitto** con il tuo editor/IDE
|
||
(es. VS Code, IntelliJ, ecc. – spesso hanno strumenti grafici per i merge).
|
||
|
||
3. **Riscrivi il codice nei blocchi segnati**:
|
||
|
||
* scegli una versione
|
||
* oppure integra le due versioni in qualcosa di coerente
|
||
* **rimuovi i marker** (`<<<<<<<`, `=======`, `>>>>>>>`)
|
||
|
||
4. **Segna il conflitto come risolto** aggiungendo il file allo staging:
|
||
|
||
```bash
|
||
git add src/report.py
|
||
```
|
||
|
||
5. **Completa il merge con un commit** (se Git non lo fa automaticamente):
|
||
|
||
```bash
|
||
git commit
|
||
# oppure (se Git ha già un messaggio pronto)
|
||
git commit --no-edit
|
||
```
|
||
|
||
6. Infine, se serve, **push**:
|
||
|
||
```bash
|
||
git push
|
||
```
|
||
|
||
---
|
||
|
||
## Se qualcosa va storto: annullare il merge
|
||
|
||
Se durante il merge ti accorgi che stai combinando guai:
|
||
|
||
```bash
|
||
git merge --abort
|
||
```
|
||
|
||
Questo comando:
|
||
|
||
* annulla il merge in corso
|
||
* riporta la working directory allo stato precedente al `git merge`
|
||
|
||
> Funziona finché non hai completato il merge con un commit.
|
||
|
||
---
|
||
|
||
## Esempio completo: integrare `development` in una feature
|
||
|
||
Scenario: stai lavorando su `feature/nuovo-report` e vuoi allinearti agli ultimi cambi di `development`.
|
||
|
||
```bash
|
||
# 1. Assicurati di essere sulla feature
|
||
git checkout feature/nuovo-report
|
||
|
||
# 2. Scarica le ultime modifiche dal server
|
||
git fetch origin
|
||
|
||
# 3. Fai il merge della branch remote development nella tua feature
|
||
git merge origin/development
|
||
```
|
||
|
||
Se ci sono conflitti:
|
||
|
||
```bash
|
||
git status # vedi i file in conflitto
|
||
# apri e risolvi i file
|
||
git add file1 file2 # marca i conflitti come risolti
|
||
git commit # completa il merge
|
||
git push # aggiorna la feature sul server
|
||
```
|
||
|
||
---
|
||
|
||
## Master vs Development
|
||
|
||
* **`master`**
|
||
|
||
* branch di produzione (codice rilasciato)
|
||
* **`development`**
|
||
|
||
* branch di integrazione dello sviluppo
|
||
|
||
Conflitti possono capitare:
|
||
|
||
* nel merge di `feature/*` → `development`
|
||
* nel merge di `development` → `master`
|
||
* nei `hotfix/*` che partono da `master` e poi vanno riportati su `development`
|
||
|
||
La logica di risoluzione rimane **sempre la stessa**:
|
||
|
||
1. controlli con `git status`
|
||
2. sistemi i file
|
||
3. `git add`
|
||
4. `git commit` per chiudere il merge
|
||
|
||
---
|
||
|
||
## Strumenti grafici (facoltativo)
|
||
|
||
Molti IDE/editors aiutano coi conflitti:
|
||
|
||
* **VS Code**: evidenzia i blocchi e ti offre pulsanti “Accept Current / Accept Incoming / Accept Both”
|
||
* IDE JetBrains (IntelliJ, PyCharm, ecc.): hanno `Merge` tool visuale
|
||
* `git mergetool`: apre uno strumento esterno configurato
|
||
|
||
Per iniziare:
|
||
|
||
* va benissimo risolvere a mano nei file
|
||
* oppure usare l’editor grafico che già usi per sviluppare
|