Qual è il modo migliore per annullare un'unione Git che cancella i file dal repository?


13

Quindi immagina quanto segue (e che stiamo usando tutti SourceTree):

  1. Stiamo lavorando tutti sull'origine / sviluppo.
  2. Vado in vacanza per una settimana.
  3. Il mio collega ha lavorato localmente negli ultimi giorni senza fondere origine / sviluppo nel suo ramo di sviluppo locale.
  4. Prova a fare una spinta, gli viene detto che prima deve unirsi, quindi fa una spinta.
  5. Ottiene un conflitto, interrompendo la procedura automatica di commit-after-a-merge.
  6. Supponendo che Git sia come SVN, il mio collega scarta i "nuovi" file nella sua copia di lavoro e quindi commette l'unione - cancellando quei "nuovi" file dal capo origine / sviluppo.
  7. Una settimana di lavoro di sviluppo continua su quella revisione.
  8. Torno dalle vacanze e scopro che mancano diversi giorni al mio lavoro.

Siamo tutti molto nuovi in ​​Git (questo è il nostro primo progetto che lo utilizza), ma quello che ho fatto per risolverlo è stato:

  1. Rinomina "sviluppo" in "sviluppo".
  2. Unisci Develop_old in un nuovo ramo "Develop_new".
  3. Ripristina il ramo develop_new sull'ultimo commit prima della fusione errata.
  4. Da allora Cherry seleziona ogni commit, uno per uno, risolvendo i conflitti a mano.
  5. Spingi Develop_old e Develop_new fino all'origine.

A questo punto, lo sviluppo è nuovo, spero, una "buona" copia di tutti i nostri cambiamenti con le settimane di lavoro successive riapplicate. Sono anche supponendo che "inversa commettere" farà cose strane su una fusione, soprattutto perché le prossime settimane vale la pena di lavoro si basa su di esso - e da quel unione contiene un sacco di cose che facciamo vogliamo insieme con roba noi don' t.

Spero che questo non accada mai più, ma se dovesse succedere di nuovo, mi piacerebbe sapere un modo più semplice / migliore di sistemare le cose. Esiste un modo migliore per annullare una fusione "cattiva", quando nel repository è stato svolto molto lavoro basato su tale unione?


1
Potresti pubblicare una schermata dell'albero git (redatto in modo appropriato) o l'output del tuo git logformato preferito con annotazioni appropriate su ciò che è accaduto nei vari commit? (Vorrei redarre / annotare git log --graph --pretty=oneline --abbrev-commite passare da lì)

1
È troppo tardi per te, ma i test unitari l'avrebbero colto.
nalply

1
@nalply: no se anche l'unione errata ha eliminato i test unitari.
Aaronaught il

Caspita, è davvero una sfortuna davvero insidiosa.
nalply

Risposte:


6

Se ho capito bene, questa è la tua situazione:

    ,-c--c--c--c--M--a--a--X ← develop
o--o--y--y--y--y-´

Dopo un po 'di storia comune (o), hai impegnato e spinto il tuo lavoro (y). Il tuo collega (c) ha lavorato sul suo repository locale e ha fatto una cattiva unione (M). Successivamente potrebbero esserci altri commit (a) in cima a M.

git reset --hard develop M^2
git branch coworker M^1

Ora il tuo grafico appare esattamente come prima della cattiva unione:

    ,-c--c--c--c ← coworker
o--o--y--y--y--y ← develop

Fai una buona unione (G):

git checkout develop
git merge coworker

Con il risultato di:

    ,-c--c--c--c-、
o--o--y--y--y--y--G ← develop

Ora trapianta i commit aggiuntivi:

git reset --hard X
git rebase --onto G M develop

Questo dà il risultato finale:

    ,-c--c--c--c-、
o--o--y--y--y--y--G--a--a--X ← develop

Tenere presente che ciò potrebbe comportare ulteriori conflitti di unione. Inoltre hai appena cambiato la cronologia, vale a dire che tutti i tuoi colleghi dovrebbero clonare / ripristinare / rifare alla nuova cronologia.

PS: ovviamente dovresti sostituire G, Me Xnei tuoi comandi, l'ID commit corrispondente.


Sembra abbastanza evidente nella domanda che tutti questi commit sono già stati trasferiti in un repository condiviso, quindi non credo che il rebasing sia una buona scelta. Il ripristino di tutti gli commit recenti e quindi la raccolta di ciliegie di quelli non in conflitto in cima alla buona unione è più sicuro.
Aaronaught il

Questa era la parte con il clone / reset / rebase. - Se ci sono solo pochi sviluppatori, dire loro di aggiornare i propri repository potrebbe essere un'opzione valida.
Michas,

1

È positivo che tu stia pensando a come riparare il repository, ma se il tuo collega ha eliminato solo i nuovi file e non ha sovrascritto molti aggiornamenti, un approccio molto più semplice sarebbe quello di ripristinare semplicemente i file che sono stati eliminati.

Probabilmente inizierei provando a selezionare ciliegie (sulla testa attuale) i commit originali in cui hai aggiunto il codice che ora è scomparso. Se per qualsiasi motivo che non funziona, dai un'occhiata alla vecchia revisione con i file che hai aggiunto e aggiungili nuovamente in un nuovo commit.

Quello che descrivi è in realtà un sottoinsieme di un noto anti-pattern Git, che per la vita di me non ricordo il nome di - ma il senso è che sta facendo qualsiasi "modifica manuale" durante una fusione Git (cioè modifiche che in realtà non stanno risolvendo alcun conflitto di unione ma stanno apportando alcune modifiche totalmente indipendenti) è considerata una pratica estremamente negativa perché sono essenzialmente mascherate dall'unione stessa e sono facilmente trascurate nelle revisioni del codice o nelle sessioni di debug.

Quindi spiega sicuramente al tuo collega che questo è stato un fallimento epico, ma considera di schiaffeggiare un cerotto prima di prepararti a un intervento chirurgico importante.


Sono d'accordo, se sono interi interi file che vanno persi, una cosa che puoi fare è questa se non ti interessa la storia nei vecchi file: 1. crea un nuovo ramo dal ramo attualmente incasinato. 2. Tornare al ramo danneggiato e creare un altro nuovo ramo che è il ramo di salvataggio 3. Dal ramo di salvataggio tornare al commit prima del commit fallito. 4. Copia i file eliminati da qualche parte al di fuori di git 5. Passa all'altro nuovo ramo. 6. Copia le nuove versioni dei file eliminati nel nuovo ramo e esegui il commit. C'è un modo più complicato che salva la storia che è un famoso post di Linus T.
Elin

1
In realtà questo mostra come è possibile utilizzare il checkout jasonrudolph.com/blog/2009/02/25/… È molto più bello.
Elin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.