ver submodulos oneline modificados log commits archivos git git-submodules revision-history

submodulos - Crea un repositorio de submódulos desde una carpeta y mantén su historial de commit de git



git ver commits (3)

Tengo una aplicación web que explora otras aplicaciones web de una manera particular. Contiene algunas demostraciones web en una carpeta demos y una de las demos ahora debe tener su propio repositorio. Me gustaría crear un repositorio separado para esta aplicación de demostración y convertirla en una subpaquete submodule del repositorio principal sin perder su historial de compromiso.

¿Es posible mantener el historial de confirmaciones de los archivos en la carpeta de un repositorio y crear un repositorio a partir de él y usarlo como un submodule ?


Solución detallada

Vea la nota al final de esta respuesta (último párrafo) para una alternativa rápida a los submódulos de git usando npm;)

En la siguiente respuesta, sabrá cómo extraer una carpeta de un repositorio y hacer un repositorio git a partir de él y luego incluirlo como un submodule lugar de una carpeta.

Inspirado en el artículo de Gerg Bayer Moviendo archivos de un repositorio de Git a otro, preservando la historia

Al principio, tenemos algo como esto:

<git repository A> someFolders someFiles someLib <-- we want this to be a new repo and a git submodule! some files

En los pasos a continuación, voy a referir esto someLib como <directory 1> .

Al final, tendremos algo como esto:

<git repository A> someFolders someFiles @submodule --> <git repository B> <git repository B> someFolders someFiles

Crea un nuevo repositorio git desde una carpeta en otro repositorio

Paso 1

Obtenga una copia nueva del repositorio para dividir.

git clone <git repository A url> cd <git repository A directory>

Paso 2

La carpeta actual será el nuevo repositorio, así que elimine el control remoto actual.

git remote rm origin

Paso 3

Extrae el historial de la carpeta deseada y compórtala

git filter-branch --subdirectory-filter <directory 1> -- --all

Ahora debería tener un repositorio de git con los archivos del directory 1 en la raíz de su repositorio con todo el historial de confirmaciones relacionado.

Etapa 4

¡Crea tu repositorio en línea y envía tu nuevo repositorio!

git remote add origin <git repository B url> git push

Es posible que deba configurar la rama upstream para su primer impulso

git push --set-upstream origin master

Limpiar <git repository A> (opcional, ver comentarios)

Queremos eliminar trazas (archivos e historial de confirmaciones) de <git repository B> desde <git repository A> para que el historial de esta carpeta solo esté allí una vez.

Esto se basa en Eliminar datos confidenciales de github.

Ir a una nueva carpeta y

git clone <git repository A url> cd <git repository A directory> git filter-branch --force --index-filter ''git rm --cached --ignore-unmatch <directory 1> -r'' --prune-empty --tag-name-filter cat -- --all

Reemplace <directory 1> por la carpeta que desea eliminar. -r lo hará recursivamente dentro del directorio especificado :). Ahora presione hacia el origin/master con --force

git push origin master --force

Etapa de jefe (ver la nota a continuación)

Crea un submodule desde <git repository B> en <git repository A>

git submodule add <git repository B url> git submodule update git commit

Verificar si todo funcionó como se esperaba y push

git push origin master

Nota

Después de hacer todo esto, me di cuenta en mi caso de que era más apropiado usar npm para administrar mis propias dependencias. Podemos especificar git urls y versiones, ver el paquete.json git urls como dependencias .

Si lo hace de esta manera, el repositorio que desea utilizar como requisito debe ser un módulo npm, por lo que debe contener un archivo package.json o obtendrá este error: Error: ENOENT, open ''tmp.tgz-unpack/package.json'' .

tldr (solución alternativa)

Puede que le resulte más fácil usar npm y administrar dependencias con git urls :

  • Mover la carpeta a un nuevo repositorio
  • ejecutar npm init dentro de ambos repositorios
  • npm install --save git://github.com/user/project.git#commit-ish donde quiera que npm install --save git://github.com/user/project.git#commit-ish instaladas sus dependencias

La solución de @GabLeRoux aplasta las ramas y las confirmaciones relacionadas.

Una forma simple de clonar y mantener todas esas ramas y confirmaciones adicionales:

1 - Asegúrate de tener este git alias

git config --global alias.clone-branches ''! git branch -a | sed -n "///HEAD /d; ///master$/d; /remotes/p;" | xargs -L1 git checkout -t''

2 - Clona el control remoto, tira de todas las ramas, cambia el control remoto, filtra tu directorio, empuja

git clone [email protected]:user/existing-repo.git new-repo cd new-repo git clone-branches git remote rm origin git remote add origin [email protected]:user/new-repo.git git remote -v git filter-branch --subdirectory-filter my_directory/ -- --all git push --all git push --tags


La solución de GabLeRoux funciona bien, excepto si usa git lfs y tiene archivos grandes en el directorio que desea separar. En ese caso, después del paso 3, todos los archivos grandes seguirán siendo archivos de puntero en lugar de archivos reales. Supongo que probablemente se deba al archivo .gitattributes que se está eliminando en el proceso de bifurcación del filtro.

Al darme cuenta de esto, creo que la siguiente solución funciona para mí:

cp .gitattributes .git/info/attributes

Copiando .gitattributes que git lfs usa para rastrear archivos grandes a .git/ directory para evitar ser eliminados.

Cuando filter-branch finaliza, no olvide volver a colocar .gitattributes si aún desea usar git lfs para el nuevo repositorio:

mv .git/info/attributes .gitattributes git add .gitattributes git commit -m ''added back .gitattributes''