Lezione 23 · Recupero
Risolvere i conflitti di unione e rebase
Risolvi lo stesso titolo concorrente in un'unione e in un rebase, scopri perché "nostro" e "loro" si scambiano tra loro, salva un risultato combinato deliberato e termina ogni operazione senza perdere l'idea di nessuna delle due persone.
- Livello: Intermedio
- 13 minuti di lettura
- 7 minuti di video
- Aggiornato
- Prima di questa lezione: Unisci rami con cronologia divergente, Ribasare il lavoro inedito su una nuova base
Avanzamenti salvati in questo browser.
La riproduzione carica il video da YouTube (modalità ottimizzata per la privacy).
Cosa imparerai
- Leggi un conflitto reale: la base, la parte attuale e la parte entrante.
- Spiega perché "nostro" e "loro" si scambiano tra una fusione e un rebase.
- Scrivi una risoluzione deliberata, quindi contrassegnala come risolta.
- Proseguire l'operazione e verificare che nulla sia lasciato a metà.
Prima di iniziare
Due compagni di squadra hanno cambiato la stessa riga della pagina. Il giorno conflict/sara, Sara ha cambiato l'intestazione dell'eroe in "Rivedi le modifiche con sicurezza". Il giorno conflict/omar, Omar ha modificato la stessa riga in "Comprendi ogni modifica salvata". Entrambi i rami iniziano dal commit M, dove l'intestazione era "Vedi chiaramente il tuo lavoro.", e ogni ramo ha esattamente un commit. Fai due copie identiche di questa divergenza: una per l'unione (gittree-conflict-merge) e una per il rebase (gittree-conflict-rebase). In entrambi, conflict/sara è estratto e l'albero di lavoro è pulito. Non è in corso alcuna unione o rebase.
Tutto è locale e nel piano gratuito (GitTree ti chiede di accedere): nessun account di hosting, nessun provider, niente Internet. Ogni identità è fittizia (esempio.com). Non eseguire mai questa lezione in un progetto reale.
Apporta le modifiche in GitTree o con i comandi Git nativi, non entrambi nella stessa copia. Leggere il risultato è sempre sicuro. Le etichette dei menu provengono dalle stringhe proprie di GitTree 2.0 e i comandi nativi sono stati eseguiti con Git 2.43 in copie usa e getta. I passaggi GitTree non sono stati eseguiti su macOS, Windows o Linux.
Effetti del concetto e dello stato
Un conflitto di contenuto significa che Git non può scegliere un risultato da solo: entrambe le parti hanno cambiato le stesse righe in modo diverso. Git si ferma e mantiene tre versioni del file nell'indice: la fase 1 è la base comune, la fase 2 è "nostra" e la fase 3 è "loro". Inoltre scrive i marcatori di conflitto nel file nell'albero di lavoro. Rimuovere i marcatori in un editor non risolve nulla per Git: il file viene risolto solo quando si salva il risultato e lo si mette in stage, riportando allo stage 0.
Le “nostre” e le “loro” sono posizioni, non persone. In una fusione sei sul ramo di Sara, quindi la nostra è la versione di Sara (il lato corrente) e la loro è quella di Omar (il lato entrante). In un rebase di Sara su Omar, Git prima si sposta sul ramo di Omar e poi riproduce il commit di Sara, quindi la nostra è la versione di Omar (il ramo su cui stai rebasando) e la loro è il commit di Sara. GitTree stampa il ruolo accanto a ciascun nome in modo da non dover ricordare: "(current)" e "(incoming)" in un merge, "(rebasing on)" e "(your commit)" in un rebase.
Il risultato giusto raramente è unilaterale. Qui la risoluzione prevista è "Rivedere ogni cambiamento con fiducia", non la linea di Sara né quella di Omar. Mantieni ogni altra riga della pagina esattamente com'era. Contrassegnare il file risolto mette in scena il risultato; continuare è un passaggio separato che termina il commit di unione o ricrea il commit di Sara su quello di Omar.
Mentre l'operazione viene interrotta, il ramo è il punto in cui l'operazione l'ha lasciato e il file è in conflitto. Niente raggiunge un server.
Preparare lo stato esatto del progetto
Fai una divergenza, poi copiala due volte. Inizia da una copia ordinaria separata del progetto così come lo ha lasciato la lezione 18 e lascia intatto il tuo gittree-features originale. Le versioni della pagina sono di seguito: MERGED è la base condivisa, SARA e OMAR sono le due versioni concorrenti e RESOLVED è il risultato che salverai.
Completare gli input del file
Risparmia solo nella fase denominata di seguito. Questi sono corpi UTF-8/LF completi con un ritorno a capo finale; non incollare mai le recinzioni Markdown. I file eseguibili non modificati ereditano l'input denominato. Le versioni in varianti separate non devono sovrascrivere l'originale.
index.html — UNISTO
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GitTree Features — course demo</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header class="site-header">
<a href="#main">GitTree Features</a>
</header>
<main id="main" tabindex="-1">
<section class="hero" aria-labelledby="hero-title">
<p class="eyebrow">GitTree Learn demo project</p>
<h1 id="hero-title">See your work clearly.</h1>
<p id="hero-copy">Choose one change, then check what Git saved.</p>
</section>
<section class="features" aria-labelledby="features-title">
<h2 id="features-title">Follow your work</h2>
<div class="cards">
<article class="feature-card">
<h3>History</h3>
<p>Read commits and branches together.</p>
</article>
<article class="feature-card">
<h3>Changes</h3>
<p>Review the exact content selected for a commit.</p>
</article>
<article class="feature-card">
<h3>Recovery</h3>
<p>Inspect the scope of a recovery point before using it.</p>
</article>
</div>
</section>
<section aria-labelledby="plans-title">
<h2 id="plans-title">Choose the workflow you need</h2>
<div class="cards">
<article class="feature-card">
<h3>Local Git</h3>
<p>Local Git workflows work without signing in.</p>
</article>
<article class="feature-card">
<h3>Connected workflows</h3>
<p>Provider integrations and Nour require Pro or an applicable trial.</p>
</article>
</div>
</section>
</main>
<footer><p>Built by a fictional team for GitTree Learn. Review one change at a time.</p></footer>
<script type="module" src="site.js"></script>
</body>
</html>indice.html — SARA
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GitTree Features — course demo</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header class="site-header">
<a href="#main">GitTree Features</a>
</header>
<main id="main" tabindex="-1">
<section class="hero" aria-labelledby="hero-title">
<p class="eyebrow">GitTree Learn demo project</p>
<h1 id="hero-title">Review changes with confidence.</h1>
<p id="hero-copy">Choose one change, then check what Git saved.</p>
</section>
<section class="features" aria-labelledby="features-title">
<h2 id="features-title">Follow your work</h2>
<div class="cards">
<article class="feature-card">
<h3>History</h3>
<p>Read commits and branches together.</p>
</article>
<article class="feature-card">
<h3>Changes</h3>
<p>Review the exact content selected for a commit.</p>
</article>
<article class="feature-card">
<h3>Recovery</h3>
<p>Inspect the scope of a recovery point before using it.</p>
</article>
</div>
</section>
<section aria-labelledby="plans-title">
<h2 id="plans-title">Choose the workflow you need</h2>
<div class="cards">
<article class="feature-card">
<h3>Local Git</h3>
<p>Local Git workflows work without signing in.</p>
</article>
<article class="feature-card">
<h3>Connected workflows</h3>
<p>Provider integrations and Nour require Pro or an applicable trial.</p>
</article>
</div>
</section>
</main>
<footer><p>Built by a fictional team for GitTree Learn. Review one change at a time.</p></footer>
<script type="module" src="site.js"></script>
</body>
</html>indice.html — OMAR
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GitTree Features — course demo</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header class="site-header">
<a href="#main">GitTree Features</a>
</header>
<main id="main" tabindex="-1">
<section class="hero" aria-labelledby="hero-title">
<p class="eyebrow">GitTree Learn demo project</p>
<h1 id="hero-title">Understand each saved change.</h1>
<p id="hero-copy">Choose one change, then check what Git saved.</p>
</section>
<section class="features" aria-labelledby="features-title">
<h2 id="features-title">Follow your work</h2>
<div class="cards">
<article class="feature-card">
<h3>History</h3>
<p>Read commits and branches together.</p>
</article>
<article class="feature-card">
<h3>Changes</h3>
<p>Review the exact content selected for a commit.</p>
</article>
<article class="feature-card">
<h3>Recovery</h3>
<p>Inspect the scope of a recovery point before using it.</p>
</article>
</div>
</section>
<section aria-labelledby="plans-title">
<h2 id="plans-title">Choose the workflow you need</h2>
<div class="cards">
<article class="feature-card">
<h3>Local Git</h3>
<p>Local Git workflows work without signing in.</p>
</article>
<article class="feature-card">
<h3>Connected workflows</h3>
<p>Provider integrations and Nour require Pro or an applicable trial.</p>
</article>
</div>
</section>
</main>
<footer><p>Built by a fictional team for GitTree Learn. Review one change at a time.</p></footer>
<script type="module" src="site.js"></script>
</body>
</html>indice.html — RISOLTO
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GitTree Features — course demo</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header class="site-header">
<a href="#main">GitTree Features</a>
</header>
<main id="main" tabindex="-1">
<section class="hero" aria-labelledby="hero-title">
<p class="eyebrow">GitTree Learn demo project</p>
<h1 id="hero-title">Review each change with confidence.</h1>
<p id="hero-copy">Choose one change, then check what Git saved.</p>
</section>
<section class="features" aria-labelledby="features-title">
<h2 id="features-title">Follow your work</h2>
<div class="cards">
<article class="feature-card">
<h3>History</h3>
<p>Read commits and branches together.</p>
</article>
<article class="feature-card">
<h3>Changes</h3>
<p>Review the exact content selected for a commit.</p>
</article>
<article class="feature-card">
<h3>Recovery</h3>
<p>Inspect the scope of a recovery point before using it.</p>
</article>
</div>
</section>
<section aria-labelledby="plans-title">
<h2 id="plans-title">Choose the workflow you need</h2>
<div class="cards">
<article class="feature-card">
<h3>Local Git</h3>
<p>Local Git workflows work without signing in.</p>
</article>
<article class="feature-card">
<h3>Connected workflows</h3>
<p>Provider integrations and Nour require Pro or an applicable trial.</p>
</article>
</div>
</section>
</main>
<footer><p>Built by a fictional team for GitTree Learn. Review one change at a time.</p></footer>
<script type="module" src="site.js"></script>
</body>
</html>Tra GitTree
Apri la tavolozza con Comando+Maiusc+P (Ctrl+Maiusc+P su Ubuntu). Le azioni su un ramo con nome utilizzano il menu di scelta rapida di quel ramo.
- Costruisci le due copie come mostra la sezione successiva. Apri gittree-conflict-merge, con
conflict/saraestratto. - Fai clic con il pulsante destro del mouse su
conflict/omare scegli Merge conflict/omar into conflict/sara. Sotto Record it as scegli Always a merge commit. La finestra di dialogo avverte "Si fermerà con un conflitto in 1 file"; scegli Merge. L'unione si interrompe, che è il risultato previsto. - Il banner dice "Unire conflitto/omar in conflitto/sara" con "1 conflitto" e Continue non è ancora disponibile: "Risolvi prima 1 conflitto". Scegli Resolve.
- Apri
index.htmlda Conflicted files. Leggi i due lati, conflict/sara (current) e conflict/omar (incoming), e usa Show Base per leggere il Base (common ancestor). - Scegli Edit Output, sostituisci l'intestazione in conflitto con
Review each change with confidence.e mantieni ogni altra riga. Quindi scegli Save and Mark Resolved. Cancellare i marcatori e chiudere il file non è sufficiente. - Torna sul banner e scegli Continue. Se viene proposto un messaggio, mantenere quello proposto. Attendi il completamento dell'unione: il nuovo commit ha due genitori.
- Apri gittree-conflict-rebase, con
conflict/saraestratto. Fai clic con il pulsante destro del mouse suconflict/omare scegli Rebase conflict/sara onto conflict/omar. Lascia disattivate le opzioni sotto Options for this rebase, quindi scegli Rebase conflict/sara. Si ferma con un conflitto. - Scegli Resolve e apri
index.html. I lati ora sono conflict/omar (rebasing onto) e conflict/sara (your commit): i ruoli sono invertiti. Fai lo stesso Edit Output → Save and Mark Resolved, quindi Continue. - Controlla entrambe le copie: il file è uguale a RESOLVED, non è rimasto alcun file in conflitto e non viene visualizzato alcun banner. Tieni i due risultati separati e non spingere.
Per ogni commit ordinario nel corso: Summary è l'oggetto dichiarato, Description è vuoto e le opzioni Amend Previous Commit, Skip Hooks, Add Signed-off-by, Different Author, Push After Commit e Allow Empty Commit rimangono disattivate.
Nel terminale
In una copia separata e pulita del risultato della lezione 18:
git switch --create conflict/sara
BASE_SHA="$(git rev-parse HEAD)"Salva SARA come index.html, quindi:
git add -- index.html
git -c user.name="Sara Lindqvist" -c user.email=sara@example.com commit --quiet -m "feat: Sara clarifies the hero"
git switch --quiet --create conflict/omar "$BASE_SHA"Salva OMAR come index.html, quindi:
git add -- index.html
git -c user.name="Omar Haddad" -c user.email=omar@example.com commit --quiet -m "feat: Omar explains the hero"
git switch --quiet conflict/saraBASE_SHA è M, prima di entrambi i commit concorrenti. Crea due copie pulite di questa divergenza, una per l'unione e una per il rebase (cd .. && cp -R gittree-features gittree-conflict-merge && cp -R gittree-features gittree-conflict-rebase). Nella copia unita:
git merge --no-ff --no-edit conflict/omar
git ls-files --unmerged
git show :2:index.html
git show :3:index.htmlLa fusione termina con il codice di uscita 1 e git ls-files --unmerged elenca tre voci, fasi 1, 2 e 3. git show :2:index.html è la versione di Sara (nostra) e :3: è quella di Omar (loro); :1: è la base. Salva RISOLTO come index.html, quindi:
git add -- index.html
git -c core.editor=true merge --continue
git ls-files --unmerged
git status --shortGli ultimi due comandi non stampano nulla. Nella copia rebase intatta:
git rebase conflict/omar
git show :2:index.html
git show :3:index.htmlIl rebase si ferma. Ora :2: è la versione di Omar e :3: è quella di Sara: i ruoli si sono scambiati. Salva RISOLTO come index.html, quindi:
git add -- index.html
git -c core.editor=true rebase --continue
git ls-files --unmerged
git status --shortEntrambi i file ora sono RISOLTI e nulla viene separato. core.editor=true accetta solo il messaggio di commit esistente per questo comando; non cambia l'impostazione dell'editor. Per abbandonare un'operazione interrotta senza risolverla, utilizzare git merge --abort o git rebase --abort.
Risultato
Where you end: la copia unificata ha un nuovo commit con due genitori e l'intestazione combinata; la copia rebase ha il commit di Sara ricreato su quello di Omar con la stessa intestazione combinata. In entrambi, index.html è uguale a RISOLTO, non è rimasta alcuna voce di conflitto, l'operazione è terminata e lo stato è pulito.
Errori comuni
- Supponendo che "nostro" significhi sempre la tua caratteristica. Significa da che parte si trova Git e questo cambia con l'operazione.
- Prendere un lato in blocco ("Prendi tutto") prima di leggere entrambe le versioni e il resto del file.
- Eliminazione degli indicatori di conflitto ma senza mai salvataggio e contrassegno del file risolto.
- Ripetere un'unione o un rebase già terminato.
Se qualcosa va storto
Se uno stop sembra sbagliato, Abort… dal banner ripristina lo stato da cui è partita l'operazione e annulla le risoluzioni prese fino a quel momento; GitTree conserva prima uno snapshot di ripristino. Se il file è cambiato mentre stavi modificando, usa le scelte Compare e Use as Output invece di forzare un vecchio salvataggio. Conserva una copia della bozza prima di sostituirla.
Controlla la tua comprensione
Rispondi a ciascuna domanda, quindi leggi il motivo. Le domande contrassegnate come "Obbligatorio" contano ai fini del completamento della lezione.
0 di 6 corretto
Rispondi correttamente alle domande richieste per completare la lezione.
Controllato in questo browser.
Pratica
Dimostra i ruoli della fase per entrambe le operazioni con git show :2:index.html e git show :3:index.html, quindi salva lo stesso file RESOLVED e completa ciascuna operazione. Prevedi cosa rimarrebbe nella pagina se prendessi alla cieca il "nostro" in entrambe le copie.
La tua conferma: il sito non può vedere il tuo computer.
Per completare la lezione rispondere correttamente alle domande richieste e confermare l'esercizio pratico.
Riepilogo
- I nostri e i loro ruoli dipendono dall’operazione.
- Salvare e contrassegnare prima come risolto, quindi continuare.
- Successivamente controllare l'intero file e lo stato dell'operazione.
Relativo
Termini del glossario introdotti
Conflitto: تعارض; base: الأساس; il nostro: نسختنا; loro: نسختهم; risolvere — حلّ.
Trascrizione video
La narrazione del video, spunto per spunto.
Mostra la trascrizione
- Un conflitto non è un errore. È un domanda a cui solo tu puoi rispondere.
- Due persone hanno cambiato la stessa linea del stesso file.
- Sara ha scritto un titolo. Omar ha scritto un altro. Entrambi sono partiti dalla stessa pagina.
- Git non può indovinare quale linea vince, quindi fallo si ferma e ti chiede.
- Costruisci prima i rami di Sara e di Omar, e due copie identiche.
- Nella prima copia ci uniamo. Nel secondo, ribasiamo.
- Apri la copia unificata, sul ramo di Sara.
- Fare clic con il tasto destro sul ramo di Omar e sceglierlo Unisci comando.
- La finestra di dialogo avverte già: questo si fermerà con un conflitto in un file.
- Scegli Sempre un commit di unione, quindi Unisci una volta. Si ferma, come previsto.
- Il banner mostra un conflitto. Continua è non ancora disponibile
- Scegli Risolvi e apri index.html.
- Due facce: il ramo di Sara è attuale, Quello di Omar è in arrivo.
- Show Base rivela l'antenato comune, il pagina prima della modifica.
- Ora modifica l'output. Sostituisci l'intestazione con una linea deliberata.
- Salva e contrassegna come risolto. Solo ora Git considerare il file come risolto.
- Tornando al banner, scegli Continua. Il unire le finiture.
- Il nuovo commit ha due genitori e il rubrica combinata.
- Adesso la copia rebase, anche su quella di Sara ramo.
- Fare clic con il tasto destro sul ramo di Omar e rebase Il ramo di Sara su di esso.
- Lascia le opzioni disattivate e riprogramma una volta. Esso si ferma con un conflitto.
- Guarda le etichette. Adesso lo è la filiale di Omar quello su cui ci basiamo.
- Il commit di Sara è quello che viene riprodotto. I ruoli si sono scambiati.
- Stessa risoluzione: Modifica output, quindi Salva e Segna risolto, quindi Continua.
- Il commit di Sara viene ricreato sopra Omar's, con la stessa intestazione.
- Nel terminale, elenca le voci non unite di una fusione interrotta.
- La seconda fase è nostra: la rotta di Sara. Palcoscenico tre sono loro: di Omar.
- In un rebase interrotto, fasi due e tre sono il contrario.
- Dopo la correzione, nulla viene separato e lo stato è vuoto.
- Il suggerimento della copia unita ha due genitori; il Il suggerimento della copia rebase ne ha uno.
- Modificare l'input: eliminare i marcatori e salva, ma non contrassegnare come risolto.
- Git vede ancora tre fasi, quindi Continua rimane non disponibile.
- Incollato? Abort rimette il ramo dove è iniziata l'operazione.
- GitTree salva prima uno snapshot di ripristino, quindi anche un aborto è sicuro.
- Non prendere mai tutto da una parte davanti a te leggi entrambe le versioni.
- Esercizio: dimostrare i ruoli scenici in entrambi copie, quindi finirle entrambe.
- Successivamente, continua, salta o interrompi un'operazione che si è fermato.