tag remove remote publicar practices create crear best git version-control mercurial dvcs bazaar

git - remove - ¿Hay algún sistema de control de revisión distribuido que admita la verificación/clonación parcial?



git tags best practices (7)

En rcs distribuidos, el historial de un archivo (o una parte del contenido) es un gráfico acíclico dirigido, ¿por qué no puede simplemente clonar este DAG en lugar del conjunto de todos los gráficos en un repositorio?

Al menos en Git, el DAG que representa el historial del repositorio se aplica a todo el repositorio, no a un solo archivo. Cada objeto de confirmación apunta a un objeto "árbol" que representa el estado completo del repositorio en ese momento.

Git 1.7 admite "desprotecciones dispersas" , que le permiten restringir el tamaño de su copia de trabajo. Sin embargo, todos los datos del repositorio aún están clonados.

Por lo que sé, todos los sistemas de control de revisión distribuidos requieren que clone todo el repositorio. Por esta razón, no es aconsejable colocar grandes cantidades de contenido en un solo repositorio (gracias por esta respuesta ). Sé que esto no es un error sino una característica, pero me pregunto si este es un requisito para todos los sistemas de control de revisión distribuidos.

En rcs distribuidos, el historial de un archivo (o una parte del contenido) es un gráfico acíclico dirigido, ¿por qué no puede simplemente clonar este DAG en lugar del conjunto de todos los gráficos en el repositorio? Tal vez echo de menos algo, pero los siguientes casos de uso son difíciles de hacer:

  • clonar solo una parte de un repositorio
  • fusionar dos repositorios (conservando sus historias!)
  • Copia algunos archivos con su historial de un repositorio a otro

Si reutilizo partes del código de otras personas de varios proyectos, no puedo conservar su historial completo. Al menos en git puedo pensar en una solución (bastante compleja):

  1. clonar un repositorio completo
  2. borrar todo el contenido que no me interesa
  3. reescribe el historial para eliminar todo lo que no está en el maestro
  4. fusionar el repositorio restante en un repositorio existente

No sé si esto también es posible con Mercurial o Bazaar, pero al menos no es nada fácil. Entonces, ¿hay algún rcs distribuido que admita el pago / clonación parcial por diseño? Debería ser compatible con un comando simple para obtener un solo archivo con su historial de un repositorio y fusionarlo en otro. De esta manera, no tendría que pensar en cómo estructurar su contenido en repositorios y submódulos, pero podría dividir y fusionar los repositorios según sea necesario (el extremo sería un repositorio para cada archivo).


A partir de Git 2.17 (Q2 2018, 10 años después), será posible hacer lo que Mercurial planeó implementar: un " clon estrecho ", es decir, un clon donde solo se recuperan datos para un subdirectorio específico.
Esto también se llama "clon parcial".

Eso difiere de la corriente.

  • clon superficial
  • copia de lo que necesita del repositorio clonado en otra carpeta de trabajo.

Consulte commit 3aa6694 , commit aa57b87 , commit 35a7ae9 , commit 1e1e39b , commit acb0c57 , commit bc2d0c3 , commit 640d8b7 , commit 10ac85c (08 Dec 2017) por Jeff Hostetler ( jeffhostetler ) .
Consulte commit a1c6d7c , commit c0c578b , commit 548719f , commit a174334 , commit 0b6069f (08 de diciembre de 2017) por Jonathan Tan ( jhowtan ) .
(Combinado por Junio ​​C Hamano - gitster - in commit 6bed209 , 13 de febrero de 2018)

Aquí están las pruebas para un clon parcial :

git clone --no-checkout --filter=blob:none "file://$(pwd)/srv.bare" pc1

Hay otros compromisos comprometidos en esa implementación de un clon estrecho / parcial .

En particular, cometer 8b4c010 :

sha1_file: soporta perezosamente la búsqueda de objetos perdidos

Enseñe a sha1_file a obtener objetos desde el control remoto configurado en extensions.partialclone cuando se solicite un objeto pero falte.

Advertencia sobre Git 2.17 / 2.18: La adición reciente de la función experimental "clon parcial" se activó cuando no debería, es decir, cuando no hay un filtro de clonación parcial definido incluso si se establece extensions.partialclone .

Ver commit cac1137 (11 de junio de 2018) por Jonathan Tan ( jhowtan ) .
(Fusionado por Junio ​​C Hamano - gitster - in commit 92e1bbc , 28 de junio de 2018)

upload-pack : deshabilita el filtrado de objetos cuando está deshabilitado por config

Cuando upload-pack obtuvo un soporte de clonación parcial (v2.17.0-rc0 ~ 132 ^ 2 ~ 12, 2017-12-08), fue protegido por el uploadpack.allowFilter configuración uploadpack.allowFilter para permitir a los operadores del servidor controlar cuándo comienzan a uploadpack.allowFilter .

Sin embargo, ese elemento de configuración no fue lo suficientemente lejos: controla si se anuncia la capacidad de '' filter '', pero si un cliente (personalizado) ignora el anuncio de capacidad y pasa una especificación de filtro de todos modos, el servidor manejará eso a pesar de que allowFilter sea falso .

Esto es particularmente importante si se descubre un error de seguridad en este nuevo código de clonación parcial experimental.
Las instalaciones sin uploadpack.allowFilter no deberían verse afectadas, ya que no tienen la intención de admitir la clonación parcial, pero se convertirían en vulnerables.

Esto se ha mejorado con Git 2.20 (Q2 2018), ya que " git fetch $repo $object " en un clon parcial no recuperó correctamente el objeto solicitado al que hace referencia un objeto en el archivo de paquete de promisor, que se ha corregido.

Ver commit 35f9e3e , commit 4937291 (21 de septiembre de 2018) por Jonathan Tan ( jhowtan ) .
(Fusionada por Junio ​​C Hamano - gitster - in commit a1e9dff , 19 de octubre de 2018)

fetch : en clon parcial, verificar la presencia de objetivos

Cuando se recupera un objeto que se conoce como un objeto de promisor al repositorio local, la verificación de conectividad en quickfetch() en builtin/fetch.c tiene éxito, lo que hace que la transferencia de objetos se omita.
Sin embargo, esto no debería ocurrir si ese objeto es meramente prometido y no está realmente presente.

Debido a que esto sucede, cuando un usuario invoca " git fetch origin <sha-1> " en la línea de comandos, es posible que el objeto <sha-1> no se recupere a pesar de que el comando devuelve un código de salida de 0. Esto es un problema similar (pero con una causa diferente) al corregido por a0c9016 ("cargar paquete: enviar objetos de refs a pesar de" filtro "", 2018-07-09, Git v2.19.0-rc0).

Por lo tanto, actualice quickfetch() para verificar directamente la presencia de todos los objetos que se van a buscar.

Puede enumerar objetos de un clon parcial, excluyendo objetos "promisor", con git rev-list --exclude-promisor-objects

(Solo para uso interno). Recorrido del objeto del prefiltro en el límite del promisor.
Esto se utiliza con clon parcial .
Esto es más fuerte que --missing=allow-promisor porque limita el recorrido, en lugar de solo silenciar los errores sobre objetos perdidos.

Pero asegúrese de usar Git 2.21 (Q1 2019) para evitar la falta de seguridad.

Ver commit 4cf6786 (05 de diciembre de 2018) por Matthew DeVore ( matvore ) .
(Fusionada por Junio ​​C Hamano - gitster - in commit c333fe7 , 14 de enero de 2019)

" git rev-list --exclude-promisor-objects " tuvo que tomar un objeto que no existe localmente (y está disponible de forma perezosa) desde la línea de comando sin barfing, pero el código no está referenciado como NULL.

list-objects.c : no segfault para objetos cmdline faltantes

Cuando se invoca un comando con los --exclude-promisor-objects , --objects-edge-aggressive , y un objeto faltante en la línea de comandos, la matriz rev_info.cmdline podría obtener un puntero NULO para el valor de un '' item '' campo.
Prevenga la desreferenciación de un puntero NULL en esa situación.

Tenga en cuenta que Git 2.21 (Q1 2019) corrige un error:

Ver commit bbcde41 (03 de diciembre de 2018) por Matthew DeVore ( matvore ) .
(Combinado por Junio ​​C Hamano - gitster - in commit 6e5be1f , 14 de enero de 2019)

exclude-promisor-objects : declara cuándo se permite la opción

La --exclude-promisor-objects provoca algunos comportamientos divertidos en al menos dos comandos: log y blame .
Causa un error de error:

$ git log --exclude-promisor-objects BUG: revision.c:2143: exclude_promisor_objects can only be used when fetch_if_missing is 0 Aborted [134]

Solucione esto de modo que la opción se trate como cualquier otra opción desconocida.
Los comandos que deben admitirlo son limitados, por lo tanto, declare en esos comandos que la bandera es compatible.
En particular:

pack-objects prune rev-list

Los comandos se encontraron al buscar la lógica que analiza --exclude-promisor-objects fuera de revision.c .
Se necesita lógica adicional fuera de revision.c porque fetch_if_missing debe estar activado antes de que revision.c vea la opción o BUG-crash. La lista anterior es compatible con el hecho de que ningún otro comando es invocado introspectivamente por otro comando que pasa --exclude-promisor-object .

Git 2.22 (Q2 2019) optimiza el clon estrecho:
Mientras ejecutamos " git diff " en un clon vago, podemos saber de antemano qué blobs faltantes necesitaremos, en lugar de esperar a que la maquinaria a pedido los descubra uno por uno.
Trate de lograr un mejor rendimiento agrupando la solicitud de estos blobs prometidos.

Consulte commit 7fbbcb2 (05 de abril de 2019) y commit 0f4a4fb (29 de marzo de 2019) por Jonathan Tan ( jhowtan ) .
(Fusionada por Junio ​​C Hamano - gitster - in commit 32dc15d , 25 de abril de 2019)

diff : captura por lotes de manchas faltantes

Cuando ejecute un comando como " git show " o " git diff " en un clon parcial, tache todos los blobs que faltan para que sean recuperados como una sola solicitud.

Esto es similar a c0c578b (" unpack-trees : obtener lotes de blobs faltantes", 2017-12-08, Git v2.17.0-rc0), pero para otro comando.


A partir de la versión 2.0, no es posible hacer un llamado "clon estrecho" con Mercurial, es decir, un clon donde solo se recuperan datos para un subdirectorio específico. Lo llamamos "clon superficial" cuando solo recuperas parte del historial, por ejemplo, las últimas 100 revisiones.

Como usted dice, no hay nada en el modelo de historial común basado en DAG que excluya esta función y hemos estado trabajando en ello. Peter Arrenbrecht, un colaborador de Mercurial, ha implementado dos enfoques diferentes para clones estrechos, pero ninguno se ha fusionado aún.

Por cierto, puede, por supuesto, dividir un repositorio de Mercurial existente en partes donde cada repositorio más pequeño solo tenga el historial de un subdirectorio específico del repositorio original. La extensión de conversión es la herramienta para esto. Sin embargo, cada uno de los repositorios más pequeños no estará relacionado con el repositorio más grande: la parte difícil es hacer que la división sea perfecta para que los conjuntos de cambios mantengan sus identidades.


De git help clone :

--depth <depth> Create a shallow clone with a history truncated to the specified number of revisions. A shallow repository has a number of limitations (you cannot clone or fetch from it, nor push from nor into it), but is adequate if you are only interested in the recent history of a large project with a long history, and would want to send in fixes as patches.

¿Eso proporciona algo como lo que estás buscando?


En bazar puede dividir y unir partes de un repositorio.

El comando dividir le permite dividir un repositorio en múltiples repositorios. El comando de combinación le permite combinar repositorios. Ambos mantienen la historia.

Sin embargo, esto no es tan práctico como el modelo SVN, donde puede retirar / confirmar un subárbol.

Hay una característica planificada llamada Nested-Trees para bazar, que tal vez permitiría verificaciones parciales.


Espero que uno de estos RCS agregue capacidad de clon estrecho. Tengo entendido que la arquitectura de GIT (cambios / movimientos rastreados en todo el repositorio) hace que esto sea muy difícil.

Bazaar se enorgullece de admitir muchos tipos diferentes de flujos de trabajo. La falta de capacidad de clonación restringida prohíbe un flujo de trabajo de tipo SVN / CVS en bzr / hg / git, así que espero que estén motivados para encontrar alguna manera de hacer esto.

Las nuevas características no deberían venir a expensas de la funcionalidad básica, como la capacidad de recuperar un solo archivo / directorio del repositorio. La característica "distribuida" de los rcs modernos es "genial", pero en mi opinión, desalienta las buenas prácticas de desarrollo (fusiones frecuentes / integración continua). Todos estos nuevos RCS parecen carecer de una funcionalidad muy básica. Incluso SVN sin soporte real de ramificación / etiquetado parecía un paso atrás de CVS imo.