Alterar la estructura del directorio del repositorio utilizando el pago disperso

6 minutos de lectura

avatar de usuario de davr
davr

con el nuevo función de pago escasa en Git 1.7.0, ¿es posible simplemente obtener el contenido de un subdirectorio como en SVN? encontré este ejemplo, pero conserva la estructura de directorios completa. Imagine que solo quisiera el contenido del directorio ‘perl’, sin un directorio real llamado ‘perl’.

— EDITAR —

Ejemplo:

Mi repositorio git contiene las siguientes rutas

repo/.git/
repo/perl/
repo/perl/script1.pl
repo/perl/script2.pl
repo/images/
repo/images/image1.jpg
repo/images/image2.jpg
repo/doc/
repo/doc/readme.txt
repo/doc/help.txt

Lo que quiero es poder producir desde el repositorio anterior este diseño:

repo/.git/
repo/script1.pl
repo/script2.pl

Sin embargo, con la función de pago disperso actual, parece que solo es posible obtener

repo/.git/
repo/perl/script1.pl
repo/perl/script2.pl

que NO es lo que quiero.

  • finalmente lo implementaron! ¡Frío!

    –Mauricio Scheffer

    25 de febrero de 2010 a las 18:42

  • ¿Por qué? ¿Cuál es el problema? ¿Y por qué quiere tener una estructura de directorio diferente en el repositorio y diferente localmente? No tiene mucho sentido a primera vista.

    –Jiri Klouda

    9 de marzo de 2010 a las 9:02

  • @Jiri: Tengo una aplicación web con código actionscript (del lado del cliente) y PHP (del lado del servidor). Los archivos están estrechamente relacionados, por lo que quiero ponerlos en un solo repositorio/rama. Sin embargo, no quiero los archivos fuente de actionscript en el servidor, solo los archivos PHP.

    – davr

    9 de marzo de 2010 a las 21:02

  • @davr esta no es una circunstancia tan rara, quería exactamente lo mismo. Lástima que aún no puedo conseguirlo.

    – preinheimer

    7 oct 2011 a las 5:00

  • @preinheimer, también es algo que estoy tratando de conseguir. Haría que desarrollar y probar un tema que estoy haciendo sea mucho más fácil.

    – apokaliptis

    4 de noviembre de 2014 a las 23:04

avatar de usuario de richq
ricaq

Todavía necesita clonar todo el repositorio, que tendrá todos los archivos. Podrías usar el --depth marca para recuperar solo una cantidad limitada de historial.

Una vez que se clona el repositorio, el truco del árbol de lectura limita su “vista” del repositorio a solo aquellos archivos o directorios que están en el .git/info/sparse-checkout expediente.

Escribí un script rápido para ayudar a manejar la escasez, ya que en este momento es un poco hostil:

#!/bin/sh
echo > .git/info/sparse-checkout
for i in "$@"
do
    echo "$i" >> .git/info/sparse-checkout
done
git read-tree -m -u HEAD

Si guarda este script como git-sparse.sh en el camino informado llamando git --exec-pathentonces puedes ejecutar git sparse foo/ bar/ solo “verificar” los directorios foo y bar, o git sparse '*' para recuperar todo de nuevo.

  • Gracias por la ayuda, pero eso no parece responder a mi pregunta. Vea mi pregunta actualizada para una aclaración.

    – davr

    26 de febrero de 2010 a las 22:59

  • Sí, disperso es solo una forma de filtrar el árbol real, no puede mover archivos. Así que no puedes hacer lo que quieres…

    – ricoq

    27 de febrero de 2010 a las 11:07

La respuesta corta es no. Git ve todos los archivos como una sola unidad.

Lo que recomiendo es que divida sus repositorios en fragmentos lógicos. Uno separado para perl, imágenes y documentos. Si también necesita mantener el estilo de repositorio uber, puede crear un repositorio compuesto por Submódulos.

Ahora, sin entrar en detalles sobre por qué querría hacer esto, su problema puede (probablemente) resolverse fácilmente mediante un enlace simbólico/atajo.

Para responder a la pregunta, no, y con una razón significativa. Todo el historial del repositorio se descarga incluso con un ‘pago escaso’. Para aclarar por qué esto es necesario, de lo contrario, el seguimiento de los archivos renombrados sería un dolor en el cuello. Imagina que mueves el archivo /repo_root/asd/file1.cpp a /repo_root/fgh/file1.cpp – ahora si solo hubieras descargado /repo_root/fgh deltas, no sabrá sobre file1.cpp. Esto significa que debe descargar todos los deltas. Pero entonces tienes un repositorio completo; no solo un corte de carpeta, por lo tanto, solo el /rero_root/fgh la carpeta no es un repositorio en sí mismo. Esto puede no parecer importante cuando realiza el pago, pero cuando se compromete, es posible que git no sepa lo suficiente como para funcionar bien.

Solución alterna: Si realmente lo desea, puede crear un script que llame a git-checkout de esa manera (para el shell sh, no debería ser difícil producir un lote para Windows):

!/bin/sh
curDir=`pwd`
cd $2
git-checkout $1
cp -R $3/* $4
cd $curDir

Aquí, el primer argumento es la rama para pagar, el segundo, la carpeta donde está presente actualmente el repositorio, el tercero, el subdirectorio que realmente desea usar y el cuarto, la ubicación en la que desea que se copie.

Advertencia: mis habilidades de shell son casi inexistentes, así que use esto después de la prueba. No debería ser difícil recrear el reverso de esta secuencia de comandos, que copia cosas, para que se pueda enviar al repositorio.

  • Tener todo el historial del repositorio no es un problema, no es un gran repositorio y tenemos mucho espacio en disco. Supongo que nuestro caso de uso particular no es tan común, por lo que los desarrolladores de git nunca pensaron en agregarlo. Es una de las pocas cosas que SVN funcionó mejor para nosotros (git hace otras 99 cosas mejor, por eso cambiamos, pero aún así)

    – davr

    7 de agosto de 2011 a las 6:01

  • los enlaces simbólicos en Windows son una pesadilla: esto no es tratable.

    – Alex Marrón

    20 de marzo de 2013 a las 17:50

La respuesta de richq estuvo cerca, pero se saltó un paso. Debe habilitar explícitamente el pago disperso:

git config core.sparsecheckout verdadero

Esta publicación de blog tiene todos los pasos descritos claramente:

http://blog.quilitz.de/2010/03/checkout-sub-directories-in-git-sparse-checkouts/comment-page-1/#comment-3146

Puede probar la trenza: rastrea los controles remotos mientras los empareja con una ruta.
https://github.com/evilchelu/trenza/wiki

Avatar de usuario de la comunidad
Comunidad

git filter-branch --subdirectory-filter es lo que necesita, consulte Separar (mover) el subdirectorio en un repositorio Git separado.

Aquí hay un pequeño script bash para hacer eso.

Esto primero hará una copia de trabajo del repositorio original, luego filtrará la rama usando el filtro de subdirectorio para obtener lo que desea.

#!/bin/bash
#
# git-subdir.sh
#
git clone --no-hardlinks $1 $2

cd $2

git filter-branch --subdirectory-filter $2 --prune-empty --tag-name-filter cat HEAD -- --all

git reset --hard

git remote rm origin

refbak=$(git for-each-ref --format="%(refname)" refs/original/)

if [ -n "$refbak" ];then
    echo -n $refbak | xargs -n 1 git update-ref -d
fi

git reflog expire --expire=now --all

git repack -ad

git gc --aggressive --prune=now

Use para el ejemplo en la pregunta, git-subdir.sh repo perl trabajaría.

Avatar de usuario de Daemeon
Demonio

Parece que lo que está tratando de hacer es cambiar el nombre del árbol de directorios para que sus archivos terminen en un lugar diferente. Me parece que lo que está pidiendo hacer es una anti-plantilla para la gestión de código/proyecto en dos aspectos: categorización de módulos (bits de Java en el nodo de Java, Perl en el nodo de Perl) y tener un proyecto con archivos en diferentes ubicaciones desde donde el desarrollador los visualiza. Dado que git mantiene hashes de los contenidos del directorio para ver qué ha cambiado, esto también rompe git como tal.

Daemeon Reiydelle

¿Ha sido útil esta solución?