UPDATE² : Mit Git 2.23 (August 2019) gibt es einen neuen Befehl
git restore
, der dies tut, siehe die akzeptierte Antwort .UPDATE : Dies wird ab Git 1.8.3 intuitiver funktionieren, siehe meine eigene Antwort .
Stellen Sie sich den folgenden Anwendungsfall vor: Ich möchte alle Änderungen in einem bestimmten Unterverzeichnis meines Git-Arbeitsbaums entfernen und alle anderen Unterverzeichnisse intakt lassen.
Ich kann
git checkout .
, aber git checkout. Fügt Verzeichnisse hinzu, die durch spärliches Auschecken ausgeschlossen sindEs gibt
git reset --hard
, aber ich kann es nicht für ein Unterverzeichnis tun:> git reset --hard . fatal: Cannot do hard reset with paths.
Nochmals: Warum kann git keine Hard / Soft-Resets nach Pfad durchführen?
Ich kann den aktuellen Status mithilfe von umgekehrt patchen
git diff subdir | patch -p1 -R
, aber dies ist eine ziemlich seltsame Art, dies zu tun.
Was ist der richtige Git-Befehl für diese Operation?
Das folgende Skript veranschaulicht das Problem. Fügen Sie den richtigen Befehl unter dem How to make files
Kommentar ein. Der aktuelle Befehl stellt die Datei wieder her, a/c/ac
die beim Auschecken mit geringer Dichte ausgeschlossen werden soll. Beachten Sie, dass ich nicht explizit wiederherstellen möchte a/a
und a/b
ich nur "weiß" a
und alles unten wiederherstellen möchte. EDIT : Und ich "weiß" auch nicht b
, oder welche anderen Verzeichnisse sich auf der gleichen Ebene befinden wie a
.
#!/bin/sh
rm -rf repo; git init repo; cd repo
for f in a b; do
for g in a b c; do
mkdir -p $f/$g
touch $f/$g/$f$g
git add $f/$g
git commit -m "added $f/$g"
done
done
git config core.sparsecheckout true
echo a/a > .git/info/sparse-checkout
echo a/b >> .git/info/sparse-checkout
echo b/a >> .git/info/sparse-checkout
git read-tree -m -u HEAD
echo "After read-tree:"
find * -type f
rm a/a/aa
rm a/b/ab
echo >> b/a/ba
echo "After modifying:"
find * -type f
git status
# How to make files a/* reappear without changing b and without recreating a/c?
git checkout -- a
echo "After checkout:"
git status
find * -type f
quelle
git stash && git stash drop
?git checkout -- /path/to/subdir/
?git stash
akzeptiert keinAntworten:
Mit Git 2.23 (August 2019) haben Sie den neuen Befehl
git restore
Dies würde sowohl den Index als auch den Arbeitsbaum durch
HEAD
Inhalte ersetzen , wiereset --hard
dies bei einem bestimmten Pfad der Fall wäre.Ursprüngliche Antwort (2013)
Beachten Sie (wie von Dan Fabulich kommentiert ), dass:
git checkout -- <path>
führt keinen Hard-Reset durch: Ersetzt den Inhalt des Arbeitsbaums durch den bereitgestellten Inhalt.git checkout HEAD -- <path>
führt einen Hard-Reset für einen Pfad durch und ersetzt sowohl den Index als auch den Arbeitsbaum durch die Version aus demHEAD
Commit.Wie von Ajedi32 beantwortet, entfernen beide Checkout-Formulare keine Dateien, die in der Zielversion gelöscht wurden .
Wenn der Arbeitsbaum zusätzliche Dateien enthält, die in HEAD nicht vorhanden sind,
git checkout HEAD -- <path>
werden diese nicht entfernt.Hinweis: Mit
git checkout --overlay HEAD -- <path>
(Git 2.22, Q1 2019) werden Dateien entfernt, die im Index und im Arbeitsbaum angezeigt werden, jedoch nicht in<tree-ish>
, damit sie<tree-ish>
genau übereinstimmen .Diese Kasse kann jedoch a respektieren
git update-index --skip-worktree
(für die Verzeichnisse, die Sie ignorieren möchten), wie unter " Warum werden ausgeschlossene Dateien in meiner git spärlichen Kasse immer wieder angezeigt? " Erwähnt .quelle
git checkout HEAD -- .
werden durch spärliches Auschecken ausgeschlossene Dateien wieder angezeigt. Wasgit update-index --skip-worktree
soll tun?git checkout HEAD -- <path>
und löschen Sie dann die Verzeichnisse, die wiederhergestellt wurden (die aber noch in der Sparse-Kasse deklariert sind).Laut dem Git-Entwickler Duy Nguyen, der die Funktion und einen Kompatibilitätsschalter freundlicherweise implementiert hat , funktioniert Folgendes wie erwartet ab Git 1.8.3 :
(Wo
a
ist das Verzeichnis, das Sie zurücksetzen möchten). Auf das ursprüngliche Verhalten kann über zugegriffen werdenquelle
git checkout -- .
where.
" das aktuelle Verzeichnis sein.git reset -- a
(wobei a das Verzeichnis ist, das Sie zurücksetzen möchten)git reset --hard
das ganze Repo wollen?rm -rf a
zuvor einen Vorgang durch.Versuchen Sie es zu ändern
zu
Seit Version 1.7.0 erkennt Git's das Skip-Worktree-Flag an .
ls-files
Ausführen Ihres Testskripts (mit einigen geringfügigen Änderungen, die sich ändern
git commit
... zugit commit -q
undgit status
zugit status --short
) Ausgaben:Ausführen Ihres Testskripts mit den vorgeschlagenen
checkout
Änderungsausgaben:quelle
git checkout
das "Skip-Worktree" -Bit überhaupt nicht respektieren?checkout.c
undtree.c
zeigt nicht, dass das Flag "Arbeitsbaum überspringen" verwendet wird.Für den Fall einfach Änderungen verwerfen, die
git checkout -- path/
odergit checkout HEAD -- path/
arbeiten Befehle von anderen Antworten vorgeschlagen groß. Wenn Sie jedoch ein Verzeichnis auf eine andere Revision als HEAD zurücksetzen möchten, weist diese Lösung ein erhebliches Problem auf: Es werden keine Dateien entfernt, die in der Zielversion gelöscht wurden.Stattdessen habe ich den folgenden Befehl verwendet:
Dies funktioniert, indem der Unterschied zwischen dem Ziel-Commit und dem Index ermittelt und dann umgekehrt auf das Arbeitsverzeichnis und den Index angewendet wird. Grundsätzlich bedeutet dies, dass der Inhalt des Index mit dem Inhalt der von Ihnen angegebenen Revision übereinstimmt. Die Tatsache, dass
git diff
ein Pfadargument verwendet wird, ermöglicht es Ihnen, diesen Effekt auf eine bestimmte Datei oder ein bestimmtes Verzeichnis zu beschränken.Da dieser Befehl ziemlich lang ist und ich ihn häufig verwenden möchte, habe ich einen Alias dafür eingerichtet, den ich benannt habe
reset-checkout
:Sie können es so verwenden:
Oder nur:
quelle
git checkout --overlay HEAD -- <path>
Befehl, den @VonC in seiner Antwort erwähnt?git checkout --overlay HEAD -- <path>
noch nicht veröffentlicht wurde (Git 2.22 wird imIch werde hier eine schreckliche Option anbieten, da ich keine Ahnung habe, wie ich etwas mit Git machen soll, außer
add
commit
undpush
hier ist, wie ich ein Unterverzeichnis "zurückgesetzt" habe:Ich habe ein neues Repository auf meinem lokalen PC gestartet, das Ganze auf das Commit zurückgesetzt, von dem ich Code kopieren wollte, und diese Dateien dann in mein Arbeitsverzeichnis
add
commit
push
et voila kopiert. Hassen Sie den Spieler nicht, hassen Sie Herrn Torvalds dafür, dass er schlauer ist als wir alle.quelle
Ein Reset ändert normalerweise alles, aber Sie können
git stash
auswählen, was Sie behalten möchten. Wie Sie bereits erwähnt haben,stash
wird ein Pfad nicht direkt akzeptiert, er kann jedoch weiterhin verwendet werden, um einen bestimmten Pfad mit dem--keep-index
Flag beizubehalten. In Ihrem Beispiel würden Sie das Verzeichnis b verstauen und dann alles andere zurücksetzen.Dies bringt Sie zu einem Punkt, an dem der letzte Teil Ihres Skripts Folgendes ausgibt:
Ich glaube, dies war das Zielergebnis (b bleibt geändert, a / * -Dateien sind zurück, a / c wird nicht neu erstellt).
Dieser Ansatz hat den zusätzlichen Vorteil, dass er sehr flexibel ist. Sie können so feinkörnig werden, wie Sie möchten, aber bestimmte Dateien, aber keine anderen, in ein Verzeichnis einfügen.
quelle
git add
alles außera
, oder? Klingt in der Praxis schwierig.git add .
danngit reset a
alles außer hinzufügena
.git add
keine gelöschten Dateien hinzugefügt werden. Wenn Sie also nur gelöschte Dateien wiederherstellen,git add .
werden alle geänderten Dateien hinzugefügt, jedoch nicht die gelöschten.Wenn die Größe des Unterverzeichnisses nicht besonders groß ist UND Sie sich von der CLI fernhalten möchten, finden Sie hier eine schnelle Lösung zum manuellen Zurücksetzen des Unterverzeichnisses:
Prost. Sie setzen einfach ein Unterverzeichnis in Ihrem Feature-Zweig manuell zurück, damit es dem des Hauptzweigs entspricht !!
quelle
Die Antwort von Ajedi32 ist genau das , wonach ich gesucht habe, aber bei einigen Commits bin ich auf diesen Fehler gestoßen :
error: cannot apply binary patch to 'path/to/directory' without full index line
Möglicherweise, weil einige Dateien des Verzeichnisses Binärdateien sind. Durch Hinzufügen der Option '--binary' zum Befehl git diff wurde Folgendes behoben:
quelle
Wie wäre es mit
quelle