Wie erzwinge ich git
das Ausführen eines post-receive
Hooks auf einem Server, auch wenn ich kein neues Commit zum Pushen habe?
Hintergrund
Ich verwende git, um eine Website automatisch auf einem Server bereitzustellen. Ich habe ein nacktes Repo in einem geschützten Bereich des Servers und einen post-receive
Hook, der den Inhalt auscheckt und bestimmte Dateien systematisch in einen public_html
Ordner kopiert . (Inspiriert von diesem Tutorial )
Ich hatte es satt, den post-receive
Hook manuell auf dem Server zu ändern, sodass mein post-receive
Hook jetzt tatsächlich eine neue Version von sich selbst aus dem Repo kopiert:
#!/bin/sh
rm -rf ~/../protected/*
GIT_WORK_TREE=~/../protected git checkout -f
# Rewrite over this file with any updates from the post-receive file
cp ~/../protected/post-receive hooks/post-receive
# Delete public_html
# Copy stuff public_html
Das Problem ist natürlich, dass der neue post-receive
Hook nie ausgeführt wird. Eine scheinbar einfache Lösung wäre lediglich, erneut zu pushen, aber jetzt ist bereits alles auf dem neuesten Stand. Dies ist ärgerlich, da ich jedes Mal, wenn ich den post-receive
Hook aktualisiere, ein neues Commit vortäuschen muss . Gibt es eine Möglichkeit, den post-receive
Hook aufzurufen , ohne ein Commit vorzutäuschen oder sich ssh
einzumischen?
Was ich versucht habe
git push
git push -f
checkout -f
ist, benutze ichrm -rf ~/repo.git/refs/heads/master
. Dadurch wird der Hauptzweig gelöscht und jedes Mal ein Push ermöglicht.Antworten:
Verwenden Sie '--allow-empty'
Nach dem ersten Push, der das Skript ersetzt, können Sie Folgendes tun:
Das
--allow-empty
Flag überschreibt das Standardverhalten von git, das verhindert, dass Sie ein Commit durchführen, wenn keine Änderungen vorgenommen werden.Verwenden Sie einen Alias und machen Sie Ihr Leben noch einfacher
Fügen Sie Folgendes hinzu:
~/.gitconfig
Jetzt mach es einfach
git pushpr
Dadurch werden alle Änderungen an master weitergeleitet, was in Ihrem Fall dazu führt, dass Ihr Post-Receive-Ersatzskript erneut gesendet wird. Anschließend wird erneut (unter Verwendung des
--allow-empty
Flags) ein Push ausgeführt, wodurch Ihr aktualisiertespost-receive
Skript ausgeführt wird.quelle
--allow-empty
mit--amend
und kombinieren-m The message from the last commit
, aber Vorsicht: Dadurch wird der Verlauf des letzten Commits neu geschrieben. Verwenden Sie es nur, wenn Sie der einzige Entwickler sind. Sie müssen das nächste Mal einen Druck erzwingen.git commit --allow-empty --amend --no-edit
, um die Festschreibungsnachricht wiederzuverwenden, ohne sie erneut einzugeben oder einen Editor zu öffnen.--amend --no-edit
brauchst du nicht--allow-empty
mehr.Ich weiß, dass dies wahrscheinlich als "gefährlich" eingestuft wird, aber ich lebe gerne am Rande.
Ich lösche einfach den Remote-Zweig und drücke ihn dann erneut. Stellen Sie zunächst sicher, dass Ihre lokale Niederlassung auf dem neuesten Stand ist, um die Wahrscheinlichkeit von Datenverlusten zu begrenzen.
Wenn ich also nach dem Empfang auslösen möchte, um in meinem Fall den Testzweig zur Bereitstellung zu bringen, tue ich nur Folgendes:
Akzeptiere dies jedoch nicht als Antwort. Es ist eher eine Sache zu Ihrer Information.
quelle
git config receive.denyDeleteCurrent false
werden, um den Remote-Zweig löschen zu könnenIch fürchte, Sie müssen ssh zum Server und das Hook-Skript manuell ausführen.
git push
Lässt den Server nicht die Pre-Push- , Pre-Receive- und Post-Receive- Hooks ausführen , wenn nichts hinzugefügt wurde (dh wenn git alles auf dem neuesten Stand druckt ).Der Rest der Antwort bezieht sich auf die Versionsverfolgung des Post-Receive- Hooks, sodass Sie ihn ändern können, ohne ihn an den Server zu senden.
Fügen Sie
do-post-receive
dem lokalen Repository ein Shell-Skript mit dem Namen hinzu :Ersetzen Sie Ihren
hooks/post-receive
Hook am Server durch:(Stellen Sie sicher,
chmod 755 hooks/post-receive
auf dem Server.)Übertragen Sie Ihre Änderungen vom lokalen Repository auf den Server und beobachten Sie, wie Ihr
do-post-receive
Code ausgeführt wird:quelle
while read ...
es gibt wenig oder nichts mehr übrig für dasdo-post-receive
Drehbuch zu lesen. (Ich habe ein Ding namens geschriebengit_xhook
, das mehrere, erweiterte Hooks erlaubt; es ist zu groß für diesen Kommentar, aber das könnte dich dorthin bringen.)Wenn Sie ein falsches neues Commit vermeiden möchten , können Sie es einfach verwenden
Dadurch wird der letzte Festschreibungsdatensatz geändert und Sie können ihn verwenden
git push -f
(vorausgesetzt, Ihre Antwort besagt, dass Sie mit dem Überschreiben einverstanden sind).Ich benutze diesen Befehl relativ oft, um etwas im letzten Commit vor dem Push zu reparieren, also habe ich einen Alias dafür erstellt:
Jetzt kann ich es direkt für den Anwendungsfall als Ihr (
git amend
) oder verwendengit amend -a
git amend -m 'better message'
quelle
Ich habe versucht, leere Commits zu erstellen und den Upload-Zweig zu löschen .
Aber was ist mit einem direkten ssh-Befehl:
quelle
ssh host bash -cl '/path/to/post-receive'
, bin ich mir jedoch nicht sicherIn meinem Fall logge ich mich bei remote ein und starte:
$ sh project.git/hooks/post-receive
funktioniert gut!
quelle
Ich habe eine Bash-Funktion gemacht, um dies zu tun. Es wird davon ausgegangen, dass Sie über einen SSH-Zugriff verfügen
~/.ssh/config
, der entsprechend eingestellt werden kann. Die Standardfernbedienung ist originkick-git() { remote="${1:-origin}" ssh $(echo $(git remote get-url "$remote")/hooks/post-receive | tr ':' ' ') }
Quelle und ausführen
kick-git [remote]
quelle
Nach dem Empfang ist der falsche Ort für künstliche Befehlsantworten.
Sie möchten Ihre serverseitigen Goodies im Pre-Receive-Exit, abhängig von der aktualisierten Referenz - tun
git update-ref refs/commands/update-hooks @
Sie dies zB auf dem Server, dann können Sie es zBgit push server +@:commands/update-hooks
und im Pre-Receive des Servers können Siequelle
Ich mag den Vorschlag von Jamie Carl, aber er funktioniert nicht und ich habe den Fehler erhalten:
In meinem Fall teste ich Post-Receive-Hooks auf meinem lokalen Host gegen ein nacktes Repository. Warnung / super wichtig, führen Sie diesen Befehl nur auf dem
remote
Serverstandort aus!Dadurch wird die Referenz für den Entwicklungszweig gelöscht (möglicherweise müssen Sie auch alle Dateien löschen, die Sie für diesen Zweig bereitgestellt haben). Anschließend können
git push deploy_localtest develop
Sie den gewünschten Push-Befehl für diesen Zweig ausführen.quelle