Lezione 31 · Recupero
Mantenere il lavoro distaccato e iniziare una storia orfana
Assegna un nome a un commit effettuato su un HEAD distaccato prima di lasciarlo, quindi avvia un ramo orfano in una copia separata e guarda cosa rimuove e cosa mantiene.
- Livello: Intermedio
- 11 minuti di lettura
- 5 minuti di video
- Aggiornato
- Prima di questa lezione: Crea un ramo di funzionalità e ritira solo il rif usa e getta, Trova un commit perso con reflog
Avanzamenti salvati in questo browser.
La riproduzione carica il video da YouTube (modalità ottimizzata per la privacy).
Cosa imparerai
- Dite a parte la TESTA attaccata, distaccata e non nata.
- Metti un ramo su un commit distaccato in modo che rimanga raggiungibile.
- Prevedi cosa fa un ramo orfano ai file tracciati, ai file non tracciati e al vecchio ramo.
- Leggi un rifiuto di pagamento causato da modifiche locali.
Prima di iniziare
Due copie usa e getta del risultato M della lezione 18. Nella prima, controlli il commit M stesso invece del ramo, apporti una piccola modifica al foglio di stile lì e vuoi mantenerlo. Nel secondo, desideri una cronologia nuova di zecca e non correlata per un ramo di sola documentazione senza toccare main.
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
HEAD normalmente nomina un ramo e il commit sposta quel ramo. Quando HEAD nomina direttamente un commit è detached: un nuovo commit è reale, ma nulla gli dà un nome, quindi spostandosi lo lascia raggiungibile solo attraverso il reflog. Mettendoci sopra un ramo si risolve il problema. La creazione di un ramo non comporta il passaggio ad esso a meno che tu non lo decida.
Un ramo orphan è diverso. HEAD nomina un ramo che non ha ancora alcun commit (un ramo non ancora nato). Il suo primo commit non ha elemento principale, quindi non condivide la cronologia con main. Git rimuove i file tracciati dalla cartella di lavoro; i file non tracciati e ignorati rimangono. Se il vecchio .gitignore veniva tracciato, le sue regole lo accompagnano e i file ignorati ora possono essere visualizzati come non tracciati. Il tuo vecchio ramo mantiene ogni commit.
Entrambi gli stati sono normali, non danni. Un checkout viene rifiutato quando sovrascriverebbe le modifiche locali; nulla è perduto.
Preparare lo stato esatto del progetto
Inizia da due copie ordinarie separate del risultato della lezione 18 e lascia intatto l'originale. I corpi sottostanti sono il foglio di stile della linea di base (BASE_CSS), quello ampliato (LAYOUT), una modifica sporca (DIRTY_LAYOUT), il file readme dell'orfano (ORPHAN_README), una nota locale (LOCAL_NOTE) e una nota ignorata (IGNORED_NOTE).
Completare gli input del file
Salva ogni corpo UTF-8/LF completo solo nella fase indicata, con un ritorno a capo finale e senza recinzioni Markdown. BASE_CSS è il riferimento 48rem ereditato; LAYOUT è il commit 52rem; DIRTY_LAYOUT è un replay 56rem separato e non messo in scena. I due file di note appartengono solo alla variante sopravvissuta. I file principali invariati ereditano l'intero ingresso L018/M.
stili.css — BASE_CSS
:root {
color-scheme: light;
--page: #f7f8fa;
--surface: #ffffff;
--text: #17212e;
--link: #154ab5;
--line: #bac4d0;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
background: var(--page);
color: var(--text);
font: 1rem/1.6 system-ui, sans-serif;
}
a {
color: var(--link);
}
.site-header,
main,
footer {
width: min(68rem, 100% - 2rem);
margin-inline: auto;
}
.site-header {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: 1rem;
padding-block: 1rem;
}
.hero {
max-width: 48rem;
padding-block: 3rem;
}
h1 {
font-size: clamp(2rem, 5vw, 3.5rem);
line-height: 1.2;
}
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
gap: 1rem;
}
.feature-card {
padding: 1rem;
border: 1px solid var(--line);
border-radius: 0.75rem;
background: var(--surface);
}
section {
margin-block-end: 2rem;
}
button,
input {
font: inherit;
}
button,
input {
padding: 0.5rem 0.75rem;
}
:focus-visible {
outline: 3px solid var(--link);
outline-offset: 3px;
}
form {
display: grid;
max-width: 28rem;
gap: 0.5rem;
}stili.css — DISPOSIZIONE
:root {
color-scheme: light;
--page: #f7f8fa;
--surface: #ffffff;
--text: #17212e;
--link: #154ab5;
--line: #bac4d0;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
background: var(--page);
color: var(--text);
font: 1rem/1.6 system-ui, sans-serif;
}
a {
color: var(--link);
}
.site-header,
main,
footer {
width: min(68rem, 100% - 2rem);
margin-inline: auto;
}
.site-header {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: 1rem;
padding-block: 1rem;
}
.hero {
max-width: 52rem;
padding-block: 3rem;
}
h1 {
font-size: clamp(2rem, 5vw, 3.5rem);
line-height: 1.2;
}
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
gap: 1rem;
}
.feature-card {
padding: 1rem;
border: 1px solid var(--line);
border-radius: 0.75rem;
background: var(--surface);
}
section {
margin-block-end: 2rem;
}
button,
input {
font: inherit;
}
button,
input {
padding: 0.5rem 0.75rem;
}
:focus-visible {
outline: 3px solid var(--link);
outline-offset: 3px;
}
form {
display: grid;
max-width: 28rem;
gap: 0.5rem;
}stili.css — DIRTY_LAYOUT
:root {
color-scheme: light;
--page: #f7f8fa;
--surface: #ffffff;
--text: #17212e;
--link: #154ab5;
--line: #bac4d0;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
background: var(--page);
color: var(--text);
font: 1rem/1.6 system-ui, sans-serif;
}
a {
color: var(--link);
}
.site-header,
main,
footer {
width: min(68rem, 100% - 2rem);
margin-inline: auto;
}
.site-header {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: 1rem;
padding-block: 1rem;
}
.hero {
max-width: 56rem;
padding-block: 3rem;
}
h1 {
font-size: clamp(2rem, 5vw, 3.5rem);
line-height: 1.2;
}
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
gap: 1rem;
}
.feature-card {
padding: 1rem;
border: 1px solid var(--line);
border-radius: 0.75rem;
background: var(--surface);
}
section {
margin-block-end: 2rem;
}
button,
input {
font: inherit;
}
button,
input {
padding: 0.5rem 0.75rem;
}
:focus-visible {
outline: 3px solid var(--link);
outline-offset: 3px;
}
form {
display: grid;
max-width: 28rem;
gap: 0.5rem;
}README.md — ORPHAN_README
# GitTree Features documentation
This branch contains a documentation-only history for the fictional course project.
The landing page remains on main; no form submits information to a server.
Keep useful detached experiments under a branch name before switching away.local-review.txt — LOCAL_NOTE
Local rehearsal note; preserve this file.report/preview.txt — IGNORED_NOTE
Ignored rehearsal preview; preserve these bytes.Tra GitTree
Apri la tavolozza con Comando+Maiusc+P (Ctrl+Maiusc+P su Ubuntu).
- Nella prima copia, fai clic con il pulsante destro del mouse sul commit M nel grafico e scegli Check Out This Commit. Il selettore del ramo riporta "Distaccato a..." e il grafico mostra HEAD, detached.
- Salva LAYOUT come
styles.css, metti in stage quel file e confermalo con il Riepilogostyle: widen the hero reading measure. Il pannello conta il resto “a TESTA staccata” mentre si lavora. - Fai clic con il pulsante destro del mouse sul nuovo commit e scegli Create Branch Here…. Chiamalo
experiment/layout, lascia disattivata l'opzione di verificarlo e scegli Create Branch. L'avviso dice "Esperimento/layout creato". e HEAD è ancora staccato. - Fai clic con il pulsante destro del mouse sull'etichetta
experiment/layoute scegli Check Out Branch. HEAD è nuovamente collegato,styles.cssè LAYOUT emainpunta ancora a M. - Dirty checkout. In un'altra copia, scollegati a
experiment/layout, modificastyles.cssin DIRTY_LAYOUT senza impegnarti e prova a controllaremain. La finestra di dialogo "Le modifiche locali sono in mezzo al main" elenca il file e offre Commit First, Stash and Switch e Discard and Switch. Scegli Annulla; Lo scarto mantiene una copia sottorefs/ogt/trashma non è necessario qui. - Orphan. Nella seconda copia, con un albero di lavoro pulito, esegui Create Orphan Branch… dalla tavolozza. In "Creare un ramo orfano in...?" digitare
orphan-docs. La finestra di dialogo indica quanti file tracciati lasciano la cartella di lavoro, quali file non tracciati e ignorati rimangono e che il vecchio commit viene mantenuto inrefs/ogt/trash. Annulla ha il focus. Scegli Create Orphan Branch. - L'avviso dice "Passato al nuovo ramo orfano orphan-docs. Annulla i passaggi indietro." La cartella non ha file tracciati e il grafico non mostra alcun commit sul nuovo ramo. Crea
README.mdda ORPHAN_README, mettilo in stage e confermalo con il Riepilogodocs: start the separate project guide. Il nuovo commit non ha genitore. - Confronta:
mainha ancora tutti i commit; il ramo orfano è una radice separata. Non spingere nessuna delle due copie.
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
Nella prima copia:
BASE_SHA="$(git rev-parse main)"
git switch --detach "$BASE_SHA"
git symbolic-ref --quiet --short HEAD; echo $?L'ultimo comando stampa 1: HEAD non è un ramo. Salva LAYOUT come styles.css, quindi:
git commit --quiet -am "style: widen the hero reading measure"
git branch experiment/layout
git symbolic-ref --quiet --short HEAD; echo $?
git rev-parse HEAD^ main
git switch --quiet experiment/layout
git symbolic-ref --short HEAD
git status --short1
experiment/layoutIl comando di creazione non allega HEAD (la seconda query stampa ancora 1), i due ID di rev-parse sono uguali (M) e lo stato è vuoto. In un'altra copia staccata in experiment/layout, modifica styles.css ed esegui git switch main: Git rifiuta con "Le tue modifiche locali ai seguenti file verrebbero sovrascritte dal checkout" e il file non viene toccato.
Nella seconda copia, con un albero pulito:
git switch --orphan orphan-docs
git symbolic-ref --short HEAD
git rev-parse --verify --quiet HEAD; echo $?
git ls-filesorphan-docs
1Il ramo esiste ma non ha commit (rev-parse esce 1) e ls-files non stampa nulla. I file tracciati sono stati rimossi dalla cartella, mentre local-review.txt e reports/ rimangono e ora vengono visualizzati come non tracciati. Crea README.md, quindi:
git add -- README.md
git commit --quiet -m "docs: start the separate project guide"
git ls-tree -r --name-only HEAD
git rev-list --max-parents=0 --count HEAD
git merge-base --all main orphan-docs; echo $?README.md
1
1Il nuovo ramo ha un commit root e nessun antenato comune con main (merge-base non stampa nulla ed esce 1).
Risultato
Where you end: il commit distaccato si chiama experiment/layout ed è stato estratto, main punta ancora a M e l'albero è pulito. La copia orfana ha orphan-docs con un commit root che non ha elemento principale, i vecchi file tracciati sono stati rimossi dalla cartella ma conservati da main e non è stato inviato nulla.
Errori comuni
- Effettuare il commit su un HEAD distaccato e passare senza un ramo, il che lascia il commit raggiungibile solo tramite il reflog.
- Previsto che
Create Branch Here…passi al nuovo ramo. - Avviare un ramo orfano con modifiche rilevate non salvate o pensare che elimini
main. - Supponendo che un file che è stato ignorato rimanga ignorato dopo che il suo
.gitignoreha lasciato la cartella.
Se qualcosa va storto
Se hai lasciato un commit distaccato senza nome, apri il reflog (lezione 29) e inseriscici un ramo. Se un ramo orfano è stato un errore, Undo torna indietro mentre il nuovo ramo non ha commit; altrimenti controlla di nuovo main. Un checkout rifiutato non ha cambiato nulla.
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
Riporta dove punta HEAD in ogni stato (ramo, distaccato, non nato), l'ID del commit distaccato e del ramo su di esso e cosa git ls-files è stampato sul ramo orfano. Quindi prevedere cosa succede a un file ignorato quando il .gitignore scompare.
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
- Un commit distaccato necessita di un ramo per rimanere raggiungibile.
- Un ramo orfano avvia una radice separata e rimuove i file tracciati dalla cartella.
- Un check-out rifiutato protegge la tua modifica.
Relativo
Termini del glossario introdotti
HEAD distaccato — HEAD منفصل; ramo orfano: فرع يتيم; ramo non ancora nato: فرع غير مولود; commit root — إيداع جذري.
Trascrizione video
La narrazione del video, spunto per spunto.
Mostra la trascrizione
- Dov'è la TESTA? Tre stati.
- HEAD può nominare un ramo, un commit o un file branch senza ancora alcun commit.
- Un impegno effettuato mentre si è distaccati è reale, ma niente lo nomina.
- Un ramo su quel commit lo mantiene raggiungibile.
- Fare clic con il pulsante destro del mouse sul commit M e scegliere Controlla Fuori questo impegno.
- Cambia il foglio di stile, mettilo in scena e impegnarsi una volta.
- Fare clic con il pulsante destro del mouse sul nuovo commit e creare un file ramo qui, senza verificarlo.
- Ora controlla la filiale. La TESTA è allegata di nuovo.
- Con una modifica non salvata, un checkout è rifiutato. Annulla mantiene tutto.
- Impegnati prima, metti da parte e cambia, o scartare. Lo scarto è quello da evitare.
- Per una nuova cronologia, esegui Crea orfano Ramo dalla tavolozza.
- Conta i file tracciati che lasciano. Quelli non tracciati e ignorati rimangono.
- Conferma. La cartella non contiene file tracciati.
- Aggiungi un file leggimi e conferma. Questo impegno ha nessun genitore.
- Nel terminale, simbolico-rif esce 1 quando La TESTA è staccata.
- Su un ramo non ancora nato, rev-parse di HEAD fallisce.
- Dopo il commit, merge-base non trova antenato comune.
- Se sei rimasto senza ramo, effettua il reflog ce l'ha ancora.
- Esercizio: nominare HEAD in ogni stato, quindi prevedere un file ignorato.
- Successivamente, recupera dagli errori dopo aver spinto.