Wie ignoriere ich mit git eine Datei in einem Zweig, habe sie aber in einem anderen Zweig festgeschrieben?

156

Ich habe ein Projekt, das ich für Heroku bereitstelle . Der Quellcodebaum enthält eine Reihe von MP3-Dateien (die Website ist für ein Aufnahmeprojekt vorgesehen, an dem ich stark beteiligt war).

Ich möchte den Quellcode dafür auf GitHub veröffentlichen , aber GitHub hat ein Limit von 300 MB für seine kostenlosen Konten. Ich möchte nicht 50 MB meines Limits für eine Reihe von MP3-Dateien verwenden. Natürlich könnte ich sie der .gitignoreDatei hinzufügen , um sie aus meinem Repo herauszuhalten.

Ich stelle jedoch Heroku mit bereit git push heroku. Die MP3-Dateien müssen in dem Zweig vorhanden sein, den ich an Heroku weitergebe, damit sie bereitgestellt werden.

Im Idealfall möchte ich .gitignoredie MP3-Dateien in meinem lokalen Master-Zweig verwenden, damit die MP3s nicht enthalten sind, wenn ich sie an GitHub übertrage. Dann würde ich eine lokale Produktionsniederlassung behalten, in der die MP3s festgeschrieben und nicht ignoriert werden. Für die Bereitstellung würde ich den Master in die Produktion einbinden und dann den Produktionszweig nach Heroku verschieben.

Ich kann das nicht richtig zum Laufen bringen.

Hier ist ein Beispiel dafür, was ich versuche zu tun ...

$ git init git-ignore-test
$ cd git-ignore-test
$ echo "*.ignored" >> .gitignore
$ git add .gitignore && git commit -m "Ignore .ignored files"
$ touch Foo.ignored

Zu diesem Zeitpunkt wird Foo.ignored in meinem Hauptzweig ignoriert, ist aber immer noch vorhanden, sodass mein Projekt es verwenden kann.

$ git checkout -b unignored
$ cat /dev/null > .gitignore
$ git add Foo.ignored .gitignore && git commit -m "Unignore .ignored files"

Jetzt habe ich einen Zweig mit diesen Dateien festgeschrieben, wie ich will. Wenn ich jedoch wieder zu meinem Hauptzweig wechsle, ist Foo.ignored nicht mehr vorhanden.

Hat jemand Vorschläge für eine bessere Einrichtung?

Bearbeiten: Zur Verdeutlichung möchte ich, dass die MP3-Dateien in beiden Zweigen vorhanden sind, damit die Site funktioniert, wenn ich die Site lokal ausführe (mit beiden Zweigen). Ich möchte nur, dass die Dateien in einem Zweig ignoriert werden. Wenn ich auf GitHub pushe, werden sie auch nicht gepusht. Normalerweise funktioniert .gitignore gut für diese Art von Dingen (dh eine lokale Kopie einer Datei, die nicht in einem Push auf eine Fernbedienung enthalten ist), aber wenn ich mit eingecheckten Dateien zum Zweig wechsle und dann zurück zum Verzweigen Sie mit den Dateien ignoriert, die Dateien verschwinden.

Myron Marston
quelle
Warum müssen die MP3-Dateien jemals in das Repository übernommen werden?
Dan Loewenherz
4
Mit Heroku ist das Festschreiben an Ihr Repo die einzige Möglichkeit, Dateien bei der Bereitstellung in Ihre App aufzunehmen. Die einzige Alternative ist, etwas wie Amazon S3 zu verwenden, um die MP3s zu bedienen, aber ich würde es vorziehen, dies zu vermeiden.
Myron Marston
Es hört sich so an, als würden Sie über Dollars
stolpern, um ein paar Cent
3
Ich stelle fest, dass Sie eine Antwort als richtig markiert haben, aber nach dem, was ich gelesen habe, ist sie möglicherweise nicht richtig. Haben Sie jemals die Antwort ausprobiert und hat es für Sie funktioniert?
Schleife
2
Off Topic: Haben Sie darüber nachgedacht, einen anderen Open Source-Repository-Host zu verwenden? BitBucket hat keine Größenbeschränkung für seine Git-Repositorys, unabhängig davon, ob sie sich in einem kostenlosen Konto befinden oder nicht (sie erwähnen jedoch, die Größe im Rahmen des Zumutbaren zu halten). Solange Ihr Repo nicht außer Kontrolle gerät, ist dies möglicherweise eine Option. HINWEIS: Ich bin nicht mit BitBucket verbunden, sondern nur mit einem zufriedenen Kunden.
NightOwl888

Antworten:

83

Diese Lösung scheint nur für bestimmte, gepatchte Versionen von git zu funktionieren. In einer neuen Antwort, die auf Problemumgehungen verweist, sowie in einer anderen Antwort und nachfolgenden Kommentaren finden Sie einen Hinweis darauf, welche Versionen möglicherweise funktionieren.

Ich habe einen Blog-Beitrag darüber geschrieben, wie man das effektiv excludesfilefür verschiedene Zweige nutzt , wie einen für öffentliche Githubs und einen für die Heroku-Bereitstellung.

Hier ist das schnelle und schmutzige:

$ git branch public_viewing
$ cd .git/
$ touch info/exclude_from_public_viewing
$ echo "path/to/secret/file" > info/exclude_from_public_viewing 

Fügen Sie dann in der Datei .git / config die folgenden Zeilen hinzu:

[core]
excludesfile = +info/exclude


[branch "public_viewing"]
excludesfile = +info/exclude_from_public_viewing

Jetzt befindet sich das gesamte globale Ignoriermaterial in der info/excludeDatei und der branchenspezifische in der Dateiinfo/exclude_from_public_viewing

Hoffentlich hilft das!

http://cogniton-mind.tumblr.com/post/1423976659/howto-gitignore-for-different-branches

Cognition.Mind
quelle
1
Es tut uns leid, dass Sie so lange gebraucht haben. Wenn Sie die .gitignore-Dateien jedoch nicht löschen, werden standardmäßig die ersten verwendet.
Cognition.Mind
4
Dies funktioniert bei mir nicht, auch wenn das Projekt .gitignore nicht verwendet. Haben Sie etwas dagegen, eine Abschrift der Befehle, die dies von Grund auf neu einrichten ( git init, ...), und die von Ihnen verwendete Version von Git bereitzustellen?
Davor Cubranic
34
Diese Lösung funktioniert nicht. Es gab einige Diskussionen im Blog, und niemand dort konnte diese Arbeit machen.
Spuder
2
In Vanilla Git bin ich mir ziemlich sicher, dass dies nicht funktioniert und nie funktioniert hat. Diejenigen von Ihnen, die es geschafft haben, dies zu reproduzieren, können Sie Ihre Git-Version und andere relevante Informationen über Ihre Umgebung teilen? Möglicherweise haben Sie eine gepatchte Version von den Git-Paketbetreuern Ihrer Distribution.
Palec
20

Wichtiger Hinweis : Die von Cognition.Mind akzeptierte Antwort funktioniert nicht mehr (seit einigen Jahren nicht mehr oder vielleicht für Vanille-Versionen von Git). siehe die Kommentare. Eine gültige Antwort und Problemumgehung finden Sie hier:

https://stackoverflow.com/a/29583813/2157640

Eine andere alternative Problemumgehung (für mein spezielles Problem arbeiten, aber manuelle Stash-Operationen oder die Implementierung eines Hooks erfordern) wäre git stash -u -a. Dies ist mühsam, wenn die Unterschiede groß sind.

Und schließlich besteht die Lösung, mit der ich jetzt arbeite, darin, meine VM, in der wir unsere Entwicklungsumgebung halten, zu info/excludesverzweigen und entsprechend für den Zweig einzurichten bzw. die fehlerhaften, nicht festgeschriebenen Dateien / Ordner zu löschen.

Murphy
quelle
14

Ich würde dringend empfehlen, diese MP3-Dateien auf S3 zu stellen. Wenn sie Teil Ihres Heroku-Pushs (und damit Teil Ihrer Heroku-Schnecke) sind, wird die Startzeit Ihres Prüfstands erheblich verlangsamt. Da Heroku EC2 verwendet, zahlen Sie nicht einmal Bandbreitengebühren, sondern nur die Gebühr für die Speicherung von 50 MB, wenn sich die Dateien in S3 befinden und nur von Ihrer App aufgerufen werden (wenn Benutzer nicht direkt mit S3 verbunden sind).

David Dollar
quelle
13

Angenommen, wir möchten den buildOrdner aller anderen Zweige außer dem productionZweig ignorieren . Da wollen wir buildOrdner in der Produktion pushen .

1) buildNicht in .gitignore aufnehmen. Wenn Sie dies tun, wird es immer für alle Zweige ignoriert.

2) Erstellen Sie eine Datei exclude_from_public_viewingim ./.git/infoOrdner (Dieser Ordner existiert bereits)touch ./.git/info/exclude_from_public_viewing

3) exclude_from_public_viewingSchreiben Sie innen eine Zeile (da Sie versuchen, buildalle Zweige zu ignorieren ). !build

4) Es ist eine Datei vorhanden .git/info/exclude. Wir müssen die folgende Zeile hinzufügen.

 build

Wir möchten den buildOrdner ignorieren, haben ihn jedoch nicht in .gitignore hinzugefügt. Also, woher weiß Git, was zu ignorieren ist? Die Antwort ist, dass wir es der excludeDatei hinzufügen und diese Datei unter bestimmten Bedingungen an übergebengit config

5) Jetzt müssen wir den buildOrdner für die productionVerzweigung bedingt aufheben . Führen Sie dazu folgende Schritte aus

6) Es gibt eine vorhandene Datei mit dem Namen, die ./.git/configwir hinzufügen müssen:

a) excludesfile = +info/excludeunten[core]

[core]
     excludesfile = +info/exclude

b) Erstellen Sie am Ende von ./.git/configas einen neuen Abschnitt

[branch "production"]
    excludesfile = +info/exclude_from_public_viewing

Lösung 2

Es gibt eine intelligente alternative Lösung. Nehmen wir an, Sie möchten einen build/Ordner zum productionZweig hinzufügen und ihn in allen anderen Zweigen ignorieren.

1) Fügen Sie es Ihrer gitignoreDatei hinzu.

2) Erzwingen Sie dabei im Produktionszweig das git addHinzufügen eines buildOrdners:git add -f --all build/

sapy
quelle
Und das unterscheidet sich von der akzeptierten Lösung wie? Mit welcher Version von git hast du es getestet? Wie die verknüpfte Antwort besagt, schlägt dies fehl, weil es branch.<name>.excludesfilein git (mehr?) Keine Unterstützung mehr gibt, nur für core.excludesfile, und meine eigenen Tests schienen dies zu bestätigen.
Murphy
@murphy es funktioniert gut mit git version 2.7.4 (Apple Git-66)und ich habe nicht branch.<name>.excludesfile in meiner Lösung verwendet.
Sapy
4
@sapy: Ich habe dies gemäß dem Anwendungsfall von OP versucht, und die Datei verschwindet immer noch, wenn ich von der Produktion zum Master wechsle. Beachten Sie, dass der Ordner "Build" in den Zweig "Produktion" übernommen werden sollte. (Außerdem stelle ich fest, dass der Zweig "Produktion" das Vorhandensein des Ordners "Build" ignoriert, wenn ich den Ordner "Build" im Zweig "Produktion" nicht festschreibe funktioniert nicht). Ich benutze genau die gleiche Version von Git wie deine. Ich habe auch versucht, den [Zweig "Produktion"] Ansatz zu verwenden, um Dateien nur im Produktionszweig zu ignorieren. Es funktioniert auch nicht, wie Murphy sagte.
halb
Lösung 2 war etwas, wonach ich gesucht habe. Vielen Dank!
Vyacheslav Cotruta
4

Haben Sie versucht, .gitignore in Ihrer Branche anders zu machen?

Sie sollten in der Lage sein, basierend auf dem Zweig, in dem Sie sich befinden, zu ignorieren, was Sie möchten, solange die Dateien in diesem Zweig nicht verfolgt werden.

KEND
quelle
6
Ich habe das versucht. Wenn Sie sich die Befehle ansehen, die ich oben gepostet habe, werden Sie sehen, dass ich genau das getan habe. Das Problem ist, dass git die Dateien verwirft, wenn ich vom Zweig mit den eingecheckten Dateien in den Zweig wechsle, wobei die Dateien ignoriert werden. Ich möchte die MP3s in meinem Hauptzweig behalten, damit die Site im Entwicklungsmodus ordnungsgemäß funktioniert, obwohl die Dateien ignoriert werden.
Myron Marston
1
er hat schon gesagt, dass er das getan hat. Vielleicht ist es am besten, nur diese Antwort zu löschen :-) Sie lenkt ab.
Blamb
3

1. Zusammenfassung

  1. Ich verwende Travis CI für die Bereitstellung ( es unterstützt die Heroku-Bereitstellung ).
  2. Ich füge hinzu .travis.yml:

    before_deploy:
    - mv misc/.gitignore .gitignore

    Wobei misc- jeder Ordner einen anderen enthält .gitignore.

    mvUNIX-Befehl Datei verschieben; überschreiben, wenn die Datei bereits vorhanden ist.

Wenn Travis CI ein Projekt bereitstellt, wird Travis CI nicht auf die Bereitstellung von Provider- Dateien und -Ordnern drängen , die ignoriert werden misc/.gitignore(nicht im Original .gitignoreder Quellen).


2. Einschränkungen

  1. Diese Antwort ist möglicherweise nicht für alle Bedingungen des Autors geeignet. Diese Antwort beantwortet jedoch die Frage: "Wie ignoriere ich mit git eine Datei in einem Zweig, habe sie aber in einem anderen Zweig festgeschrieben?"
  2. Ich bin kein Heroku-Benutzer, meine Beispiele für GitHub , nicht für Heroku. Die Daten dieser Antwort funktionieren für mich in GitHub, aber möglicherweise nicht für Heroku.

3. Relevanz

Diese Antwort ist für April 2018 relevant. In Zukunft sind die Daten dieser Antwort möglicherweise veraltet.


4. Demonstration

mein echtes Projekt .

Beispiel für eine erfolgreiche Bereitstellung .

4.1. Aufgabe

Ich stelle mein Projekt vom src-Zweig zum dest-Zweig desselben Repositorys bereit.

Ich möchte, diese Datei PaletteMira.suricate-profile:

  • Lokale Maschine - existiert für alle Zweige,
  • src remote branch - existiert nicht,
  • dest remote branch - existiert.

Wenn ich den Autor der Frage richtig verstanden habe, hat er eine ähnliche Aufgabe.

4.2. src

Quellen Zweig - SashaYAML .

Teil von .travis.yml:

before_deploy:
- mv misc/.gitignore .gitignore

deploy:
  provider: pages
  on:
    branch: SashaYAML
  keep-history: true
  skip-cleanup: true
  target-branch: SashaDevelop
  repo: Kristinita/PaletteMira
  github-token: $GITHUB_TOKEN
  committer-from-gh: true
  project-name: PaletteMira
verbose: true

Teil von .gitignore:

*.sublime-snippet
*.suricate-profile

Teil von misc/.gitignore

*.sublime-snippet

*.suricate-profilenicht in misc/.gitignore.

PaletteMira.suricate-profile existiert in diesem Zweig nicht remote, sondern lokal.

4.3. dest

Zielzweig - SashaDevelop

Teil von .gitignore:

*.sublime-snippet

*.suricate-profilenicht in misc/.gitignore.

PaletteMira.suricate-profileexistiert für diesen Zweig remote und lokal.

4.4. Schritte zum Reproduzieren

Ich aktiviere das PaletteMira GitHub-Repository für Travis CI → Ich setze die Umgebungsvariable $GITHUB_TOKEN mit dem Wert - meinem GitHub-Token → Ich mache ein Commit für meinen src-Zweig.

Wenn keine Fehler vorliegen, muss ich das erwartete Verhalten erhalten .

Саша Черных
quelle
0

Können Sie Heroku verpflichten und drängen?

zB Fügen Sie das Audio hinzu, schieben Sie es auf Github und in Heroku, entfernen Sie die Dateien auf der Arbeitskopie auf Heroku. Entfernen Sie das Audio aus dem Repo, aber nicht von der Festplatte, und drücken Sie diese Änderung zurück auf Github.

Tom
quelle