¿Cómo clonar superficialmente un compromiso específico con profundidad 1?

83

¿Es posible clonar superficialmente una confirmación específica en un repositorio, es decir, con profundidad 1? Algo como

git clone http://myrepo.git 728a4d --depth 1

para obtener el estado del repositorio como está en el compromiso con SHA 728a4d...?

La motivación es evitar tener que clonar todo el repositorio y luego ver esa confirmación específica, cuando solo estamos interesados ​​en el estado del repositorio en esa confirmación específica.

Barbilla
fuente
Posible duplicado de ¿Cómo clonar el repositorio de git con una revisión / conjunto de cambios específicos?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Respuestas:

81

Comenzando con Git 2.5.0 (que debe estar disponible tanto en el lado del cliente como en el del servidor), puede configurar uploadpack.allowReachableSHA1InWant=trueen el lado del servidor para habilitar la obtención de SHA1 específicos:

git init
git remote add origin <url>
git fetch --depth 1 origin <sha1>
git checkout FETCH_HEAD

Tenga en cuenta que no encontré una sintaxis para hacer esto git clonedirectamente.

sschuberth
fuente
3
No funciona con github al menos. No pude buscar para github.com/Seldaek/monolog/commit/… . git fetch --depth 1 origin d6be96bc...espectáculosfatal: Couldn't find remote ref d6be96bc...
Kirby
9
Correcto, GitHub solo ha habilitado allowTipSHA1InWant, pero ni allowReachableSHA1InWanttampoco allowAnySHA1InWant.
sschuberth
Recibí un error que decíaerror: pathspec 'FETCH_HEAD' did not match any file(s) known to git
rocketspacer
2
Jugando con esto, descubrí que solo funcionaba en una versión muy moderna del cliente git. Incluso git 2.17 no funcionó para mí. Reconstruí git en 2.24 y funcionó.
Eyal
1
Funcionó para mí con 2.27.0.windows.1 en github.com/dotnet/aspnetcore @ 62c098bc170f50feca15916e81cb7f321ffc52ff
JJS
25

NOTA: Mi ejemplo no ayuda a clonar mediante un hash de confirmación, pero ayudará a clonar una etiqueta y tener un repositorio ligero.

Si solo tiene que tener una confirmación en su "clon" y va a utilizar el hash de confirmación, la respuesta corta es NO .

Utilizo esta construcción de comandos (probada en v2.13.2.windows.1 ) para etiquetas:

git clone --depth 1 [email protected]:VENDOR/REPO.git --branch 1.23.0 --single-branch

Ejemplo completo:

$ git clone --depth 1 [email protected]:Seldaek/monolog.git --branch 1.23.0 --single-branch
Cloning into 'monolog'...
remote: Counting objects: 201, done.
remote: Compressing objects: 100% (188/188), done.
remote: Total 201 (delta 42), reused 32 (delta 5), pack-reused 0
Receiving objects: 100% (201/201), 190.30 KiB | 0 bytes/s, done.
Resolving deltas: 100% (42/42), done.
Note: checking out 'fd8c787753b3a2ad11bc60c063cff1358a32a3b4'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

$ cd monolog

.gittamaño de directorio ( 267K vs 2.6M usando full clone):

$ du -h --max-depth=0 .git
267K    .git

Me gustaría denotar, --branchpuede tomar una etiqueta / rama.

https://git-scm.com/docs/git-clone#git-clone---branchltnamegt

--branch también puede tomar etiquetas y separar HEAD en esa confirmación en el repositorio resultante.

UPD

En pocas palabras, puede tomar "referencias". Puede leer más aquí: ¿Qué significa el mensaje de error de git "El servidor no permite la solicitud de un objeto no anunciado"?

Además, no hay trucos como:

git fetch --depth 1 origin <COMMIT_HASH>

Gracias @BenjiWiebe por señalarme mi error.

Kirby
fuente
2
Un millón de votos a favor por esto. Demasiadas personas afirman que esto no es posible.
bromas
3
--branchno no apoyar las confirmaciones, sólo los nombres de rama ... esto no resuelve en absoluto. Como no es cierto.
Abourget
1
Kirby Estoy intentando hacer esto ahora, y no funciona para confirmaciones , como dice @abourget. Quizás funcione para etiquetas y ramas, pero estoy tratando de hacerlo con hash de confirmación y eso no funciona.
BenjiWiebe
@BenjiWiebe, tengo su punto, chicos. Sí, parece que GIT no puede determinar un compromiso específico. : - / Lo profundizaré más.
Kirby
@BenjiWiebe, entonces, desafortunadamente no hay forma de usar el hash de confirmación. Solo comprobado dos veces.
Kirby
6

La respuesta inmediata es: no puedes.
¿Por qué? La explicación detallada se puede encontrar aquí: ¿Por qué no hay una opción de confirmación específica para clones de Git?

¿Qué más puedes hacer?

¿Cómo clonar el repositorio a una confirmación específica? (clon completo)

# Create empty repository to store your content
git clone <url>
git reset <sha-1> --hard

Más información:

¿Cómo clonar una sola rama?

git clone <url> --branch <branch_name> --single-branch <folder_name>

¿Cómo clonar solo la última confirmación de una rama determinada?

git clone <url> --depth=1 --branch <branch_name> --single-branch <folder_name>

¿Cómo clonar superficialmente un compromiso específico con profundidad 1?

Como comentó @sschuberth: --depthimplica --single-branch.

En lugar de clonar, use el comando fetch:

# fetch a commit (or branch or tag) of interest
# In this case you will have the full history of this commit
git fetch origin <sha1>
CodeWizard
fuente
5
Esto no responde a la pregunta. El interrogador quiere saber cómo verificar una única confirmación incluso si no hay una referencia que apunte directamente a ella.
Joseph K. Strauss
Lo siento, me lo perdí, de alguna manera entendí que necesitaba la última confirmación. Actualizando la respuesta. Gracias
CodeWizard
--depthimplica --single-branch, por lo que podría eliminarlo en ese caso.
sschuberth
¿ git fetchRealmente acepta un SHA1 para refspec?
Phil Frost
nop. es simplemente "descargar" los datos que coinciden con el nombre de la sucursal
CodeWizard
5

Intente usar whileen bash:

git clone --depth=1 $url
i=1; while ! git show $sha1; do git fetch --depth=$((i+=1)); done

Esto es bastante lento porque recupera cada confirmación individualmente; podría aumentar el incremento (para obtener confirmaciones en lotes y mejorar el rendimiento en una red) pero sigue siendo un enfoque de fuerza bruta.

Corin
fuente
¿Por qué los votos negativos? ... ¡De hecho necesitaba hacer esto y mi solución lo hizo!
Corin
¿Qué pasa si quieres un compromiso hecho hace años o que ya no existe?
Daan Bakker
@DaanBakker, si la confirmación ya no existe, entonces la única forma de determinar esto es buscar todo el repositorio remoto y si no está allí y no hay otros clones, desafortunadamente se encuentra en un callejón sin salida.
Corin