2016-04-01 11 views
1

Pro Git erklärt git reset wie folgt aus:git reset --hard macht den Arbeitsbaum nicht wie ein Index?

Recap

Der reset Befehl diese drei Bäume in einer bestimmten Reihenfolge überschreibt, zu stoppen, wenn Sie es zu sagen:

  1. den Zweig Kopf bewegen zeigt auf (hier zu stoppen, wenn --soft)
  2. Machen Sie den Index wie HEAD aussehen (hier aufhören, es sei denn --hard)
  3. das Arbeitsverzeichnis wie der Index aussehen

So wie ich verstanden, dass, wenn ich es tue git reset --hard, dann meine beiden Index und mein Arbeitsverzeichnis würde genau wie mein Kopf werden. Also ging ich weiter und tat dies:

# make a git repo 
mkdir mygitrepo 
cd mygitrepo 
git init 

# init commit 
touch old_file 
git commit -a 

# stage a file 
touch staged 
git add staged 

# create file that is not staged 
touch unstaged 

Bisher meine Repo sieht wie folgt aus:

  • HEAD old_file
  • index old_file +
  • inszeniert
  • working dir old_file + inszeniert + unstaged

Nun, wenn ich git reset --hard ausführen, dann erwarte ich m y-Repo werden:

  • HEAD old_file
  • index old_file
  • working dir old_file

Aber ich würde diese Stelle bekommen:

  • HEAD old_file
  • index old_file
  • working dir old_file + unstaged

I ähnlichen Test tat durch explizites Ziel Argument übergeben, wie git reset --hard target, und ich habe ähnliches Ergebnis: inszenierte Dateien sind alle weg, aber unstaged Dateien sind noch vorhanden, nachdem git reset --hard.

Könnte jemand erklären, wenn ich irgendetwas über git reset missverstanden habe?

Antwort

1

Wie erwähnt in "Undoing Changes"

git clean Der Befehl wird oft in Verbindung mit git reset --hard ausgeführt.
Denken Sie daran, dass das Zurücksetzen nur auf verfolgte Dateien wirkt. Daher ist ein separater Befehl erforderlich, um nicht verfolgte Dateien zu bereinigen.

Mit diesen beiden Befehlen können Sie das Arbeitsverzeichnis in den genauen Status eines bestimmten Commits zurückversetzen.

Die --hard Option wird dokumentiert:

Resets den Index und Arbeits Baum.
Alle Änderungen an verfolgt Dateien im Arbeitsbaum seit <commit> werden verworfen.


Dies wurde bereits im Jahr 2008
Simply put by Linux Torvalds diskutiert zurück:

Wenn Sie "git checkout -f" oder "git reset --hard" zu tun, die beide dieser Kontrollen (*) verwendet sind werden einfach ignoriert. Schließlich haben Sie um einen erzwungenen Wechsel gebeten.

(* prüft = schmutzig Datei oder untracked Dateien)

Und zumindest im zweiten Fall, was ich denke, passiert ist, dass git wird die Datei es doesn nicht entfernen Wissen Sie, so haben Sie einen "Turd" links um. obwohl


Added Dateien ... auch wenn es nie begangen wurden (ganz neu ist), werden nach wie vor von einem git reset --hard gelöscht, wie seen also in 2008:

ich tatsächlich versehentlich gelöscht hundert von neu hinzugefügten Dateien gestern tun gerade dies.

Meine Frage ist, warum „git reset --hard“ kann kein Sonderfall für neu hinzugefügte verfolgt Dateien machen?
Schließlich "git status" weiß, dass sie "neue Dateien" sind, und "git reset --hard" könnte erkennen, dass das Abwischen von der Oberfläche der Erde nicht die hilfreichste Sache ist, die möglich ist.

Als Anregung, git read-tree -m HEAD oder git rm --cached <file list>vor ein git reset --hard würde helfen, diese neuen Dateien zu halten um

Junio C. Hamano stil argues (sie aus dem Index zu entfernen):

würden Sie wollen "reset --hard" zu entfernen Sie diesen Pfad, wenn ein Pfad nicht in dem HEAD, aber in Index in anderen Fällen vorhanden ist.
Und es ist meine Erfahrung, dass viel öfter als es wünschenswert ist.

(wie aus einem Konflikt merge von crufts Loswerden)

Beachten Sie, dass in diesem Fall git fsck can still help recover those deleted new files.

+0

Wusste nicht, dass es nur für verfolgte Dateien funktioniert. Vielen Dank! –

1

Es gibt eine wichtige Regel, die Git immer befolgt (es sei denn, es wurde explizit gesagt, es nicht zu tun): Nicht ungeschickte Datei berühren.

Mit der Standardfunktionalität führt Git niemals Aktionen durch, die zu Datenverlusten nicht nachverfolgbarer Dateien führen. Das liegt daran, dass Informationen von nicht verdeckten Dateien niemals von Git wiederhergestellt werden können: Sie "wissen" nichts über sie, also speichert sie ihren Inhalt nicht irgendwo, was jede Operation sehr gefährlich macht. Also wird es sie einfach nicht berühren.

Dies ist auch der Grund, warum Git nicht zu einer Verzweigung mit einer nicht aufgezeichneten Datei wechseln kann, wenn diese Verzweigung eine getrackte Datei mit demselben Pfad enthält. Da dies Ihre nicht verfolgte Datei überschreiben und sie durch die Datei aus dieser Verzweigung ersetzen würde, könnten Sie diese nicht aufgezeichnete Datei niemals wiederherstellen. Also wird Git den Zweig einfach nicht wechseln und Sie bitten, sich zuerst um die nicht verfolgte Datei zu kümmern (was bedeuten könnte, sie umzubenennen, sie zu Git hinzuzufügen oder sie sogar zu löschen). Wenn Sie also git reset tun, werden Sie nur den Index beeinflussen. Und git reset --hard wirkt sich auf den Index und das Arbeitsverzeichnis aus. Und für Git enthält das Arbeitsverzeichnis nur verfolgte Dateien. Das ist der Grund, warum git reset --hard weder nicht aufgezeichnete Dateien noch Dateien entfernt, die sich in Ihrem .gitignore befinden. Git "weiß" nicht über sie, also wird es sie nicht berühren.

Wenn Sie nicht verfolgte Dateien entfernen möchten, gibt es einen Befehl, der dafür verantwortlich ist: git clean. Der Befehl kommt mit verschiedenen Kombinationen von Argumenten, die alle verschiedene verschiedene Aufgaben ausführen.

Der Standardfall, git clean -f, löscht die unverschlüsselten Dateien, behalte aber ignorierte Dateien intakt. Wenn Sie auch ignorierte Dateien löschen möchten, können Sie git clean -x -f verwenden. Beachten Sie, dass Sie normalerweise immer -f (oder --force) für git clean angeben müssen, um irgendetwas zu tun. Dies ist nur ein zusätzlicher Sicherheitsmechanismus, um sicherzustellen, dass Sie wissen, was Sie tun. Sie können stattdessen -n verwenden, um einen Trockenlauf durchzuführen und nur zu zeigen, welche Dateien Git löschen würde. Das macht es einfach, Probleme zu vermeiden.

+1

Sehr hilfreiche Einführung auf Git Philosophie, danke! –

Verwandte Themen