Digamos que tengo una configuración que se parece a
phd/code/
phd/figures/
phd/thesis/
Por razones históricas, todos estos tienen sus propios repositorios git. Pero me gustaría combinarlos en uno solo para simplificar un poco las cosas. Por ejemplo, en este momento podría hacer dos conjuntos de cambios y tener que hacer algo como
cd phd/code
git commit
cd ../figures
git commit
Sería (ahora) bueno solo realizar
cd phd
git commit
Parece que hay un par de formas de hacer esto usando submódulos o sacando de mis sub-repositorios, pero eso es un poco más complejo de lo que estoy buscando. Por lo menos, sería feliz con
cd phd
git init
git add [[everything that's already in my other repositories]]
Pero eso no parece una frase. ¿Hay algo en git
eso que pueda ayudarme?
Respuestas:
Aquí hay una solución que di aquí :
Primero haga una copia de seguridad completa de su directorio de doctorado: ¡no quiero ser responsable de sus años perdidos de trabajo duro! ;-)
Mueva el contenido de
phd/code
aphd/code/code
y corrija el historial para que parezca que siempre ha estado allí (esto usa el comando filter-branch de git ):Lo mismo para el contenido de
phd/figures
yphd/thesis
(solo reemplacecode
configures
ythesis
).Ahora su estructura de directorio debería verse así:
Luego cree un repositorio git en el directorio raíz, extraiga todo y elimine los repositorios antiguos:
Finalmente, ahora deberías tener lo que querías:
Un lado bueno de este procedimiento es que dejará en su lugar archivos y directorios no versionados .
Espero que esto ayude.
Sin embargo, solo una palabra de advertencia: si su
code
directorio ya tiene uncode
subdirectorio o archivo, las cosas podrían salir muy mal (lo mismo parafigures
ythesis
por supuesto). Si ese es el caso, simplemente cambie el nombre de ese directorio o archivo antes de realizar todo este procedimiento:Y cuando finalice el procedimiento, agregue este paso final:
Por supuesto, si el
code
subdirectorio o el archivo no está versionado, simplemente use enmv
lugar degit mv
y olvide elgit commit
s.fuente
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
y luego funcionó muy bien!fuente
Quizás, simplemente (de manera similar a la respuesta anterior, pero usando comandos más simples), haga en cada uno de los repositorios antiguos separados una confirmación que mueva el contenido a un subdirectorio adecuadamente nombrado, por ejemplo:
y luego fusionando los tres repositorios separados en uno nuevo, haciendo algo como:
Luego guardará sus historias, pero continuará con un solo repositorio.
fuente
Puede probar la estrategia de combinación de subárbol . Te permitirá combinar el repositorio B en el repositorio A. La ventaja
git-filter-branch
es que no requiere que reescribas tu historial de repositorio A (rompiendo sumas de SHA1).fuente
La solución git-filter-branch funciona bien, pero tenga en cuenta que si su repositorio git proviene de una importación SVN, puede fallar con un mensaje como:
En este caso, debe excluir la revisión inicial de la rama de filtro, es decir, cambiarla
HEAD
al final para[SHA of 2nd revision]..HEAD
ver:http://www.git.code-experiments.com/blog/2010/03/merging-git-repositories.html
fuente
La solución @MiniQuark me ayudó mucho, pero desafortunadamente no tiene en cuenta las etiquetas que están en los repositorios de origen (al menos en mi caso). A continuación se muestra mi mejora en la respuesta @MiniQuark.
Primero cree un directorio que contendrá repositorios compuestos y repositorios combinados, cree un directorio para cada uno combinado.
Haga una extracción de cada repositorio y obtenga todas las etiquetas. (Presentación de instrucciones solo para el
code
subdirectorio)(Esta es una mejora al punto 2 en respuesta MiniQuark) Mover el contenido de
new_phd/code
anew_phd/code/code
y añadircode_
prefeix antes de cada etiquetaDespués de hacerlo, habrá el doble de etiquetas que antes de hacer filter-branch. Las etiquetas antiguas permanecen en repositorio y
code_
se agregan nuevas etiquetas con prefijo.Eliminar etiquetas viejas manualmente:
Repita el punto 2,3,4 para otros subdirectorios.
Ahora tenemos una estructura de directorios como en @MiniQuark y el punto 3.
Haga lo mismo que en el punto 4 de MiniQuark anwser, pero después de hacer un tirón y antes de eliminar el
.git
directorio, obtenga etiquetas:Seguir..
Esta es solo otra solución. Espero que ayude a alguien, me ayudó :)
fuente
La respuesta de git-stitch-repo de Aristóteles Pagaltzis solo funciona para repositorios con una historia lineal simple.
La respuesta de MiniQuark funciona para todos los repositorios, pero no maneja etiquetas y ramas.
Creé un programa que funciona de la misma manera que MiniQuark describe, pero utiliza una confirmación de fusión (con N padres) y también recrea todas las etiquetas y ramas para señalar estas confirmaciones de fusión.
Consulte el repositorio git-merge-repos para ver ejemplos de cómo usarlo.
fuente
He creado una herramienta que hace esta tarea. El método utilizado es similar (internamente crea algunas cosas como --filter-branch) pero es más amigable. Es GPL 2.0
http://github.com/geppo12/GitCombineRepo
fuente
En realidad, git-stitch-repo ahora admite ramas y etiquetas, incluidas las etiquetas anotadas (descubrí que había un error que informé, y se solucionó). Lo que encontré útil es con etiquetas. Dado que las etiquetas se adjuntan a los commits, y algunas de las soluciones (como el enfoque de Eric Lee) no logran manejar las etiquetas. Intenta crear una rama a partir de una etiqueta importada, y deshacerá cualquier combinación / movimiento de git y lo enviará de vuelta como si el repositorio consolidado fuera casi idéntico al repositorio del que proviene la etiqueta. Además, hay problemas si usa la misma etiqueta en múltiples repositorios que 'fusionó / consolidó'. Por ejemplo, si tiene los repositorios A y B, ambos tienen la etiqueta rel_1.0. Combina el repositorio A y el repositorio B en el repositorio AB. Como las etiquetas rel_1.0 están en dos confirmaciones diferentes (una para A y otra para B), ¿Qué etiqueta será visible en AB? La etiqueta del repositorio A importado o del repositorio B importado, pero no ambos.
git-stitch-repo ayuda a resolver ese problema creando etiquetas rel_1.0-A y rel_1.0-B. Es posible que no pueda pagar la etiqueta rel_1.0 y esperar ambas, pero al menos puede ver ambas, y en teoría, puede fusionarlas en una rama local común y luego crear una etiqueta rel_1.0 en esa rama fusionada (suponiendo que solo fusionar y no cambiar el código fuente). Es mejor trabajar con sucursales, ya que puede combinar ramas similares de cada repositorio en sucursales locales. (dev-a y dev-b se pueden fusionar en una rama de desarrollo local que luego se puede enviar al origen).
fuente
La secuencia que sugeriste
funcionará, pero perderá su historial de confirmaciones.
fuente
Para fusionar un segundo proyecto dentro de un proyecto principal:
A) En el segundo proyecto
B) En el proyecto principal:
En esta rama, realice todas las transformaciones pesadas que necesita hacer y comprométalas.
C) Luego de vuelta al maestro y una fusión clásica entre las dos ramas:
fuente
Lanzaré mi solución aquí también. Básicamente es un envoltorio de script bash bastante simple
git filter-branch
. Al igual que otras soluciones, solo migra ramas maestras y no migra etiquetas. Sin embargo, los historiales completos de confirmación maestra se migran y es una secuencia de comandos bash corta, por lo que debería ser relativamente fácil de revisar o modificar para los usuarios.https://github.com/Oakleon/git-join-repos
fuente
Este script bash soluciona el problema de caracteres de tabulación sed (en MacOS, por ejemplo) y el problema de los archivos faltantes.
Esta es una combinación de publicaciones de miniquark , marius-butuc y ryan . Saludos a ellos!
fuente