Copie varios files y directorys de un repository git a otro mientras mantiene su historial original

Mi requisito: desglosar un repository de git, en múltiples repositorys de git, conservando la misma estructura de directorys que en el repository original, y preservar el historial de confirmaciones para los files que se copyn al nuevo repository. Lo que ya he intentado:

  1. Primero probé git filter-branch –subdirectory-filter basado en las sugerencias en http://gbayer.com/development/moving-files-from-one-git-repository-to-another-preserving-history/ Result: The la historia se mantiene, pero solo se puede ver al ejecutar el logging de git –follow Además, el historial de confirmaciones original no se puede ver en Github. Simplemente muestra mi confirmación de fusión como la única confirmación para ese file, y no muestra ninguna confirmación previa. Todavía puedo vivir con esta limitación y aceptarla como una solución. Pero otra preocupación que tengo con este enfoque es que, para cada carpeta y cada file que quiero copyr, necesito clonar el repository original varias veces y también repetir todos esos 12 o 13 pasos cada vez. Me gustaría saber si hay alguna forma más sencilla de hacerlo, ya que estoy moviendo una gran cantidad de files. Además, dado que la publicación tiene 5 años, ¿me pregunto si hay disponibles soluciones más nuevas y sencillas? (Sorprendentemente, Google muestra principalmente este blog como el primer resultado de búsqueda)

  2. Lo siguiente que probé fue un comentario sobre la publicación anterior de Greg Bayer http://gbayer.com/development/moving-files-from-one-git-repository-to-another-preserving-history/#comment-2685894846 Esta solución hecha las cosas son un poco más simples usando la subsplit de subtítulos de git, pero los resultados fueron los mismos que se enumeraron en el primer caso.

  3. Luego probé la opción de logging de git –patch-with-stat y git am según esta respuesta http://sofes.miximages.com/a/11426261/5497551 Resultado: esto generalmente da errores al encontrar una combinación, mientras aplica el parche. Probé una de las sugerencias a esta respuesta de usar -m –primer padre. Esto resolvió los errores pero no expande ninguna fusión en sus confirmaciones, solo enumera la fusión como una única confirmación. Por lo tanto, la mayor parte del historial de compromisos se pierde. Así que agregué otra opción de –3way . Esto fue una y otra vez a través de los commits, y no condujo a ninguna solución aceptable.

En conclusión, preferiría usar la tercera solución, si solo hubiera una opción para tener todos los commits en una fusión para ser listdos en el historial del nuevo repository. De lo contrario, tengo que apegarme a la primera solución, que es un poco incómoda y tediosa en mi situación. Cualquier consejo, ayuda sería muy apreciado.

Gracias.

Esto es lo que funcionó para mí (combinando respuestas de @ AD7six y @Olivier) para dividir mi orig-repo en varios orig-repo nuevos. Estoy enumerando aquí los pasos para crear solo un nuevo repository new-repo1 . Pero lo mismo se ha usado para crear los otros también.

Primero crea un nuevo repository vacío en Github con el nombre new-repo1

 git clone [Github url of orig-repo] git clone --no-hardlinks orig-repo new-repo1 cd new-repo1 git remote rm origin git checkout -b master //This step can be skipped. I had to do it since the default branch on my orig-repo was `develop`, but on the new-repo1 I wanted to create it as `master` //I used a script here to delete files and directories not requinetworking in the new-repo1. //But if you have very few files/dirs to be deleted then you can do the below. git rm <path of file 1 to be deleted> git rm <path of file 2 to be deleted> git rm -rf <path of dir 1 to be deleted> git commit -m "Deleted non-new-repo1 code" git ls-files > keep-these.txt git filter-branch --force --index-filter "git rm --ignore-unmatch --cached -qr . ; cat $PWD/keep-these.txt | xargs git reset -q \$GIT_COMMIT --" --prune-empty --tag-name-filter cat -- --all rm -rf .git/refs/original/ git reflog expire --expire=now --all git gc --prune=now git init git remote add origin [Github url of new-repo1] git push -u origin master 

Después de esto, puedo ver el historial de files en new-repo1 en Github, así como a través de la command-line usando git log

Con el método 1, ¿clonas desde un directory local o una URL? Si clonas desde un directory local, debes usar la --no-hardlinks . De lo contrario, lo que hagas en un clon podría afectar los directorys .git de los otros, porque git tiene files vinculados.

Así es como lo hago:

  • Clona el repository local:

     git clone --no-hardlinks source_repo detached_repo 
  • En detached_repo , elimine el origen (más información aquí para preservar las twigs que no sean la actual):

     git remote rm origin 
  • Elimina las tags que no quieres conservar Para eliminar todas las tags, use git tag -l | xargs git tag -d git tag -l | xargs git tag -d

  • Utilice filter-branch para excluir los otros files, de modo que puedan ser eliminados. --tag-name-filter cat --prune-empty también --tag-name-filter cat --prune-empty para eliminar las confirmaciones vacías y reescribir las tags (más información aquí si tiene varias twigs para mantener):

     git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter folder/to/keep HEAD 
  • A continuación, elimine los reflogs de copy de security para que el espacio pueda recuperarse realmente (ahora la operación es destructiva):

     git reset --hard git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d git reflog expire --expire=now --all git gc --aggressive --prune=now 

    y ahora tiene un repository git local de la folder/to/keep subdirectory con toda su historia preservada.

EDITAR

Como necesita mantener más de un subdirectory, files_to_keep que tiene una list de files para save en un file llamado files_to_keep . A continuación, cambie el paso de la git filter-branch a:

 git filter-branch --tag-name-filter cat --prune-empty \ --index-filter 'git ls-tree -z -r --name-only --full-tree $GIT_COMMIT \ | grep -z -v -F -f /absolute/path/to/files_to_keep \ | xargs -0 -r git rm --cached -r' HEAD 

Puede generar la list de files para mantener ejecutando este command:

 git log --pretty=format: --name-status | cut -f2- | sort -u > all_files 

y eliminando los files que no desea conservar.

Parece que hay una solución mucho más fácil. Después de search en las networkinges internas arriba y abajo, este script demostró ser realmente útil: git-import

La versión corta es que crea files de parche del file o directory dado ( $object ) del repository existente:

 cd old_repo git format-patch --thread -o "$temp" --root -- "$object" 

que luego se aplica a un nuevo repository:

 cd new_repo git am "$temp"/*.patch 

Para más detalles, mira hacia arriba:

  • la fuente documentada
  • git formatting-parche
  • git am

Para tal escenario uno podría querer probar git-import .

Básicamente, crea parches del file o directory dado ( $object ) de un repository y los aplica a otro mientras mantiene el historial.

 cd old_repo git format-patch --thread -o "$temp" --root -- "$object" 

Estos parches luego se aplican a un nuevo repository:

 cd new_repo git am "$temp"/*.patch 

(Este procedimiento puede repetirse para diferentes partes del antiguo repository, si es necesario).

Para más detalles, mira hacia arriba:

  • la fuente documentada
  • git formatting-parche
  • git am