2017-01-30 2 views
5

Ich muss ein Git Repo in ein bestehendes Verzeichnis klonen ($HOME, für die Verwaltung von dotfiles). Ich mache einen nackten Klon und rekonfiguriere ihn, weil ich in ein vorhandenes unsauberes Arbeitsverzeichnis klonen muss. Es funktioniert, aber ich finde, dass git status versucht, Filter bei der ersten Verwendung auszuführen. Warum macht es das und wie kann ich es verhindern?Warum gibt 'git status' Filter aus?

Try this:

# create a test repo 
mkdir test && cd test 
git init 
echo hello > hello.txt 
git add . 
git commit -m 1 
echo 'hello.txt filter=foo diff=bar' > .gitattributes 
git add . 
git commit -m 2 

# clone it bare and configure it 
mkdir ../test2 && cd ../test2 
git clone --bare ../test .git 
git config core.bare false 
git config core.logallrefupdates true 
git reset 
git checkout . 
git config filter.foo.clean foo 
git config filter.foo.smudge foo 
git config diff.bar.textconv bar 

Diese Borks

$ git status 
error: cannot run foo: No such file or directory 
error: cannot fork to run external filter 'foo' 
error: external filter 'foo' failed 
On branch master 
nothing to commit, working tree clean 

Dies gilt nicht

$ git status 
On branch master 
nothing to commit, working tree clean 

Auch zunächst git status mehrmals kurz hintereinander zu tun (dh git status; git status; git status) können mehrere Ausbeute Fehler Manchmal

Soweit ich durch much reading bestätigen kann, sollten die Filter nur beim Ein- und Auschecken von Dateien ausgeführt werden.

Warum funktioniert git status sie?

+0

was ist deine 'git --version'? –

+0

git version 2.11.0 – starfry

+0

Übrigens würde ich dot-files auf diese Weise nicht verwalten (und nicht). Stattdessen habe ich ein Git-Verzeichnis mit dem Namen 'Dotfiles' in meinem Home-Verzeichnis, das eine gewöhnliche, nicht-bare Struktur ist, und dann symbole ich' 'was auch immer 'auf' Dotfiles/was auch immer'. – torek

Antwort

2

Die Idee, dass Filter nur beim Ein-/Auschecken ausgeführt werden, ist eine Art white lie. Es soll Filter erklärbarer machen.

In der Tat, obwohl Filter laufen, wenn Dateien zwischen dem Index und Arbeitsbaum (und auch bewegen, in ausreichend modernen Versionen von Git, wenn sie mit --path= Optionen in git show und git cat-file und git hash-object auch angefragt: einige davon sind Übergänge direkt vom Repository zu stdout oder stdin zum Repository). Dies ist meist entspricht Checkin/Checkout-Zeit. Aber git status hat aufgrund des Cache-Aspekts des Index ebenfalls eine Sondergenehmigung.

Aus Gründen der Leistung möchte Git wissen, ob eine Datei im Arbeitsbaum in Bezug auf die Version im Index "schmutzig" sein könnte. Git geht davon aus, dass der Wert statst_mtime, die in der Regel von einer Sekunde Auflösung, kann für diesen Zweck verwendet werden: Wenn die st_mtime Zeit der Datei -die Arbeit Baum Einsteiger ist älter als ein gespeicherte st_mtime in einem Indexeintrag, dann ist der Indexeintrag auf dem Laufenden und „sauber“ ist: was in dem Index ist übereinstimmt, was in der Arbeit Baum ist nach sauberen Filter usw. Anwendung

Wenn die Zeitstempel der Arbeit Baum Eintrag ist neuer als der gespeicherte Indexeintrag, dann wurde die Datei definitiv geändert: der Indexeintrag kann veraltet sein. Es ist nicht garantiert veraltet, da die Arbeitsbaumdatei möglicherweise in einer Weise geändert worden ist, die schließlich keine Änderung machte. Aber es ist natürlich notwendig, den sauberen Filter (und jede CR/LF-Linie, die Hacker endet) auszuführen.

Wenn die beiden Zeitstempel gleich sind, ist der Arbeitsbaumeintrag unbestimmt. (Git nennt das "racily clean", obwohl "racily dirty" genauso zutreffend wäre.)

In allen diesen Fällen wird git status den sauberen Filter (und alle CR/LF-Änderungen input-to-Git direction) über die Arbeitsbaumdatei ausführen, um einen neuen Hash zu berechnen. Wenn der neue Hash dem Index-Hash entspricht, kann und wird Git den Index-Eintrag aktualisieren, um die Datei als "tatsächlich sauber" zu markieren. Wenn Sie das nächste Mal etwas machen, muss Git den sauberen Filter nicht mehr ausführen.

Es sei denn, Sie tun alles innerhalb der Auflösung des st_mtime stat Feldes. In diesem Fall wird der Indexeintrag "racily clean" und Git muss es erneut versuchen. Dies beobachten Sie hier.

(Beachten Sie, nebenbei gesagt, dass git status laufen zwei diffs: ein von HEAD zu indizieren, und ein aus dem Index zu Baum arbeitet Es ist die zweite diff, die enorm von dem Cache-Aspekte des Index Nutzen Der.. Index kann nun auch speichert Informationen über uncached Dateien und Verzeichnisse, auch!)


Einige stat Anrufe geben Unter zweiter Präzision, aber aus verschiedenen Gründen, wobei der Index/Cache-Eintrag speichert nur die 1 - Zeitstempel der zweiten Auflösung auf jeden Fall, n ormal.

Für (viel) mehr dazu, siehe the racy-git.txt file in the technical documentation.

+0

Große Erklärung! Es erklärt auch, warum 'touch hello.txt'' 'git status' 'die Filter laufen lässt. Und es erklärt, warum sie erneut ausgeführt werden, wenn die Zeit zwischen dem Ändern der Dateizeitmarke und der Statusprüfung zu kurz ist (<1s). Angesichts dieser Erklärung würde ich annehmen, dass es keine Möglichkeit gibt, die Ausführung der Filter zu verhindern (in meinem Fall werden die Filter fehlschlagen, bis ein Kryptoschlüssel bereitgestellt wird). In diesem Fall ist mein Work-around "Schlaf 1 && git status &>/dev/null" das Beste, auf das ich hoffen kann ...? – starfry

+0

Diese Problemumgehung sollte funktionieren. Ich weiß nicht, warum Sie diese Dinge überhaupt verschlüsseln. – torek

+0

private Schlüssel, API-Schlüssel, etc. Ich kryptiere nur die Dinge, die empfindlich sind, auf einer Pro-Datei-Basis. – starfry

Verwandte Themen