Git selektive lokale Änderungen aus einer Datei zurücksetzen

149

In meinem Git-Repo, das ein SVN-Repo verfolgt, habe ich eine Reihe von Änderungen an einer einzelnen Datei vorgenommen.

Jetzt möchte ich diese Änderungen zurücksetzen (wie svn revert), aber nur Teile der Datei.

Ich möchte in der Lage sein, die Unterschiede in der Datei anzuzeigen, die Änderungen, die ich nicht möchte, zu verwerfen (zurückzusetzen) und die gewünschten Änderungen beizubehalten.

das

git add -i 

Befehl scheint eine Option zu haben, aber ich möchte dies noch nicht inszenieren.

Pradeep
quelle

Antworten:

91

Sie können das direkt mit tun git checkout -p. Siehe Daniel Stutzbachs Antwort unten.


Alte Antwort (vorher checkout -peingeführt):

Sie können es so machen:

git add -i

(Wählen Sie die Hunks aus, die Sie behalten möchten.)

git commit -m "tmp"

Jetzt haben Sie ein Commit mit nur den Änderungen, die Sie behalten möchten, und der Rest ist nicht bereitgestellt.

git reset --hard HEAD

Zu diesem Zeitpunkt wurden nicht festgeschriebene Änderungen verworfen, sodass Sie ein sauberes Arbeitsverzeichnis mit den Änderungen haben, die Sie festschreiben möchten.

git reset --mixed HEAD^

Dadurch wird das letzte Commit ('tmp') entfernt, die Änderungen in Ihrem Arbeitsverzeichnis bleiben jedoch nicht bereitgestellt.

BEARBEITEN: ersetzt --softdurch --mixed, um den Bereitstellungsbereich zu bereinigen.

Paolo Capriotti
quelle
Dadurch werden die Änderungen übernommen, die ich behalten möchte, nicht wahr? Ich möchte diese Änderungen noch nicht übernehmen. mm vielleicht nehme ich Commits zu ernst. Vielleicht sollte ich mich jetzt entspannen, da alles in einem lokalen Repo ist. Übrigens, was macht Git Reset - Soft HEAD ^?
Pradeep
"git reset --soft HEAD ^" macht ein Commit in dem Sinne rückgängig, dass das Arbeitsverzeichnis und der Index unverändert bleiben, und verschiebt den aktuellen Zweig um ein Commit zurück.
Jakub Narębski
Danke Jakub. Paolo, warum sollte hier ein Soft-Reset auf Kopf 1 erforderlich sein? Das teilweise Festschreiben und das Hard-Reset sollten ausreichen, um einige Änderungen beizubehalten und andere zu verwerfen.
Pradeep
1
Daniels Antwort unten ist sehr einfach und scheint der richtige Weg zu sein.
Umang
309

Ich glaube, Sie können es am einfachsten tun mit:

git checkout -p <optional filename(s)>

Aus der Manpage:

   −p, −−patch
       Interactively select hunks in the difference between the <tree−ish>
       (or the index, if unspecified) and the working tree. The chosen
       hunks are then applied in reverse to the working tree (and if a
       <tree−ish> was specified, the index).
       This means that you can use git checkout −p to selectively discard
       edits from your current working tree.
Daniel Stutzbach
quelle
1
Wenn Sie dies nicht selektiv tun möchten, können Sie "git checkout - <Datei> ..." verwenden, um Änderungen zu verwerfen.
db42
Handelt es sich um Verzeichnisse?
bbum
1
Dies scheint mir beim Verwerfen von Änderungen sehr fehlzuschlagen ("Fehler: Patch fehlgeschlagen <Datei>", "Fehler: <Datei> Patch gilt nicht"). Seltsamerweise erhalte ich diese Fehler, wenn ich die aOption im Patch-Modus verwende, um eine gesamte Datei zu verwerfen, aber es git checkout -- <file>funktioniert wie erwartet. Weiß jemand warum?
Chrnola
Ich hatte diesen Fehler einige Male, wenn die Datei bereits gepatcht wurde, und daher war der interaktive Patch mit den angewendeten Patches der aktuellen Datei nicht mehr aktuell. Es passierte, wenn ich ein GUI-Tool wie den Quellbaum verwendete, wenn ich ein Stück zweimal versehentlich verwarf. Das zweite Mal würde diesen Fehler erzeugen.
Phyatt
3

Sie könnten laufen git diffauf die Datei, Speichern Sie die diff, bearbeiten es um die Änderungen zu entfernen Sie sie speichern möchten, führen Sie es dann durch patch -Rdie restlichen diffs rückgängig zu machen.

git diff file.txt> patch.tmp
# edit patch.tmp, um die Hunks zu entfernen, die Sie behalten möchten
patch -R <patch.tmp
Greg Hewgill
quelle
Ich hatte 2 Hunks in meiner Patch-Datei und entfernte einen. Ich bin mir nicht sicher, was der Grund ist, aber der Patch -R wird immer wieder abgelehnt.
Pradeep
2
Sie erwähnen in einem anderen Kommentar, dass git diffdie gesamte Datei als geändert angezeigt wird. Dies geschieht normalerweise, wenn Sie die Datei mit anderen Zeilenenden als zuvor gespeichert haben. Dies würde auch dazu führen patch, dass die Patch-Datei abgelehnt wird. Klingt das nach dem, was passiert sein könnte?
Greg Hewgill
Du hast recht. Die Zeilenenden werden umgeschaltet, wenn ich den Patch-Befehl verwende. Ich bin an Fenstern und benutze Creme / Vim. Ich denke, ich muss das zuerst klären.
Pradeep
Ich konnte das Problem mit dem Patch unter Windows nicht beheben. Obwohl ich sicher bin, dass dies funktioniert, bevorzuge ich Paolos Rezept. Aus Liebe zu diesen interaktiven Befehlen, um mit den Unterschieden mit git add -i zu arbeiten.
Pradeep
3

Sieht aus wie du willst

 git revert --no-commit $REVSISON 

Sie können dann verwenden

 git diff --cached

um zu sehen, welche Änderung vor dem Festschreiben vorgenommen wird (da das Zurücksetzen nur ein Festschreiben in Vorwärtsrichtung ist, das die Umkehrung einer Änderung in der Vergangenheit repliziert)

Wenn Sie mit einem reinen Git-Repository arbeiten, können Sie möglicherweise abhängig von Ihren Zielen interaktive rebase ( git rebase -i) verwenden, um zu dem Commit zurückzukehren, das Ihnen nicht gefallen hat, und das Commit rückwirkend bearbeiten, sodass die Änderungen, die Sie nicht mögen, nie vorgenommen werden , aber das ist im Allgemeinen nur, wenn Sie wissen, dass Sie es nie wieder sehen wollen.

Kent Fredric
quelle
Ich habe, wie Sie bereits erwähnt haben, zu einer früheren Version zurückgekehrt (ist das richtig?) Und jetzt zeigt git diff nur die gesamte Datei als geändert an. Es soll die Änderungen zeigen, die ich vorgenommen hatte?
Pradeep
1

Wenn Sie die Frage erneut lesen, klingt es so, als ob Sie Änderungen in Ihrem Arbeitsbaum rückgängig machen möchten und nicht Änderungen, die zuvor festgeschrieben wurden. Einige der anderen Antworten lassen jedoch den Eindruck entstehen, dass meine Lesung möglicherweise falsch ist. Könntest Du das erläutern?

Wenn sich die Änderungen nur in Ihrer Arbeitskopie befinden, können Sie dies am einfachsten tun, indem Sie die Änderungen vornehmen, die Sie beibehalten möchten:

git add -i <file>

Werfen Sie dann die Änderungen weg, die Sie nicht behalten möchten, indem Sie die Indexversion überprüfen:

git checkout -- <file>

Dann entfernen Sie die Änderungen, wenn Sie sie noch nicht inszenieren möchten:

git reset -- <file>

Dieses Rezept setzt nur ausgewählte Änderungen an der Datei (oder den von Ihnen angegebenen Dateien) zurück und erstellt kein temporäres Commit, das dann zurückgesetzt werden muss.

Wenn Sie nur einige der in früheren Festschreibungen vorgenommenen Änderungen selektiv anwenden möchten, können Sie zuerst eine Datei auf den vorherigen festgeschriebenen Status zurücksetzen:

git reset <commit_before_first_unwanted_change> -- <file>

Dann können Sie dem vorherigen Rezept folgen git add -i <file>, um die Änderungen, die Sie behalten möchten, git checkout -- <file>zu git reset -- <file>inszenieren, die unerwünschten Änderungen wegzuwerfen und die Änderungen zu "entfernen".

CB Bailey
quelle
0

Die in den Antworten hier beschriebenen Befehlszeilenoptionen sind praktisch, wenn sich die Datei auf einem Server befindet, auf den ich über ein SSH-Terminal zugreife. Wenn sich die Datei jedoch auf meinem lokalen Computer befindet, bevorzuge ich den folgenden Weg:

Öffnen Sie die Datei im NetBeans-Editor (der mit Git-Unterstützung geliefert wird). Netbeans setzt rote / grüne / blaue Markierungen an den Zeilennummern, um anzuzeigen, wo Inhalte gelöscht / hinzugefügt / geändert wurden.

Wenn Sie mit der rechten Maustaste auf eine dieser Markierungen klicken, können Sie diese Änderung rückgängig machen. Außerdem können Sie mit der rechten Maustaste auf rote und blaue Markierungen klicken, um die alte Version in einem Popup anzuzeigen.

Abhishek Anand
quelle