2009-12-13 13 views
9

Digamos que tengo la función X en el archivo A, y quería mover esa función al archivo B. Mientras tanto, alguien más realizó cambios en la función X en el archivo A.¿Cómo maneja git el código de fusión que se movió a un archivo diferente?

¿Hay algo especial cuando fusiona esos dos? cambios? ¿Reconocería que la misma función se movió al archivo B y aplicará los cambios allí? ¿O podríamos terminar perdiendo los cambios o tener dos copias de la misma función en el archivo A y B?

La mayoría de los artículos que encontré sobre cómo mover código en git se refieren principalmente al cambio de nombre de archivos completos y no bloques de código dentro de archivos. Lo más cerca que he encontrado es un blurb from Linus at kerneltrap:

Y cuando se utiliza git, el conjunto 'movimiento mantienen código separado de cambios' tiene una razón aún más fundamental: git puede seguir el movimiento de código (de nuevo, si se mueve un archivo completo o solo una función entre archivos), y al hacer un 'git culpa' -C en realidad seguirá el movimiento del código entre los archivos. Lo hace que para el análisis de similitud, pero significa que si ambos se mueven el código y cambio que, al mismo tiempo, git no puede ver que 'oh, esa función vino originalmente de ese otro archivo', y ahora obtienes peores anotaciones sobre dónde se originó realmente el código.

Parece que git reconocerá que el código se movió a otra parte, pero realmente no dice lo que sucede durante una fusión.

Respuesta

6

No, git no hará este nivel de cambio. Se dará cuenta cuando mueva un archivo completo; así que, por ejemplo, si movió el archivo, borró todo lo demás, entonces podría tener la oportunidad de detectar los cambios. Pero no hace un cambio en un subarchivo o cualquier tipo de refactorización.

+0

por lo que si estoy de combinar los cambios a X en A en mi rama donde moví X a B, básicamente perdería esos cambios porque Git cree que borré esas líneas? Supongo que solo necesito mirar cuidadosamente los diffs entonces ... – jtjin

+2

No los perderás: tendrás que fusionar el conflicto a mano. –

8

No creo que la respuesta anterior sea correcta en el caso general, porque a git realmente no le importan los archivos; el nombre de archivo se usa como base para algunas heurísticas, pero la manera en que git piensa sobre el contenido no es t centrado completamente en torno a la idea de un archivo. A diferencia de otros VCS, git rastrea contenido, y en este caso el contenido se ha movido, pero es el mismo contenido.

Como resultado, git debería ser capaz de manejar las fusiones entre sucursales incluso cuando los archivos han sido renombrados, o el código se mueve entre archivos, por lo que dependiendo de lo que hayas hecho, probablemente manejará la fusión.

Mientras los cambios en X no causan un conflicto de combinación (que podría suceder si habías cambiado tanto la versión original y la versión renombrada), el hecho de que X se ha movido a B shouldn' Importa, y el resultado de la fusión debe contener el resultado de ambos cambios. Si hay es un problema, esto indicaría que git no ha rastreado correctamente el movimiento del código.

En la práctica, la respuesta anterior probablemente se basa en la experiencia personal cuando falló la maquinaria de detección, en cuyo caso https://git.wiki.kernel.org/index.php/GitFaq#How_to_manually_resolve_conflicts_when_Git_failed_to_detect_rename.3F puede ser útil.

2

Creo que AlBlue es correcto, no Nye.

En mi simple prueba, git 1.7.0.5 no pudo fusionar automáticamente dos ramas donde una rama insertaba una línea en una función, y la otra movía esa función a una nueva ubicación en el mismo archivo. Según parece, git no rastrea fragmentos de contenido más pequeños que el archivo.

Para resolver el conflicto de combinación, la persona que realiza la fusión debería conocer cómo funcionaron los dos cambios y cómo deben combinarse.

Ver también git merge: apply changes to code that moved to a different file

0

Creo que la situación real es mucho más compleja, pero por lo que he experimentado, git puede manejar este tipo de 3 vías se fusionan bien.

Por ejemplo:

Una de las funciones de un archivo en la rama A se trasladó a otra ubicación en el mismo archivo y al mismo tiempo crear una rama B para sostenerlo. La diferencia entre la rama B y la rama A es solo el cambio de ubicación del código en el mismo archivo.

La sucursal C cambió esa función.

Así que, si lo hace:

$ git rebase --onto B A C

se fusionará automáticamente el cambio de rama C a la nueva ubicación de esa función en la rama B.

Cuestiones relacionadas