Git Post-Receive-Hook für Website-Staging

Lesezeit: 10 Minuten

Git Post Receive Hook fur Website Staging
Matt

Ich versuche, Git zum Staging meiner Website einzurichten, damit ich das kann git pull um die aktuelle Version lokal zum Laufen zu bringen und dann git push um die Änderungen auf den Remote-Server zu übertragen. Ich habe es so eingerichtet, dass es so funktioniert, wie ich es möchte, aber nachdem ich es gedrückt habe, muss ich es manuell ausführen git checkout -f oder git reset --hard HEAD auf dem Remote-Server.

Ich habe versucht, diese in ein Shell-Skript als Post-Receive-Hook auf dem Server einzufügen, aber es scheint einfach keine Wirkung zu haben. Ich weiß, dass das Skript ausgeführt wird, weil ich nach dem Push “Änderungen auf den Server übertragen” sehe. Hier ist der Post-Receive-Hook:

#!/bin/sh
git reset --hard HEAD
echo "Changes pushed to server."

  • @VonC: Der wichtigste Teil Ihrer Antwort wurde größtenteils geschrieben bash Sprache, während der Downvoter wahrscheinlich seine Muttersprache behauptete;)

    – nimmthin

    1. Oktober 2010 um 13:15 Uhr

Git Post Receive Hook fur Website Staging
Paul

Die Antwort auf deine Frage ist hier: http://toroid.org/ams/git-website-howto

Kurz gesagt, Sie möchten dem Bare-Repository einen “separaten Arbeitsbaum” hinzufügen. Normalerweise stellen Sie sich vor, dass Ihr Arbeitsbaum die enthält .git Verzeichnis. Bare-Repositorys haben per Definition keinen Arbeitsbaum, aber Sie können einen erstellen, solange er sich in einem anderen Verzeichnis als das Bare-Repository befindet.

Der Post-Receive-Hook ist nur ein einfacher git checkout -f um die des Repositorys zu replizieren HEAD ins Arbeitsverzeichnis. Apache verwendet dies als Dokumentstammverzeichnis, und Sie sind fertig. Jedes Mal, wenn Sie in das Bare-Repository pushen, beginnt Apache sofort damit, es bereitzustellen.

Ich verwende dies im Allgemeinen, um automatisch auf einen Staging-Server zu pushen, um zu sehen, ob die “echte” Umgebung auf meine Änderungen kotzt. Die Bereitstellung auf dem Live-Server ist eine ganz andere Geschichte. 🙂

  • Danke, ich bin immer noch neu bei Git und als ich mit diesem Projekt anfing, war ich mir nicht sicher, warum es ein reines Repository geben sollte, wenn ich in das Dokumentenstammverzeichnis wechseln und einfach git init starten könnte. Ich denke, ich verstehe jetzt, dass es nur die Git-Metadaten aus dem Dokumentenstamm heraushält. Ist das korrekt?

    – Matt

    1. Oktober 2010 um 14:30 Uhr

  • Außerdem zeigt das Beispiel im obigen Link, wie Sie von Grund auf neu beginnen und von einem lokalen Repository auf den Server übertragen. Was ist die beste Methode, um ein leeres Repository (außerhalb des Stammverzeichnisses des Webdokuments) von dem zu erhalten, das sich derzeit darin befindet?

    – Matt

    1. Oktober 2010 um 14:35 Uhr

  • Matt, ein Bare-Repository wird im Allgemeinen auf Ihrem zentralen Server verwendet. Wenn Sie nur eine Kopie des Repositorys haben und direkt von dort aus bereitstellen, werden Sie schnell auf Probleme stoßen. Erstellen Sie ein Bare-Repository in einem anderen Verzeichnis mit git init --bare. Dann in Ihrem lokalen Klon des Repositorys tun git origin add path_to_central_repo um das neue zentrale Repo als Original zu markieren. Endlich, git push origin master wird alles, was Sie getan haben, an den Meister weitergeben. Erstellen Sie einen getrennten Arbeitsbaum aus dem zentralen Repo und Sie werden Ihre Site mit jedem inszenieren push von deinem Klon.

    – Paulus

    4. Oktober 2010 um 14:29 Uhr

  • +1 … Diese Lösung scheint die intelligenteste zu sein, die ich bisher gefunden habe … Sie ermöglicht es, nicht nur Änderungen mit wenigen Befehlsschritten zu transportieren … sondern auch sozusagen die Überwachungskette aufrechtzuerhalten, wenn Arbeit ist direkt auf dem Server ausgeführt, sodass ein Pull erforderlich ist, wenn Änderungen aus der Ferne vorgenommen werden …

    – Edward J. Beckett

    4. Mai 2012 um 20:02 Uhr


  • Ein weborientierter Git-Workflow ist ein weiterer guter Artikel mit einem etwas anderen Ansatz.

    – Ian Dunn

    14. August 2012 um 23:49 Uhr

1646641089 581 Git Post Receive Hook fur Website Staging
VonC

Aktualisierung März 2015

Wie ich in “Was ist diese Git-Warnmeldung beim Pushen von Änderungen an ein Remote-Repository?” erwähnt habe, können Sie tatsächlich pushen direkt jetzt zu einem nicht-nackten Repo (Git 2.3.0+, Februar 2015) mit:

git config receive.denyCurrentBranch updateInstead

Aktualisieren Sie den Arbeitsbaum entsprechend, aber verweigern Sie dies, wenn es nicht festgeschriebene Änderungen gibt.

Auf diese Weise können Sie jeden Post-Receive-Hook vermeiden.


(Ursprüngliche Antwort: Okt. 2010)

Die GitFAQ empfiehlt für Nicht-nacktes Repo dieser Post-Update-Hook:
(Es könnte Ihnen mehr Hinweise darauf geben, was tatsächlich bei der Hook-Ausführung vor sich geht. Beachten Sie, dass dies ein Post-Update-Hook ist, kein Post-Receive)

#!/bin/sh
#
# This hook does two things:
#
#  1. update the "info" files that allow the list of references to be
#     queries over dumb transports such as http
#
#  2. if this repository looks like it is a non-bare repository, and
#     the checked-out branch is pushed to, then update the working copy.
#     This makes "push" function somewhat similarly to darcs and bzr.
#
# To enable this hook, make this file executable by "chmod +x post-update".

git-update-server-info

is_bare=$(git-config --get --bool core.bare)

if [ -z "$is_bare" ]
then
    # for compatibility's sake, guess
    git_dir_full=$(cd $GIT_DIR; pwd)
    case $git_dir_full in */.git) is_bare=false;; *) is_bare=true;; esac
fi

update_wc() {
    ref=$1
    echo "Push to checked out branch $ref" >&2
    if [ ! -f $GIT_DIR/logs/HEAD ]
    then
        echo "E:push to non-bare repository requires a HEAD reflog" >&2
        exit 1
    fi
    if (cd $GIT_WORK_TREE; git-diff-files -q --exit-code >/dev/null)
    then
        wc_dirty=0
    else
        echo "W:unstaged changes found in working copy" >&2
        wc_dirty=1
        desc="working copy"
    fi
    if git diff-index --cached [email protected]{1} >/dev/null
    then
        index_dirty=0
    else
        echo "W:uncommitted, staged changes found" >&2
        index_dirty=1
        if [ -n "$desc" ]
        then
            desc="$desc and index"
        else
            desc="index"
        fi
    fi
    if [ "$wc_dirty" -ne 0 -o "$index_dirty" -ne 0 ]
    then
        new=$(git rev-parse HEAD)
        echo "W:stashing dirty $desc - see git-stash(1)" >&2
        ( trap 'echo trapped $$; git symbolic-ref HEAD "'"$ref"'"' 2 3 13 15 ERR EXIT
        git-update-ref --no-deref HEAD [email protected]{1}
        cd $GIT_WORK_TREE
        git stash save "dirty $desc before update to $new";
        git-symbolic-ref HEAD "$ref"
        )
    fi

    # eye candy - show the WC updates :)
    echo "Updating working copy" >&2
    (cd $GIT_WORK_TREE
    git-diff-index -R --name-status HEAD >&2
    git-reset --hard HEAD)
}

if [ "$is_bare" = "false" ]
then
    active_branch=`git-symbolic-ref HEAD`
    export GIT_DIR=$(cd $GIT_DIR; pwd)
    GIT_WORK_TREE=${GIT_WORK_TREE-..}
    for ref
    do
        if [ "$ref" = "$active_branch" ]
        then
            update_wc $ref
        fi
    done
fi

Damit dies funktioniert, müssten Sie dennoch ausdrücklich zulassen, dass Änderungen an den aktuellen Zweig übertragen werden, indem Sie eine der folgenden Konfigurationseinstellungen verwenden:

git config receive.denyCurrentBranch ignore

oder

git config receive.denyCurrentBranch warn

  • +1: Das Skript mag sperrig oder ausführlich erscheinen, aber es ist aus gutem Grund so; im Gegensatz zu den stumpfen Ansätzen der Verwendung einer Ebene git reset --hard oder git checkout -fwerden alle nicht festgeschriebenen Änderungen in einem Stash beibehalten.

    – Chris Johnsen

    1. Oktober 2010 um 13:39 Uhr


  • Dieses Skript ist völlig fubar und es tut nichts. Ich habe es geschafft, es zu reparieren (hoffentlich richtig), siehe meine Antwort …

    – Tronik

    27. Juli 2012 um 16:52 Uhr

  • Mit Git 2.3 brauchen Sie diesen Hook nicht mehr, das können Sie tun git config receive.denyCurrentBranch updateInstead. Sehen github.com/blog/1957-git-2-3-has-been-released .

    – Aurelien

    15. März 2015 um 20:37 Uhr

  • @Aurelien Stimmt, guter Punkt. Ich habe die Antwort bearbeitet, da ich diese Option letzten Februar tatsächlich in stackoverflow.com/a/28262104/6309 behandelt hatte.

    – VonC

    15. März 2015 um 20:51 Uhr


Git Post Receive Hook fur Website Staging
ich mache

Ich hatte genau das gleiche Problem. In einer Antwort auf diesen Link: http://toroid.org/ams/git-website-howto – Folgender Befehl hat es geschafft:

sudo chmod +x hooks/post-receive

Wir haben eine verpasst sudo Berechtigung konfigurierte zuerst das Zeug.

Feste Version des Skripts von VonC, funktioniert für mich (absolut keine Garantien).

#!/bin/sh
#
# This hook does two things:
#
#  1. update the "info" files that allow the list of references to be
#     queries over dumb transports such as http
#
#  2. if this repository looks like it is a non-bare repository, and
#     the checked-out branch is pushed to, then update the working copy.
#     This makes "push" function somewhat similarly to darcs and bzr.
#
# To enable this hook, make this file executable by "chmod +x post-update".

set -e

git update-server-info

is_bare=$(git config --get --bool core.bare)

if [ -z "${is_bare}" ]
then
    # for compatibility's sake, guess
    git_dir_full=$(cd $GIT_DIR; pwd)
    case $git_dir_full in */.git) is_bare=false;; *) is_bare=true;; esac
fi

update_wc() {
    ref=$1
    echo "Push to checked out branch $ref" >&2
    if [ ! -f ${GIT_DIR}/logs/HEAD ]
    then
        echo "E:push to non-bare repository requires a HEAD reflog" >&2
        exit 1
    fi
    if (cd ${GIT_WORK_TREE}; git diff-files -q --exit-code >/dev/null)
    then
        wc_dirty=0
    else
        echo "W:unstaged changes found in working copy" >&2
        wc_dirty=1
        desc="working copy"
    fi
    if git diff-index --cached [email protected]{1} >/dev/null
    then
        index_dirty=0
    else
        echo "W:uncommitted, staged changes found" >&2
        index_dirty=1
        if [ -n "$desc" ]
        then
            desc="$desc and index"
        else
            desc="index"
        fi
    fi
    if [ "$wc_dirty" -ne 0 -o "$index_dirty" -ne 0 ]
    then
        new=$(git rev-parse HEAD)
        echo "W:stashing dirty $desc - see git-stash(1)" >&2
        ( trap 'echo trapped $$; git symbolic-ref HEAD "'"$ref"'"' 2 3 13 15 ERR EXIT
        git update-ref --no-deref HEAD [email protected]{1}
        cd ${GIT_WORK_TREE}
        git stash save "dirty $desc before update to $new";
        git symbolic-ref HEAD "$ref"
        )
    fi

    # eye candy - show the WC updates :)
    echo "Updating working copy" >&2
    (cd ${GIT_WORK_TREE}
    git diff-index -R --name-status HEAD >&2
    git reset --hard HEAD
    # need to touch some files or restart the application? do that here:
    # touch *.wsgi
    )

}

if [ x"${is_bare}" = x"false" ]
then
    active_branch=$(git symbolic-ref HEAD)
    export GIT_DIR=$(cd ${GIT_DIR}; pwd)
    GIT_WORK_TREE="${GIT_DIR}/.."
    for ref in $(cat)
    do
        if [ x"$ref" = x"${active_branch}" ]
        then
            update_wc $ref
        fi
    done
fi

1646641090 767 Git Post Receive Hook fur Website Staging
Honza

Einfaches Skript zum Einstellen dieser Git-Bereitstellung:

Post-Receive-Hook vorbereiten:

echo '#!/bin/sh'        >  .git/hooks/post-receive
echo 'git checkout -f'  >> .git/hooks/post-receive
echo 'git reset --hard' >> .git/hooks/post-receive
chmod +x .git/hooks/post-receive

Push in dieses Repository zulassen, obwohl es nicht leer ist:

git config receive.denycurrentbranch false

  • Sie können auch einen externen Arbeitsbaum verwenden: git config core.worktree /path/to/workdir. Sie können dafür ein bloßes Repository in eines mit Worktree umwandeln (git config core.bare false)

    – Vi.

    21. September 2013 um 1:22 Uhr

  • Warum brauchst du git reset --hard Übrigens?

    – Vi.

    21. September 2013 um 1:23 Uhr

  • Sie können auch hinzufügen git diff -R --cached --name-status vor dem Auschecken, um eine schöne Auflistung der Dateien zu erhalten, die auf der Push-Seite aktualisiert werden.

    – Vi.

    21. September 2013 um 1:23 Uhr


  • Vi: Wenn ich es ohne “git reset –hard” versuche, wurde der Sametime-Arbeitsbaum nicht geändert, wenn ich in das Repository pushe, und git verhielt sich so, als ob ich Dateien im Arbeitsbaum des Servers manuell zurückgeändert hätte.

    – Honza

    21. September 2013 um 15:31 Uhr


1646641091 482 Git Post Receive Hook fur Website Staging
nimmthin

Ich vermute nur, aber das könnte ein Berechtigungsproblem sein (vollständiger Pfad erforderlich? cd?). Überprüfen Sie in den Protokolldateien, was wirklich passiert.

Das Veröffentlichen der Dateien über Git ist jedoch immer nur eine Aufgabe des Veröffentlichungsprozesses. Normalerweise müssen Sie einige Dateien kopieren, andere löschen, einrichten, Berechtigungen aktualisieren, Dokumente generieren usw.

Für eine komplexe Lösung ist ein Build-Skript möglicherweise besser als jeder Git-Hook. Tools, die diese Aufgaben sehr gut bewältigen können:

(Mir ist klar, dass dies nicht die Antwort ist, die Sie erwarten, aber es ist zu lang, um es als Kommentar zu posten.)

  • Sie können auch einen externen Arbeitsbaum verwenden: git config core.worktree /path/to/workdir. Sie können dafür ein bloßes Repository in eines mit Worktree umwandeln (git config core.bare false)

    – Vi.

    21. September 2013 um 1:22 Uhr

  • Warum brauchst du git reset --hard Übrigens?

    – Vi.

    21. September 2013 um 1:23 Uhr

  • Sie können auch hinzufügen git diff -R --cached --name-status vor dem Auschecken, um eine schöne Auflistung der Dateien zu erhalten, die auf der Push-Seite aktualisiert werden.

    – Vi.

    21. September 2013 um 1:23 Uhr


  • Vi: Wenn ich es ohne “git reset –hard” versuche, wurde der Sametime-Arbeitsbaum nicht geändert, wenn ich in das Repository pushe, und git verhielt sich so, als ob ich Dateien im Arbeitsbaum des Servers manuell zurückgeändert hätte.

    – Honza

    21. September 2013 um 15:31 Uhr


964310cookie-checkGit Post-Receive-Hook für Website-Staging

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy