Git Diff sagt, das Teilprojekt sei schmutzig

227

Ich habe gerade ein Git-Diff ausgeführt und erhalte die folgende Ausgabe für alle meine ca. 10 Submodule

diff --git a/.vim/bundle/bufexplorer b/.vim/bundle/bufexplorer
--- a/.vim/bundle/bufexplorer
+++ b/.vim/bundle/bufexplorer
@@ -1 +1 @@
-Subproject commit 8c75e65b647238febd0257658b150f717a136359
+Subproject commit 8c75e65b647238febd0257658b150f717a136359-dirty

Was bedeutet das? Wie behebe ich das?

mrwooster
quelle

Antworten:

268

Wie in Mark Longairs Blog-Beitrag Git Submodules Explained erwähnt ,

Die Versionen 1.7.0 und höher von git enthalten eine ärgerliche Änderung im Verhalten des Git-Submoduls.
Submodule gelten jetzt als fehlerhaft, wenn sie geänderte oder nicht verfolgte Dateien enthalten , während dies zuvor nur der Fall war, wenn HEAD im Submodul auf das falsche Commit zeigte.

Die Bedeutung des Pluszeichens ( +) in der Ausgabe des Git-Submoduls hat sich geändert. Wenn Sie zum ersten Mal darauf stoßen, dauert es eine Weile, bis Sie herausgefunden haben, was falsch läuft, z. B. indem Sie die Änderungsprotokolle durchsehen oder Git-Halbierung für Git verwenden .git, um die Änderung zu finden. Es wäre für die Benutzer viel freundlicher gewesen, ein anderes Symbol für "in der angegebenen Version, aber schmutzig" einzuführen.

Sie können das Problem beheben, indem Sie:

  • Übernehmen oder Rückgängigmachen der Änderungen / Entwicklungen in jedem Ihrer Submodule, bevor Sie zum übergeordneten Repo zurückkehren (wo der Diff keine "schmutzigen" Dateien mehr melden sollte). Um alle Änderungen an Ihrem Submodul rückgängig zu machen, gehen Sie einfach cdin das Stammverzeichnis Ihres Submoduls und tun Sie diesgit checkout .

    dotnetCarpenter kommentiert, dass Sie Folgendes tun können:git submodule foreach --recursive git checkout .

  • oder fügen Sie --ignore-submodulesIhre hinzu git diff, um diese "schmutzigen" Submodule vorübergehend zu ignorieren.

Neu in Git Version 1.7.2

Wie Noam weiter unten kommentiert , wird in dieser Frage erwähnt, dass Sie seit Git-Version 1.7.2 die schmutzigen Submodule ignorieren können mit:

git status --ignore-submodules=dirty
VonC
quelle
2
Auch eine gute Sache zu wissen: Sie können immer noch ausführen, git commit -aohne sich Sorgen machen zu müssen, diese Änderungen hinzuzufügen. Obwohl sie Mvorne mit markiert sind , landen sie nicht in Ihrem Commit.
Gitaarik
1
Für mich musste ich in jedes schmutzige Submodul gehen und rennen git clean -id.
GDP2
1
@ GDP2 Was Sie in einer Zeile anziehen können, mit git submodule foreach --recursive git clean -id(zuerst in einem Backup-Repo getestet werden;))
VonC
1
Der Fall, in dem ich dies unerklärlicherweise immer wieder sah, war, dass ich nicht verfolgte Dateien hatte, die nicht im Submodul waren .gitignore. Das Hinzufügen dort oder zu meiner globalen Ignorierliste hat feste Dinge behoben.
Ben
21

Auch das Entfernen das Submodul und dann läuft git submodule initund git submodule updatewird natürlich den Trick tut, kann aber nicht immer sinnvoll oder möglich sein.

user1178907
quelle
1
Dies funktionierte für mich, als ich einige vorhandene Ordner in Submodule konvertierte und dann auf einen anderen Computer zog, auf dem noch die alten Ordner vorhanden waren.
Roger Lipscombe
17

Verwenden Sie den folgenden Befehl, um alle nicht verfolgten Dateien in einem Submodul zu ignorieren.

git config --global diff.ignoreSubmodules dirty

Es wird die folgende Konfigurationsoption zu Ihrer lokalen Git-Konfiguration hinzugefügt:

[diff]
  ignoreSubmodules = dirty

Weitere Informationen finden Sie hier

Devpool
quelle
16

EDIT : Diese Antwort (und die meisten anderen) sind veraltet; siehe stattdessen Devpools Antwort .


Ursprünglich gab es keine Konfigurationsoptionen, um " git diff --ignore-submodules" und " git status --ignore-submodules" zum globalen Standard zu machen (siehe auch Setzen von Git-Standardflags für Befehle ). Eine Alternative besteht darin, eine Standardkonfigurationsoption ignorefür jedes einzelne Submodul festzulegen, das Sie ignorieren möchten (für beide git diffund git status), entweder in der .git/configDatei (nur lokal) oder .gitmodules(wird von git versioniert). Beispielsweise:

[submodule "foobar"]
    url = [email protected]:foo/bar.git
    ignore = untracked

ignore = untrackedNur nicht verfolgte Dateien ignore = dirtyzu ignorieren , auch geänderte Dateien ignore = allzu ignorieren und auch Commits zu ignorieren. Es gibt anscheinend keine Möglichkeit, es für alle Submodule als Platzhalter zu verwenden.

Ralph Versteegen
quelle
13

Dies ist der Fall, weil der Zeiger, den Sie für das Submodul haben, nicht der ist, der sich tatsächlich im Submodulverzeichnis befindet. Um dies zu beheben, müssen Sie git submodule updateerneut ausführen :

Robin Ren
quelle
9
git submodule foreach --recursive git checkout .

Dies hat mir nicht geholfen, aber es gab mir eine Liste von Dateien (in meinem Fall nur eine), die im Submodul geändert wurden (ohne dass ich dort etwas getan habe).

So konnte ich zum Submodul gehen und der Git-Status zeigte mir, dass mein HEAD getrennt war -> Git-Checkout-Master, Git-Status, um die geänderte Datei noch einmal zu sehen, Git-Checkout> Dateiname <, Git-Pull und alles wieder in Ordnung.

Nur ein wenig
quelle
9

Am Ende habe ich das Submodul-Verzeichnis entfernt und es erneut initialisiert

cd my-submodule
git push
cd ../
rm -rf my-submodule
git submodule init
git submodule update
Szymon Wygnański
quelle
4
Ich würde lieber verstehen, was passiert ist, aber dies war auch das einzige, was für mich funktioniert hat ...
smilebomb
6

Ein Submodul wird möglicherweise als fehlerhaft markiert, wenn die Dateimoduseinstellungen aktiviert sind und Sie die Dateiberechtigungen im Submodul-Teilbaum geändert haben.

Um den Dateimodus in einem Submodul zu deaktivieren, können Sie /.git/modules/path/to/your/submodule/config bearbeiten und hinzufügen

[core]
  filemode = false

Wenn Sie alle schmutzigen Zustände ignorieren möchten, können Sie entweder die ignore = dirtyEigenschaft in der Datei /.gitmodules festlegen , aber ich denke, es ist besser, nur den Dateimodus zu deaktivieren.

Dryobs
quelle