Wie kann ich nur ein Unterverzeichnis meines Git-Repos in Heroku bereitstellen / pushen?

121

Ich habe ein Projekt, das Serve verwendet und mit Git versioniert wird. Serve erstellt einen outputOrdner mit statischen Dateien, die ich für Heroku bereitstellen möchte.

Ich möchte das Serve-Projekt nicht selbst bereitstellen, da der Heroku Cedar-Stack es nicht besonders zu mögen scheint, aber vor allem möchte ich Herokus großartige Unterstützung für statische Websites nutzen.

Gibt es eine Möglichkeit, einen Unterordner auf einer Git-Fernbedienung bereitzustellen? Sollte ich ein Git-Repo im outputOrdner erstellen (das klingt falsch) und das an Heroku senden?

Olivier Lacan
quelle
1
Möglicherweise suchen Sie nach Submodulen: book.git-scm.com/5_submodules.html
greg0ire

Antworten:

220

Es gibt einen noch einfacheren Weg über Git-Subtree . Angenommen, Sie möchten die Ausgabe Ihres Ordners als Stamm an Heroku senden, können Sie Folgendes tun:

git subtree push --prefix output heroku master

Es scheint derzeit, dass git-subtree in git-core aufgenommen wird, aber ich weiß nicht, ob diese Version von git-core noch veröffentlicht wurde.

Anhansmenschen
quelle
1
Ja, aber der Teilbaum ist (ab 1.8.0.2) immer noch nicht über das Git-Installationsprogramm enthalten . Glücklicherweise ist die Installation von der Quelle schnell und unkompliziert. Diese Seite hat bei mir auf dem Mac funktioniert.
Dribnet
14
Wenn Sie brauchen --force, verwenden Sie git push heroku `git subtree split --prefix output master`:master --force. Siehe stackoverflow.com/a/15623469/2066546 .
Fiedl
2
Aber was ist der richtige Weg, um ein bestimmtes Tag zu pushen. Ich dachte es sollte sein git subtree push --prefix output heroku +refs/tags/v1.0.0:refs/heads/master. Aber das funktioniert nicht und kommt mit zurück +refs/tags/v1.0.0:refs/heads/master does not look like a ref. Ich benötige diese Art von Funktionalität, um später auf bestimmte Tags zurückgreifen zu können. Was ist der richtige Weg, das zu tun?
Denis
1
Ich erhalte die Fehlermeldung "Aktualisierungen wurden abgelehnt, weil sich eine gedrückte Verzweigungsspitze hinter der Fernbedienung befindet"
Ally
2
@ and-dev @Eric Burel Ich habe den outputOrdner, der nur in meinem developZweig vorhanden war, erfolgreich in den heroku masterZweig verschoben, ohne dass eine Angabe erforderlich develop:masterwar. Anscheinend wird er in den von Ihnen angegebenen Zielzweig aus Ihrem aktuell ausgecheckten Zweig verschoben .
Cprcrack
9

Ich hatte ein ähnliches Problem. In meinem Fall war es nie ein Problem, alles im Heroku-Repository wegzublasen und durch das zu ersetzen, was sich in meinem Unterverzeichnis befindet. In diesem Fall können Sie das folgende Bash-Skript verwenden. Legen Sie es einfach in Ihrem Rails-App-Verzeichnis ab.

#!/bin/bash

#change to whichever directory this lives in
cd "$( dirname "$0" )"

#create new git repository and add everything
git init
git add .
git commit -m"init"
git remote add heroku [email protected]:young-rain-5086.git

#pull heroku but then checkback out our current local master and mark everything as merged
git pull heroku master
git checkout --ours .
git add -u
git commit -m"merged"

#push back to heroku, open web browser, and remove git repository
git push heroku master
heroku open
rm -fr .git

#go back to wherever we started.
cd -

Ich bin mir sicher, dass es viele Möglichkeiten gibt, dies zu verbessern - also zögern Sie nicht, mir zu sagen, wie!

JnBrymn
quelle
+1Vielen Dank. Diese Lösung funktioniert hervorragend, wenn Sie sich nicht für Git-Protokolle auf Heroku interessieren. Sie können das obige Skript optimieren, falls Sie einige Ordner innerhalb des zu implementierenden Anwendungsunterpfads ignorieren möchten. Zum Beispiel wollte ich keinen specOrdner auf Heroku. Beispiel Gist
ch4nd4n
+1Aber Sie können vereinfachen, indem Sie nicht ziehen und in Heroku Master verschmelzen und stattdessen einfachgit push --force heroku master
MK Safi
9

Ich habe mit dem angefangen, was John Berryman gesagt hat, aber tatsächlich kann es einfacher sein, wenn Sie sich überhaupt nicht für die Heroku-Git-Geschichte interessieren.

cd bin
git init
git add .
git commit -m"deploy"
git push [email protected]:your-project-name.git -f
rm -fr .git

Ich denke, offiziell git subtreeist die beste Antwort, aber ich hatte Probleme, den Teilbaum auf meinem Mac zum Laufen zu bringen.

LessQuesar
quelle
4

Nach einem langen und harten Monat, in dem ich verschiedene Dinge ausprobiert und jedes Mal gebissen wurde, wenn ich merkte,

Nur weil Heroku ein Git-Repository als Bereitstellungsmechanismus verwendet, sollten Sie es nicht als Git-Repository behandeln

es hätte genauso gut rsync sein können, sie haben sich für git entschieden, lassen Sie sich deswegen nicht ablenken

Wenn Sie dies tun, öffnen Sie sich allen Arten von Verletzungen. Alle oben genannten Lösungen scheitern irgendwo kläglich:

  1. Es erfordert, dass jedes Mal oder in regelmäßigen Abständen etwas getan wird oder unerwartete Dinge passieren (Submodule verschieben, Teilbäume synchronisieren, ...)
  2. Wenn Sie zum Beispiel eine Engine verwenden, um Ihren Code zu modularisieren, wird Bundler Sie lebendig essen. Es ist unmöglich zu beschreiben, wie frustriert ich mit diesem Projekt war, als ich nach einer guten Lösung dafür gesucht habe
    • Wenn Sie versuchen, die Engine als Git-Repo-Link hinzuzufügen + bundle deploy- fehlgeschlagen, müssen Sie jedes Mal ein Update bündeln
    • Wenn Sie versuchen, die Engine als :path+ bundle deploy- Fehler hinzuzufügen , betrachtet das :pathEntwicklerteam die Option als "Sie verwenden Bundler nicht mit dieser Edelsteinoption", sodass sie nicht für die Produktion gebündelt wird
    • Außerdem möchte jede Aktualisierung des Motors Ihren Schienenstapel aktualisieren -_-
  3. Die einzige Lösung, die ich gefunden habe, besteht darin, die Engine als /vendorSymlink in der Entwicklung zu verwenden und die Dateien tatsächlich für die Produktion zu kopieren

Die Lösung

Die betreffende App hat 4 Projekte in Git Root:

  1. API - abhängig vom Profil läuft auf 2 verschiedenen Heroku-Hosts - Upload und API
  2. Web - die Website
  3. web-old - die alte Website, die sich noch in der Migration befindet
  4. common - die gemeinsamen Komponenten, die in einem Motor extrahiert werden

Alle Projekte haben einen vendor/commonSymlink, der die Wurzel der commonEngine betrachtet. Beim Kompilieren des Quellcodes für die Bereitstellung in Heroku müssen wir den Symlink entfernen und den Code rsyncieren, damit er sich physisch im Herstellerordner jedes einzelnen Hosts befindet.

  1. akzeptiert eine Liste von Hostnamen als Argumente
  2. Führt einen Git-Push in Ihrem Entwicklungs-Repo aus und führt dann einen sauberen Git-Pull in einem separaten Ordner aus, um sicherzustellen, dass keine schmutzigen (nicht festgeschriebenen) Änderungen automatisch auf die Hosts übertragen werden
  3. stellt die Hosts parallel bereit - jedes Heroku-Git-Repo wird gezogen, neuer Code wird an den richtigen Stellen synchronisiert und mit grundlegenden Push-Informationen im Git-Commit-Kommentar festgeschrieben.
  4. Am Ende senden wir einen Ping mit Locken, um den Hobby-Gastgebern zu sagen, dass sie aufwachen und die Protokolle verfolgen sollen, um zu sehen, ob alles Wein ist
  5. spielt auch gut mit Jenkins: D (automatischer Code-Push zum Testen von Servern nach erfolgreichen Tests)

Funktioniert sehr, sehr gut in freier Wildbahn mit minimalen (nein?) Problemen seit 6 Monaten

Hier ist das Skript https://gist.github.com/bbozo/fafa2bbbf8c7b12d923f

Update 1

@AdamBuczynski, es ist noch nie so einfach.

Erstens haben Sie immer mindestens eine Produktions- und Testumgebung - und im schlimmsten Fall eine Reihe funktionsspezifischer Cluster - plötzlich muss 1 Ordner als ziemlich grundlegende Anforderung n Heroku-Projekten zugeordnet werden, und alles muss irgendwie so organisiert werden Das Skript "weiß", welche Quelle Sie wo bereitstellen möchten.

sync_commonZweitens möchten Sie Code zwischen Projekten teilen - jetzt kommt der Teil, bei dem die Shennanigans mit Symlinks in der Entwicklung durch tatsächlichen rsynchronisierten Code auf Heroku ersetzt werden, da Heroku eine bestimmte Ordnerstruktur benötigt und Bundler und Rubygems die Dinge wirklich sehr, sehr, sehr hässlich machen, wenn Sie möchte die gemeinsamen Fäden in einen Edelstein extrahieren

3. Sie möchten CI einstecken und es ändert sich ein wenig, wie Unterordner und Git-Repo organisiert werden müssen. Am Ende erhalten Sie im einfachsten Anwendungsfall den oben genannten Kern.

In anderen Projekten muss ich Java-Builds einbinden. Wenn Sie Software an mehrere Clients verkaufen, müssen Sie Module filtern, die abhängig von den Installationsanforderungen installiert werden.

Ich sollte wirklich darüber nachdenken, Dinge in einem Rakefile oder so zu bündeln und alles so zu machen ...

bbozo
quelle
Hallo @bbozo, würde es Ihnen etwas ausmachen, Ihre Lösung ein wenig zu verdichten und sie spezifisch für den Anwendungsfall zu machen, einen bestimmten Unterordner für ein bestimmtes Heroku-Projekt bereitzustellen und alle Dinge herauszunehmen, die für Heroku nicht benötigt / spezifisch sind?
Adam Reis
Vielen Dank für die Aktualisierung Ihrer Antwort. Ich denke, ich werde einfach in die Kugel beißen und meinen clientseitigen und serverseitigen Code in separate Repositorys aufteilen. Nicht ideal für unsere Situation, aber es wird die erzwungenen Teilbaum-Pushs übertreffen, die wir jetzt ausführen müssen, und nach meinen Erkenntnissen wird es auch viel einfacher sein, als zu versuchen, Symlinks zu verwenden.
Adam Reis
Haben Sie keine Angst vor einem "Bereitstellungsskript", es zahlt sich aus
bbozo