2010-06-23 16 views
8

Tengo un repositorio git (que cubre más o menos el historial del proyecto) y fuentes separadas (solo un archivo tar con pocos archivos) que se han bifurcado hace algún tiempo (en realidad en 2004 o 2005).Encontrar dónde se ha ramificado la fuente desde git

Las fuentes de tarball han sufrido un montón de cambios que me gustaría incorporar. Ahora la pregunta es: cómo averiguar cuál fue en realidad el punto de ramificación para que las fuentes modificadas obtengan una diferencia mínima de lo que ha sucedido allí.

Lo que básicamente quiero es encontrar un lugar en la historia de git, donde el código es más similar al tarball de las fuentes que tengo. Y no quiero hacer eso manualmente.

También vale la pena mencionar que las fuentes modificadas incluyen solo un subconjunto de archivos y han dividido algunos archivos en más. Sin embargo, el código que está allí parece tener solo pequeñas modificaciones y varias adiciones.

Si quieres jugar con eso mismo, el archivo tar con las fuentes es here y Git está alojado en Gitorious: git://gitorious.org/gammu/mainline.git

+1

Me he dado cuenta de que los archivos más antiguos de que el alquitrán se modificaron en 31/10/2006 12: 57. Comenzaría mi búsqueda allí. – Douglas

+0

Como mencioné en la publicación original, sé más o menos que se bifurcaron en algún lugar en 2004/2005, pero eso es demasiado para investigar manualmente. –

Respuesta

4

En el caso general, tendría que examinar cada compromiso, porque no tiene manera de saber si podría tener una gran diferencia en una, pequeña diferencia al siguiente, luego otra gran diferencia, luego un medio diff ...

Probablemente su mejor opción sea limitarse a archivos específicos. Si considera solo un archivo, no debería llevar mucho tiempo recorrer todas las versiones de ese archivo (use git rev-list <path> para obtener una lista, de modo que no tenga que probar cada confirmación). Para cada confirmación que modificó el archivo, puede verificar el tamaño de la diferencia, y bastante rápidamente encontrar un mínimo. Haz esto para un puñado de archivos, ¡con suerte estarán de acuerdo!

La mejor manera de configurarte para la diferencia es realizar una confirmación temporal simplemente copiando en tu tarball, para que puedas comparar una rama llamada tarball. De esta manera, usted puede hacer esto:

git rev-list path/to/file | while read hash; do echo -n "$hash "; git diff --numstat tarball $hash path/to/file; done 

para conseguir una buena lista de todas las confirmaciones con sus tamaños diff (las tres primeras columnas serán SHA1, el número de líneas añadió, y el número de líneas eliminado).Posteriormente, se podría simplemente tubería awk '{print $1,$2+$3}' | sort -n -k 2 en en, y que tendría una lista ordenada de confirmaciones y sus tamaños diff!

Si no puede limitarse a un puñado de archivos para probar, podría sentir la tentación de implementar a mano algo similar a git-bisect - simplemente trate de reducir su camino a una pequeña diferencia, suponiendo que en con toda probabilidad, se compromete cerca de su mejor de los casos también tendrá diferenciaciones más pequeños, y se compromete ni mucho menos tendrá diferenciaciones más grandes. (En algún lugar entre el método de Newton y un lleno en la búsqueda binaria/sistema, probablemente?)

Editar: Otra posibilidad, sugerida en Douglas' answer, si usted piensa que algunos archivos podrían ser idéntica a los que de alguna confirmación, es para discutir utilizando git-hash-object, y luego ver lo que se compromete en su historia tiene que blob. Hay un question with some excellent answers acerca de cómo hacer eso. Si hace esto con un puñado de archivos - preferentemente los que han cambiado con frecuencia - que podría ser capaz de reducir el objetivo comprometerse con bastante rapidez.

+0

Creo que un buen lugar para comenzar a limitar el conjunto de archivos que está viendo es probablemente archivos que son comunes a ambos pero que no han cambiado en mucho tiempo o que han cambiado rara vez en uno (o mejor) árbol . Es probable que los archivos de encabezado sean buenos candidatos, siempre y cuando no contengan muchas cosas condicionales del preprocesador loco. Es mucho más fácil cuantificar los cambios en un diff de una larga línea de '# define's que en el código real. – nategoose

+0

Este parece ser el mejor enfoque. Solo lo cambié para no usar un solo archivo, sino una lista de archivos completa que tengo en el árbol modificado y una lista limitada de revisiones al intervalo que supuse de algunas partes del código. Gracias. –

+1

Esto funcionó muy bien para mí, sin embargo, ofrezco esta advertencia: si está moviendo archivos entre * nix y Windows (o Mac), * TENGA CUIDADO CON LOS ALIMENTOS DE LÍNEA *. Dale al comando diff la opción -w, por lo que los ignorará, de lo contrario podrías obtener una gran diferencia, cuando en realidad los dos archivos son los mismos, excepto los de línea. –

0

cómo se hizo el tenedor? ¿Fue un clon que alguien más hizo y luego hizo su propio trabajo? si es así, entonces esto es realmente fácil. todo lo que necesita hacer es crear una sucursal local que extraiga el código de la bifurcación. git verá la ascendencia de la rama bifurcada apuntando a uno de los commits desde su repositorio original y "conectará los puntos" por así decirlo ... reconectará el historial de su repositorio original a la bifurcación.

usted debería ser capaz de hacer esto:

git remote add thefork git://wherever.it.lives/thefork.git 

git fetch thefork 

git branch -f thefork-branch thefork/branchname 

git checkout thefork-branch 

en este punto, puede ejecutar gitk y ver la historia completa de la rama bifurcada y su repositorio local, y ver si se conectan o no.

+0

Ah, no estaba claro que las fuentes bifurcadas sean solo un tarball, en realidad no el git repo. Actualizará la pregunta para dejarlo en claro. –

+0

¡ay! Sí ... eso es nuevo para mí ... no estoy seguro de saber cómo manejar esa situación. –

2

No es una gran solución, pero para adivinar qué revisiones podría ser: Supongamos que algunos de los archivos en la bola de alquitrán no se han modificado desde que se ramificaron. Ejecute git hash object contra cada archivo en la bola de alquitrán, luego busque esos archivos en el repositorio usando git show. Luego intente y encuentre las confirmaciones bajo las cuales se incluyeron estos archivos, posiblemente usando git whatchanged. La respuesta a su pregunta podría ser la confirmación con los archivos más comunes, pero todavía será un poco al azar.

+0

Esta es una gran idea, de hecho, escribí mi respuesta suponiendo que todos los archivos tendrían pequeñas diferencias, por lo que no sería posible encontrar la versión exacta en el repositorio. – Cascabel

+0

Excelente idea, desafortunadamente no hay archivo sin cambios. –

+0

@Michal Čihař: A continuación, continúe con mi respuesta, que proporciona algunas formas básicas de intentar y encontrar una versión mínima de diferencia. – Cascabel

0

Importe los archivos en el tarball en una revisión git, en una rama separada o completamente nueva: la posición en el gráfico de revisión no es importante, solo queremos que esté disponible como un árbol.

Ahora, para cada revisión en el maestro, solo diff contra ese árbol/revisión ('importados') y acaba de salida de cuán grande es el diff es. Algo así como:

git rev-list master | while read rev; do patchsize=$(git diff $rev imported | wc -c); echo $rev $patchsize; done 

Así que la revisión con el tamaño más pequeño parche será el "más cercano", por una regla muy general del pulgar. (Una revisión idéntica producirá un tamaño del parche de 0, y cualquier otra cosa será, sin duda no es cero, y más que eso ha cambiado, el más grande).

+0

Desafortunadamente, el árbol completo diferente siempre lleva a la revisión más antigua, porque no tiene tantos archivos adicionales. –

1

en base a lo araqnid dije que se me ocurrió 9c6c864426bf88429e77c7e22b5aa78e9295b97a (sólo pedimos cosas entre 0.61.0 y HEAD), este no es el mejor es probablemente) que podría hacer mejor con algo así como

git rev-list --no-merges --all | while read rev; do patchsize=$(git diff $rev | wc -c); echo $patchsize $rev; done | sort -n | less 

suponiendo que' he importado el fichero tar en git y tienen esa revisión desprotegido (hice esto untaring y luego

git init 
git add . 
git commit -m "import tarball" 
git remote add origin git://gitorious.org/gammu/mainline.git 

Así que después de hacer eso y la pista de lo anterior se debe hacer salir el tamaño de todos los diferenciales en orden ascendente de patchsize (el primero será 0 ya que encontrará la cabeza actual) tardará mucho tiempo ... pero debería encontrar la diferencia más pequeña ...

0

Si tiene una idea aproximada de dónde ocurrió la horquilla, considere utilizar Will Manley's git meld. (Consulte también: View differences of branches with meld?.)

Para hacer esto, agregue los contenidos de tarball a su repositorio (lo cual hará de todos modos). Después de instalar Meld y git-meld, ejecute

git meld branch_from_tarball commit_to_check & 

en diferentes confirmaciones hasta que encuentre el que tiene menos diferencias. Este comando abrirá meld y verá los cambios en el árbol de directorios entre las confirmaciones especificadas, con archivos idénticos ocultos.Ejemplo de pantalla:

Meld muestra dos commits muy diferentes:
Very different

muestran dos confirmaciones similares: Similar

Cuestiones relacionadas