Pregunta

Tengo un Git repositorio que contiene un número de subdirectorios.Ahora he descubierto que uno de los subdirectorios no está relacionado con el otro y deben ser separadas de un repositorio separado.

¿Cómo puedo hacer esto mientras se mantiene la historia de los archivos en el subdirectorio?

Supongo que podría hacer un clon y eliminar las partes no deseadas de cada clon, pero supongo que eso me daría el árbol completo cuando salga una versión anterior, etc.Esto puede ser aceptable, pero prefiero ser capaz de pretender que los dos repositorios no tiene una historia compartida.

Sólo para que quede claro, tengo la siguiente estructura:

XYZ/
    .git/
    XY1/
    ABC/
    XY2/

Pero me gustaría que este lugar:

XYZ/
    .git/
    XY1/
    XY2/
ABC/
    .git/
    ABC/
¿Fue útil?

Solución

Actualizar : Este proceso es tan común, que el equipo de git hizo que fuera mucho más sencillo con una nueva herramienta, git subtree. Ver aquí: Separar subdirectorio (mover) en separada repositorio Git


Se desea clonar su repositorio y luego usar git filter-branch para marcar todo menos el subdirectorio que desea en su nueva operación para estar recolección de basura.

  1. Para clonar el repositorio local:

    git clone /XYZ /ABC
    

    (Nota:. El repositorio será clonado utilizando enlaces duros, pero eso no es un problema ya que los archivos de disco duro vinculada no serán modificados en sí mismos - se crearán otros nuevos)

  2. Ahora, vamos a preservar las ramas interesantes que queremos volver a escribir así, y luego quitar el origen para evitar empujar allí y para asegurarse de que los viejos se compromete a no serán referenciados por el origen:

    cd /ABC
    for i in branch1 br2 br3; do git branch -t $i origin/$i; done
    git remote rm origin
    

    o para todas las ramas remotas:

    cd /ABC
    for i in $(git branch -r | sed "s/.*origin\///"); do git branch -t $i origin/$i; done
    git remote rm origin
    
  3. Ahora es posible que desee eliminar también las etiquetas que no tienen relación con el subproyecto; también se puede hacer eso más adelante, pero puede que tenga que podar tu repositorio nuevo. Yo no lo hice y obtuve un WARNING: Ref 'refs/tags/v0.1' is unchanged para todas las etiquetas (ya que todos estaban sin relación con el subproyecto); Además, después de la eliminación de tales etiquetas más espacio será reclamado. Al parecer git tag -l | xargs git tag -d debe ser capaz de reescribir otras etiquetas, pero no pude verificar esto. Si desea eliminar todas las etiquetas, utilice --tag-name-filter cat --prune-empty.

  4. A continuación, utilice filtro de rama y se restablece para excluir los otros archivos, por lo que se puede podar. Vamos a añadir también -- --all para eliminar compromete vacías y volver a escribir las etiquetas (nótese que esto tendrá que quitar su firma):

    git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC -- --all
    

    o, alternativamente, sólo para volver a escribir la rama HEAD y pasar por alto las etiquetas y otras ramas:

    git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC HEAD
    
  5. A continuación, elimine los reflogs de copia de seguridad por lo que el espacio puede ser realmente recuperado (aunque 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 usted tiene un repositorio Git local del subdirectorio ABC con toda su historia preservada.

Nota: Para la mayoría de usos, all debe de hecho tener el parámetro añadido <=>. Si eso es realmente - - espacio - - <=>. Esto tiene que ser los últimos parámetros para el comando. Como descubrió Matli, esto mantiene las ramas y las etiquetas de los proyectos incluidos en la nueva operación.

Editar:. Diversas sugerencias de los comentarios a continuación fueron incorporados para asegurarse de que, por ejemplo, que el depósito es en realidad encogido (que no fue siempre el caso antes)

Otros consejos

La Manera Más Fácil™

Resulta que este es un común y útil en la práctica que los señores de git hace que sea muy fácil, pero tienes que tener una versión más reciente de git (>= 1.7.11 de Mayo de 2012).Ver el apéndice para saber cómo instalar la última git.También, hay un ejemplo de la vida real en el tutorial a continuación.

  1. Preparar el viejo repo

    pushd <big-repo>
    git subtree split -P <name-of-folder> -b <name-of-new-branch>
    popd
    

    Nota: <name-of-folder> NO debe contener caracteres iniciales o finales.Por ejemplo, la carpeta con el nombre subproject Se DEBE pasar como subproject, NO ./subproject/

    Nota para usuarios de windows: cuando su carpeta de profundidad es > 1, <name-of-folder> debe tener *nix estilo separador de carpeta (/).Por ejemplo, la carpeta con el nombre path1\path2\subproject Se DEBE pasar como path1/path2/subproject

  2. Crear la nueva repo

    mkdir <new-repo>
    pushd <new-repo>
    
    git init
    git pull </path/to/big-repo> <name-of-new-branch>
    
  3. Enlace de la nueva repo de Github o donde sea

    git remote add origin <git@github.com:my-user/new-repo.git>
    git push origin -u master
    
  4. De limpieza, si lo desea

    popd # get out of <new-repo>
    pushd <big-repo>
    
    git rm -rf <name-of-folder>
    

    Nota:Esto deja a todas las referencias históricas en el repositorio.Ver el Apéndice a continuación si usted está realmente preocupado por haber cometido una contraseña o que usted necesita para reducir el tamaño del archivo de su .git carpeta.

...

Tutorial

Estos son los mismos pasos anteriores, pero siguiendo mis pasos exactos para mi repositorio en lugar de utilizar <meta-named-things>.

He aquí un proyecto que tengo para la implementación de JavaScript del navegador de módulos en node:

tree ~/Code/node-browser-compat

node-browser-compat
├── ArrayBuffer
├── Audio
├── Blob
├── FormData
├── atob
├── btoa
├── location
└── navigator

Quiero dividir una sola carpeta, btoa, en un repositorio git

pushd ~/Code/node-browser-compat/
git subtree split -P btoa -b btoa-only
popd

Ahora tengo una nueva rama, btoa-only, que sólo ha compromete para btoa y quiero crear un nuevo repositorio.

mkdir ~/Code/btoa/
pushd ~/Code/btoa/
git init
git pull ~/Code/node-browser-compat btoa-only

A continuación, he creado un nuevo repo en Github o bitbucket, o lo que sea y agregar es el origin (por cierto, "el origen" es sólo una convención, no una parte de los comandos que se podría llamar "server remoto" o lo que quieras)

git remote add origin git@github.com:node-browser-compat/btoa.git
git push origin -u master

Feliz día!

Nota: Si ha creado un repo con un README.md, .gitignore y LICENSE, usted tendrá que tirar de primera:

git pull origin -u master
git push origin -u master

Por último, me querrá quitar la carpeta desde el más grande del repo

git rm -rf btoa

...

Apéndice

Última git en OS X

Para obtener la última versión de git:

brew install git

Para obtener cerveza para OS X:

http://brew.sh

Última git en Ubuntu

sudo apt-get update
sudo apt-get install git
git --version

Si eso no funciona (tiene una versión muy antigua de ubuntu), trate de

sudo add-apt-repository ppa:git-core/ppa
sudo apt-get update
sudo apt-get install git

Si eso no funciona, trate de

sudo chmod +x /usr/share/doc/git/contrib/subtree/git-subtree.sh
sudo ln -s \
/usr/share/doc/git/contrib/subtree/git-subtree.sh \
/usr/lib/git-core/git-subtree

Gracias a rui.araujo de los comentarios.

borrar el historial

Por defecto eliminación de archivos de git en realidad no eliminarlos de git, sólo se compromete a que ellos no están más.Si desea eliminar las referencias históricas (es decir,usted tiene un cometido una contraseña), tienes que hacer esto:

git filter-branch --prune-empty --tree-filter 'rm -rf <name-of-folder>' HEAD

Después de que usted puede comprobar que su archivo o carpeta ya no muestra en el git de la historia en todos los

git log -- <name-of-folder> # should show nothing

Sin embargo, usted no se puede "empujar" elimina a github y el como.Si intenta usted obtendrá un mensaje de error y tendrá que git pull antes de que usted puede git push - y después de que usted vuelva a tener todo en su historia.

Así que si quieres borrar el historial desde el "origen" - es decir para borrarlo de github, bitbucket, etc), tendrás que eliminar la repo y volver a empujar una poda copia de la repo.Pero espera - hay más!- Si usted está realmente preocupado acerca de cómo deshacerse de una contraseña o algo así que tendrás que podar la copia de seguridad (ver más abajo).

hacer .git más pequeños

El mencionado borrar el historial de comandos deja detrás de un montón de archivos de copia de seguridad - porque git es muy amable en la ayuda de usted para no arruinar tu repo por accidente.Finalmente se eliminan archivos huérfanos durante los días y meses, pero se deja allí por un tiempo en caso de que te das cuenta de que has borrado algo que no quieres.

Así que si usted realmente quiere vaciar la papelera a reducir el tamaño clon de un repo de inmediato que usted tiene que hacer todo esto realmente cosas raras:

rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --prune=now

git reflog expire --all --expire-unreachable=0
git repack -A -d
git prune

Dicho esto, me gustaría recomendar no realizar estos pasos, a menos que usted sabe que usted necesita - sólo en caso de que usted hizo la poda de los mal subdirectorio, sabes?Los archivos de copia de seguridad no debe ser clonado cuando usted empuje de la repo, que sólo va a ser en su copia local.

De crédito

de Pablo respuesta crea un nuevo repositorio que contiene / ABC, pero no quita / ABC desde dentro / XYZ. El siguiente comando eliminará / ABC desde dentro / XYZ:

git filter-branch --tree-filter "rm -rf ABC" --prune-empty HEAD

Por supuesto, probarlo en un 'clon' --no-hardlinks repositorio primero, y seguir con el restablecimiento, GC y comandos de ciruela Pablo lista.

He encontrado que con el fin de eliminar adecuadamente la vieja historia del nuevo depósito, que tiene que hacer un poco más de trabajo después de la filter-branch paso.

  1. Hacer el clon y el filtro:

    git clone --no-hardlinks foo bar; cd bar
    git filter-branch --subdirectory-filter subdir/you/want
    
  2. Eliminar todas las referencias a la historia antigua. “Origen” fue el seguimiento de su clon, y “original” es donde filter-branch guarda el material antiguo:

    git remote rm origin
    git update-ref -d refs/original/refs/heads/master
    git reflog expire --expire=now --all
    
  3. Incluso ahora, su historia podría ser atrapado en un PACKFILE que fsck no va a tocar. Romperlo en pedazos, la creación de un nuevo PACKFILE y eliminar los objetos no utilizados:

    git repack -ad
    

Hay una explicación de este en la href="http://git-scm.com/docs/git-filter-branch#_checklist_for_shrinking_a_repository" manual de rel="noreferrer"> .

Editar: Script Bash añadió

.

Las respuestas dadas aquí funcionaba parcialmente para mí; Un montón de archivos de gran tamaño se quedaron en la memoria caché. Lo que finalmente trabajado (después de horas en #git en freenode):

git clone --no-hardlinks file:///SOURCE /tmp/blubb
cd blubb
git filter-branch --subdirectory-filter ./PATH_TO_EXTRACT  --prune-empty --tag-name-filter cat -- --all
git clone file:///tmp/blubb/ /tmp/blooh
cd /tmp/blooh
git reflog expire --expire=now --all
git repack -ad
git gc --prune=now

Con las soluciones anteriores, el tamaño del repositorio fue de alrededor de 100 MB. Éste la bajó a 1,7 MB. Tal vez ayude a alguien:)


La siguiente escritura del golpe automatiza la tarea:

!/bin/bash

if (( $# < 3 ))
then
    echo "Usage:   $0 </path/to/repo/> <directory/to/extract/> <newName>"
    echo
    echo "Example: $0 /Projects/42.git first/answer/ firstAnswer"
    exit 1
fi


clone=/tmp/${3}Clone
newN=/tmp/${3}

git clone --no-hardlinks file://$1 ${clone}
cd ${clone}

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

git clone file://${clone} ${newN}
cd ${newN}

git reflog expire --expire=now --all
git repack -ad
git gc --prune=now

Esto ya no es tan complejo que sólo puede utilizar el git filter-branch comando en un clon de ti repo de sacrificar los subdirectorios que no desea y luego empujar a la nueva distancia.

git filter-branch --prune-empty --subdirectory-filter <YOUR_SUBDIR_TO_KEEP> master
git push <MY_NEW_REMOTE_URL> -f .

Actualizar : El módulo de git-sub árbol fue tan útil que el equipo git tiró de ella hacia el núcleo y lo hizo git subtree. Ver aquí: Separar subdirectorio (mover) en separada repositorio Git

git-subárbol puede ser útil para este

http://github.com/apenwarr/git -subtree / blob / master / git-subtree.txt (en desuso)

http: // psionides.jogger.pl/2010/02/04/sharing-code-between-projects-with-git-subtree/

Aquí está una pequeña modificación a CoolAJ86's "De la Manera más Fácil™" respuesta con el fin de dividir varios sub carpetas (digamos que sub1y sub2) en un nuevo repositorio git.

La Manera más Fácil™ (varios sub carpetas)

  1. Preparar el viejo repo

    pushd <big-repo>
    git filter-branch --tree-filter "mkdir <name-of-folder>; mv <sub1> <sub2> <name-of-folder>/" HEAD
    git subtree split -P <name-of-folder> -b <name-of-new-branch>
    popd
    

    Nota: <name-of-folder> NO debe contener caracteres iniciales o finales.Por ejemplo, la carpeta con el nombre subproject Se DEBE pasar como subproject, NO ./subproject/

    Nota para usuarios de windows: cuando su carpeta de profundidad es > 1, <name-of-folder> debe tener *nix estilo separador de carpeta (/).Por ejemplo, la carpeta con el nombre path1\path2\subproject Se DEBE pasar como path1/path2/subproject.Además no uso mvcomando pero move.

    Nota Final: la única y gran diferencia con la base de la respuesta es la segunda línea de la secuencia de comandos "git filter-branch..."

  2. Crear la nueva repo

    mkdir <new-repo>
    pushd <new-repo>
    
    git init
    git pull </path/to/big-repo> <name-of-new-branch>
    
  3. Enlace de la nueva repo de Github o donde sea

    git remote add origin <git@github.com:my-user/new-repo.git>
    git push origin -u master
    
  4. De limpieza, si lo desea

    popd # get out of <new-repo>
    pushd <big-repo>
    
    git rm -rf <name-of-folder>
    

    Nota:Esto deja a todas las referencias históricas en el repositorio.Ver el Apéndice en la respuesta original si usted está realmente preocupado por haber cometido una contraseña o que usted necesita para reducir el tamaño del archivo de su .git carpeta.

La pregunta original quiere XYZ / ABC / (* archivos) para convertirse en ABC / DE / (archivos *) ABC. Después de la aplicación de la respuesta aceptada por mi propio código, me di cuenta de que en realidad cambia (archivos *) XYZ / ABC / a (archivos *) ABC /. La página del manual filter-branch llega a decir,

  

El resultado contendrá ese directorio (y sólo eso) como su raíz del proyecto ".

En otras palabras, se promueve la carpeta de nivel superior "arriba" de una sola planta. Esa es una distinción importante porque, por ejemplo, en mi historia había cambiado el nombre de una carpeta de nivel superior. Mediante la promoción de carpetas "arriba" de una sola planta, git pierde la continuidad en el comprometerse donde hice el cambio de nombre.

Perdí contiuity después de filtro-rama

Mi respuesta a la pregunta entonces es hacer 2 copias del repositorio y eliminar manualmente la carpeta (s) que desea mantener en cada uno. La página de hombre me hace copias de seguridad con esto:

  

[...] evitar el uso de [este comando] si un simple única confirmación sería suficiente para arreglar el problema

Para añadir a de Pablo respuesta , encontré que en última instancia para recuperar espacio, tengo que empujar HEAD para un repositorio limpia y que recorta el tamaño del directorio / .git / objetos paquete.

es decir.

$ mkdir ...ABC.git
$ cd ...ABC.git
$ git init --bare

Después de la ciruela GC, también hacer:

$ git push ...ABC.git HEAD

A continuación, puede hacer

$ git clone ...ABC.git

y el tamaño de ABC / .git se reduce

En realidad, algunos de los pasos de tiempo que consume (por ejemplo git gc) no son necesarios con el empuje de limpiar repositorio, es decir:.

$ git clone --no-hardlinks /XYZ /ABC
$ git filter-branch --subdirectory-filter ABC HEAD
$ git reset --hard
$ git push ...ABC.git HEAD

Forma correcta ahora es la siguiente:

git filter-branch --prune-empty --subdirectory-filter FOLDER_NAME [first_branch] [another_branch]

GitHub ahora incluso tienen pequeño artículo sobre tales casos.

Sin embargo, asegúrese de clonar tu repositorio original al directorio separado en primer lugar (como sería eliminar todos los archivos y directorios y otros que probable necesidad de trabajar con ellos).

Así que su algoritmo debe ser:

  1. clonar tu repositorio remoto a otro directorio
  2. git filter-branch utilizando sólo los archivos que quedan bajo algún subdirectorio, empujar a control remoto nuevo
  3. Crear comprometerse a eliminar este subdirectorio de su cesión temporal a distancia original

Parece que la mayoría (todos?) de las respuestas que aquí se basan en alguna forma de git filter-branch --subdirectory-filter y los de su calaña.Esto puede funcionar "la mayoría de las veces" sin embargo, para algunos casos, por ejemplo el caso de cuando se le cambió el nombre a la carpeta, por ejemplo:

 ABC/
    /move_this_dir # did some work here, then renamed it to

ABC/
    /move_this_dir_renamed

Si vas a hacer una normal git estilo del filtro para extraer "move_me_renamed" perderá archivo de historial de cambios que se produjeron desde atrás cuando era inicialmente move_this_dir (ref).

Así pues, parece que la única manera de mantener todos historial de cambios (si el tuyo es un caso como este), es, en esencia, para copiar el repositorio (crear un nuevo repositorio, establece que para ser el origen), nuke todo lo demás y cambiar el nombre del subdirectorio para el padre como este:

  1. Clon de la multi-módulo de proyecto a nivel local
  2. Ramas - comprobar que lo que hay: git branch -a
  3. Hacer una caja para cada rama para ser incluido en la división para obtener una copia local en su estación de trabajo: git checkout --track origin/branchABC
  4. Hacer una copia en un directorio nuevo: cp -r oldmultimod simple
  5. Ir en el nuevo proyecto de la copia: cd simple
  6. Deshacerse de los otros módulos que no son necesarios en este proyecto:
  7. git rm otherModule1 other2 other3
  8. Ahora sólo el subdirectorio del módulo de destino sigue siendo
  9. Deshacerse del módulo subdir para que el módulo de la raíz se convierte en el nuevo proyecto de la raíz
  10. git mv moduleSubdir1/* .
  11. Eliminar la reliquia subdir: rmdir moduleSubdir1
  12. Comprobar los cambios en cualquier momento: git status
  13. Crear el nuevo repositorio git y copiar su URL a punto de este proyecto en:
  14. git remote set-url origin http://mygithost:8080/git/our-splitted-module-repo
  15. Verifique que esta es la buena: git remote -v
  16. Empujar los cambios hasta el remoto repo: git push
  17. Ir a la repo remoto y comprobar que todo lo que hay
  18. Repetir para cualquier otra rama necesario: git checkout branch2

Esta de la siguiente manera el github doc "la División de una subcarpeta en un nuevo repositorio" los pasos 6-11 para empujar el módulo a un nuevo repo.

Esto no ahorra espacio en tu .git carpeta, pero va a conservar su historia de cambio de los archivos, incluso a través cambia el nombre.Y esto no puede ser vale la pena si no hay "un montón" de la historia perdida, etc.Pero al menos se garantiza que no se pierda mayores comete!

Yo tenía exactamente este problema, pero todas las soluciones estándar basadas en git filter-branch eran extremadamente lento. Si usted tiene un pequeño repositorio entonces esto no puede ser un problema, que era para mí. Escribí otro programa de filtrado basado en git libgit2 que, como un primer paso crea ramas para cada filtrado del repositorio principal y luego empuja estos para limpiar los depósitos como el siguiente paso. En mi repositorio (500 MB) 100000 compromete el tracto gastrointestinal métodos estándar filter-branch tomaron días. Mi programa toma unos minutos para hacer lo mismo de filtrado.

Tiene el nombre de la fabulosa git_filter y vive aquí:

https://github.com/slobobaby/git_filter

en GitHub.

Espero que sea útil a alguien.

Por lo que vale, aquí es cómo el uso de GitHub en una máquina Windows. Digamos que usted tiene un acuerdo de recompra clonado en residir en C:\dir1. La estructura de directorios es el siguiente: C:\dir1\dir2\dir3. El dir3 directorio es el que yo quiero ser una nueva operación separada.

Github:

  1. Crea tu nuevo repositorio: MyTeam/mynewrepo

Símbolo Bash:

  1. $ cd c:/Dir1
  2. $ git filter-branch --prune-empty --subdirectory-filter dir2/dir3 HEAD
    Devuelto: Ref 'refs/heads/master' was rewritten (FYI:. Dir2 / dir3 mayúsculas y minúsculas)

  3. $ git remote add some_name git@github.com:MyTeam/mynewrepo.git
    git remote add origin etc. no funcionó, regresó "remote origin already exists"

  4. $ git push --progress some_name master

Como mencionado anteriormente , tenía que usar la inversa solución (eliminando todos los commits no tocar mi dir/subdir/targetdir), que parecía funcionar bastante bien la eliminación de alrededor del 95% de las confirmaciones (según se desee). Hay, sin embargo, dos pequeñas cuestiones pendientes.

PRIMERA , filter-branch hizo un trabajo bang de eliminar confirmaciones que introducen o modifican el código, pero al parecer, Combinar commit son por debajo de su estación en el Gitiverse.

Este es un problema cosmético que es probable que pueda vivir con (él dice ... retrocediendo lentamente con ojos desviados) .

SEGUNDO las pocas confirmaciones que quedan son más o menos TODO duplicado! Me parece que han adquirido una segunda línea de tiempo, redundante que se extiende por casi toda la historia del proyecto. Lo interesante (que se puede ver en la foto de abajo), es que mis tres ramas locales no están todos en la misma línea de tiempo (que es, sin duda por qué existe y no es sólo basura recogida).

La única cosa que puedo imaginar es que una de las confirmaciones eliminado era, quizás, la única combinación que cometen <=> realmente hizo eliminar , y que creó la línea de tiempo en paralelo, ya que cada ahora unmerged hebra tomó su propia copia de las confirmaciones. ( encogimiento ¿Dónde está mi Tardis?) Estoy bastante seguro de que puedo solucionar este problema, aunque me realmente amo a entender cómo sucedió.

En el caso de locura mergefest-O-Rama, voy a estar dejando probable que una sola ya que se ha afianzado tan firmemente en mi propia historia cometer-amenazador a mí cada vez que vengo NEAR, que no parece ser en realidad causar ningún problema no cosméticos y porque es muy bonita en Tower.app.

Utilice este comando de filtro se borra un directorio, preservando al mismo tiempo sus etiquetas y ramas:

git filter-branch --index-filter \
"git rm -r -f --cached --ignore-unmatch DIR" --prune-empty \
--tag-name-filter cat -- --all

La manera más fácil

  1. git splits . He creado como una extensión de git, basado en la solución de jkeating .
  2. Dividir los directorios en una rama 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 XY1 XY2

  3. Crear una cesión temporal vacío en alguna parte. Vamos a suponer que hemos creado un repo vacío llamado xyz en GitHub que tiene ruta: git@github.com:simpliwp/xyz.git

  4. Pulsar para la nueva operación. #add a new remote origin for the empty repo so we can push to the empty repo on GitHub git remote add origin_xyz git@github.com:simpliwp/xyz.git #push the branch to the empty repo's master branch git push origin_xyz XYZ:master

  5. Clonar el repositorio remoto de nueva creación en un nuevo directorio local de
    #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 git@github.com:simpliwp/xyz.git

guía de GitHub a la división subcarpetas en una nueva repositorio. Los pasos son similares a de Pablo respuesta , pero he encontrado que las instrucciones eran fáciles de entender.

He modificado las instrucciones para que se apliquen para un repositorio local, en lugar de uno alojado en GitHub.


  

División de una subcarpeta a cabo en una nuevo repositorio

     
      
  1. Abrir Git Bash.

  2.   
  3. Cambiar el directorio de trabajo actual a la ubicación en la que desea crear su nuevo repositorio.

  4.   
  5. Clonar el repositorio que contiene la subcarpeta.

  6.   
     

git clone OLD-REPOSITORY-FOLDER NEW-REPOSITORY-FOLDER
     
      
  1. Cambiar el directorio de trabajo actual a su repositorio clonado.
  2.   
     

cd REPOSITORY-NAME
     
      
  1. Para filtrar la subcarpeta del resto de los archivos en el repositorio, ejecutar git filter-branch, el suministro de esta información:      
        
    • FOLDER-NAME: La carpeta dentro de su proyecto que desea crear un depósito separado de.      
          
      • Consejo:. Los usuarios de Windows deben utilizar / para delimitar las carpetas
      •   
    •   
    • BRANCH-NAME:. La rama por defecto para su proyecto actual, por ejemplo, master o gh-pages
    •   
  2.   
     

git filter-branch --prune-empty --subdirectory-filter FOLDER-NAME  BRANCH-NAME 
# Filter the specified branch in your directory and remove empty commits
Rewrite 48dc599c80e20527ed902928085e7861e6b3cbe6 (89/89)
Ref 'refs/heads/BRANCH-NAME' was rewritten

Es posible que tenga algo como "git reflog expire = --expire ahora --all" antes de la recolección de basura para limpiar realmente los archivos fuera. git filter-branch sólo elimina las referencias en la historia, pero no elimina las entradas reflog que contienen los datos. Por supuesto, probar esto primero.

Mi uso del disco se redujo drásticamente en hacer esto, aunque mis condiciones iniciales eran algo diferentes. Tal vez --subdirectory-filtro niega esta necesidad, pero lo dudo.

Salida proyecto git_split en https://github.com/vangorra/git_split

directorios Encienda git en sus propios repositorios en su propia ubicación. Sin subárbol negocio divertido. Este script se llevará a un directorio existente en su repositorio Git y convertir ese directorio en un repositorio independiente de su propia. En el camino, se copiará todo el historial de cambios para el directorio que ya ha proporcionado.

./git_split.sh <src_repo> <src_branch> <relative_dir_path> <dest_repo>
        src_repo  - The source repo to pull from.
        src_branch - The branch of the source repo to pull from. (usually master)
        relative_dir_path   - Relative path of the directory in the source repo to split.
        dest_repo - The repo to push to.

Ponga esto en su gitconfig:

reduce-to-subfolder = !sh -c 'git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter cookbooks/unicorn HEAD && git reset --hard && git for-each-ref refs/original/ | cut -f 2 | xargs -n 1 git update-ref -d && git reflog expire --expire=now --all && git gc --aggressive --prune=now && git remote rm origin'

Estoy seguro de sub-árbol git es todo fino y maravilloso, pero mis subdirectorios de git código que quería mover era todo en Eclipse administrado. Así que si usted está utilizando egit, es dolorosamente fácil. Tome el proyecto que desea mover y en equipo> desconexión, y luego en equipo> compartirlo a la nueva ubicación. Se pondrá por defecto a tratar de usar la ubicación de recompra de edad, pero se puede desactivar la selección utilización existente y escoger el nuevo lugar para moverlo. Todo el granizo egit.

He encontrado la solución hacia adelante bastante recta, La idea es copiar repositorio y luego simplemente eliminar parte innecesaria. Así es como funciona:

1) clonar un repositorio desea dividir

git clone git@git.thehost.io:testrepo/test.git

2) Mover a carpeta git

cd test/

2) Eliminar carpetas innecesarias y cometerlo

rm -r ABC/
git add .
enter code here
git commit -m 'Remove ABC'

3) Eliminar carpetas innecesarias (s) forma la historia con BFG

cd ..
java -jar bfg.jar --delete-folders "{ABC}" test
cd test/
git reflog expire --expire=now --all && git gc --prune=now --aggressive
  

para las carpetas se multiplican puede usar una coma

java -jar bfg.jar --delete-folders "{ABC1,ABC2}" metric.git

4) Compruebe que la historia no contiene los archivos / carpetas que acaba de eliminar

git log --diff-filter=D --summary | grep delete

5) Ahora usted tienen repositorio limpia sin ABC, por lo que sólo empuje en su nuevo origen

remote add origin git@github.com:username/new_repo
git push -u origin master

Eso es todo. Puede repetir los pasos para obtener otro repositorio,

acaba de quitar XY1, XY2 y cambiar el nombre XYZ -> ABC en el paso 3

Usted puede tratar fácilmente la https://help.github.com/enterprise/2.15/user/articles/splitting-a-subfolder-out-into-a-new-repository/

Esto funcionó para mí. Los problemas que enfrenté en los pasos dados anteriormente son

  1. En este comando git filter-branch --prune-empty --subdirectory-filter FOLDER-NAME BRANCH-NAME El BRANCH-NAME es principal

  2. Si el último paso falla al cometer debido al problema de protección seguimiento - https://docs.gitlab.com/ee/user/project/protected_branches.html

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top