2015-02-20 23 views
6

Dopo aver terminato lavorando su un ramo argomento, ho unito il ramo argomento in maestro come segue:Git: rebasing un'unione conflittuale commettere

  o---*---o---o topic 
     /   \ 
o---o---o---*---o---o---+ master 

i commit contrassegnati con '*' modificato lo stesso codice, quindi la fusione di piombo per unire i conflitti risolti nel commit di unione (contrassegnati con '+').

Mentre ho fuso e risolti i conflitti, il mio collega spinto nuovi commit da padroneggiare (contrassegnato come 'n'), con conseguente seguente storia:

  o---*---o---o topic 
     /   \ 
o---o---o---*---o---o---+ master 
        \ 
        n---n origin/master 

Ora, spingendo il mio ramo principale locale naturalmente porta ad un errore, in quanto non è un fast-forward-push, così ho due scelte:

  1. buttare via il mio lavoro, master reset di origine/master e rifare l'unione. Vorrei evitarlo, visto che dovrei risolvere nuovamente i conflitti.

  2. Rebase master su origine/master e spingere. Ecco il mio problema: fare questo rebase (anche quando si utilizza lo switch -p) non funziona correttamente, il commit di merge mostra gli stessi conflitti di nuovo, anche se il nuovo commit ('n') non ha cambiato nulla toccato dal ramo dell'argomento . Così avrei dovuto risolvere i conflitti di nuovo durante il rebase e avrei lo stesso risultato con l'opzione 1.

Quello che mi piacerebbe realizzare è rebasing l'unione commit '+', senza dover risolvere i conflitti ancora:

  o---*---o---o-------- topic 
     /     \ 
o---o---o---*---o---o---n---n---+ master & origin/master 

Edit:

L'interruttore rerere è abilitato ma non sembra aiutare in qualsiasi modo; devo fare qualcosa di più che impostare config.rerere su true per risolvere il mio problema?

Edit 2:

Unire l'unione-commit ('+') per origin/master potrebbe anche funzionare (come proposto nei commenti e una risposta), ma porterebbe a una sorta di storia brutta che ho' Mi piacerebbe evitare di avere un solo merge commit.

+0

È anche possibile eseguire il backmerge dell'origine/master prima di unirvi il nuovo master. – ScayTrase

+0

@ScayTrase Sarebbe possibile, ma porterebbe a una brutta storia; Preferirei la soluzione pulita con un solo commit commit – rhabarbersaft

+0

Sfortunatamente, non c'è una vera via d'uscita da questo: non importa quale delle due opzioni finisci per scegliere, molto probabilmente dovrai risolvere nuovamente i conflitti. Se prevedi che ti troverai nella stessa situazione in futuro, dovresti prendere in considerazione l'attivazione di ['rerere'] (http://stackoverflow.com/questions/25670519/git-rebase-preserve-merges-fails/ 25671230 # 25671230). – Jubobs

risposta

0

cosa succede se si rebase argomento in cima maestro, ripristinare master al commit precedente e tirare dal telecomando, in modo che si avrebbe in questo modo:

  o---*---o---o 
     /   \ 
o---o---o---*---o---o---+ topic 
        \ 
        n---n master & origin/master 

E poi si uniscono in argomento maestro, risultante in questo (nuovo commit unione contrassegnato con '#'):

  o---*---o----o 
     /   \ 
o---o---o---*---o---o----+ topic 
        \  \ 
        n--n--# master 

Ciò causa conflitti? Funzionerebbe per te?

+0

Vorrei impedire questa storia 'brutta' e avere un solo commit commit – rhabarbersaft

1

Il primo modo sarebbe il migliore. Annullare l'unione e ripetere l'operazione per ottenere le modifiche del collega nel commit di unione. Ma non è necessario buttare via le modifiche.

Poiché si sa che le modifiche del collega non hanno influenzato i file in cui sono stati risolti i conflitti. Potresti creare un nuovo ramo (lo chiameremo conflict-fix) dallo stato attuale del master. Reimposta il tuo ramo e ripristina l'unione.

Piuttosto che utilizzare git mergetool o qualsiasi altro editor che si utilizza. Puoi portare il file in master dal tuo altro ramo usando git checkout conflict-fix -- <file names>. git add i file e si impegnano a completare l'unione. Quindi è possibile eliminare il ramo conflict-fix.

Questo è abbastanza facile da eseguire e comporterà il commit singolo merge che si sta cercando oltre a consentire di spingere le modifiche. Se il nuovo commit ha influenzato i file che hai risolto, i conflitti in te dovrebbero essere ripetuti comunque.

EDIT

non sono completamente familiarità con git rerere ma che dovrebbe avere funzionato. Tuttavia, in base al tuo commento, non è necessario rebase. Avresti comunque annullato il commit unione, git fetch gli aggiornamenti e ri-eseguito l'unione. Dovresti semplicemente chiamare il comando git rerere e risolvere i conflitti nei file per te. Con il vostro albero in cerca in questo modo:

  o---*---o---A topic 
     /   \ 
o---o---o---*---o---o---+ master 
       \ 
        n---n origin/master 

Si potrebbe effettuare le seguenti operazioni:

git reset --hard A 
git checkout master 
git pull 
git merge topic 
git rerere 
//Fix other conflicts 
git push 

E si dovrebbe finire con:

  o---*---o---o-------- topic 
     /     \ 
o---o---o---*---o---o---n---n---+ master & origin/master 

Non ci dovrebbe essere bisogno di rebase nulla.

http://git-scm.com/docs/git-rerere

+0

Solo provato funziona bene Ma: se origin/master ha cambiamenti nello stesso file che portano a conflitti (modificati in '*') ma su altre linee (non porta a conflitti di unione aggiuntivi), tali modifiche verrebbero ripristinate se eseguo il checkout di 'conflict-fix '-versioni dei file in conflitto. Quindi sto ancora cercando una soluzione con Git che riapplica automaticamente la soluzione di conflitto che ho fatto nella prima fusione (e ho pensato che 'rerere' lo farebbe) – rhabarbersaft

+0

Sfortunatamente' rerere' non funziona in questo caso, solo provato di nuovo per essere sicuro. Dice anche "Risoluzione registrata per ..." quando si esegue la fusione per la prima volta, ma non esegue alcuna operazione durante la fusione di nuovo come proposto. – rhabarbersaft

0

rerere è il modo per evitare questo è tale una seccatura, ma se non lo avete attivato prima di fatto la prima fusione non ti aiuterà. Puoi sapere se è abilitato perché fornirà messaggi su "registrazione preimage"

Recentemente mi sono imbattuto in questo perché avevo una nuova macchina di sviluppo e ho dimenticato di abilitare la rerere prima di una brutta unione. Non c'è una soluzione geniale solo a questo scenario, ma quanto segue è il recupero più semplice di questa situazione che potrei trovare.

  1. assicurarsi che la directory di lavoro è esattamente il risultato della fusione (git di reset HEAD --hard) e copiare l'albero dei sorgenti dal commettere la stampa in un posto sicuro
  2. ripristinare la filiale locale di nuovo prima di qualsiasi commit unite (ripristino git --hard maestro ~ o git di reset HEAD ~ n dove n è quanto indietro è necessario andare)
  3. git pull file
  4. git merge argomento
  5. origine della copia di nuovo nel vostro albero di lavoro sovrascrittura.
  6. git mergetool (per gestire qualsiasi cancellati vs conflitti modificati)
  7. commettere e spingere

Dal momento che stavamo lavorando con Gerrit ho anche fatto in modo che il cambiamento-Id era lo stesso come il mio merge precedente commettere così Potrei verificare che nulla fosse andato storto.

Problemi correlati