2009-07-03 13 views
134

Qui ho incontrato un po 'di problemi: avevo un ramo specifico del problema 28s in Git, che ho unito nel ramo generale develop. Ho scoperto che l'avevo fatto troppo velocemente, quindi ho usato git-revert per annullare l'unione. Ora, tuttavia, è giunto il momento di unire 28s in develop, ma il comando git-merge vede l'unione originale e annuncia felicemente che tutto va bene e che i rami sono già stati uniti. Cosa faccio ora? Crea un "Revert" Ripristina "28s -> sviluppo" "" commit? Non sembra essere un buon modo per farlo, ma non riesco a immaginarne nessun altro al momento.Rifare una fusione ripristinata in Git

Che la struttura ad albero assomiglia:

Git log output

+0

Che cos'è la GUI? –

+3

È GitX (http://gitx.frim.nl). –

risposta

110

Si deve "riportare il Ripristina". Dipende da come l'hai ripristinato, potrebbe non essere così facile come sembra. Guarda lo official document on this topic.

---o---o---o---M---x---x---W---x---Y 
      /
     ---A---B-------------------C---D 

per consentire:

---o---o---o---M---x---x-------x-------* 
      /     /
     ---A---B-------------------C---D 

Ma lo fa tutto il lavoro? Certo che lo fa È possibile ripristinare un'unione e, da un angolo prettamente tecnico di , git lo ha fatto in modo molto naturale e non ha avuto problemi reali .
È stato considerato un cambiamento da "stato prima dell'unione" a "stato dopo unione", e così era.
Niente di complicato, niente di strano, niente di veramente pericoloso. Git lo farà senza nemmeno pensarci.

Quindi, da un punto di vista tecnico, non c'è niente di sbagliato con un ritorno di una stampa, ma da un angolo del flusso di lavoro è qualcosa che in genere dovrebbe cercare di evitare di .

Se possibile, ad esempio, se si trova un problema che ha ottenuto fuse nell'albero principale, piuttosto che ripristina l'unione, provare davvero difficile:

  • bisect il problema giù nel ramo che hai unito, e basta ripararlo,
  • o provare a ripristinare il singolo commit che lo ha causato.

Sì, è più complesso, e no, non è sempre andare a lavorare (a volte la risposta è: "oops, io davvero non avrei dovuto fusa, perché non era ancora pronto, e Devo davvero annullare all dell'unione "). Quindi, in questo caso, è necessario ripristinare l'unione con lo , ma quando si desidera eseguire nuovamente l'unione, è necessario eseguire il ripristino con il ripristinando il ripristino.

+5

Buon collegamento (+1). Mi sono preso la libertà di copiare parte del documento nella risposta per consentire ai lettori di vedere immediatamente le opzioni rilevanti in questo caso. Se non sei d'accordo, sentiti libero di tornare. – VonC

+3

Ci siamo imbattuti in un caso in cui avevamo bisogno di fare questo e abbiamo scoperto che il divertimento non si ferma qui. Si trattava di un ramo a lungo termine che era stato integrato, quindi dovevamo continuare ad aggiornarlo. Il mio approccio qui: http://tech.patientslikeme.com/2010/09/29/dealing-with-git-merge-revisions/ – jdwyah

+0

ho seguito il post sul blog di jdwyah ed è stato glorioso (sul serio, è stato fantastico che fosse solo lavorato). – hellatan

2

Invece di utilizzare git-revert si potrebbe avere usato questo comando nel devel ramo per buttare via (annullare) l'unione sbagliata commit (invece di un ritorno esso).

git checkout devel 
git reset --hard COMMIT_BEFORE_WRONG_MERGE 

Questo regolerà anche il contenuto della directory di lavoro di conseguenza. Fare attenzione:

  • Salvare le modifiche nel ramo sviluppo (dal momento che l'unione sbagliata) perché troppo verranno cancellati dal git-reset. Tutto si impegna dopo quello specificato come l'argomento git reset sarà sparito!
  • Inoltre, non eseguire questa operazione se le modifiche sono già state trasferite da altri repository perché il ripristino riscrive la cronologia.

Si consiglia di studiare attentamente la pagina man git-reset prima di provare questo.

Ora, dopo il reset è possibile ri-applicare le modifiche in devel e poi fare

git checkout devel 
git merge 28s 

Questa sarà una vera e propria unione da 28s in devel come quello iniziale (che ora è cancellato dalla git di storia).

+5

Per chi non ha molta familiarità con git e potrebbe voler seguire queste istruzioni: attento a combinare 'reset --hard' e' push origin'. Inoltre, sappi che un push push all'origine può davvero mettere in crisi le pubbliche relazioni aperte su GitHub. – funroll

+0

Molto utile per risolvere alcuni problemi di unione su un server git privato. Grazie! – mix3d

+2

modifica cronologia. – njzk2

29

Supponiamo di avere tale storia

---o---o---o---M---W---x-------x-------* 
      /      
     ---A---B 

dove A, B falliti i depositi e le W - è tornare di M

Quindi, prima di cominciare riparare trovato problemi io cherry-pick di W si impegnano a mio ramo

git cherry-pick -x W 

Poi ho Revert W commettere il mio ramo

git revert W 

Dopo che posso continuare a riparare.

La storia finale potrebbe essere simile:

---o---o---o---M---W---x-------x-------* 
      /     / 
     ---A---B---W---W`----------C---D 

Quando mando un PR lo farà mostra chiaramente che PR è undo revert e aggiunge alcune nuove commit.

+1

Sembra che potrebbe essere utile, ma è così scarso nei dettagli (quali sono C, D nell'ultimo diagramma) che è più frustrante che utile – Isochronous

+0

@ C e D isocrono sembrano essere commit che risolvono i problemi introdotti da A e B. – Thomas

+0

@Thomas esattamente –

2

per riportare il revert senza rovinare il flusso di lavoro troppo:

  • Creare una copia spazzatura locale sviluppare
  • ripristinare le Revert commettere sulla copia locale di sviluppare
  • Merge che copia nella vostra funzione branch e spinga il tuo ramo di funzione sul tuo server git.

Il tuo ramo di funzionalità dovrebbe ora essere unito come normale quando sei pronto per questo. L'unico svantaggio qui è che avrai qualche fusione/reinserimento extra nella tua cronologia.

1

Ho appena trovato questo post di fronte allo stesso problema. Trovo che sia troppo difficile fare i reset hard ecc. Finirò per cancellare qualcosa che non voglio, e non potrò recuperarlo.

Invece ho verificato il commit volevo che il ramo tornasse ad es. git checkout 123466t7632723. Quindi convertito in un ramo git checkout my-new-branch. Ho quindi cancellato il ramo che non volevo più. Ovviamente questo funzionerà solo se sarai in grado di buttare via il ramo che hai incasinato.

+0

Il 'git reflog' ti proteggerà su un hard reset per un paio di mesi nel caso in cui successivamente scopri che hai bisogno dei commit persi. Il reflog è limitato al repository locale. – Todd