Git rebase fallisce continuamente e richiede un intervento manuale di unione
Domanda
Sto riscontrando un problema con il passaggio dal master al ramo "deploy" all'interno di uno dei miei repository.
Il mio repository è configurato come segue:
master - of course, the main branch
deploy - a branch created where files like Capfile, deploy.rb etc are created and configured - these changes will NEVER be merged back into Master
Generalmente il mio flusso di lavoro è:
- Esegui lo sviluppo sul ramo principale ... testa, sorridi, commetti.
- Guarda il
deploy
ramo - Esegui
git rebase master
sul ramo di distribuzione: funzionava senza problemi - Premi sul telecomando e quindi esegui
cap deploy
- Relax
Il problema che sto riscontrando ora è che quando eseguo git rebase --continue
sul ramo di distribuzione viene visualizzato un errore richiesto di unione / unione manuale a 3 vie (non credo che il messaggio di errore sia abbastanza generico per inviare). Git mi dice di eseguire un'unione, quindi utilizzare git rebase master --interactive
per finire, il che non funziona mai.
Quello che ho trovato funziona 'funziona' è in esecuzione <=>, ripulendo l'elenco di selezione (ci sono 5 o più 'commit' ripetuti ma con numeri di riferimento diversi (stesso messaggio) in questo elenco, quindi sceglierò uno di questi) e quindi eseguire manualmente l'unione. Una volta fatto questo per ogni commit, posso continuare il rebase ed è tutto felice ...
Alla prossima ho bisogno di eseguire un rebase.
Quindi qualcuno sa cosa potrebbe essere felice? Il progetto non è davvero "segreto", quindi se necessario posso pubblicare messaggi, registri, grafici di rami, ecc.
Grazie
Soluzione
Ciò che sembra potrebbe accadere è che hai cambiato la cronologia di commit di quelle " ripetute " si impegna in modo tale da avere un diverso sha1. Ogni sha1 è unico non solo per il commit, ma per la cronologia del commit. Quindi, è impossibile (beh, altamente improbabile accadere durante la vita dell'universo), avere due sha1 identici nella stessa storia o avere due sha1 anche in due storie diverse. Se cambi qualcosa nel tuo commit, ad esempio con una modifica o un rebase interattivo, cambierai sha1. Quindi due commit che potrebbero apparire uguali, in realtà sono trattati in modo diverso.
Quindi molto probabilmente, ti sei allontanato dall'altro ramo, hai fatto qualche tipo di rebase interattivo o modificato i commit, hai continuato a impegnare un po 'più di codice che ha modificato quella stessa parte del codice, quindi sul rebase successivo hai dei conflitti perché il i commit che hai nel tuo ramo locale che differiscono dal ramo da cui stai effettuando la rebasing vengono rimossi dal ramo, viene inserito il monte a monte incluso quel commit di cui hai già eseguito il pull e modificato sha1, e quindi quando i commit vengono rigiocati sul ramo si finisce con un conflitto perché lo stato del codice è cambiato rispetto a quanto previsto dal commit perché era originale creato da una cronologia diversa da quella che ora si ha sul proprio ramo. Caspita, è stata una lunga frase ...
Quando sei " pulizia " nella lista di prelievo ... probabilmente stai eliminando questi commit ripetuti prima di procedere alla riformulazione, quindi ora non stai riapplicando le modifiche che sono già state applicate, quindi niente più conflitti.
Tuttavia, se volessi solo risolvere i conflitti durante il rebase, questa sarebbe probabilmente la scommessa migliore in modo da non eliminare accidentalmente un commit che desideri. La risoluzione dei conflitti renderà il set di modifiche di quel commit diverso e applicabile alla cronologia che hai. Dopo aver inviato questa risoluzione dei conflitti di unione, non dovresti più visualizzare i problemi a meno che non modifichi i commit che sono già stati inviati di nuovo.
Per trovare quali file hanno i conflitti di unione, fare:
git status
o
git ls-files -u
Una volta che sai quali file sono in conflitto, se hai una configurazione di mergetool puoi fare:
git mergetool <file>
Se preferisci unire manualmente, puoi trovare gli indicatori e le linee di unione facendo:
grep -Hnr '^=\{7\}\|^<\{7\}\|^>\{7\}' *
al livello superiore del percorso repository e modifica. Quando modifichi manualmente, assicurati di rimuovere i marcatori e di far apparire la versione finale del file come desideri ... git non fa nulla di speciale con i marcatori per te. Quando hai finito di modificare manualmente, assicurati di fare
git add <file>
per aggiungere il file per aggiungerlo all'indice e rimuovere il flag non unito. Al termine della risoluzione di tutti i file non uniti, eseguire
git rebase --continue
Per completare il rebase.
Altri suggerimenti
Per far funzionare git rebase --continue
devi effettivamente unire i file in conflitto (modificali, scegli le parti che vuoi tra i marcatori di conflitto & # 8220; < < lt; < < < < & # 8221 ;, & # 8220; ======= & # 8221 ;, & # 8220; & Gt; & Gt; & Gt; & Gt; & Gt; & Gt; & Gt; & # 8221;) e quindi git add
all'indice (l'indice è dove sono registrati come in conflitto, l'aggiunta di un file cancella il suo stato in conflitto). Controlla l'attuale diff con git diff --cached
, quindi git log -p master..deploy
se sembra giusto.
Prima di tentare il rebase (o dopo aver interrotto un problema), controlla git rebase -i
per visualizzare i commit che stai tentando di rebase. È uno di questi che è in conflitto con qualsiasi cosa tu abbia in master .
Questi si impegnano a eliminare eliminando il loro & # 8216; scegli & # 8217; le righe in log -p
potrebbero non essere esattamente le stesse (anche se hanno lo stesso & # 8216; oggetto & # 8217; nel loro messaggio di commit). Il fatto che pensi che dovrebbe essercene solo uno indica che sta succedendo qualcosa di sospetto nel tuo ramo deploy . Questi sono & # 8216; duplicati & # 8217; commit sulla punta di deploy o ci sono altri commit dopo di loro? Forse vedendo il contenuto di quelli & # 8216; fishy & # 8217; commit (<=>, sopra) ti darà un indizio sulla loro fonte.
È possibile definire un attributo nella directory principale del tuo " deploy & SPECIFICI quot; file, per selezionare sempre il contenuto del ramo di distribuzione in caso di unione.
Per un esempio di Merge Manager, vedi questa risposta SO .
Altre sono state discusse , ma la chiave rimane: considera sempre un'unione come " un'unione a livello di progetto " e non un'unione basata su file. Da qui gli attributi per affinare quell'unione a livello di progetto quando si tratta di alcune & Quot; speciali & Quot; file.