2011-03-09 23 views
11

Estoy dividiendo un árbol fuente grande en dos componentes separados y un submódulo compartido. Para prepararme para esta división, primero moví las cosas compartidas a un único directorio "común", actualicé todas las referencias y realicé una confirmación. Hasta aquí todo bien. Ahora me gustaría extraer ese directorio en un submódulo.Extrae el subdirectorio git mientras conservas el historial WITH renombra

Normalmente me gustaría hacer esto con

git filter-branch --subdirectory-filter 

Pero en este caso, toda la historia interesante ocurrió fuera de ese subdirectorio, por lo que la historia se pierde.

Entiendo que no tiene sentido guardar el historial completo, ya que eso no estaría filtrando ningún dato en absoluto. Pero realmente no estoy buscando la posibilidad de retroceder en el tiempo y construir, solo quiero poder ver las confirmaciones de cada archivo.

¿Hay alguna forma de mantener el comportamiento de la rama de filtro mientras se mantiene el historial de los archivos individuales?

Respuesta

4

Realmente no. --subdirectory-filter es un caso especial en el sentido de que realmente está modificando el contenido de los árboles de manera significativa (ya que está moviendo las cosas uno o más niveles de anidamiento de directorios).

Como tal, no hay realmente una buena asignación entre los archivos que están fuera del subdirectorio que está filtrando y los árboles que podrían almacenarse como parte de commits en el resultado.

Recuerde que filter-branch está reescribiendo por completo su historial: el resultado es un conjunto de confirmaciones completamente nuevo, y no hay ningún "vínculo" con los compromisos anteriores, por lo que cualquier información adicional debe poder expresarse como parte del nuevo comete

+2

Todo eso tiene sentido para mí, pero al menos en principio puedo imaginar tomar el conjunto actual de archivos en un directorio y rastrear el historial de compromisos para cada uno, contando los cambios de nombre. De esta forma, cada objeto de compromiso implica o no los archivos en un subdirectorio. Aquellos que no los involucren podrían descartarse, y los que lo hagan podrían reescribirse para dejar de lado los otros archivos. No me importa tener un compromiso de movimiento en la punta de mi historia, solo quiero mantener todos los cambios en el camino. –

+0

Si tuviera que 'git checkout' uno de los commits de" historia anterior "en su submódulo, ¿qué haría' git'? Si el archivo solía estar "arriba" de lo que ahora es el directorio de nivel superior del repositorio, no hay una buena manera de que Git lo maneje. – Amber

+0

Me quemé un montón de tiempo en esto en vano ... Aún así creo que puede ser hecho por alguien de suficiente inteligencia. –

3

Así es como solo ha resuelto un problema similar. Comencé un proyecto en un repositorio "misc" casi privado, renombré algunos archivos y luego quise subir el proyecto a GitHub al https://github.com/kragen/aikidraw.

$ git clone misc aikidraw 
$ cat > aikidraw-wanted 
aikidraw.js 
aikidraw.html 
caposketchra.html 
caposketchra.js 
jquery-1.2.6.js 
^D 
$ cd aikidraw 
$ git filter-branch --tree-filter 'bash -c "comm -23 <(/bin/ls | sort) <(sort ~/devel/aikidraw-wanted) | xargs rm -rf"' HEAD 

Eso parece haber funcionado bien hasta ahora, aparte de no borrar comienzan con un punto (como .git, bueno, y .gitignore, malo) pero al parecer mi versión de Git (1.6.0.4) no tiene git filter-branch --prune-empty. Por lo que ahora el nuevo clon, repo más pequeño (con el fin de hacerlo más rápido para copiarlo través de la red) y copiar el repositorio a otra máquina que tiene Git 1.7.2.5 en él:

$ time git clone aikidraw aikidraw-smaller 
$ du -sh aikidraw/.git aikidraw-smaller/.git 
8.6M aikidraw/.git 
1.2M aikidraw-smaller/.git 

$ time rsync -Pav aikidraw-smaller panacea.canonical.org:devel/aikidraw/ 
real 1m23.251s 

Y luego en la panacea .canonical.org:

$ cd ~/devel/aikidraw/aikidraw-smaller # Oops. I hate rsync sometimes. 
$ git checkout # otherwise I get "Cannot rewrite branch(es) with a dirty working directory." 
$ git filter-branch --prune-empty HEAD 
$ cd ../.. 
$ mv aikidraw i-hate-rsync 
$ mv i-hate-rsync/aikidraw-smaller/ aikidraw 

Luego de vuelta en mi netbook:

$ mv aikidraw aikidraw-big 
$ git clone panacea.canonical.org:devel/aikidraw 
$ du -sh aikidraw/.git 
268K aikidraw/.git 

Ahora, si estuviera haciendo esto con dos directorios en lugar de cinco archivos, es posible que en este punto que desee cambiar el nombre de todo el interior el subdirectorio restante en la raíz del repositorio, usando git mv. En mi caso, ya he hecho mi cambio de nombre.

$ git remote add github [email protected]:kragen/aikidraw.git 
$ git push github master 

Hope this helps!

Cuestiones relacionadas