2010-10-28 10 views
50

Tengo un proyecto en git. Un día moví todos los archivos del proyecto desde el directorio actual al foo/bar/ en el proyecto. Lo hice usando git mv. Luego agregué algunos archivos más e hice algunos cambios a los archivos ya existentes.¿Cómo puedo reescribir el historial para que todos los archivos, excepto los que ya he movido, estén en un subdirectorio?

Como resultado, ahora cuando miro el historial de foo/bar/file.c, solo puedo ver los cambios que hice después de mover el archivo.

Traté de solucionar esto de varias maneras (filter-branch con filtro de subdirectorio, etc.), pero no sirvió de nada, así que estoy bastante apilado aquí. Apreciaré cualquier ayuda que me puedas dar. Gracias!

Respuesta

85

Para volver a escribir la historia de los archivos movidos:

Si quieren la historia del proyecto a parecer que todos los archivos han sido siempre en el directorio foo/bar, entonces usted tiene que hacer una pequeña cirugía. Utilice git filter-branch con el "filtro de árbol" para reescribir las confirmaciones de manera que en cualquier lugar foo/bar no existe, se crea y todos los archivos se mueven a la misma:

git filter-branch --prune-empty --tree-filter ' 
if [ ! -e foo/bar ]; then 
    mkdir -p foo/bar 
    git ls-tree --name-only $GIT_COMMIT | xargs -I files mv files foo/bar 
fi' 

Ahora la historia se registrará como si todos los archivos eran siempre ubicado en foo/bar.

Para ver el historial de un archivo que ha cambiado:

Si lo que desea es ver la historia de un archivo que se ha movido o cambiado de nombre en algún momento en el pasado, a continuación, sólo tiene que utilizar la opción --follow a git log:

git log --follow foo/bar/file.c 
+1

@Alexander: Es posible que desee intentar poner el delineador (todo en las comillas simples) en un guión real, con una línea bash shebang. Creo que 'filter-branch' probablemente intente ejecutar esto en' sh', no 'bash'. – Cascabel

+0

Hice algunos progresos. Parece que los paréntesis dobles en la instrucción if estaban causando este error. Los corchetes individuales funcionan mejor, pero aun así no funcionan. El problema es que antes de mover todo a foo/bar/tenía el directorio llamado foo con algo de contenido en el proyecto. Entonces ahora se queja "no se puede mover 'foo' a un subdirectorio de sí mismo,' foo/bar/foo '". –

+0

@Alexander: solo tendrá que ajustar la secuencia de comandos en consecuencia. Algo como: 'si [[! -e foo/bar]]; luego mkdir -p foo/bar; git ls-tree --name-only $ GIT_COMMIT | grep -v^foo $ | xargs -I archivos mv archivos foo/bar; fi' Utiliza grep para filtrar 'foo' de la lista de archivos a mover. Tenga en cuenta que también asumo que el subdirectorio 'bar' nunca existió hasta que movió todo debajo de él. Si ese no es el caso, tendrá que dar cuenta de eso en el guión también. –

6

para envolver las cosas aquí es un breve resumen de lo que hice. El comando que trabajó para mí era:

if [ ! -e foo/bar ]; then mkdir -p foo/bar; git ls-tree --name-only $GIT_COMMIT | grep -v ^foo$ | xargs -I files mv files foo/bar || echo ""; fi 

El comando echo de que he añadido al final se aseguró de que incluso cuando falla mv toda comando continuará funcionando. No movió los contenidos de foo/bar/foo, pero puedo vivir con eso.

Muchas gracias a Dan Moulding (!!!) y Jefromi por la ayuda.

Cuestiones relacionadas