2009-08-01 9 views
7

Sto riscontrando un problema con il rebasing dal master su un ramo 'deploy' all'interno di uno dei miei repository.Git rebase fallisce continuamente e richiede un intervento di unione manuale

mio repo si effettua 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 

In generale il mio flusso di lavoro è:

  1. fare lo sviluppo sul ramo maestro ... prova, sorriso, commit.
  2. Checkout ramo deploy
  3. Eseguire git rebase master sul ramo Deploy - questo usato per funzionare senza problemi
  4. Push to remoto e quindi eseguire cap deploy
  5. Relax

Il problema ora sto avendo è che quando eseguo git rebase master sul ramo di distribuzione viene generato un errore di unione/fusione manuale a 3 vie richiesto (non penso che il messaggio di errore sia davvero abbastanza generico da postare). Git mi dice di eseguire una fusione, quindi usare git rebase --continue per terminare, il che non funziona mai.

Quello che ho trovato "funziona" è in esecuzione git rebase master --interactive, pulendo l'elenco di selezione (sono presenti 5 o più "commit" ma con numeri di riferimento diversi (stesso messaggio) in questo elenco, quindi selezionerò uno di loro) e quindi eseguire l'unione manualmente. Una volta che ho fatto questo per ogni commit, posso continuare il rebase e tutto è felice ...

Fino alla prossima volta ho bisogno di eseguire un rebase.

Quindi qualcuno sa cosa potrebbe essere felice? Il progetto non è realmente 'segreto', quindi se necessario posso pubblicare messaggi, registri, grafici ecc filiali

Grazie

+2

Quanti commit hai sul tuo ramo di distribuzione e possono essere schiacciati? rebase deve conservare tutti i commit intermedi in una lista di commit e sembra che alcuni di questi ora causino conflitti artificiali mentre tentano di preservare uno stato intermedio artificiale che non ha più senso. –

risposta

1

Quello che potrebbe sembrare che stia succedendo è che hai cambiato la cronologia dei commit di quei commit "ripetuti" in modo che abbiano uno sha1 differente. Ogni sha1 è unico non solo per il commit, ma anche per la cronologia del commit. Quindi, è impossibile (beh, altamente improbabile che accada durante la vita dell'universo), avere due sha1 identici nella stessa storia o avere due sha1 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 sembrare uguali, vengono in realtà trattati in modo diverso.

Quindi molto probabilmente, è stato effettuato un nuovo collegamento dall'altro ramo, è stato eseguito un qualche tipo di rebase interattivo o sono stati modificati i commit, ha continuato a eseguire il commit di un altro codice che ha modificato la stessa parte del codice, quindi nel successivo rebase si sono verificati conflitti i commit che hai nel tuo ramo locale che differiscono dal ramo da cui ti stai riposizionando vengono rimossi dal ramo, viene inserito il monte che include quel commit che hai già tirato dentro e cambiato lo sha1 di, e poi quando i commit sono riprodotto sul ramo si finisce con un conflitto perché lo stato del codice è cambiato da ciò che era previsto dal commit perché è stato creato originariamente da una cronologia diversa da quella che si ha ora sul ramo. Wow, quella era una lunga frase ...

Quando "pulisci" la lista di prelievo ... quello che stai facendo è probabilmente cancellando questi commit ripetuti prima di ridiscutere, quindi ora non stai riapplicando le modifiche che sono già stati applicati, quindi non ci sono più conflitti.

Tuttavia, se si volesse risolvere i conflitti durante il rebase, questa sarebbe probabilmente la scelta migliore in modo da non eliminare accidentalmente un commit che si desidera. Risolvendo i conflitti, il set di modifiche di tale commit diventerà diverso e applicabile alla cronologia che hai. Dopo aver premuto questa risoluzione conflitto di unione, non si dovrebbe visualizzare nuovamente i problemi a meno che non si modifichi i commit che sono stati già inseriti nuovamente.

Per trovare quali file sono i conflitti di unione fare:

git status 

o

git ls-files -u 

Una volta che sai quali file sono in conflitto, se si dispone di una configurazione mergetool si può fare:

git mergetool <file> 

Se preferisci unire manualmente, puoi trovare gli indicatori di unione e le linee eseguendo:

grep -Hnr '^=\{7\}\|^<\{7\}\|^>\{7\}' * 

al livello superiore del percorso repo e modifica. Quando si modifica manualmente, assicurarsi di rimuovere i marcatori e rendere la versione finale del file simile a come si desidera ... git non fa nulla di speciale con i marcatori per te.Quando hai finito di editting manualmente, assicurarsi di fare

git add <file> 

per aggiungere il file per aggiungerlo al indice e rimuovere il flag unmerged. Al termine della risoluzione di tutti i file non raggruppati, fare

git rebase --continue 

Per completare il rebase.

1

Si potrebbe definire un attribute nella directory principale dei file "distribuire-specifiche" , per selezionare sempre il contenuto del ramo di distribuzione in caso di unione.

Per un esempio di gestore unione, vedere this SO answer.

Altro strategies have been discussed, ma la chiave rimane: considerare sempre un'unione come "unione di un progetto" e non un'unione basata su file. Da qui gli attributi per perfezionare quell'unione in tutto il progetto quando si tratta di alcuni file "speciali".

2

Per arrivare git rebase --continue a lavorare si deve fondere in realtà i file in conflitto (modificarli, scegliere le parti che si desidera da tra i marcatori di conflitto “< < < < < < <”, “=======” , ">>>>>>>") 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). Controllare il diff attuale con git diff --cached, quindi git rebase --continue se sembra corretto.

Prima di tentare il rebase (o dopo aver interrotto uno problematico), controllare git log -p master..deploy per visualizzare i commit che si sta tentando di rebase.È uno di questi che è in conflitto con quello che hai nel master .

Questi commit che si sta eliminando eliminando le loro righe di prelievo in git rebase -i potrebbero non essere esattamente uguali (anche se hanno lo stesso 'oggetto' nel messaggio di commit). Il fatto che tu pensi che ci dovrebbe essere solo uno di questi indica che qualcosa di strano sta succedendo con il tuo distribuire il ramo. Questi comandi "duplicati" vengono commessi sulla punta di , distribuire o ci sono altri commit dopo di essi? Forse vedere il contenuto di quei commit "fishy" (log -p, sopra) ti darà un indizio sulla loro fonte.