¿Cuál es la mejor manera de deshacer una fusión Git que borra archivos del repositorio?

13

Así que imagina que sucede lo siguiente (y que todos estamos usando SourceTree):

  1. Todos estamos trabajando desde el origen / desarrollo.
  2. Me voy de vacaciones por una semana.
  3. Mi compañero de trabajo ha estado trabajando localmente durante los últimos días sin fusionar origen / desarrollo en su rama de desarrollo local.
  4. Intenta dar un empujón, le dicen que primero tiene que fusionarse y luego tira.
  5. Obtiene un conflicto, impidiendo que continúe la confirmación automática después de una fusión.
  6. Asumiendo que Git es como SVN, mi compañero de trabajo descarta los "nuevos" archivos en su copia de trabajo y luego confirma la fusión, borrando esos "nuevos" archivos del jefe de origen / desarrollo.
  7. Unas semanas de trabajo de desarrollo se suman a esa revisión.
  8. Regreso de vacaciones y descubro que faltan varios días de mi trabajo.

Todos somos muy nuevos en Git (este es nuestro primer proyecto usándolo), pero lo que hice para solucionarlo fue:

  1. Cambie el nombre de "revelar" a "revelar"
  2. Fusionar desarrollo_old en una nueva rama "desarrollo_nuevo".
  3. Restablezca la rama del desarrollo a la última confirmación antes de la fusión incorrecta.
  4. Cherry elige cada commit desde entonces, uno por uno, resolviendo conflictos a mano.
  5. Empuje desarrollo_veces y desarrollo_nuevo hasta el origen.

En este punto, desarrollo_nuevo es, espero, una copia "buena" de todos nuestros cambios con las semanas posteriores de trabajo reaplicadas. También estoy asumiendo que "cometen inversa" va a hacer cosas extrañas en una fusión, sobre todo porque las próximas semanas la pena de trabajo se basa en él - y puesto que de mezcla contiene una gran cantidad de cosas que queremos junto con cosas que don' t.

Espero que esto nunca vuelva a suceder, pero si vuelve a suceder, me gustaría saber de una manera más fácil / mejor de arreglar las cosas. ¿Existe una mejor manera de deshacer una fusión "mala", cuando se ha realizado mucho trabajo en el repositorio basado en esa fusión?

Jorge
fuente
1
¿Podría publicar una captura de pantalla del árbol de git (redactado adecuadamente) o la salida de su git logformato favorito con anotaciones apropiadas sobre lo que sucedió en las diferentes confirmaciones? (Redactaría / anotaría git log --graph --pretty=oneline --abbrev-commite iría desde allí)
1
Es demasiado tarde para ti, pero las pruebas unitarias habrían captado eso.
nalply
1
@nalply: no si la combinación incorrecta también eliminó las pruebas unitarias.
Aaronaught
Wow, eso es realmente mala suerte insidiosa.
nalply

Respuestas:

6

Si entendí correctamente, esta es tu situación:

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

Después de un poco de historia común (o), te comprometiste y empujaste tu trabajo (y). Su compañero de trabajo (c) trabajó en su repositorio local e hizo una mala fusión (M). Posteriormente puede haber algunas confirmaciones adicionales (a) sobre M.

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

Ahora su gráfico se ve exactamente como antes de la fusión incorrecta:

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

Haz una buena fusión (G):

git checkout develop
git merge coworker

Resultando en:

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

Ahora trasplante los commits adicionales:

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

Esto da el resultado final:

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

Tenga en cuenta que esto podría generar más conflictos de fusión. También acaba de cambiar el historial, es decir, todos sus compañeros de trabajo deben clonar / restablecer / volver a crear un nuevo historial.

PD: por supuesto, debe reemplazar G, My Xen sus comandos por la identificación de confirmación correspondiente.

michas
fuente
Parece bastante evidente en la pregunta que todos estos commits ya se han enviado a un repositorio compartido, por lo que no creo que rebase sea una buena opción. Revertir todos los commits recientes y luego elegir los revertidos no conflictivos en la parte superior de la buena fusión es más seguro.
Aaronaught
Esa fue la parte con el clon / reset / rebase. - Si solo hay unos pocos desarrolladores, decirles que actualicen sus repositorios podría ser una opción válida.
michas
1

Es bueno que esté pensando en cómo arreglar el repositorio, pero si su compañero de trabajo solo eliminó nuevos archivos y no sobrescribió muchas actualizaciones, entonces un enfoque mucho más simple sería simplemente restaurar los archivos que se eliminaron.

Probablemente comenzaría intentando simplemente seleccionar (en el encabezado actual) las confirmaciones originales en las que agregó el código que ahora ha desaparecido. Si por alguna razón eso no funciona, simplemente revise la revisión anterior con los archivos que agregó y vuelva a agregarlos en una nueva confirmación.

Lo que usted describe es en realidad un subconjunto de un conocido antipatrón Git, que por mi vida no puedo recordar el nombre, pero lo esencial es hacer cualquier "edición manual" durante una fusión Git (es decir, ediciones que en realidad no están resolviendo ningún conflicto de fusión, pero están haciendo un cambio totalmente no relacionado) se considera una práctica extremadamente mala porque están esencialmente enmascarados por la fusión en sí misma y se pasan por alto fácilmente en las revisiones de código o sesiones de depuración.

Así que definitivamente explique a su compañero de trabajo que esto fue un fracaso épico, pero considere darle una tirita antes de prepararse para una cirugía mayor.

Aaronaught
fuente
Estoy de acuerdo, si son archivos enteros completos que se han ido, una cosa que puede hacer es esto si no le importa el historial en los archivos antiguos: 1.Haga una nueva rama de la rama actualmente desordenada. 2. Vuelva a la rama defectuosa y cree otra nueva rama que sea su rama de rescate 3. Desde su rama de rescate, vuelva a la confirmación antes de la confirmación fallida. 4. Copie los archivos eliminados en algún lugar fuera de git 5. Cambie a la otra rama nueva. 6. Copie las nuevas versiones de los archivos eliminados a la nueva rama y confirme. Hay una forma más complicada de salvar la historia que es una publicación famosa de Linus T.
Elin
1
En realidad, esto muestra cómo puedes usar el proceso de pago jasonrudolph.com/blog/2009/02/25/... Eso es mucho mejor.
Elin