Usted podría tratar de usar el archivo de injerto (.git/info/grafts
) donde se puede sobrescribir la paternidad de una confirmación (como el primero de projectB
tener para los padres el último de projectA
)
Véase también "What are .git/info/grafts for?" y "How to prepend the past to a git repository?" para más sobre esta manipulación.
skaleecomments sobre el artículo "Git: Grafting repositories" (de SO usuario Ben Straub) para un ejemplo concreto.
Ahora lo que queremos hacer es cambiar el primer commit en el “nuevo
” repo (“New commit #1
”) de modo que su padre es la última confirmación en el “viejo” de recompra (“viejo # 3”). ¡Un poco de vudú:
git fetch ../old master:ancient_history
Git permite hacer salir de cualquier otro repositorio git, si esta cesión temporal se relaciona con ella o no! ¡Brillante! Esto nos deja con esto:
Nota cómo cambiamos el nombre de la antigua rama principal a ancient_history. Si no lo hubiéramos hecho, Git habría intentado fusionar los dos, y probablemente habría renunciado con disgusto.
Ahora todavía tenemos un problema.
Los dos árboles no están conectados, y de hecho, un git pull ni siquiera obtendrá la rama ancient_history. Necesitamos una forma de hacer una conexión entre los dos.
Git tiene una función llamada injerto, que básicamente simula un enlace primario entre dos confirmaciones.
para hacer uno, basta con insertar una línea en el archivo .git/info/grafts
en este formato:
[ref] [parent]
Ambos tienen que ser el hash completo de las confirmaciones de que se trate. Así que vamos a encontrar ellos:
$ git rev-list master | tail -n 1
d7737bffdad86dc05bbade271a9c16f8f912d3c6
$ git rev-parse ancient_history
463d0401a3f34bd381c456c6166e514564289ab2
$ echo d7737bffdad86dc05bbade271a9c16f8f912d3c6 \
463d0401a3f34bd381c456c6166e514564289ab2 \
> .git/info/grafts
(en una línea, como suggested por ssokolow)
echo $(git rev-list master | tail -n 1) $(git rev-parse ancient_history) > .git/info/grafts
Hay.Ahora nuestra historia se parece a esto:
clonar esta reporto resultados en esta:
Woops. Resulta que los injertos solo tienen efecto para el repositorio local. Podemos solucionar este problema con la aplicación juiciosa de git fast-import
:
$ git fast-export --all > ../export
$ mkdir ../nuevo-complete
$ cd ../nuevo-complete
$ git init
$ git fast-import < ../export
git-fast-import statistics: [...]
(en una línea, como suggested por ssokolow)
git filter-branch $(git rev-parse ancient_history)..HEAD
Esto convierte efectivamente nuestro enlace de “falsa” la historia en Están solos.
Todos los ingenieros tendrán que volver a clonar desde este nuevo repositorio, ya que los hashes serán todos diferentes, pero ese es un pequeño precio a pagar por el tiempo de inactividad y un historial completo.
Como Qix comentarios below:
fast-import
parece que acaba de importar la información de git, pero no comprueba nada.
git init
originalmente lo pone en maestro, por lo que necesita un git reset --hard HEAD
para realmente verificar los archivos después de fast-import
.
Funcionó muy bien para mí, gracias VonC, no pensé que sería así de simple. – SilentGhost
Luego puede reescribir el historial usando 'git filter-branch' para hacer que el injerto sea permanente ... pero esto reescribe el historial. –
Artículo corto y prolijo que realmente me ayudó a entender qué son los injertos y paso a paso cómo unir esas historias: http://ben.straubnet.net/post/939181602/git-grafting-repositories – skalee