Wie kann ich Git dazu bringen, zukünftige Revisionen einer Datei zu ignorieren?

140

Ich habe eine Standardversion einer Datei erstellt, die in einem Git-Repository enthalten ist. Es ist wichtig, dass jemand, der das Repository klont, eine Kopie dieser Datei erhält. Ich möchte jedoch git so einstellen, dass Änderungen an dieser Datei später ignoriert werden. .gitignorefunktioniert nur bei nicht verfolgten Dateien.

Meine Motivation ist, dass diese Datei maschinenspezifische Informationen enthält. Ich möchte Standardwerte bereitstellen und gleichzeitig zulassen, dass Benutzer lokale Änderungen vornehmen, die nicht in das Ursprungs-Repository zurückgeschoben werden, und beim Zusammenführen neuer Änderungen Zusammenführungskonflikte verursachen.

Wir sind im Allgemeinen ziemlich faul und verwenden git add .viel. Wenn ich git nicht anweisen kann, diese Datei zu ignorieren, werden Änderungen daran letztendlich festgeschrieben und gepusht.

Zusammenfassen,

  1. Ich möchte eine Datei erstellen, sie aufrufen default_values.txt, die meinem Git-Repository hinzugefügt wird und enthalten ist, wenn jemand dieses Repository klont.
  2. git add .sollte nicht default_values.txtzum Commit hinzugefügt werden .
  3. Dieses Verhalten sollte an alle Klone des Repositorys weitergegeben werden.
Marc
quelle
1
Können Sie Git-Hooks verwenden, um einen Pre-Commit-Hook zu haben, der ein Commit abbricht, wenn die geänderte Datei default_values.txt (say) ist?
Sateesh
1
Git-Puristen würden sagen, sei nicht faul und benutze den Staging-Bereich richtig, dafür ist es da.
Xint0
Git-Puristen würden sagen, dass sie Smudge / Clean-Skripte verwenden. Es ist die am besten zu wartende Lösung.
Adam Dymitruk
1
Xint0: wahr. Aber wie können Sie verhindern, dass andere Personen versehentlich einchecken?
Alan
Mögliches Duplikat von Committing Machine Specific Configuration Files
Senseful

Antworten:

115

Wie viele andere bereits erwähnt haben, ist eine gute moderne Lösung:

git update-index --skip-worktree default_values.txt

Dadurch werden Änderungen an dieser Datei, sowohl lokal als auch vorgelagert, ignoriert, bis Sie sie erneut zulassen mit:

git update-index --no-skip-worktree default_values.txt

Sie können eine Liste der Dateien erhalten, die als übersprungen markiert sind:

git ls-files -v . | grep ^S

Beachten Sie, dass im Gegensatz dazu --skip-worktreeder --assume-unchangedStatus verloren geht, sobald eine vorgelagerte Änderung vorgenommen wird.

Moodboom
quelle
2
Wenn jemand anderes das Repo zieht und die Datei bearbeitet, werden Änderungen in seinem Verzeichnis ignoriert? Ich hoffe, sie müssten tippen --no-skip-worktree, um ihre Änderungen hinzuzufügen.
Neaumusic
3
Was mit ihren Änderungen gemacht wird, wird von ihnen gesteuert. Mit anderen Worten, sie müssten einen Skip-Worktree für die Datei in ihrem Repo festlegen, wenn sie nicht möchten, dass ihre Änderungen übertragen werden. Wenn es sich um eine Datei handelt, die an alle gesendet werden soll und bei der alle nachfolgenden Änderungen ignoriert werden, müssen alle dieselben Anweisungen befolgen.
Moodboom
3
Beachten Sie, dass Sie möglicherweise den --skip-worktreeStatus einer Datei rückgängig machen müssen, bevor Sie die Verzweigung wechseln können, wenn dieselbe Datei in der anderen Verzweigung verfolgt wird.
Moodboom
3
hmm, es funktioniert ... nachdem ich einige Änderungen an der Datei vorgenommen habe, wurde sie nicht angezeigt git status, aber als ich versuchte, in einen anderen Zweig error: Your local changes to the following files would be overwritten by checkout: error: Entry 'wix-stores-merchant-app/demo/credentials.js' not uptodate. Cannot merge.
auszuchecken
1
Ich habe diese Alias ​​auf git ignoreund git unignore.
Michael - Wo ist Clay Shirky
48

Was Sie suchen, ist git update-index --assume-unchanged default_values.txt.

Weitere Informationen finden Sie in den Dokumenten: http://www.kernel.org/pub/software/scm/git/docs/git-update-index.html

tamasd
quelle
11
Das funktioniert nicht. obwohl es git hinzufügen lässt. Ignorieren Sie die Datei im lokalen Zweig. Ein Klon des Archivs weist dieses Verhalten nicht auf (wenn Sie die Datei default_values.txt im geklonten Archiv ändern, wird sie mit "git add." zum Commit hinzugefügt.)
Marc
6
Ja, weil Sie es nur für das lokale Repo einstellen. Sie können diese Art von Informationen nicht weitergeben.
Tamasd
8
@Indradhanush - Diese Lösung erfüllt nicht das Kriterium 3 - "Das Verhalten sollte an alle Klone des Repositorys weitergegeben werden" - weshalb ich es nicht akzeptiert habe. Das heißt nicht, dass es keine gute Antwort ist.
Marc
Ich habe das 3. Kriterium nie bemerkt. Weil ich nicht danach gesucht habe. :)
Indradhanush Gupta
3
Für lokale Konfigurationsdateien mit privaten App-Einstellungen möchten Sie wahrscheinlich skip-worktreeanstelle von assume-unchangedmehr Info stackoverflow.com/questions/13630849/…
Aaron Hoffman
21

Der Ansatz, den ich allgemein gesehen habe, besteht darin, eine Datei mit einem anderen Namen zu erstellen, z. B. default_values_template.txt, und default_values.txt in Ihren .gitignore einzufügen. Weisen Sie die Benutzer an, default_values_template.txt in default_values.txt in ihren lokalen Arbeitsbereichen zu kopieren und bei Bedarf Änderungen vorzunehmen.

Laurence Gonsalves
quelle
hmmm ... könnte ich vielleicht einen Hook schreiben, um default_values_template automatisch in default_values ​​zu kopieren, wenn default_values ​​nicht existiert?
Marc
2
Dies ist meiner Erfahrung nach der häufigste Weg, dies zu lösen. Es ist so ziemlich der Weg des geringsten Widerstands, da es "einfach funktioniert", und Sie können Ihren Code leicht überprüfen lassen, ob die lokale Konfigurationsdatei vorhanden ist, und einen hilfreichen Fehler anzeigen, wenn dies nicht der Fall ist.
Jani Hartikainen
Ich denke, die Lösung besteht in der Tat darin, so etwas zu tun, vorzugsweise mit einem Skript, das ausgeführt wird, wenn Sie ziehen oder klonen. Eine Idee wäre, dass alles mit einer bestimmten Erweiterung (z. B. .basefile) in eine Datei kopiert wird, deren Erweiterung gelöscht wird, und dann der Dateiname zu .gitignore in diesem Verzeichnis hinzugefügt wird. Also würde ich eine Datei default_values.txt.basefile erstellen und diese festschreiben. Ich habe nicht die Git oder Perl Chops, um das zu tun, aber ich werde einen Freund fragen, der das tut und dich wissen lassen, wie es funktioniert.
Marc
1
@AdamDymitruk: Ja, in diesem Fall kann Clean / Smudge verwendet werden, aber es ist alles andere als klar, dass dies die beste Option ist. Dies macht es beispielsweise ziemlich schwierig, wenn die Leute die Datei wirklich ändern möchten , da das Reinigen / Verschmieren im Weg ist. Ich würde den hier beschriebenen Ansatz tatsächlich bevorzugen.
Sleske
1
Ich nehme ein Stichwort von Git selbst (speziell Git Hooks) und verwende das .sampleSuffix. Also in deinem Falldefault_values.txt.sample
tir38
5

Schauen Sie sich Smudge / Clean Scripting an. Auf diese Weise können Sie die Versionskontrolle der Datei durchführen, aber wenn sie ausgecheckt ist, "verwischen" Sie sie, indem Sie die generischen Daten / Platzhalterdaten durch maschinenspezifische Daten in der Datei ersetzen.

Wenn Sie es festschreiben, "bereinigen" Sie es, indem Sie die maschinenspezifischen Informationen durch allgemeine Informationen oder Platzhalterinformationen ersetzen.

Smudge / Clean-Skripte müssen dahingehend deterministisch sein, dass sie mehrmals angewendet werden. In unterschiedlichen Reihenfolgen entspricht dies nur dem Ausführen des letzten Skripts in der Sequenz.

Dasselbe kann mit Kennwörtern angewendet werden, wenn Sie Ihr Repository verfügbar machen müssen, der Inhalt jedoch vertrauliche Informationen enthalten kann.

Adam Dymitruk
quelle
Sind Clean and Smudge-Skripte lokal oder Teil des Repos?
Alan
Ja. :) ... das heißt, Sie können den Fleck sauber über das Repo teilen, aber es ist keine gute Idee, wenn sie sensible Daten wie Produktionskennwörter enthalten. Wenn dies kein Problem darstellt, müssen Sie das Skript explizit aktivieren. Andernfalls könnten Benutzer böswillige Dinge über Github und andere gemeinsam genutzte Repos für andere Benutzer tun.
Adam Dymitruk
Ich muss etwas mehr darüber lesen. Grundsätzlich möchte ich ein Projekt user.jsoneinrichten, dessen Standard mit den Creds jedes Entwicklers überschrieben werden muss, aber ich möchte nicht, dass der Entwickler versehentlich seine Creds eincheckt.
Alan
Ich würde nach sauberen Fleck-Beispielskripten suchen. Sehen Sie, was auf Sie zukommt. Springe auch auf den Git-IRC-Raum auf Freenode. Sie erhalten sofort Hilfe.
Adam Dymitruk
3

Ich habe dieses Problem gelöst, indem ich den Filter "sauber" definiert habe, um einfach den Inhalt der Datei im Index zu erfassen.

git show :path/to/myfile sollte nur den Inhalt des Index für die angegebene Datei drucken, damit wir diesen in einem Skript verwenden können, um die Arbeitskopie durch die unberührte Kopie im Index zu ersetzen:

#! /bin/sh

git show :$1

Legen Sie dies als "sauberen" Filter für die betreffende Datei fest (vorausgesetzt, Sie haben dies in "discard_changes" eingefügt):

$ git config filter.ignore_myfile.clean "discard_changes path/to/myfile"
$ echo "path/to/myfile filter=ignore_myfile" >> .gitattributes

Leider kann ich keinen Weg finden, dies auf mehrere Dateien verallgemeinerbar zu machen, da es keine Möglichkeit gibt, innerhalb des sauberen Skripts zu erkennen, welche Datei wir verarbeiten. Natürlich hindert Sie nichts daran, für jede Datei eine andere Filterregel hinzuzufügen, aber es ist etwas umständlich.

Haddon CD.
quelle
1

Ich habe eine Lösung gefunden, die für mein Team funktioniert. Wir teilen unsere Githooks über Symlinks und nachdem ich eine Vorlagendatei zu Git hinzugefügt habe, habe ich einen Pre-Commit-Hook hinzugefügt, der prüft, ob die Vorlagendatei geändert wurde und wenn ja git reset -- templatefile.txt. Wenn es die einzige geänderte Datei ist, brich ich auch das Commit ab.

Obstcodierer
quelle
-1

Ich schlage vor, Submodule zu untersuchen. Wenn Sie die maschinenspezifischen Dateien in einem Submodul ablegen, sollte git add dies ignorieren.

ivanpro
quelle
Das ist eine gute Idee, aber dann muss ich auch das Repository für einzelne Dateien auf dem Git-Server ablegen, was nicht optimal ist, nur weil wir Github verwenden und eine begrenzte Anzahl von Repositorys haben.
Marc
@Marc werfen Sie einen Blick auf Visual Studio Team Services, unbegrenzt kostenlose private Projekte und Git-Repositorys. Kanban-Boards, Workitem- und Bug-Tracking, Verknüpfen von Checkins mit Workitems, Verwalten von Sprints, wenn Sie sich für Scrum oder andere Projekttypen interessieren. Darüber hinaus verfügt es über hervorragende Build-Tools zum Erstellen auf mehreren Plattformen, zu viele Dinge, um sie zu erwähnen, die alle kostenlos sind. Einige Leute verprügeln es, weil es Microsoft ist, aber es übertrifft zweifellos das, was Github in Bezug auf Tools zu bieten hat, abgesehen von nur Repository-Hosting. Es gibt Grenzen, was Sie kostenlos tun können, aber ich überschreite sie selten.
Aran Mulholland
@Marc Eine weitere Sache, die ich sehr nützlich finde, ist, dass ich so viele Konten einrichten kann, wie ich möchte. Wenn ich also ein Projekt für einen Kunden schreibe, der die Quellcodeverwaltung besitzen möchte, kann ich ein Konto erstellen und es verwenden Um das Projekt zu planen, zu entwerfen und auszuführen, und wenn ich fertig bin, kann ich das Eigentum an dem Konto auf den Kunden übertragen.
Aran Mulholland