repositorio - github tutorial español
Separar(mover) el subdirectorio en un repositorio Git separado (22)
La manera más fácil
- instalar
git splits
. Lo creé como una extensión de git, basada en la solución de jkeating . 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#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 XY2Crear un repositorio vacío en algún lugar.
[email protected]:simpliwp/xyz.git
que hemos creado un repositorio vacío llamadoxyz
en GitHub que tiene la 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
Tengo un repositorio Git que contiene varios subdirectorios. Ahora he encontrado que uno de los subdirectorios no está relacionado con el otro y debería ser separado a un repositorio separado.
¿Cómo puedo hacer esto mientras mantengo el historial de los archivos dentro del subdirectorio?
Supongo que podría hacer un clon y eliminar las partes no deseadas de cada clon, pero supongo que esto me daría el árbol completo al revisar una revisión anterior, etc. Esto podría ser aceptable, pero preferiría poder fingir que Dos repositorios no tienen un historial compartido.
Solo para dejarlo claro, tengo la siguiente estructura:
XYZ/
.git/
XY1/
ABC/
XY2/
Pero me gustaría esto en su lugar:
XYZ/
.git/
XY1/
XY2/
ABC/
.git/
ABC/
The Easy Way ™
Resulta que esta es una práctica tan común y útil que los amos de git lo hicieron realmente fácil, pero tienes que tener una versión más nueva de git (> = 1.7.11 mayo de 2012). Vea el apéndice para saber cómo instalar el último git. Además, hay un ejemplo del mundo real en el tutorial a continuación.
Preparar el viejo repositorio
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 llamadasubproject
DEBE pasarse comosubproject
, NO./subproject/
Nota para los usuarios de Windows: cuando la profundidad de su carpeta es> 1,
<name-of-folder>
debe tener un separador de carpeta de estilo * nix (/). Por ejemplo, la carpeta llamadapath1/path2/subproject
DEBE pasarse comopath1/path2/subproject
Crea el nuevo repositorio.
mkdir <new-repo> pushd <new-repo> git init git pull </path/to/big-repo> <name-of-new-branch>
Vincula el nuevo repositorio a Github o donde sea
git remote add origin <[email protected]:my-user/new-repo.git> git push origin -u master
Limpieza, si se desea
popd # get out of <new-repo> pushd <big-repo> git rm -rf <name-of-folder>
Nota : Esto deja todas las referencias históricas en el repositorio. Consulte el Apéndice a continuación si está realmente preocupado por haber ingresado una contraseña o si necesita disminuir el tamaño del archivo de su carpeta
.git
.
...
Recorrido
Estos son los mismos pasos que arriba , pero siguiendo mis pasos exactos para mi repositorio en lugar de usar <meta-named-things>
.
Aquí hay un proyecto que tengo para implementar módulos de navegador de JavaScript en el nodo:
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 de git separado
pushd ~/Code/node-browser-compat/
git subtree split -P btoa -b btoa-only
popd
Ahora tengo una nueva rama, btoa-only
, que solo tiene confirmaciones 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, creo un nuevo repositorio en Github o bitbucket, o lo que sea y añado que es el origin
(por cierto, "origen" es solo una convención, no es parte del comando, puede llamarlo "servidor remoto" o lo que quiera)
git remote add origin [email protected]:node-browser-compat/btoa.git
git push origin -u master
¡Día feliz!
Nota: Si creó un repositorio con un README.md
, .gitignore
y LICENSE
, deberá extraer primero:
git pull origin -u master
git push origin -u master
Por último, querré eliminar la carpeta del repositorio más grande
git rm -rf btoa
...
Apéndice
Último git en OS X
Para obtener la última versión de git:
brew install git
Para obtener cerveza para OS X:
Las últimas git en Ubuntu
sudo apt-get update
sudo apt-get install git
git --version
Si eso no funciona (tienes una versión muy antigua de ubuntu), prueba
sudo add-apt-repository ppa:git-core/ppa
sudo apt-get update
sudo apt-get install git
Si eso todavía no funciona, intente
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.
limpiando tu historia
De forma predeterminada, eliminar archivos de git no los elimina de git, simplemente confirma que ya no están allí. Si desea eliminar realmente las referencias históricas (es decir, ha confirmado una contraseña), debe hacer esto:
git filter-branch --prune-empty --tree-filter ''rm -rf <name-of-folder>'' HEAD
Después de eso, puedes verificar que tu archivo o carpeta ya no aparezca en el historial de git
git log -- <name-of-folder> # should show nothing
Sin embargo, no puede "empujar" las eliminaciones a github y similares. Si lo intentas, obtendrás un error y tendrás que hacer git pull
antes de poder git push
- y luego volverás a tener todo en tu historial.
Por lo tanto, si desea eliminar el historial del "origen", es decir, eliminarlo de github, bitbucket, etc., deberá eliminar el repositorio y volver a enviar una copia eliminada del repositorio. Pero espera, ¡ hay más ! - Si está realmente preocupado por deshacerse de una contraseña o algo así, tendrá que eliminar la copia de seguridad (ver más abajo).
haciendo .git
más pequeño
El comando para eliminar el historial mencionado anteriormente todavía deja un montón de archivos de copia de seguridad, ya que git es muy amable y te ayuda a no arruinar tu repo por accidente. Eventualmente, eliminará los archivos huérfanos a lo largo de los días y los meses, pero los dejará allí por un tiempo en caso de que se dé cuenta de que accidentalmente eliminó algo que no deseaba.
Entonces, si realmente quieres vaciar la basura para reducir el tamaño de clon de un repositorio, inmediatamente tienes que hacer todo esto realmente extraño:
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, recomendaría no realizar estos pasos a menos que sepa que debe hacerlo, en caso de que haya borrado el subdirectorio incorrecto, ¿sabe? Los archivos de copia de seguridad no se deben clonar cuando presiona el repositorio, simplemente estarán en su copia local.
Crédito
Aquí hay una pequeña modificación a la de "The Easy Way ™" para dividir varias subcarpetas (digamos sub1
y sub2
) en un nuevo repositorio de git.
The Easy Way ™ (subcarpetas múltiples)
Preparar el viejo repositorio
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 llamadasubproject
DEBE pasarse comosubproject
, NO./subproject/
Nota para los usuarios de Windows: cuando la profundidad de su carpeta es> 1,
<name-of-folder>
debe tener un separador de carpeta de estilo * nix (/). Por ejemplo, la carpeta llamadapath1/path2/subproject
DEBE pasarse comopath1/path2/subproject
. Por otra parte, no utilice el comandomv
peromove
.Nota final: la única y gran diferencia con la respuesta básica es la segunda línea del script "
git filter-branch...
"Crea el nuevo repositorio.
mkdir <new-repo> pushd <new-repo> git init git pull </path/to/big-repo> <name-of-new-branch>
Vincula el nuevo repositorio a Github o donde sea
git remote add origin <[email protected]:my-user/new-repo.git> git push origin -u master
Limpieza, si se desea
popd # get out of <new-repo> pushd <big-repo> git rm -rf <name-of-folder>
Nota : Esto deja todas las referencias históricas en el repositorio. Consulte el Apéndice en la respuesta original si realmente está preocupado por haber ingresado una contraseña o si necesita disminuir el tamaño del archivo de su carpeta
.git
.
Como mencioné anteriormente , tuve que usar la solución inversa (eliminando todas las confirmaciones que no tocan mi dir/subdir/targetdir
) que parecía funcionar bastante bien eliminando aproximadamente el 95% de las confirmaciones (como se desea). Hay, sin embargo, dos pequeños problemas pendientes.
PRIMERO , filter-branch
hizo un gran trabajo al eliminar las confirmaciones que introducen o modifican el código, pero aparentemente, las confirmaciones de combinación están debajo de su estación en Gitiverse.
Este es un problema cosmético con el que probablemente pueda vivir (dice ... retrocediendo lentamente con los ojos desviados) .
SEGUNDA las pocas confirmaciones que quedan están prácticamente TODAS duplicadas! Parece que he adquirido una segunda línea de tiempo redundante que abarca casi toda la historia del proyecto. Lo interesante (que se puede ver en la imagen de abajo), es que mis tres sucursales locales no están todas en la misma línea de tiempo (que es, ciertamente, por qué existe y no solo se recolecta la basura).
Lo único que puedo imaginar es que una de las confirmaciones eliminadas fue, tal vez, la única confirmación de fusión que el filter-branch
realmente eliminó, y que creó la línea de tiempo paralela ya que cada hebra sin combinar tomó su propia copia de las confirmaciones. ( encogerse de hombros, ¿dónde está mi TARDIS?) Estoy bastante seguro de que puedo solucionar este problema, aunque realmente me encantaría entender cómo sucedió.
En el caso de mergefest-O-RAMA loco, probablemente lo dejaré solo, ya que se ha afianzado tan firmemente en mi historial de compromisos (me amenaza cuando me acerque), no parece estar causando realmente Cualquier problema no cosmético y porque es bastante bonito en Tower.app.
Consulte el proyecto git_split en https://github.com/vangorra/git_split
Convierta los directorios de git en sus propios repositorios en su propia ubicación. No hay negocio de subárbol divertido. Este script tomará un directorio existente en su repositorio git y lo convertirá en un repositorio independiente propio. En el camino, copiará el historial de cambios completo para el directorio que proporcionó.
./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.
Descubrí que para eliminar correctamente el historial antiguo del nuevo repositorio, tiene que hacer un poco más de trabajo después del paso de filter-branch
.
Haz el clon y el filtro:
git clone --no-hardlinks foo bar; cd bar git filter-branch --subdirectory-filter subdir/you/want
Eliminar todas las referencias a la historia antigua. "Origen" fue rastrear tu clon, y "original" es donde filtro-rama guarda las cosas antiguas:
git remote rm origin git update-ref -d refs/original/refs/heads/master git reflog expire --expire=now --all
Incluso ahora, su historial puede estar atascado en un paquete de archivos que fsck no tocará. Rasgarlo en tiras, creando un nuevo paquete de archivos y eliminando los objetos no utilizados:
git repack -ad
Hay una explicación de esto en el manual para la rama de filtro .
Es posible que necesite algo como "git reflog expire --expire = now --all" antes de la recolección de basura para eliminar realmente los archivos. git filter-branch simplemente elimina las referencias en el historial, pero no elimina las entradas de búsqueda que contienen los datos. Por supuesto, prueba esto primero.
Mi uso del disco se redujo drásticamente al hacer esto, aunque mis condiciones iniciales fueron algo diferentes. Quizás --subdirectory-filter niega esta necesidad, pero lo dudo.
Esto ya no es tan complejo que solo puede usar el comando git filter-branch en un clon de su repositorio para seleccionar los subdirectorios que no desea y luego enviar al nuevo control remoto.
git filter-branch --prune-empty --subdirectory-filter <YOUR_SUBDIR_TO_KEEP> master
git push <MY_NEW_REMOTE_URL> -f .
La forma correcta ahora es la siguiente:
git filter-branch --prune-empty --subdirectory-filter FOLDER_NAME [first_branch] [another_branch]
GitHub ahora incluso tiene un pequeño artículo sobre tales casos.
Pero asegúrese de clonar su repo original para separar el directorio primero (ya que eliminaría todos los archivos y otros directorios y probablemente necesite trabajar con ellos).
Entonces tu algoritmo debería ser:
- Clone su repositorio remoto a otro directorio
- utilizando
git filter-branch
solo deja archivos en algún subdirectorio, presione para nuevo control remoto - Cree un compromiso para eliminar este subdirectorio de su repositorio remoto original
La pregunta original quiere que XYZ / ABC / (archivos *) se convierta en ABC / ABC / (archivos *). Después de implementar la respuesta aceptada para mi propio código, noté que en realidad cambia XYZ / ABC / (* archivos) en ABC / (* archivos). La página de manual de filtro-rama incluso dice:
El resultado contendrá ese directorio (y solo ese) como su raíz del proyecto ".
En otras palabras, promueve que la carpeta de nivel superior "suba" un nivel. Esa es una distinción importante porque, por ejemplo, en mi historial he cambiado el nombre de una carpeta de nivel superior. Al promover las carpetas "hacia arriba" en un nivel, git pierde continuidad en la confirmación donde hice el cambio de nombre.
Mi respuesta a la pregunta es hacer 2 copias del repositorio y eliminar manualmente las carpetas que desea guardar en cada una. La página de manual me respalda con esto:
[...] evite usar [este comando] si una simple confirmación simple sería suficiente para solucionar su problema
Para agregar a la respuesta de Paul , encontré que para recuperar el espacio en última instancia, tengo que empujar HEAD a un repositorio limpio y eso reduce el tamaño del directorio .git / objects / pack.
es decir
$ mkdir ...ABC.git $ cd ...ABC.git $ git init --bare
Después de la poda gc, también haz:
$ git push ...ABC.git HEAD
Entonces puedes hacer
$ git clone ...ABC.git
y se reduce el tamaño de ABC / .git
En realidad, algunos de los pasos que consumen tiempo (por ejemplo, git gc) no son necesarios con el empuje para limpiar el repositorio, es decir:
$ git clone --no-hardlinks /XYZ /ABC $ git filter-branch --subdirectory-filter ABC HEAD $ git reset --hard $ git push ...ABC.git HEAD
Para lo que vale la pena, aquí está cómo usar GitHub en una máquina con Windows. Digamos que tiene un repositorio clonado en residir en C:/dir1
. La estructura del directorio se ve así: C:/dir1/dir2/dir3
. El directorio dir3
es el que quiero que sea un nuevo repositorio separado.
Github:
- Crea tu nuevo repositorio:
MyTeam/mynewrepo
Mensaje de Bash:
-
$ cd c:/Dir1
$ git filter-branch --prune-empty --subdirectory-filter dir2/dir3 HEAD
Devuelto: laRef ''refs/heads/master'' was rewritten
(fyi: dir2 / dir3 distingue entre mayúsculas y minúsculas)$ git remote add some_name [email protected]:MyTeam/mynewrepo.git
git remote add origin etc
no funcionó, devuelto "remote origin already exists
"$ git push --progress some_name master
Parece que la mayoría (todas?) De las respuestas aquí dependen de alguna forma de git filter-branch --subdirectory-filter
y su ilk. Esto puede funcionar "la mayoría de las veces", sin embargo, en algunos casos, por ejemplo, cuando cambió el nombre de la carpeta, por ejemplo:
ABC/
/move_this_dir # did some work here, then renamed it to
ABC/
/move_this_dir_renamed
Si realiza un estilo de filtro de git normal para extraer "move_me_renamed", perderá el historial de cambios de archivos que se produjo cuando era inicialmente move_this_dir ( ref ).
Por lo tanto, parece que la única forma de mantener realmente todo el historial de cambios (si el suyo es un caso como este), es, en esencia, copiar el repositorio (crear un nuevo repositorio, establecer que sea el origen), y luego destruir todo lo demás. y renombra el subdirectorio al padre de esta manera:
- Clona el proyecto multi-módulo localmente
- Sucursales - verifique que hay ahí:
git branch -a
- Haga un pago a cada sucursal para incluirlo en la división para obtener una copia local en su estación de trabajo:
git checkout --track origin/branchABC
- Haga una copia en un nuevo directorio:
cp -r oldmultimod simple
- Entra en la nueva copia del proyecto:
cd simple
- Deshazte de los otros módulos que no son necesarios en este proyecto:
-
git rm otherModule1 other2 other3
- Ahora solo queda el subdirectorio del módulo de destino.
- Deshágase del módulo subdir para que la raíz del módulo se convierta en la nueva raíz del proyecto.
-
git mv moduleSubdir1/* .
- Eliminar el
rmdir moduleSubdir1
:rmdir moduleSubdir1
- Compruebe los cambios en cualquier punto:
git status
- Crea el nuevo repositorio de git y copia su URL para apuntar este proyecto en él:
-
git remote set-url origin http://mygithost:8080/git/our-splitted-module-repo
- Verifica que esto sea bueno:
git remote -v
- Empuje los cambios hasta el repositorio remoto:
git push
- Ve al repositorio remoto y comprueba que está todo allí.
- Repítelo para cualquier otra rama necesaria:
git checkout branch2
Esto sigue los pasos 6-11 de github doc "Dividir una subcarpeta en un nuevo repositorio" para llevar el módulo a un nuevo repositorio.
Esto no le ahorrará espacio en su carpeta .git, pero conservará todo su historial de cambios para esos archivos, incluso a través de renombrados. Y puede que esto no valga la pena si no se pierde "mucha" historia, etc. ¡Pero al menos está garantizado que no perderá compromisos más antiguos!
Recomiendo la guía de GitHub para dividir las subcarpetas en un nuevo repositorio . Los pasos son similares a los de la respuesta de Paul , pero sus instrucciones me parecieron más fáciles de entender.
He modificado las instrucciones para que soliciten un repositorio local, en lugar de uno alojado en GitHub.
División de una subcarpeta en un nuevo repositorio
Abrir Git Bash.
Cambie el directorio de trabajo actual a la ubicación donde desea crear su nuevo repositorio.
Clone el repositorio que contiene la subcarpeta.
git clone OLD-REPOSITORY-FOLDER NEW-REPOSITORY-FOLDER
- Cambie el directorio de trabajo actual a su repositorio clonado.
cd REPOSITORY-NAME
- Para filtrar la subcarpeta del resto de los archivos en el repositorio, ejecute
git filter-branch
, proporcionando esta información:
FOLDER-NAME
: la carpeta dentro de su proyecto del que desea crear un repositorio separado.
- Consejo: los usuarios de Windows deben usar
/
para delimitar carpetas.BRANCH-NAME
: la rama predeterminada para su proyecto actual, por ejemplo,master
ogh-pages
.
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
Tenía exactamente este problema, pero todas las soluciones estándar basadas en git filter-branch eran extremadamente lentas. Si tienes un pequeño repositorio, entonces esto puede no ser un problema, fue para mí. Escribí otro programa de filtrado de git basado en libgit2 que, como primer paso, crea ramas para cada filtrado del repositorio principal y luego los empuja a limpiar repositorios como el siguiente paso. En mi repositorio (500Mb 100000 confirmaciones) los métodos estándar de rama-filtro de git tomaron días. Mi programa toma minutos para hacer el mismo filtrado.
Tiene el fabuloso nombre de git_filter y vive aquí:
https://github.com/slobobaby/git_filter
en GitHub.
Espero que sea de utilidad para alguien.
Utilice este comando de filtro para eliminar un subdirectorio, a la vez que conserva sus etiquetas y ramas:
git filter-branch --index-filter /
"git rm -r -f --cached --ignore-unmatch DIR" --prune-empty /
--tag-name-filter cat -- --all
Edición: Bash script añadido.
Las respuestas dadas aquí funcionaron solo parcialmente para mí; Muchos archivos grandes permanecieron en el caché. Lo que finalmente funcionó (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 era de alrededor de 100 MB. Éste lo bajó a 1.7 MB. Tal vez ayuda a alguien :)
La siguiente secuencia de comandos bash 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
Actualización : el módulo git-subárbol fue tan útil que el equipo de git lo introdujo en el núcleo y lo convirtió en el git subtree
. Vea aquí: Separe (mueva) el subdirectorio en un repositorio Git separado
git-subárbol puede ser útil para esto
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/
Actualización : este proceso es tan común, que el equipo de git lo hizo mucho más simple con una nueva herramienta, git subtree
. Vea aquí: Separe (mueva) el subdirectorio en un repositorio Git separado
Desea clonar su repositorio y luego usar git filter-branch
para marcar todo, excepto el subdirectorio que desea en su nuevo repositorio para ser recogido en la basura.
Para clonar tu repositorio local:
git clone /XYZ /ABC
(Nota: el repositorio se clonará utilizando enlaces físicos, pero eso no es un problema, ya que los archivos enlazados no se modificarán en sí mismos; se crearán nuevos).
Ahora, conservemos las ramas interesantes que también queremos reescribir, y luego eliminemos el origen para evitar empujar allí y asegurarnos de que el origen no haga referencia a las confirmaciones antiguas:
cd /ABC for i in branch1 br2 br3; do git branch -t $i origin/$i; done git remote rm origin
o para todas las sucursales remotas:
cd /ABC for i in $(git branch -r | sed "s/.*origin////"); do git branch -t $i origin/$i; done git remote rm origin
Ahora es posible que también desee eliminar las etiquetas que no tienen relación con el subproyecto; También puedes hacerlo más tarde, pero es posible que tengas que podar tu repositorio nuevamente. No lo hice y obtuve una
WARNING: Ref ''refs/tags/v0.1'' is unchanged
para todas las etiquetas (ya que no estaban relacionadas con el subproyecto); Además, después de eliminar dichas etiquetas, se reclamará más espacio. Aparentemente,git filter-branch
debería poder reescribir otras etiquetas, pero no pude verificar esto. Si desea eliminar todas las etiquetas, usegit tag -l | xargs git tag -d
git tag -l | xargs git tag -d
.Luego use filter-branch y reinicie para excluir los otros archivos, para que puedan ser podados. También agreguemos
--tag-name-filter cat --prune-empty
para eliminar las confirmaciones vacías y reescribir las etiquetas (tenga en cuenta que esto tendrá que eliminar su firma):git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC -- --all
o alternativamente, para volver a escribir la rama HEAD e ignorar las etiquetas y otras ramas:
git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC HEAD
Luego borre los respaldos de respaldo para que el espacio pueda ser realmente reclamado (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 tiene un repositorio local de git del subdirectorio ABC con todo su historial conservado.
Nota: Para la mayoría de los usos, git filter-branch
debería tener el parámetro agregado -- --all
. Sí, eso es realmente - - espacio - - all
. Este debe ser el último parámetro para el comando. Como descubrió Matli, esto mantiene las ramas y etiquetas del proyecto incluidas en el nuevo repositorio.
Edición: se incorporaron varias sugerencias de los comentarios a continuación para asegurarse, por ejemplo, de que el repositorio está realmente reducido (lo que no siempre fue así antes).
La respuesta de Paul crea un nuevo repositorio que contiene / ABC, pero no elimina / ABC desde / XYZ. El siguiente comando eliminará / ABC desde / XYZ:
git filter-branch --tree-filter "rm -rf ABC" --prune-empty HEAD
Por supuesto, pruébelo primero en un repositorio de ''clone --no-hardlinks'', y sígalo con los comandos reset, gc y prune de Paul.
Pon esto en tu 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 que el subárbol de git está bien y es maravilloso, pero mis subdirectorios del código administrado de git que quería mover estaban en eclipse. Así que si estás usando egit, es muy fácil. Tome el proyecto que desea mover y equipo-> desconéctelo, y luego equipo-> compártelo en la nueva ubicación. Por defecto, intentará utilizar la ubicación de repositorio anterior, pero puede desmarcar la selección de uso existente y elegir el nuevo lugar para moverla. Todos saludan egit.