name - ¿Es git stash stack empujado al repositorio remoto?
git stash stack overflow (2)
Como regla general, no. Podrías empujarlo sin embargo, si quisieras.
Esto es lo que pasa con push (y, para el caso, fetch): estos funcionan basados en "refspecs", donde nombra un nombre de referencia local, o, para casos push y específicos, un ID de compromiso sin procesar, y luego también un remoto nombre de referencia.
Entonces, ¿qué diablos es un nombre de referencia?
La mayoría de las veces, nombra una referencia de rama, como master
, o una "rama remota" como origin/master
. Confusamente, lo que git llama una "sucursal remota" es en realidad una entidad local, no una sucursal en una remota, sino una sucursal en su repositorio con un nombre especial.
Una rama es realmente solo una referencia cuyo nombre comienza con refs/heads/
. Eso es realmente casi toda una rama es. (Hay otra cosa especial sobre una rama: las ramas se mueven automáticamente cuando haces nuevas confirmaciones en ellas. Es decir, si estás en tu rama master
y haces una nueva confirmación, git actualiza refs/heads/master
para apuntar a la nuevo commit.)
Una "rama remota" es solo una referencia cuyo nombre comienza con refs/remotes/
y luego contiene el nombre del remoto (generalmente de origin
). Por lo tanto, refs/remotes/origin/master
es una "rama remota": una entidad local, un nombre en su repositorio, que su git usa para hacer un seguimiento de "dónde estaba master
última vez que git registró con origin
". Cada vez que obtiene o presiona desde / hasta el origin
, 1 git actualiza sus nombres de origin/ branch
función de lo que ve "allá".
Las etiquetas son simplemente referencias que comienzan con refs/tags/
.
Normalmente, se omiten todos estos prefijos y simplemente se escribe master
para referirse a su rama maestra en refs/heads/master
, origin/master
para significar refs/remotes/origin/master
y v2.3
para significar refs/tags/v2.3
. Git se da cuenta de cuál automáticamente, ya que es obvio. Las reglas precisas se describen en gitrevisions . (Molestamente, git checkout
y git branch
no siempre siguen exactamente las reglas de gitrevisions : cuando saben que algo debe ser un nombre de rama, simplemente asumen los refs/heads/
part. Sin embargo, otros comandos de git funcionan como se describe).
El script de stash
utiliza una referencia que se deletrea simplemente refs/stash
. Así que puedes nombrar esta referencia escribiendo stash
; git encontrará que no es una rama, ni una rama remota, ni una etiqueta, y finalmente recurrirá a usar refs/stash
para resolver el nombre. 2
... lo que significa, ¿qué?
Esto significa que si escribiste:
$ git push origin stash:ssss
git encontraría tu alijo (solo el único alijo) e intentaría empujarlo a una referencia remota llamada ssss
. Esto muy probablemente fallaría; Esto es lo que pasó cuando lo probé:
error: unable to push to unqualified destination: ssss
The destination refspec neither matches an existing ref on the remote nor
begins with refs/, and we are unable to guess a prefix based on the source ref.
error: failed to push some refs to ''ssh://[redacted]/tmp/t''
Solo por diversión, probé el siguiente comando y obtuve un error diferente:
$ git push origin stash:refs/ssss
Counting objects: 8, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 485 bytes | 0 bytes/s, done.
Total 4 (delta 3), reused 0 (delta 0)
remote: error: refusing to create funny ref ''refs/ssss'' remotely
To ssh://[redacted]/tmp/t
! [remote rejected] stash -> refs/ssss (funny refname)
error: failed to push some refs to ''ssh://[redacted]/tmp/t''
Sin embargo, esto funcionó:
$ git push origin stash:refs/heads/ssss
Esta vez, creó una nueva rama en el control remoto, llamada ssss
. También trabajaría para empujar a una etiqueta remota ( refs/tags/ tagname
).
Un alijo no tiene mucho sentido, ya sea como una rama o una etiqueta, pero puede empujarlo como si fuera uno. Todo lo que sabe el control remoto, una vez que lo intente, es que está enviando algunos objetos de confirmación y sus árboles, blobs, etc. asociados, y que debe almacenar la confirmación "la mejor" bajo el nombre (completo) usted suministra 3 Esta es la razón por la que puede insertar ID de compromiso sin procesar, por ejemplo, para crear una etiqueta en el control remoto:
$ git push af7ec93:refs/tags/foo
(Suponiendo que haya un commit cuya ID comience con af7ec93
por supuesto).
Otra nota sobre el "stash stack"
La "pila" se hace usando el reflog para la referencia refs refs/stash
. Cuando escribe stash@{1}
, esto usa las mismas reglas de gitrevisions para resolver un ID de confirmación. Ya que git push
permite usar cualquier cosa que se resuelva con una ID válida, también podría enviar estos a nombres remotos. Pero probablemente no deberías; Al igual que el artículo de mayor valor escondido bajo refs/stash
, estos no tienen mucho sentido como confirmaciones regulares. (Los escondites se almacenan internamente como confirmaciones de combinación, pero su contenido está empaquetado de forma extraña, y tratar de usarlos como confirmaciones ordinarias produce resultados no tan útiles).
1 Esto es literalmente cierto en git desde 1.8.2 o así; pero las versiones más antiguas de git a veces omiten la actualización de una rama remota al git fetch
, particularmente cuando git fetch
es invocado por git pull
.
2 Si consulta gitrevisions , verá que esto tampoco es del todo exacto: encontrará el stash
como refs/stash
antes de buscar el nombre de una rama.
3 git push
usualmente construye el nombre completo automáticamente: si está presionando a su master
, que es refs/heads/master
, sabe que esto es una rama, así que git push master:newbranch
crea git push master:newbranch
refs/heads/newbranch
en el control remoto. Sin embargo, puede deletrear un nombre completo, por ejemplo, para crear una etiqueta en el control remoto. Esto también funciona para las operaciones de eliminación, cuando se presiona una referencia local vacía para eliminar una referencia remota: git push :refs/tags/delete_me
, por ejemplo.
Como ya dijo bcmcfc , mantener una gran cantidad de escondites suele ser una mala idea. Lo que hago en cambio es mantener una gran cantidad de ramas (que evito empujar a menos que realmente quiera guardarlas en algunos controles remotos); estos tienen nombres, y por lo tanto son un poco más manejables (pero solo un poco). No hay diferencia en la eficiencia, ya que los depósitos y las ramas simplemente sirven para contener los compromisos, ya sea los compromisos especiales de combinación al estilo o los compromisos comunes. Sin embargo, es posible que desee asegurarse de que su push.default
esté configurado para evitar empujar todas sus sucursales, si usa sucursales en lugar de escondites.
¿Mi pila de escondites es empujada al repositorio remoto? ¿O es completamente ignorado? Solo tengo curiosidad por si debería ocuparme de ella de vez en cuando para dejar algo de espacio para ahorrar espacio en el servidor.
No. Los alijos son locales.
$ man git stash
:
Use git stash cuando desee registrar el estado actual del directorio de trabajo y el índice, pero desea volver a un directorio de trabajo limpio. El comando guarda sus modificaciones locales y revierte el directorio de trabajo para que coincida con la confirmación HEAD.
Sin embargo, no mantendría demasiados a nivel local. Los perderás de vista con el tiempo y se volverán inútiles.