resettare duro su Git Push

Ho uno script di hook post-ricezione seduto sul repository remoto che sto spingendo a fare un git reset --hard

Qualcosa come questo:

 $ 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 

Quello che non capisco qui è – il telecomando dice che la testa è ora in XXX, ma quando accedo al server – la copia di lavoro remota non viene affatto aggiornata!

qualche idea?

    Il problema è una differenza nel modo in cui i comandi Git si comportano nell’ambiente creato per gli script di hook rispetto al tuo ambiente normale.

    Innanzitutto, gli script hook vengono eseguiti con la loro directory di lavoro corrente impostata sulla directory Git stessa (ovvero la directory .git/ di un repository non nudo). In secondo luogo, gli script di hook vengono eseguiti con la variabile di ambiente GIT_DIR impostata e puntano al repository Git (di nuovo, la directory .git/ di un repository non nudo).

    Normalmente, se provate a eseguire git reset --hard dalla directory .git/ , morirà con il seguente messaggio:

     fatal: This operation must be run in a work tree 

    Ma quando GIT_DIR è impostato, i comandi Git presuppongono che la directory corrente sia l’albero di lavoro. Poiché la directory corrente quando si esegue l’hook è la directory .git/ , il tuo git reset --hard realtà “controlla” i tuoi file dell’albero di lavoro direttamente in .git/ invece della sua directory madre (cioè ora hai una copia del tuo contenuto con versione nella tua directory .git/ ).

    Speriamo che nessuno dei contenuti con versione nel tuo repository abbia nomi di percorso che coincidano con i nomi di percorso che Git usa negli stessi repository Git . Se coincidono, allora il tuo git reset --hard avrà sovrascritto un po ‘della struttura interna del tuo repository e probabilmente vorrai ricrearlo da qualche altro repository. Se sei sicuro che nessuno dei contenuti in versione è in conflitto con i percorsi interni di Git, allora potresti essere in grado di ripulirlo con questo:

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

    Questo rimuoverà solo i file attualmente tracciati (lascerà dietro di sé file che sono stati rimossi da allora, ma che una volta sono stati rintracciati nelle puntate commesse mentre il hook rotto era attivo).


    Una soluzione è quella di cambiare la directory di lavoro corrente nella normale struttura di lavoro e disinserire GIT_DIR e GIT_WORK_TREE prima di chiamare i comandi Git.

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

    Un’altra soluzione è ripristinare esplicitamente GIT_DIR, impostare GIT_WORK_TREE e chdir lì. The Git FAQ “Perché non vedrò cambiamenti nel repository remoto dopo” git push “?” Raccomanda uno script post-aggiornamento che fa proprio questo. Lo script collegato è anche molto più sicuro poiché crea una scorta se l’indice o l’albero di lavoro sono sporchi prima di eseguire il ripristino completo.

    In breve, usa l’hook one-liner:

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

    Per essere più precisi, modifica il file .git/hooks/post-receive sul server:

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

    Impostalo eseguibile:

     chmod +x .git/hooks/post-receive 

    Quando si spinge a questo repo dal client, dovrebbe dire qualcosa del tipo:

     HEAD is now at abcd123 comment 

    Beh, probabilmente lo script non è in esecuzione. Non funzionerà su server http stupido. Funzionerà su ssh. Non sono sicuro con il server http intelligente.

    Se non è così, dovresti controllare la permisssione ‘esegui’ sul hook (chmod + x .git / hooks / post-receive). Mentre ci sei, in genere controlla il condominio e le autorizzazioni.

    Se ciò sembra ok, includi semplicemente un logstatement come prima riga nello script (es. date "%T $0 executed" >> /tmp/debug_hook.log ) e controlla il file di log per vedere se qualcosa è stato aggiornato.

    Inoltre, è ansible che una spinta non faccia effettivamente nulla (tutto aggiornato). In tal caso, ha senso che l’hook non venga chiamato

    Se tutto questo non fornisce un suggerimento, per favore pubblica .git / config come risiede sul server (o almeno in parte). git log -1 HEAD fornisce il risultato previsto sul server? Il tuo script di hook contiene qualcosa che potrebbe ignorare GIT_DIR, GIT_WORK_TREE o GIT_INDEX_FILE?