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-filter
argumento git filter-branch
no funcionará porque elimina todo excepto el directorio dado la primera vez que se ejecuta. Pensé que usar el --index-filter
argumento 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 cat
a 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
merge
comando 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.md
etc.4 - Combinar repositorio de aplicaciones primero:
Ahora debería ver el directorio de aplicaciones dentro de su nuevo repositorio.
git log
deberí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-histories
congit merge
5 - 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
.gitignore
yREADME.md
archivos.git merge .. git read-tree
paso, 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-branch
más de una vez? Puede hacerlo todo en un barrido, por lo que no es necesario forzarlo (tenga en cuenta que debeextglob
habilitarlo 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 elextglob
se evalúa por su shell en lugar del filtro de índice, que utiliza lash
orden internaeval
(dondeextglob
no está disponible). Consulte ¿Cómo habilito las opciones de shell en git? para más detalles sobre eso.fuente
git
comandos y, por lo tanto, no es tan susceptible a las diferencias en cómols
se 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 subtree
ygit-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-A
ymaster-B
cada 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
checkout
y 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
newRepo
historial de confirmación, hay duplicados cuando el conjunto de cambios afectó a ambosapps/AAA
ylibs/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 add
para 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 splits
es un script bash que es un contenedorgit branch-filter
que 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 -f
opción para forzar la eliminación de la copia de seguridad. Debido a quegit splits
opera 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
xyz
en GitHub que tiene ruta:[email protected]:simpliwp/xyz.git
Empuje 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:master
Clone 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.git
fuente
fuente
for
bucle 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-branch
no 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 fetch
a 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
-f
indicador en llamadas posteriores afilter-branch
para 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