2017-06-14 4 views
1

Um zu versuchen, git revert zu verstehen, machte ich eine Reihe von 4 einfachen Commits - A, B, C, D - zu einer Textdatei, foo.txt , mit der Absicht, nur das Commit B später rückgängig zu machen und die Commits A, C, D intakt zu lassen.git revert: Kann ein individuelles Commit auch in einem einfachen Fall nicht rückgängig machen

Also, in jedem Commit, habe ich jeweils eine neue Zeile in die Datei hinzugefügt, entweder eine Funktion hinzugefügt oder einen Fehler eingeführt.

begehen Nach A, Inhalt foo.txt:

Feature A 

Nach B, Inhalt foo.txt begehen:(Hier stelle ich einen Fehler, den ich später rückgängig machen/revert werde es versuchen.)

Feature A 
Bug 

Nach C, Inhalt foo.txt commit :

Feature A 
Bug 
Feature C 
Feature D 

nun rückgängig zu machen, die Auswirkungen von Commit B (die den Fehler eingeführt), ich tat:

git revert master^^ 

Feature A 
Bug 
Feature C 

Nach D, Inhalte von foo.txt verpflichten

Was ich erwartet habe, war, eine neue Commit E, die die Bug Zeile aus der Datei entfernt, so dass die Datei cont ents als:

Feature A 
Feature C 
Feature D 

Allerdings habe ich den Fehler bekam:

error: could not revert bb58ed3... Bug introduced 
hint: after resolving the conflicts, mark the corrected paths 
hint: with 'git add <paths>' or 'git rm <paths>' 
hint: and commit the result with 'git commit' 

mit dem Inhalt der Datei nach dem erfolglosen git revert Wesen:

Feature A 
<<<<<<< HEAD 
Bug 
Feature C 
Feature D 
======= 
>>>>>>> parent of bb58ed3... Bug introduced 

(bb58ed3 ist der Hash von Commit B und 'Bug eingeführt' Commit's Kommentar.)

Frage:

  1. Was ist hier los?

  2. Wenn selbst ein solches einfaches, einzeiliges Commit nicht automatisch rückgängig gemacht/rückgängig gemacht werden kann und eine manuelle Lösung von mir erfordern muss, wie kann ich dann ein komplexeres Commit durchführen, dessen ursprünglicher Entwickler möglicherweise jemand anderes ist!

  3. Gibt es spezielle Fälle, in denen git revert besser geeignet wäre?

Antwort

1

git sieht jeder begehen als Änderungsliste (I vereinfachen die Dinge hier) und versucht, „Unapply“, dass, wenn Sie git revert nennen.Jede Änderungsliste enthält auch einen Kontext, um sicherzustellen, dass die Änderung sinnvoll ist. Zum Beispiel, wenn die Änderung, die wir vornehmen möchten, lautet "add return nach Zeile 10", ist es wahrscheinlicher, Dinge zu brechen als "add return nach Zeile 10, wenn Zeilen 7-9 X, Y und Z enthalten". So können wir Ihre zweite beschreiben begehen als (wieder, vereinfacht dies ein wenig hier):

  1. Unter der Annahme, dass die erste Zeile der Datei Feature A ist.
  2. Angenommen, dass es keine zweite Zeile gibt. Geben Sie in die zweite Zeile Bug ein.

Nachdem Sie hinzugefügt haben einige Zeilen, Kontext des Bug wesentlich verändert, so git revert nicht sicher ist, ob es einfach die Zeile entfernen kann. Vielleicht haben die neu hinzugefügten Zeilen den Fehler behoben. Sie werden aufgefordert, den Kontextzusammenhang explizit zu lösen.

Wie für Ihre Fragen 2-3: ja, git revert kann in Fällen verwendet werden, wenn Sie ein Stück der Datei, die seit damals nicht geändert wurde, rückgängig machen. Zum Beispiel wurde der Fehler in einer foo Funktion eingeführt, aber nur die bar Funktion (die zehn Zeilen darunter liegt) wurde seitdem geändert. In diesem Fall wird git revert die Änderung wahrscheinlich automatisch rückgängig machen, da sie sieht, dass der Kontext unverändert ist.

UPD: hier ist ein Beispiel dafür, warum Kontext wichtig ist, auch wenn Sie Ihren eigenen Code sind versuchen zurückzukehren:

Commit A (beachten Sie die Tippfehlern):

int some_vlue = 0; 
read_int_into(some_vlue); 
some_vlue = some_vlue++; 

Commit B (Fehler eingeführt):

int some_vlue = 0; 
some_vlue = 123; 
some_vlue = some_vlue++; 

Commit C (Name fest):

int some_value = 0; 
some_value = 123; 
some_value = some_value++; 

Jetzt, um Commit B zurückzusetzen, muss man einen Kontext haben, wie wir some_value = 123 mit älterer Zeile read_int_into(some_vlue) einfach nicht ersetzen können - es wäre Kompilierungsfehler.

+0

Ich denke, die Kontext-Sache tut mehr weh als helfen. 'git' sollte erlauben, die Verwendung von Kontext über eine Option zu' git-revert' zu deaktivieren. Kontext wäre nützlich, wenn Sie Patches senden und blind anwenden oder nicht genau wissen, ob sie auf das richtige Ziel und dessen Version angewendet werden. Aber in Fällen wie meiner weiß 'git' selbst genau die Quelle und das Ziel, also warum Kontext nutzen, frage ich mich! Schätze deine Erklärung, übrigens. Ich werde noch etwas warten, bevor ich das Finale festsetze. – Harry

+1

@Harry Ich habe eine Erklärung hinzugefügt. Es kann komplexere Situationen mit Variablenumbenennungen, Methodenumbenennungen geben, und in einigen von ihnen würde der resultierende Code sogar kompilieren. Es ist also unmöglich, automatisch zu prüfen, ob wir den Kontext ignorieren können oder nicht und 'Git' spielt sicher. – yeputons

+0

Ihr Beispiel macht definitiv Sinn. Aber wie könnte sich 'git' jemals auf (einen begrenzten) Kontext verlassen, da Umbenennungen auch außerhalb des Kontextes stattfinden können? – Harry

Verwandte Themen