2011-04-03 17 views
10

tengo un post-script gancho recibir sentado en el repositorio remoto estoy empujando a que hace un Algo git reset --hardrestablecimiento completo en git push

así:

$ git push opal 
Counting objects: 74, done. 
Delta compression using up to 2 threads. 
Compressing objects: 100% (45/45), done. 
Writing objects: 100% (53/53), 16.68 KiB, done. 
Total 53 (delta 20), reused 0 (delta 0) 
remote: warning: updating the current branch 
remote: HEAD is now at 88f1e35 tweak lavalamp styles 

Lo que no entiendo aquí está - el control remoto dice que la cabeza ahora está en XXX pero cuando inicio sesión en el servidor - ¡la copia de trabajo remota no se actualiza en absoluto!

alguna idea?

+0

Realmente debe publicar su script de gancho cuando tenga problemas con él. –

+0

Chris, mi script posterior a la recepción solo contiene esa única línea. no es necesario publicar – David

Respuesta

0

Bueno, es probable que el script no se haya ejecutado. No se ejecutará en el servidor http tonto. Se ejecutará en ssh. No estoy seguro con el servidor http inteligente.

Si no es eso, debe verificar el permiso 'execute' en el gancho (chmod + x .git/hooks/post-receive). Mientras lo hace, generalmente verifique la titularidad y los permisos.

Si eso parece correcto, simplemente incluya una posición de registro como primera línea en el script (por ejemplo, date "%T $0 executed" >> /tmp/debug_hook.log) y verifique el archivo de registro para ver si se actualizó algo.

Además, es posible que un empuje a no realmente haga cualquier cosa (todo lo que esté actualizado). En ese caso, tiene sentido que el gancho no se llame

Si todo esto no da una pista, publique .git/config como reside en el servidor (o al menos parte de). ¿git log -1 HEAD dan el resultado esperado en el servidor? ¿Su secuencia de comandos de gancho contiene algo que puede anular GIT_DIR, GIT_WORK_TREE o GIT_INDEX_FILE?

+0

El mensaje 'HEAD is now at ...' solo es posible que provenga de 'git checkout' o' git reset'. Ninguno de los dos forma parte de un impulso normal, por lo que casi con seguridad se está ejecutando el script de enlace. –

+0

¿Hizo alguna de las otras verificaciones? Especialmente el cheque HEAD? Al leer la otra publicación, tendrías que haber obtenido un resultado positivo en el cheque 'GIT_DIR' ... – sehe

22

El problema es la diferencia en cómo se comportan los comandos de Git en el entorno creado para las secuencias de comandos hook en comparación con su entorno normal.

En primer lugar, las secuencias de comandos de anzuelo se ejecutan con su directorio de trabajo actual establecido en el directorio de Git (es decir, el directorio .git/ de un depósito no desnudo). En segundo lugar, las secuencias de comandos de anzuelo se ejecutan con la variable de entorno GIT_DIR configurada y apuntando al repositorio de Git (nuevamente, el directorio .git/ de un repositorio no desnudo).

Normalmente, si intenta ejecutar git reset --hard desde el directorio .git/, morirá con el siguiente mensaje:

fatal: This operation must be run in a work tree 

Pero cuando se establece GIT_DIR, comandos de Git asumir que el directorio actual es el directorio de trabajo. Dado que el directorio actual cuando se ejecuta el gancho es .git/, su git reset --hard realmente está "revisando" los archivos de árbol de trabajo directamente en .git/ en lugar de su directorio principal (es decir, ahora tiene una copia de su contenido versionado en su directorio .git/).

Esperemos que ninguno de los contenidos versionados en su repositorio tenga nombres de rutas que coincidan con pathnames that Git uses in Git repositories themselves. Si coinciden, entonces su git reset --hard habrá sobrescrito parte de la estructura interna de su repositorio y es probable que desee volver a clonarlo desde otro repositorio.Si está seguro de que ninguno de los contenidos conflictos con versiones con nombres de rutas internas de Git, entonces usted puede ser capaz de limpiarlo con esto:

# make a backup of your repository first! 
(cd .git && GIT_DIR=$PWD git ls-files -cz | xargs -0 rm) 

Esto sólo eliminan archivos actualmente rastreados (que dejará atrás los archivos que tienen desde que se eliminó, pero una vez se realizó un seguimiento en las confirmaciones de punta empujadas mientras el gancho roto estaba activo).


Una solución es cambiar el directorio de trabajo actual en el árbol de trabajo normal y desarmar GIT_DIR y GIT_WORK_TREE antes de llamar a los comandos de Git.

⋮ 
test "${PWD%/.git}" != "$PWD" && cd .. 
unset GIT_DIR GIT_WORK_TREE 
# you can now safely use Git commands 
⋮ 

Otra solución es reiniciar explícitamente GIT_DIR, establecer GIT_WORK_TREE y chdir allí. El FAQ de Git “Why won't I see changes in the remote repo after "git push"?” recomienda un post-update script que hace justamente esto. La secuencia de comandos vinculada también es mucho más segura ya que crea un alijo si el índice o el árbol de trabajo está sucio antes de realizar el restablecimiento completo.

+0

cosas excelentes, gracias – sehe

+1

+1 Aargh, eso es horrible. Peor aún, no me di cuenta previamente de que $ PWD y $ GIT_DIR no son consistentes para ganchos diferentes cuando se ejecutan en un repositorio no simple. (por ejemplo, en 'post-commit' están configurados en el árbol de trabajo y' .git', respectivamente.) –

+0

@Mark: Hmm, no le había prestado mucha atención a los ganchos "locales". Parece que pueden ser simplemente los ganchos "remotos" (recibir y actualizar variaciones) los que configuran este entorno problemático. Los otros ganchos están principalmente destinados a actividades que requieren un árbol de trabajo y parecen ejecutarse con una configuración sana para comandos Git que necesitan un árbol de trabajo (lo cual tiene sentido ya que tales ganchos suelen invocarse desde comandos que necesitan un árbol operativo) . –

13

En resumen, utilice el gancho de una sola línea:

git --git-dir=. --work-tree=$PWD/.. reset --hard 

Para ser más precisos, editar el archivo .git/hooks/post-receive en el servidor:

#!/bin/sh 
git --git-dir=. --work-tree=$PWD/.. reset --hard 

Conjunto ejecutable:

chmod +x .git/hooks/post-receive 

Al presionar para este repositorio del cliente, debería decir algo como:

HEAD is now at abcd123 comment 
+1

Incluso mejor que mutar el entorno y disponible en git antes de que se hiciera la pregunta. – digenishjkl

+1

debería ser la respuesta aceptada. – sjy