Esta pregunta se basa en el subdirectorio Detach en un repositorio Git separado
En lugar de separar un solo subdirectorio, quiero separar un par. Por ejemplo, mi árbol de directorios actual se ve así:
/apps
/AAA
/BBB
/CCC
/libs
/XXX
/YYY
/ZZZ
Y me gustaría esto en su lugar:
/apps
/AAA
/libs
/XXX
El --subdirectory-filterargumento git filter-branchno funcionará porque elimina todo excepto el directorio dado la primera vez que se ejecuta. Pensé que usar el --index-filterargumento para todos los archivos no deseados funcionaría (aunque sea tedioso), pero si intento ejecutarlo más de una vez, recibo el siguiente mensaje:
Cannot create a new backup.
A previous backup already exists in refs/original/
Force overwriting the backup with -f
¿Algunas ideas? TIA
fuente

--tag-name-filter cata sus parámetrosPasos manuales con comandos simples de git
El plan es dividir directorios individuales en sus propios repositorios, luego fusionarlos. Los siguientes pasos manuales no empleaban scripts geek-to-use, sino comandos fáciles de entender y podían ayudar a fusionar subcarpetas N adicionales en otro repositorio único.
Dividir
Supongamos que su repositorio original es: original_repo
1 - Aplicaciones divididas:
2 - Librerías divididas
Continúe si tiene más de 2 carpetas. Ahora tendrá dos repositorios git nuevos y temporales.
Conquista mediante la fusión de aplicaciones y bibliotecas
3 - Prepare el nuevo repositorio:
Y deberá realizar al menos una confirmación. Si se deben omitir las siguientes tres líneas, su primer repositorio aparecerá inmediatamente debajo de la raíz de su repositorio:
Con el archivo temporal comprometido, el
mergecomando en la sección posterior se detendrá como se esperaba.Tomando de los comentarios del usuario, en lugar de agregar un archivo aleatorio como
a_file_and_make_a_commit, puede elegir agregar un.gitignore, oREADME.mdetc.4 - Combinar repositorio de aplicaciones primero:
Ahora debería ver el directorio de aplicaciones dentro de su nuevo repositorio.
git logdebería mostrar todos los mensajes de confirmación históricos relevantes.Nota: como Chris señaló a continuación en los comentarios, para la versión más nueva (> = 2.9) de git, debe especificar
--allow-unrelated-historiescongit merge5 - Fusionar libs repo a continuación de la misma manera:
Continúe si tiene más de 2 repositorios para fusionar.
Referencia: fusionar un subdirectorio de otro repositorio con git
fuente
.gitignoreyREADME.mdarchivos.git merge .. git read-treepaso, ya que los registra como archivos recientemente agregados y todas mis git guis no hacen la conexión a sus confirmaciones anteriores.¿Por qué querrías correr
filter-branchmás de una vez? Puede hacerlo todo en un barrido, por lo que no es necesario forzarlo (tenga en cuenta que debeextglobhabilitarlo en su shell para que esto funcione):Esto debería deshacerse de todos los cambios en los subdirectorios no deseados y mantener todas sus ramas y confirmaciones (a menos que solo afecten a los archivos en los subdirectorios eliminados, en virtud de
--prune-empty) - no hay problema con confirmaciones duplicadas, etc.Después de esta operación, los directorios no deseados se enumerarán como no seguidos por
git status.El
$(ls ...)es necesario st elextglobse evalúa por su shell en lugar del filtro de índice, que utiliza lashorden internaeval(dondeextglobno está disponible). Consulte ¿Cómo habilito las opciones de shell en git? para más detalles sobre eso.fuente
gitcomandos y, por lo tanto, no es tan susceptible a las diferencias en cómolsse interpreta en los sistemas operativos, como descubrió @Bae.Respondiendo mi propia pregunta aquí ... después de muchas pruebas y errores.
Logré hacer esto usando una combinación de
git subtreeygit-stitch-repo. Estas instrucciones se basan en:Primero, saqué los directorios que quería mantener en su propio repositorio separado:
Luego creé un nuevo repositorio vacío e importé / cosí los dos últimos:
Esto crea dos ramas
master-Aymaster-Bcada una contiene el contenido de uno de los repositorios cosidos. Para combinarlos y limpiarlos:Ahora no estoy muy seguro de cómo / cuándo sucede esto, pero después del primero
checkouty elpull, el código se fusiona mágicamente en la rama maestra (¡se aprecia cualquier idea de lo que está sucediendo aquí!)Todo parece haber funcionado como se esperaba, excepto que si miro a través del
newRepohistorial de confirmación, hay duplicados cuando el conjunto de cambios afectó a ambosapps/AAAylibs/XXX. Si hay una manera de eliminar duplicados, entonces sería perfecto.fuente
export PERL5LIB="$PERL5LIB:/usr/local/git/lib/perl5/site_perl/"a mi configuración de bash para que pudiera encontrar Git.pm. Luego lo instalé con cpan.git subtree addpara realizar esta tarea. Ver stackoverflow.com/a/58253979/1894803He escrito un filtro git para resolver exactamente este problema. Tiene el fantástico nombre de git_filter y se encuentra en github aquí:
https://github.com/slobobaby/git_filter
Se basa en el excelente libgit2.
Necesitaba dividir un repositorio grande con muchos commits (~ 100000) y las soluciones basadas en git filter-branch tardaron varios días en ejecutarse. git_filter tarda un minuto en hacer lo mismo.
fuente
Use la extensión git 'git splits'
git splitses un script bash que es un contenedorgit branch-filterque creé como una extensión git, basado en la solución de jkeating .Fue hecho exactamente para esta situación. Para su error, intente usar la
git splits -fopción para forzar la eliminación de la copia de seguridad. Debido a quegit splitsopera en una nueva rama, no reescribirá su rama actual, por lo que la copia de seguridad es extraña. Consulte el archivo Léame para obtener más detalles y asegúrese de usarlo en una copia / clon de su repositorio (¡por las dudas!) .git splits.Dividir los directorios en una sucursal local.
#change into your repo's directory cd /path/to/repo #checkout the branch git checkout XYZ#split multiple directories into new branch XYZ git splits -b XYZ apps/AAA libs/ZZZ
Crea un repositorio vacío en alguna parte. Asumiremos que hemos creado un repositorio vacío llamado
xyzen GitHub que tiene ruta:[email protected]:simpliwp/xyz.gitEmpuje al nuevo repositorio.
#add a new remote origin for the empty repo so we can push to the empty repo on GitHub git remote add origin_xyz [email protected]:simpliwp/xyz.git #push the branch to the empty repo's master branch git push origin_xyz XYZ:masterClone el repositorio remoto recién creado en un nuevo directorio local
#change current directory out of the old repo cd /path/to/where/you/want/the/new/local/repo #clone the remote repo you just pushed to git clone [email protected]:simpliwp/xyz.gitfuente
fuente
forbucle es digno de reconocer, ya que otras respuestas similares no lo incluyen. Si no tiene una copia local de cada rama en su clon,filter-branchno las tomará en cuenta como parte de su reescritura, lo que podría excluir los archivos introducidos en otras ramas, pero que aún no se fusionaron con su rama actual. (Aunque también vale la pena hacer una visitagit fetcha cualquier sucursal que haya verificado previamente para asegurarse de que permanezca actualizada).Una solución fácil: git-filter-repo
Tuve un problema similar y, después de revisar los diversos enfoques enumerados aquí, descubrí git-filter-repo . Se recomienda como alternativa a git-filter-branch en la documentación oficial de git aquí .
Para crear un nuevo repositorio a partir de un subconjunto de directorios en un repositorio existente, puede usar el comando:
Filtra varios archivos / carpetas encadenándolos:
Entonces, para responder la pregunta original , con git-filter-repo solo necesitarías el siguiente comando:
fuente
Si. Forzar la sobrescritura de la copia de seguridad mediante el uso del
-findicador en llamadas posteriores afilter-branchpara anular esa advertencia. :) De lo contrario, creo que tiene la solución (es decir, erradicar un directorio no deseado a la vez confilter-branch).fuente
Elimine la copia de seguridad presente en el directorio .git en refs / original como sugiere el mensaje. El directorio está oculto.
fuente