Kann ich eine Datei "git commit" und ihre Inhaltsänderungen ignorieren?

355

Jeder Entwickler in meinem Team hat seine eigene lokale Konfiguration. Diese Konfigurationsinformationen werden in einer aufgerufenen Datei gespeichert, devtargets.rbdie in unseren Rake-Build-Aufgaben verwendet wird. Ich möchte jedoch nicht, dass Entwickler die Devtargets-Datei des anderen überfrachten.

Mein erster Gedanke war, diese Datei in die .gitignoreListe aufzunehmen, damit sie nicht an git gebunden ist.

Dann begann ich mich zu fragen: Ist es möglich, die Datei festzuschreiben, aber Änderungen an der Datei zu ignorieren? Also würde ich eine Standardversion der Datei festschreiben und wenn ein Entwickler sie auf seinem lokalen Computer ändert, würde git die Änderungen ignorieren und sie würde nicht in der Liste der geänderten Dateien angezeigt, wenn Sie einen Git-Status oder ein Git-Commit durchführen .

Ist das möglich? Es wäre sicherlich eine nette Funktion ...

Derick Bailey
quelle
1
Siehe auch stackoverflow.com/questions/3318043/… zu einem ähnlichen Thema.
VonC
Mögliches Duplikat von Committing Machine Specific Configuration Files
Senseful

Antworten:

458

Klar, ich mache genau das von Zeit zu Zeit mit

git update-index --assume-unchanged [<file> ...]

So machen Sie das Tracking rückgängig und starten es erneut (wenn Sie vergessen haben, welche Dateien nicht mehr verfolgt wurden, lesen Sie diese Frage ):

git update-index --no-assume-unchanged [<file> ...]

Relevante Dokumentation :

- [no-] angenommen-unverändert
Wenn dieses Flag angegeben wird, werden die für die Pfade aufgezeichneten Objektnamen nicht aktualisiert. Stattdessen setzt / deaktiviert diese Option das Bit "Unverändert annehmen" für die Pfade. Wenn das Bit "Unverändert annehmen" aktiviert ist, verspricht der Benutzer, die Datei nicht zu ändern, und lässt Git davon ausgehen, dass die Arbeitsbaumdatei mit den im Index aufgezeichneten übereinstimmt. Wenn Sie die Arbeitsbaumdatei ändern möchten, müssen Sie das Bit deaktivieren, um Git zu informieren. Dies ist manchmal hilfreich, wenn Sie mit einem großen Projekt in einem Dateisystem arbeiten, das einen sehr langsamen lstat(2)Systemaufruf hat (z. B. cifs).

Git schlägt (ordnungsgemäß) fehl, wenn diese Datei im Index geändert werden muss, z. B. beim Zusammenführen in einem Commit. Wenn die angenommene, nicht verfolgte Datei vorgelagert geändert wird, müssen Sie die Situation daher manuell behandeln.

Ein ordnungsgemäßer Fehler bedeutet in diesem Fall, dass Änderungen an dieser Datei (legitime Änderungen usw.) beim Ziehen angezeigt werden:

$ git pull
…
From https://github.com/x/y
   72a914a..106a261  master     -> origin/master
Updating 72a914a..106a261
error: Your local changes to the following files would be overwritten by merge:
                filename.ext

und wird sich weigern zu fusionieren.

An diesem Punkt können Sie dies überwinden, indem Sie entweder Ihre lokalen Änderungen rückgängig machen. Hier ist eine Möglichkeit:

 $ git checkout filename.ext

Ziehen Sie dann erneut und ändern Sie Ihre lokale Datei erneut, oder stellen –no-assume-unchangedSie sie ein, und Sie können an diesem Punkt normales Verstecken und Zusammenführen usw. durchführen.

Rob Wilkerson
quelle
10
macht dieser Befehl seine Sache lokal im Ordner .git? Ich meine, wenn ich diesen Befehl für eine config.php-Datei ausführe, wird dies an andere Benutzer weitergegeben, die das Repo verwenden?
Magus
16
@Magus: Nein. Dies funktioniert nur für Sie.
Rob Wilkerson
3
Und bald später möchten Sie wissen, wie Sie feststellen können, ob
Ciro Santilli 法轮功 冠状 病 六四 事件 20
10
Änderungen an Dateien, die auf diese Weise ignoriert werden, gehen verloren, wenn "git stash" verwendet wird. Gibt es einen Weg, das zu umgehen?
Alexis
5
Dafür ist nicht da git update-index --assume-unchanged. public-inbox.org/git/…
jsageryd
97

Der bevorzugte Weg, dies zu tun, ist die Verwendung git update-index --skip-worktree <file>, wie in dieser Antwort erläutert :

assume-unchangedwurde für Fälle entwickelt, in denen es teuer ist, zu überprüfen, ob eine Gruppe von Dateien geändert wurde. Wenn Sie das Bit setzen, geht git (natürlich) davon aus, dass die Dateien, die diesem Teil des Index entsprechen, in der Arbeitskopie nicht geändert wurden. So wird ein Durcheinander von stat-Anrufen vermieden. Dieses Bit geht verloren, wenn sich der Eintrag der Datei im Index ändert (also wenn die Datei stromaufwärts geändert wird).

skip-worktreeist mehr als das: selbst wenn git weiß, dass die Datei geändert wurde (oder durch ein Zurücksetzen geändert werden muss - hart oder dergleichen), wird es so tun, als ob dies nicht der Fall wäre, und stattdessen die Version aus dem Index verwenden. Dies bleibt so lange bestehen, bis der Index verworfen wird.

Verwenden Sie zum Rückgängigmachen dies git update-index --no-skip-worktree <file>

Seit der Git-Version 2.25.1 ist dies auch nicht mehr der empfohlene Weg.

Benutzer versuchen häufig, die Bits "Unverändert annehmen" und "Arbeitsbaum überspringen" zu verwenden, um Git anzuweisen, Änderungen an nachverfolgten Dateien zu ignorieren. Dies funktioniert nicht wie erwartet, da Git bei bestimmten Vorgängen möglicherweise weiterhin Arbeitsbaumdateien anhand des Index überprüft. Im Allgemeinen bietet Git keine Möglichkeit, Änderungen an nachverfolgten Dateien zu ignorieren. Daher werden alternative Lösungen empfohlen.

Wenn es sich bei der zu ändernden Datei beispielsweise um eine Art Konfigurationsdatei handelt, kann das Repository eine Beispielkonfigurationsdatei enthalten, die dann in den ignorierten Namen kopiert und geändert werden kann. Das Repository kann sogar ein Skript enthalten, mit dem die Beispieldatei als Vorlage behandelt und automatisch geändert und kopiert wird.

1615903
quelle
Funktioniert dies für alle Benutzer, die das Repository auschecken? Erhalten sie bestimmte Dateien, können aber versehentlich keine Änderungen mehr hinzufügen, es sei denn, dies wird ausdrücklich angegeben?
mmm
2
@momomo das Flag wird im Index gespeichert, also nein, es ist nur für einen einzelnen Benutzer. In der Antwort von Erjiang finden Sie Informationen zu allen Benutzern.
1615903
Ich versuche herauszufinden, wie der Inhalt der Datei aussehen soll. Ich habe die Antwort, auf die Sie sich bezogen haben, kommentiert, aber keine Antwort erhalten. Wo soll es sich befinden und was ist der Inhalt? Wissen Sie?
mmm
Ich folge nicht. Der Befehl wird verwendet, um eine bestimmte Datei zu ignorieren, die Sie im Befehl angeben. Der Inhalt dieser Datei ist nicht relevant.
1615903
1
In der Git-Dokumentation heißt es ausdrücklich, nicht git update-index --skip-worktreefür diesen Zweck zu verwenden.
bk2204
43

Es scheint gängige Praxis zu sein, eine zu erstellen devtargets.default.rbund devtargets.rbfestzuschreiben und dann jeden Benutzer anzuweisen, diese Datei zu kopieren (die sich in der .gitignore-Liste befindet). Zum Beispiel macht CakePHP dasselbe für seine Datenbankkonfigurationsdatei, die sich natürlich von Maschine zu Maschine ändert.

Erjiang
quelle
6
Sie können eine Datei, die verfolgt wird, nicht .gitignore. .gitignore wirkt sich nur auf Dateien aus, die nicht im Index enthalten sind.
CB Bailey
1
Ich habe versucht, dies zu vermeiden, obwohl ich wirklich keinen guten Grund habe. Wir machen es jetzt und ich denke, es ist ein Schmerz, sich daran zu erinnern, dass ich meine eigene Version ohne ".default" im Namen erstellen muss.
Derick Bailey
11
@DerickBailey Aber um fair zu sein, ist es einfacher, sich daran zu erinnern, die Datei zu kopieren, als sich daran zu erinnern, die --assume-unchangedOption für alle zu verwenden, die das Repository klonen.
Dan
1
@DerickBailey Sie können Ihren Rake-Build auch standardmäßig so einrichten, devtargets.default.rbdass er devtargets.rbnicht vorhanden ist.
Luke
@erjang was ist in dieser devtargets.default.rb Datei? Ein Beispiel?
mmm
2

Für IntelliJ IDEA-Benutzer: Wenn Sie Änderungen für eine Datei (oder Dateien) ignorieren möchten, können Sie sie in eine andere verschieben Change Set.

  • Gehe zu Local Changes( Cmd + 9)
  • Wählen Sie die Datei (en) aus, die Sie ignorieren möchten
  • F6 um sie zu einem anderen zu bewegen Change Set
Eugene
quelle