¿Cómo importar un repositorio Git existente a otro?

14 minutos de lectura

¿Como importar un repositorio Git existente a otro
Vijay Patel

Tengo un repositorio Git en una carpeta llamada XXXy tengo un segundo repositorio de Git llamado AAAA.

quiero importar el XXX repositorio en el AAAA repositorio como un subdirectorio llamado ZZZ y agrega todo XXXHistorial de cambios a AAAA.

Estructura de carpetas antes:

├── XXX
│   ├── .git
│   └── (project files)
└── YYY
    ├── .git
    └── (project files)

Estructura de carpetas después de:

YYY
├── .git  <-- This now contains the change history from XXX
├──  ZZZ  <-- This was originally XXX
│    └── (project files)
└──  (project files)

¿Se puede hacer esto o debo recurrir al uso de submódulos?

  • En Github, ahora es posible hacer esto desde la interfaz web cuando crea un nuevo repositorio.

    – código bg

    16/09/2015 a las 17:58

  • Posible duplicado de ¿Cómo fusionar dos repositorios de git?

    – ZUMBIDO-dEE

    17 de febrero de 2016 a las 9:32

  • El comentario de @bgcode fue realmente útil para mí, gracias. Puede importar otro repositorio directamente desde la interfaz de usuario de GitHub y ahorrar una tonelada de trabajo

    – Chum Kui

    3 feb a las 11:01

¿Como importar un repositorio Git existente a otro
ebneter

Probablemente la forma más sencilla sería tirar de la XXX cosas en una rama en AAAA y luego fusionarlo en maestro:

En AAAA:

git remote add other /path/to/XXX
git fetch other
git checkout -b ZZZ other/master
mkdir ZZZ
git mv stuff ZZZ/stuff                      # repeat as necessary for each file/dir
git commit -m "Moved stuff to ZZZ"
git checkout master                
git merge ZZZ --allow-unrelated-histories   # should add ZZZ/ to master
git commit
git remote rm other
git branch -d ZZZ                           # to get rid of the extra branch before pushing
git push                                    # if you have a remote, that is

De hecho, acabo de probar esto con un par de mis repositorios y funciona. A diferencia de la respuesta de Jörg, no le permitirá continuar usando el otro repositorio, pero no creo que lo haya especificado de todos modos.

Nota: Dado que esto se escribió originalmente en 2009, git agregó la combinación de subárboles mencionada en la respuesta a continuación. Probablemente usaría ese método hoy, aunque, por supuesto, este método todavía funciona.

  • Gracias. Utilicé una versión ligeramente modificada de su técnica: creé una rama de ‘puesta en escena’ en XXX donde creé la carpeta ZZZ y moví las ‘cosas’ a ella. Luego fusioné XXX en YYY.

    – Vijay Patel

    7 de noviembre de 2009 a las 10:45

  • Esto funciono muy bien para mi. Los únicos cambios que hice fueron: 1) “git branch -d ZZZ” antes del impulso porque no quería que esta rama temporal estuviera dando vueltas. 2) “git push” me estaba dando el error: “No hay referencias en común y ninguna especificada; no hace nada. Quizás debería especificar una rama como ‘maestro'”. (El origen al que estaba empujando era un repositorio desnudo vacío). Pero “git push –all” funcionó como un campeón.

    – Crazy Pyro

    24 de febrero de 2011 a las 20:28

  • Quería terminar con solo la carpeta ZZZ más el historial en el repositorio YYY: quería eliminar el repositorio XXX original y la rama ZZZ en el repositorio YYY. Encontré eliminar la rama ZZZ como @CrazyPyro sugirió eliminar el historial; para mantenerlo, fusioné la rama ZZZ en maestra antes de eliminar.

    –Oli Studholme

    12 de mayo de 2012 a las 5:24

  • @SebastianBlask Acabo de jugar con esto con dos de mis repositorios, y me di cuenta de que falta un paso que nadie parece haber notado nunca, a pesar de haber recibido votos a favor durante años. 🙂 I mencionado fusionándolo en maestro, pero en realidad no lo mostró. Editándolo ahora…

    – ebneter

    28 de febrero de 2013 a las 2:26

  • podría agregar algo como esto, al mover archivos a su subcarpeta: git mv $(ls|grep -v <your foldername>) <your foldername>/ Esto copiará todos los archivos y carpetas en su nueva carpeta

    – sérum

    29 de enero de 2016 a las 13:17


1646961798 233 ¿Como importar un repositorio Git existente a otro
ColinM

Si desea conservar el historial de confirmación exacto del segundo repositorio y, por lo tanto, también conservar la capacidad de fusionar fácilmente los cambios anteriores en el futuro, este es el método que desea. Da como resultado un historial sin modificar del subárbol que se importa a su repositorio más una confirmación de combinación para mover el repositorio combinado al subdirectorio.

git remote add XXX_remote <path-or-url-to-XXX-repo>
git fetch XXX_remote
git merge -s ours --no-commit --allow-unrelated-histories XXX_remote/master
git read-tree --prefix=ZZZ/ -u XXX_remote/master
git commit -m "Imported XXX as a subtree."

Puede realizar un seguimiento de los cambios ascendentes de esta manera:

git pull -s subtree XXX_remote master

Git descubre por sí mismo dónde están las raíces antes de realizar la fusión, por lo que no es necesario especificar el prefijo en las fusiones posteriores.

los Abajo es que en el historial fusionado los archivos no tienen prefijo (no en un subdirectorio). Como resultado git log ZZZ/a le mostrará todos los cambios (si los hay) excepto los del historial fusionado. Tu puedes hacer:

git log --follow -- a

pero eso no mostrará los cambios que no sean en el historial combinado.

En otras palabras, si no cambias ZZZarchivos de en el repositorio XXXentonces necesitas especificar --follow y un camino sin prefijo. Si los cambia en ambos repositorios, entonces tiene 2 comandos, ninguno de los cuales muestra todos los cambios.

Versiones de Git anteriores a la 2.9: No es necesario pasar el --allow-unrelated-histories opción a git merge.

El método en la otra respuesta que usa read-tree y se salta el merge -s ours El paso no es diferente de copiar los archivos con cp y confirmar el resultado.

La fuente original era de Artículo de ayuda “Subtree Merge” de github. Y otro enlace útil.

  • esto no parece haber preservado la historia… si hago un git log en cualquiera de los archivos que saqué, solo veo la confirmación de combinación única y nada de su vida anterior en el otro repositorio. Git 1.8.0

    – Anentrópico

    21 de enero de 2013 a las 13:14


  • ¡Ajá! si uso la ruta anterior del archivo importado, es decir, omito el subdirectorio al que se importó, entonces git log me dará el historial de confirmación, por ejemplo git log -- myfile en lugar de git log -- rack/myfile

    – Anentrópico

    21 de enero de 2013 a las 17:28

  • @FrancescoFrassinelli, ¿no es deseable? Traer la historia es una rasgo de este método.

    – pattivacek

    9 de septiembre de 2013 a las 14:34

  • @FrancescoFrassinelli, si no quieres historia, ¿por qué no hacer una copia normal? Estoy tratando de averiguar qué te atraería a este método si no fuera por la historia, ¡esa es la única razón por la que usé este método!

    – pattivacek

    9 sep 2013 a las 20:57

  • Desde Git 2.9, necesitas la opción --allow-unrelated-histories al hacer la fusión.

    – stuXnet

    28 de julio de 2016 a las 14:43

¿Como importar un repositorio Git existente a otro
kynan

git-subtree es un script diseñado exactamente para este caso de uso de fusionar múltiples repositorios en uno mientras se preserva el historial (y/o se divide el historial de los subárboles, aunque eso parece ser irrelevante para esta pregunta). Se distribuye como parte del árbol git. desde el lanzamiento 1.7.11.

Para fusionar un repositorio <repo> en revisión <rev> como subdirectorio <prefix>utilizar git subtree add como sigue:

git subtree add -P <prefix> <repo> <rev>

git-subtree implementa el estrategia de combinación de subárboles de una manera más amigable para el usuario.

Para su caso, dentro del repositorio YYY, ejecutaría:

git subtree add -P ZZZ /path/to/XXX.git master

los Abajo es que en el historial fusionado los archivos no tienen prefijo (no en un subdirectorio). Como resultado git log ZZZ/a le mostrará todos los cambios (si los hay) excepto los del historial fusionado. Tu puedes hacer:

git log --follow -- a

pero eso no mostrará los cambios que no sean en el historial combinado.

En otras palabras, si no cambias ZZZarchivos de en el repositorio XXXentonces necesitas especificar --follow y un camino sin prefijo. Si los cambia en ambos repositorios, entonces tiene 2 comandos, ninguno de los cuales muestra todos los cambios.

más sobre eso aquí.

  • Si tiene un directorio para fusionar en lugar de un repositorio simple o remoto, git subtree add -P name-of-desired-prefix ~/location/of/git/repo-without-.git branch-name

    – Tatsh

    22 de noviembre de 2015 a las 10:32

  • Experiencia de novato: git (versión 2.9.0.windows.1) responde “fatal: argumento ambiguo ‘HEAD’: revisión desconocida o ruta que no está en el árbol de trabajo” cuando probé esto en un repositorio local recién inicializado, no desnudo, Pero funcionó bien después de que yo De Verdad puso en marcha el nuevo repositorio, es decir, después de agregar un archivo sin formato y confirmar de la manera habitual.

    – Stein

    1 de diciembre de 2016 a las 19:49

  • Funcionó muy bien para mi escenario.

    – Johnny Utahh

    14 de junio de 2018 a las 17:39

  • Oh, esto es fantástico.

    – dwjohnston

    17 de octubre de 2019 a las 1:41

1646961799 550 ¿Como importar un repositorio Git existente a otro
Jörg W. Mittag

Hay una instancia bien conocida de esto en el propio repositorio de Git, que se conoce colectivamente en la comunidad de Git como “la fusión más genial de la historia” (después de la línea de asunto que Linus Torvalds usó en el correo electrónico a la lista de correo de Git que describe esta fusión). En este caso, el gitk Git GUI, que ahora es parte de Git propiamente dicho, en realidad solía ser un proyecto separado. Linus logró fusionar ese repositorio en el repositorio de Git de una manera que

  • aparece en el repositorio de Git como si siempre se hubiera desarrollado como parte de Git,
  • toda la historia se mantiene intacta y
  • todavía se puede desarrollar de forma independiente en su antiguo repositorio, con cambios simplemente siendo git pulledición

El correo electrónico contiene los pasos necesarios para reproducir, pero no es para los débiles de corazón: primero, Linus escribió Git, por lo que probablemente sepa un poco más que tú o yo, y segundo, esto fue hace casi 5 años y Git ha mejorado. importantemente desde entonces, así que tal vez ahora sea mucho más fácil.

En particular, supongo que hoy en día uno usaría un submódulo gitk, en ese caso específico.

1646961801 891 ¿Como importar un repositorio Git existente a otro
Damián R.

La forma más sencilla de hacerlo es usar git format-patch.

Supongamos que tenemos 2 repositorios git Foo y bar.

Foo contiene:

  • foo.txt
  • .git

bar contiene:

  • barra.txt
  • .git

y queremos terminar con Foo que contiene el bar historia y estos archivos:

  • foo.txt
  • .git
  • foobar/bar.txt

Así que para hacer eso:

 1. create a temporary directory eg PATH_YOU_WANT/patch-bar
 2. go in bar directory
 3. git format-patch --root HEAD --no-stat -o PATH_YOU_WANT/patch-bar --src-prefix=a/foobar/ --dst-prefix=b/foobar/
 4. go in foo directory
 5. git am PATH_YOU_WANT/patch-bar/*

Y si queremos reescribir todas las confirmaciones de mensajes desde la barra, podemos hacerlo, por ejemplo, en Linux:

git filter-branch --msg-filter 'sed "1s/^/\[bar\] /"' COMMIT_SHA1_OF_THE_PARENT_OF_THE_FIRST_BAR_COMMIT..HEAD

Esto agregará “[bar] ” al comienzo de cada mensaje de confirmación.

  • Si el repositorio original contenía ramas y fusiones, git am probablemente fallará.

    – Adam Monsen

    12 de septiembre de 2012 a las 14:57

  • Minor gotcha: git am tira cualquier cosa en [ ] del mensaje de confirmación. Así que deberías usar un marcador diferente al [bar]

    – HRJ

    3 de junio de 2013 a las 16:55

  • No funcionó para mí. Obtuve “error: foobar/mySubDir/test_host1: no existe en el índice. La copia del parche que falló se encuentra en: /home/myuser/src/proj/.git/rebase-apply/patch Cuando haya resuelto este problema , ejecute “git am –continue”. Esto fue después de aplicar 11 parches (de 60).

    – oligofreno

    20 de marzo de 2014 a las 12:32


  • este blog tiene una respuesta similar a una pregunta algo diferente (mover solo archivos seleccionados).

    –Jesse Glick

    11 de agosto de 2014 a las 14:11

  • Veo una desventaja, todas las confirmaciones se agregan al HEAD del repositorio de destino.

    – CSchulz

    23 de septiembre de 2014 a las 16:59

1646961802 290 ¿Como importar un repositorio Git existente a otro
Andrei Izman

Esta función clonará el repositorio remoto en el directorio del repositorio local, después de fusionar todas las confirmaciones se guardarán, git log se mostrarán las confirmaciones originales y las rutas adecuadas:

function git-add-repo
{
    repo="$1"
    dir="$(echo "$2" | sed 's/\/$//')"
    path="$(pwd)"

    tmp="$(mktemp -d)"
    remote="$(echo "$tmp" | sed 's/\///g'| sed 's/\./_/g')"

    git clone "$repo" "$tmp"
    cd "$tmp"

    git filter-branch --index-filter '
        git ls-files -s |
        sed "s,\t,&'"$dir"'/," |
        GIT_INDEX_FILE="$GIT_INDEX_FILE.new" git update-index --index-info &&
        mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"
    ' HEAD

    cd "$path"
    git remote add -f "$remote" "file://$tmp/.git"
    git pull "$remote/master"
    git merge --allow-unrelated-histories -m "Merge repo $repo into master" --edit "$remote/master"
    git remote remove "$remote"
    rm -rf "$tmp"
}

Cómo utilizar:

cd current/package
git-add-repo https://github.com/example/example dir/to/save

Si realiza pequeños cambios, incluso puede mover archivos/directorios del repositorio fusionado a diferentes rutas, por ejemplo:

repo="https://github.com/example/example"
path="$(pwd)"

tmp="$(mktemp -d)"
remote="$(echo "$tmp" | sed 's/\///g' | sed 's/\./_/g')"

git clone "$repo" "$tmp"
cd "$tmp"

GIT_ADD_STORED=""

function git-mv-store
{
    from="$(echo "$1" | sed 's/\./\\./')"
    to="$(echo "$2" | sed 's/\./\\./')"

    GIT_ADD_STORED+='s,\t'"$from"',\t'"$to"',;'
}

# NOTICE! This paths used for example! Use yours instead!
git-mv-store 'public/index.php' 'public/admin.php'
git-mv-store 'public/data' 'public/x/_data'
git-mv-store 'public/.htaccess' '.htaccess'
git-mv-store 'core/config' 'config/config'
git-mv-store 'core/defines.php' 'defines/defines.php'
git-mv-store 'README.md' 'doc/README.md'
git-mv-store '.gitignore' 'unneeded/.gitignore'

git filter-branch --index-filter '
    git ls-files -s |
    sed "'"$GIT_ADD_STORED"'" |
    GIT_INDEX_FILE="$GIT_INDEX_FILE.new" git update-index --index-info &&
    mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"
' HEAD

GIT_ADD_STORED=""

cd "$path"
git remote add -f "$remote" "file://$tmp/.git"
git pull "$remote/master"
git merge --allow-unrelated-histories -m "Merge repo $repo into master" --edit "$remote/master"
git remote remove "$remote"
rm -rf "$tmp"

Avisos

Las rutas reemplazan a través de sedasí que asegúrese de que se haya movido en las rutas adecuadas después de la fusión.
los --allow-unrelated-histories el parámetro solo existe desde git >= 2.9.

  • Si el repositorio original contenía ramas y fusiones, git am probablemente fallará.

    – Adam Monsen

    12 de septiembre de 2012 a las 14:57

  • Minor gotcha: git am tira cualquier cosa en [ ] del mensaje de confirmación. Así que deberías usar un marcador diferente al [bar]

    – HRJ

    3 de junio de 2013 a las 16:55

  • No funcionó para mí. Obtuve “error: foobar/mySubDir/test_host1: no existe en el índice. La copia del parche que falló se encuentra en: /home/myuser/src/proj/.git/rebase-apply/patch Cuando haya resuelto este problema , ejecute “git am –continue”. Esto fue después de aplicar 11 parches (de 60).

    – oligofreno

    20 de marzo de 2014 a las 12:32


  • este blog tiene una respuesta similar a una pregunta algo diferente (mover solo archivos seleccionados).

    –Jesse Glick

    11 de agosto de 2014 a las 14:11

  • Veo una desventaja, todas las confirmaciones se agregan al HEAD del repositorio de destino.

    – CSchulz

    23 de septiembre de 2014 a las 16:59

1646961803 861 ¿Como importar un repositorio Git existente a otro
x-yuri

Déjame usar nombres a (en lugar de XXX y ZZZ) y b (en lugar de YYY), ya que eso hace que la descripción sea un poco más fácil de leer.

Digamos que desea fusionar el repositorio a dentro b (Supongo que están ubicados uno al lado del otro):

cd a
git filter-repo --to-subdirectory-filter a
cd ..
cd b
git remote add a ../a
git fetch a
git merge --allow-unrelated-histories a/master
git remote remove a

Para esto necesitas git-filter-repo instalado (filter-branch es desanimado).

Un ejemplo de fusionar 2 repositorios grandes, colocando uno de ellos en un subdirectorio: https://gist.github.com/x-yuri/9890ab1079cf4357d6f269d073fd9731

más sobre eso aquí.

  • Excelente. La historia aparece en git log sin problemas, a diferencia de la solución con git subtree add -P ....

    – Martín Jambón

    12 oct 2020 a las 19:47

  • Lo único que quería el solicitante original era que XXX estuviera en una carpeta ZZZ. De ahí el comando ‘git mv stuff ZZZ/stuff’. No veo cómo su solución aborda ese requisito.

    – Jim

    5 mayo 2021 a las 20:45

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad